source: trunk/grails-app/controllers/nl/tno/massSequencing/AssaySampleController.groovy

Last change on this file was 74, checked in by robert@…, 9 years ago
  • Several bugfixes
  • Added an extra step in the worker process for importing data
File size: 7.8 KB
Line 
1package nl.tno.massSequencing
2
3import java.util.List;
4import org.codehaus.groovy.grails.commons.ConfigurationHolder
5import nl.tno.massSequencing.classification.Classification
6
7class AssaySampleController {
8        def fastaService
9        def sampleExcelService
10        def fileService
11        def workerService
12
13        /**
14         * Shows information about this assaySample in dialog style
15         */
16        def show = {
17                AssaySample assaySample = AssaySample.get( params.id as long );
18
19                if( !assaySample ) {
20                        render "Sample not found";
21                        return
22                }
23
24                if (!assaySample.assay.study.canRead( session.user ) ) {
25                        flash.error = "You don't have the right authorizaton to access sample " + assaySample.sample.name
26                        redirect(controller: 'study')
27                        return null
28                }
29
30                // Determine the number of classifications for this sample
31                def numClassifications = Classification.executeQuery( "SELECT SUM( c.unclassified ) FROM Classification c WHERE c.assaySample = :assaySample", [ "assaySample": assaySample ] )
32
33                [assaySample: assaySample, entityType: params.entityType, numClassifications: numClassifications ? ( numClassifications[ 0 ] ?: 0 )  : 0 ]
34        }
35
36        def sequenceLengthHistogram = {
37                def id = params.long( 'id' );
38                def assaySample = id ? AssaySample.get( id ) : null
39
40                if( !id || !assaySample ) {
41                        flash.message = "No sample selected";
42                        redirect( action: "index" );
43                        return;
44                }
45               
46                def title = "sample " + assaySample.sample.name + " (" + assaySample.assay.study.name + " / " + assaySample.assay.name + ")"
47                renderSequenceLengthHistogram( title, [assaySample] )
48        }
49       
50        def sequenceLengthHistogramForRun = {
51                def id = params.long( 'id' );
52                def run = id ? Run.get( id ) : null
53
54                if( !id || !run ) {
55                        flash.message = "No run selected";
56                        redirect( controller: 'run', action: "index" );
57                        return;
58                }
59               
60                def title = "run " + run.name
61                renderSequenceLengthHistogram( title, run.assaySamples?.toList() )
62        }
63       
64        def sequenceLengthHistogramForAssay = {
65                def id = params.long( 'id' );
66                def assay = id ? Assay.get( id ) : null
67
68                if( !id || !assay ) {
69                        flash.message = "No assay selected";
70                        redirect( controller: 'assay', action: "index" );
71                        return;
72                }
73               
74                def title = "assay " + assay.name
75                renderSequenceLengthHistogram( title, assay.assaySamples?.toList() )
76        }
77       
78        def sequenceLengthHistogramForStudy = {
79                def id = params.long( 'id' );
80                def assay = id ? Study.get( id ) : null
81
82                if( !id || !study ) {
83                        flash.message = "No study selected";
84                        redirect( controller: 'study', action: "index" );
85                        return;
86                }
87               
88                def title = "study " + study.name
89                renderSequenceLengthHistogram( title, study.assays*.assaySamples.flatten().unique().findAll { it } )
90        }
91        /**
92         * Renders a histogram for the given assaySamples
93         * @param title
94         * @param assaySamples
95         */
96        protected void renderSequenceLengthHistogram( String title, def assaySamples ) {
97                log.debug "Rendering histogram for " + assaySamples?.size() + " samples";
98               
99                def numSequences = assaySamples.collect { it.numSequences() }.sum()
100                render( view: "sequenceLengthHistogram", model: [ title: title, numSequences: numSequences, histogram: fastaService.sequenceLengthHistogram( assaySamples ) ] );
101        }
102
103        /**
104         * Exports data about one or more runs in fasta format
105         */
106        def exportAsFasta = {
107                def assaySamples = getAssaySamples( params )?.unique();
108
109                if( assaySamples?.size() == 0 ) {
110                        flash.error = "No samples selected";
111                        redirect( action: "list" );
112                        return;
113                }
114
115                // Start the export in the background
116                def name = "samples";
117                def returnUrl;
118               
119                if( params.entityType && params.entityId )
120                        returnUrl = createLink( controller: params.entityType, action: "show", id: params.entityId ).toString()
121                else
122                        returnUrl = createLink( controller: "query", action: "list" ).toString()
123                       
124                def finishUrl = createLink( controller: "assaySample", action: 'downloadFasta', params: [ processId: '%s' ] ).toString();
125                def url = fastaService.startExportProcess( assaySamples, session, name, returnUrl, finishUrl )
126
127                // Show a waiting screen
128                redirect( url: url );
129        }
130       
131        def downloadFasta = {
132                def processId = params.processId;
133               
134                // Retrieve the file
135                def file = fileService.get( session.process[ processId ].filename );
136
137                try {
138                        // Send the file to the user
139                        response.setHeader "Content-disposition", "attachment; filename=" + session.process[ processId ].name  + ".zip"
140                        response.setHeader "Content-Length", file.size().toString();
141                       
142                        response.outputStream << file.newInputStream();
143                        response.outputStream.flush();
144                } catch( Exception e ) {
145                        log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." );
146                        e.printStackTrace();
147                } finally {
148                        // Delete the file since it has to be downloaded only once
149                        fileService.delete( session.process[ processId ].filename );
150                }
151        }
152       
153        /**
154         * Export metadata of selected samples in excel format
155         */
156        def exportMetaData = {
157                def assaySamples = getAssaySamples( params );
158                def name
159
160                if( assaySamples?.size() == 0 ) {
161                        flash.error = "No samples selected";
162                        redirect( action: "list" );
163                        return;
164                }
165
166                name = "samples";
167
168                // Export the metadata
169                try {
170                        // The export functionality needs a assaysSample-tag list, but it
171                        // should be empty when only exporting metadata
172                        def tags = [];
173                        assaySamples.unique().each { assaySample ->
174                                tags << [assaySampleId: assaySample.id, sampleName: assaySample.sample.name, assayName: assaySample.assay.name, studyName: assaySample.assay.study.name, tag: "-"]
175                        }
176                        response.setHeader "Content-disposition", "attachment; filename=${name}.xls"
177                       
178                        sampleExcelService.sessionToken = session.sessionToken
179                       
180                        if( !sampleExcelService.exportExcelSampleData( assaySamples.unique(), tags, response.outputStream ) ) {
181                                flash.error = "An error occurred while fetching sample data. Maybe the session has timed out.";
182                                response.setHeader( "Content-disposition", "" );
183                                redirect( action: "index" );
184                        }
185                        response.outputStream.flush();
186                } catch( Exception e ) {
187                        log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." );
188                        e.printStackTrace();
189                }
190        }
191
192        /**
193         * Shows a form to edit the specified assaySample in dialog mode
194         */
195        def editForm = {
196                // load assaySample with id specified by param.id
197                AssaySample assaySample = AssaySample.get( params.id as long );
198
199                if( !assaySample ) {
200                        render "Sample not found";
201                        return
202                }
203
204                if (!assaySample.assay.study.canWrite( session.user ) ) {
205                        flash.error = "You don't have the right authorizaton to access sample " + assaySample.sample.name
206                        redirect(controller: params.parent ?: "run" )
207                        return null
208                }
209
210                [parent: params.parent ?: "run", parentId: params.parentId ?: assaySample.run?.id, assaySample: assaySample]
211        }
212
213        def update = {
214               
215                // load assaySample with id specified by param.id
216                AssaySample assaySample = AssaySample.get( params.id as long );
217
218                if( !assaySample) {
219                        redirect(controller: params.parent ?: "run", action: 'list')
220                        return
221                }
222
223                assaySample.properties = params.sample
224               
225                if( assaySample.save() ) {
226                        flash.message = "Sample succesfully saved";
227                } else {
228                        flash.error = "Sample could not be saved: " + assaySample.getErrors();
229                }
230
231                redirect( controller: params.parent ?: "run", action: 'show', id: params.parentId ?: assaySample.run?.id )
232        }
233
234        protected List getAssaySamples( params ) {
235                def ids = params.list( 'ids' );
236                def tokens = params.list( 'tokens' );
237               
238                ids = ids.findAll { it.isLong() }.collect { Long.parseLong( it ) }
239               
240                if( !ids && !tokens ) {
241                        def message = "No assaysample ids given"
242                        flash.error = message
243                        redirect( controller: "run", action: "index" );
244                        return;
245                }
246               
247                def samples = [];
248               
249                if( ids ) 
250                        samples += AssaySample.executeQuery( "FROM AssaySample a WHERE a.id IN (:ids)", [ "ids": ids ] );
251               
252                if( tokens )
253                        samples += AssaySample.executeQuery( "FROM AssaySample a WHERE a.sample.sampleToken IN (:tokens)", [ "tokens": tokens ] );
254                       
255                return samples; 
256        }
257}
Note: See TracBrowser for help on using the repository browser.