18
18
# -----------------------------------------------------------------------------
19
19
from __future__ import division
20
20
from collections import defaultdict
21
+ from itertools import product
21
22
from os .path import join
22
23
23
24
from future .utils import viewitems
@@ -62,6 +63,7 @@ class Analysis(QiitaStatusObject):
62
63
share
63
64
unshare
64
65
build_files
66
+ summary_data
65
67
"""
66
68
67
69
_table = "analysis"
@@ -99,7 +101,7 @@ def get_by_status(cls, status):
99
101
return {x [0 ] for x in conn_handler .execute_fetchall (sql , (status ,))}
100
102
101
103
@classmethod
102
- def create (cls , owner , name , description , parent = None ):
104
+ def create (cls , owner , name , description , parent = None , from_default = False ):
103
105
"""Creates a new analysis on the database
104
106
105
107
Parameters
@@ -112,23 +114,53 @@ def create(cls, owner, name, description, parent=None):
112
114
Description of the analysis
113
115
parent : Analysis object, optional
114
116
The analysis this one was forked from
117
+ from_default : bool, optional
118
+ If True, use the default analysis to populate selected samples.
119
+ Default False.
115
120
"""
121
+ queue = "create_analysis"
116
122
conn_handler = SQLConnectionHandler ()
123
+ conn_handler .create_queue (queue )
117
124
# TODO after demo: if exists()
118
-
119
- # insert analysis information into table with "in construction" status
120
- sql = ("INSERT INTO qiita.{0} (email, name, description, "
121
- "analysis_status_id) VALUES (%s, %s, %s, 1) "
122
- "RETURNING analysis_id" .format (cls ._table ))
123
- a_id = conn_handler .execute_fetchone (
124
- sql , (owner .id , name , description ))[0 ]
125
+ # Needed since issue #292 exists
126
+ status_id = conn_handler .execute_fetchone (
127
+ "SELECT analysis_status_id from qiita.analysis_status WHERE "
128
+ "status = 'in_construction'" )[0 ]
129
+ if from_default :
130
+ # insert analysis and move samples into that new analysis
131
+ dflt_id = owner .default_analysis
132
+ sql = """INSERT INTO qiita.{0}
133
+ (email, name, description, analysis_status_id)
134
+ VALUES (%s, %s, %s, %s)
135
+ RETURNING analysis_id""" .format (cls ._table )
136
+ conn_handler .add_to_queue (queue , sql , (owner .id , name ,
137
+ description , status_id ))
138
+ # MAGIC NUMBER 3: command selection step
139
+ # needed so we skip the sample selection step
140
+ sql = """INSERT INTO qiita.analysis_workflow
141
+ (analysis_id, step) VALUES (%s, %s)
142
+ RETURNING %s"""
143
+ conn_handler .add_to_queue (queue , sql , ['{0}' , 3 , '{0}' ])
144
+ sql = """UPDATE qiita.analysis_sample
145
+ SET analysis_id = %s
146
+ WHERE analysis_id = %s RETURNING %s"""
147
+ conn_handler .add_to_queue (queue , sql , ['{0}' , dflt_id , '{0}' ])
148
+ else :
149
+ # insert analysis information into table as "in construction"
150
+ sql = """INSERT INTO qiita.{0}
151
+ (email, name, description, analysis_status_id)
152
+ VALUES (%s, %s, %s, %s)
153
+ RETURNING analysis_id""" .format (cls ._table )
154
+ conn_handler .add_to_queue (
155
+ queue , sql , (owner .id , name , description , status_id ))
125
156
126
157
# add parent if necessary
127
158
if parent :
128
159
sql = ("INSERT INTO qiita.analysis_chain (parent_id, child_id) "
129
- "VALUES (%s, %s)" )
130
- conn_handler .execute ( sql , ( parent .id , a_id ) )
160
+ "VALUES (%s, %s) RETURNING child_id " )
161
+ conn_handler .add_to_queue ( queue , sql , [ parent .id , '{0}' ] )
131
162
163
+ a_id = conn_handler .execute_queue (queue )[0 ]
132
164
return cls (a_id )
133
165
134
166
# ---- Properties ----
@@ -470,6 +502,23 @@ def has_access(self, user):
470
502
return self ._id in Analysis .get_by_status ('public' ) | \
471
503
user .private_analyses | user .shared_analyses
472
504
505
+ def summary_data (self ):
506
+ """Return number of studies, processed data, and samples selected
507
+
508
+ Returns
509
+ -------
510
+ dict
511
+ counts keyed to their relevant type
512
+ """
513
+ sql = """SELECT COUNT(DISTINCT study_id) as studies,
514
+ COUNT(DISTINCT processed_data_id) as processed_data,
515
+ COUNT(DISTINCT sample_id) as samples
516
+ FROM qiita.study_processed_data
517
+ JOIN qiita.analysis_sample USING (processed_data_id)
518
+ WHERE analysis_id = %s"""
519
+ conn_handler = SQLConnectionHandler ()
520
+ return dict (conn_handler .execute_fetchone (sql , [self ._id ]))
521
+
473
522
def share (self , user ):
474
523
"""Share the analysis with another user
475
524
@@ -511,17 +560,26 @@ def add_samples(self, samples):
511
560
512
561
Parameters
513
562
----------
514
- samples : list of tuples of (int, str)
563
+ samples : dictionary of lists
515
564
samples and the processed data id they come from in form
516
- [( processed_data_id, sample_id) , ...]
565
+ { processed_data_id: [sample1, sample2 , ...], ...}
517
566
"""
518
567
conn_handler = SQLConnectionHandler ()
519
568
self ._lock_check (conn_handler )
520
- sql = ("INSERT INTO qiita.analysis_sample "
521
- "(analysis_id, processed_data_id, sample_id) VALUES "
522
- "(%s, %s, %s)" )
523
- conn_handler .executemany (sql , [(self ._id , s [0 ], s [1 ])
524
- for s in samples ])
569
+
570
+ for pid , samps in viewitems (samples ):
571
+ # get previously selected samples for pid and filter them out
572
+ sql = """SELECT sample_id FROM qiita.analysis_sample
573
+ WHERE processed_data_id = %s and analysis_id = %s"""
574
+ prev_selected = [x [0 ] for x in
575
+ conn_handler .execute_fetchall (sql ,
576
+ (pid , self ._id ))]
577
+
578
+ select = set (samps ).difference (prev_selected )
579
+ sql = ("INSERT INTO qiita.analysis_sample "
580
+ "(analysis_id, processed_data_id, sample_id) VALUES "
581
+ "({}, %s, %s)" .format (self ._id ))
582
+ conn_handler .executemany (sql , [x for x in product ([pid ], select )])
525
583
526
584
def remove_samples (self , proc_data = None , samples = None ):
527
585
"""Removes samples from the analysis
0 commit comments