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

Last change on this file since 73 was 73, checked in by robert@…, 8 years ago
  • Fixed nullpointer bug in querying
  • Changed order of classification buttons
  • Added content-length to file downloads
File size: 7.6 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 = createLink( controller: params.entityType, action: "show", id: params.entityId ).toString()
118                def finishUrl = createLink( controller: "assaySample", action: 'downloadFasta', params: [ processId: '%s' ] ).toString();
119                def url = fastaService.startExportProcess( assaySamples, session, name, returnUrl, finishUrl )
120
121                // Show a waiting screen
122                redirect( url: url );
123        }
124       
125        def downloadFasta = {
126                def processId = params.processId;
127               
128                // Retrieve the file
129                def file = fileService.get( session.process[ processId ].filename );
130
131                try {
132                        // Send the file to the user
133                        response.setHeader "Content-disposition", "attachment; filename=" + session.process[ processId ].name  + ".zip"
134                        response.setHeader "Content-Length", file.size().toString();
135                       
136                        response.outputStream << file.newInputStream();
137                        response.outputStream.flush();
138                } catch( Exception e ) {
139                        log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." );
140                        e.printStackTrace();
141                } finally {
142                        // Delete the file since it has to be downloaded only once
143                        fileService.delete( session.process[ processId ].filename );
144                }
145        }
146       
147        /**
148         * Export metadata of selected samples in excel format
149         */
150        def exportMetaData = {
151                def assaySamples = getAssaySamples( params );
152                def name
153
154                if( assaySamples?.size() == 0 ) {
155                        flash.error = "No samples selected";
156                        redirect( action: "list" );
157                        return;
158                }
159
160                name = "samples";
161
162                // Export the metadata
163                try {
164                        // The export functionality needs a assaysSample-tag list, but it
165                        // should be empty when only exporting metadata
166                        def tags = [];
167                        assaySamples.unique().each { assaySample ->
168                                tags << [assaySampleId: assaySample.id, sampleName: assaySample.sample.name, assayName: assaySample.assay.name, studyName: assaySample.assay.study.name, tag: "-"]
169                        }
170                        response.setHeader "Content-disposition", "attachment; filename=${name}.xls"
171                       
172                        sampleExcelService.sessionToken = session.sessionToken
173                       
174                        if( !sampleExcelService.exportExcelSampleData( assaySamples.unique(), tags, response.outputStream ) ) {
175                                flash.error = "An error occurred while fetching sample data. Maybe the session has timed out.";
176                                response.setHeader( "Content-disposition", "" );
177                                redirect( action: "index" );
178                        }
179                        response.outputStream.flush();
180                } catch( Exception e ) {
181                        log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." );
182                        e.printStackTrace();
183                }
184        }
185
186        /**
187         * Shows a form to edit the specified assaySample in dialog mode
188         */
189        def editForm = {
190                // load assaySample with id specified by param.id
191                AssaySample assaySample = AssaySample.get( params.id as long );
192
193                if( !assaySample ) {
194                        render "Sample not found";
195                        return
196                }
197
198                if (!assaySample.assay.study.canWrite( session.user ) ) {
199                        flash.error = "You don't have the right authorizaton to access sample " + assaySample.sample.name
200                        redirect(controller: params.parent ?: "run" )
201                        return null
202                }
203
204                [parent: params.parent ?: "run", parentId: params.parentId ?: assaySample.run?.id, assaySample: assaySample]
205        }
206
207        def update = {
208               
209                // load assaySample with id specified by param.id
210                AssaySample assaySample = AssaySample.get( params.id as long );
211
212                if( !assaySample) {
213                        redirect(controller: params.parent ?: "run", action: 'list')
214                        return
215                }
216
217                assaySample.properties = params.sample
218               
219                if( assaySample.save() ) {
220                        flash.message = "Sample succesfully saved";
221                } else {
222                        flash.error = "Sample could not be saved: " + assaySample.getErrors();
223                }
224
225                redirect( controller: params.parent ?: "run", action: 'show', id: params.parentId ?: assaySample.run?.id )
226        }
227
228        protected List getAssaySamples( params ) {
229                def ids = params.list( 'ids' );
230                def tokens = params.list( 'tokens' );
231               
232                ids = ids.findAll { it.isLong() }.collect { Long.parseLong( it ) }
233               
234                if( !ids && !tokens ) {
235                        def message = "No assaysample ids given"
236                        flash.error = message
237                        redirect( controller: "run", action: "index" );
238                        return;
239                }
240               
241                def samples = [];
242               
243                if( ids ) 
244                        samples += AssaySample.executeQuery( "FROM AssaySample a WHERE a.id IN (:ids)", [ "ids": ids ] );
245               
246                if( tokens )
247                        samples += AssaySample.executeQuery( "FROM AssaySample a WHERE a.sample.sampleToken IN (:tokens)", [ "tokens": tokens ] );
248                       
249                return samples; 
250        }
251}
Note: See TracBrowser for help on using the repository browser.