Changeset 7 for trunk/grails-app/controllers
- Timestamp:
- Jan 26, 2011, 5:08:25 PM (12 years ago)
- Location:
- trunk/grails-app/controllers/nl/tno/metagenomics
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/controllers/nl/tno/metagenomics/AssayController.groovy
r4 r7 5 5 class AssayController { 6 6 def synchronizationService 7 def gscfService 7 8 def fuzzySearchService 8 9 9 10 def fileService 10 11 def excelService 11 12 // Fields to be edited using excel file and manually 13 def sampleNameName = "Sample name" 14 def tagSequenceName = "Tag sequence" 15 def oligoNumberName = "Oligo number" 16 def possibleFields = [sampleNameName, tagSequenceName, oligoNumberName] 17 12 def sampleExcelService 13 14 def index = { 15 // Filter studies for the ones the user is allowed to see 16 def studies = Study.list(); 17 [studies: studies.findAll { it.canRead( session.user ) }, 18 gscfAddUrl: gscfService.urlAddStudy() ] 19 } 20 18 21 def show = { 19 // load study with id specified by param.id 20 def assay = Assay.get(params.id as Long) 21 22 if (!assay) { 23 flash.message = "No assay found with id: $params.id" 24 redirect('action': 'errorPage') 25 return 26 } 22 def assay = getAssay( params.id ); 23 if( !assay ) 24 return 27 25 28 26 // Make sure the newest data is available … … 61 59 if( !assay ) { 62 60 flash.message = "No assay found with token: $params.id" 63 redirect( 'action': 'errorPage')61 redirect(controller: 'study') 64 62 } 65 63 } … … 79 77 */ 80 78 def downloadTagsExcel = { 81 def sheetIndex = 0;82 83 79 // load study with id specified by param.id 84 def assay = Assay.get(params.id as Long) 85 86 if (!assay) { 87 flash.message = "No assay found with id: $params.id" 88 redirect('action': 'errorPage') 89 return 90 } 91 92 // Create an excel sheet 93 def wb = excelService.create(); 94 95 // Put the headers on the first row 96 excelService.writeHeader( wb, possibleFields, sheetIndex ); 97 98 // Adding the next lines 99 def sortedSamples = assay.assaySamples.toList().sort { it.sample.name } 100 ArrayList data = []; 101 sortedSamples.each { assaySample -> 102 data << [assaySample.sample.name, assaySample.tagSequence, assaySample.oligoNumber ]; 103 } 104 excelService.writeData( wb, data, sheetIndex, 1 ); 105 106 // Auto resize columns 107 excelService.autoSizeColumns( wb, sheetIndex, 0..2) 80 def assay = getAssay( params.id ); 81 if( !assay ) 82 return 83 84 def filename = assay.study.name + "_" + assay.name + "_tags.xls" 85 excelService.downloadSampleExcel( assay.assaySamples ); 108 86 109 87 // Make file downloadable 110 log.trace( "Creation for downloading the file " + assay.study.name + "_" + assay.name + "_tags.xls")111 excelService.downloadFile( wb, assay.study.name + "_" + assay.name + "_tags.xls", response)88 log.trace( "Creation for downloading the file " + filename ) 89 sampleExcelService.excelService.downloadFile( wb, filename, response ) 112 90 } 113 91 … … 116 94 */ 117 95 def parseTagExcel = { 118 def sheetIndex = 0 119 def headerRow = 0 120 def dataStartsAtRow = 1 121 def numExampleRows = 5 122 123 // load study with id specified by param.id 124 def assay = Assay.get(params.id as Long) 125 126 if (!assay) { 127 flash.message = "No assay found with id: $params.id" 128 redirect('action': 'errorPage') 129 return 130 } 96 def assay = getAssay( params.id ); 97 if( !assay ) 98 return 131 99 132 100 def filename = params.filename … … 150 118 // Save the filename in session for later use 151 119 session.filename = filename; 152 153 // Create an excel workbook instance of the file 154 def workbook 120 def excelData; 155 121 try { 156 workbook = excelService.open( file );122 excelData = sampleExcelService.parseTagsExcel( file ); 157 123 } catch( Throwable e ) { // Catch a throwable here instead of an exception, since the apache poi stuff gives an Error on failure 158 124 // Couldn't create a workbook from this file. 159 125 response.status = 400 // Bad request 160 render "Uploaded file is not a valid excel file." 161 return 162 } 163 164 // Read headers from the first row and 5 of the first lines as example data 165 def headers = excelService.readRow( workbook, sheetIndex, headerRow ); 166 def exampleData = excelService.readData( workbook, sheetIndex, dataStartsAtRow, -1, numExampleRows ); // -1 means: determine number of rows yourself 167 168 // Try to guess best matches between the excel file and the column names 169 def bestMatches = [:] 170 171 headers.eachWithIndex { header, idx -> 172 // Do matching using fuzzy search. The 0.1 treshold makes sure that no match if chosen if 173 // there is actually no match at all. 174 bestMatches[idx] = fuzzySearchService.mostSimilar( header, possibleFields, 0.1 ); 175 } 176 177 [assay: assay, headers: headers, exampleData: exampleData, filename: filename, possibleFields: [ "Don't import" ] + possibleFields, bestMatches: bestMatches] 126 render "Uploaded file is not a valid excel file: " + e.getMessage() 127 return 128 } 129 session.possibleFields = excelData.possibleFields 130 131 [assay: assay, headers: excelData.headers, exampleData: excelData.exampleData, filename: filename, possibleFields: [ "Don't import" ] + excelData.possibleFields, bestMatches: excelData.bestMatches] 178 132 } 179 133 … … 182 136 */ 183 137 def updateTagsByExcel = { 184 def sheetIndex = 0 185 def headerRow = 0 186 def dataStartsAtRow = 1 187 188 // load study with id specified by param.id 189 def assay = Assay.get(params.id as Long) 190 191 if (!assay) { 138 def assay = getAssay( params.id ); 139 if( !assay ) { 192 140 // Now delete the file, since we don't need it anymore 193 141 _deleteUploadedFileFromSession() 194 195 flash.message = "No assay found with id: $params.id" 196 redirect('action': 'errorPage') 197 return 142 return; 198 143 } 199 144 … … 210 155 def matchColumns = params[ 'matches']; 211 156 212 if( !matchColumns ) {213 // Now delete the file, since we don't need it anymore214 _deleteUploadedFileFromSession()215 216 flash.error = "No column matches found for excel file. Please try again."217 redirect( action: 'show', id: params.id)218 return219 }220 221 // Determine column numbers222 def columns = [:]223 def dataMatches = false;224 possibleFields.each { columnName ->225 columns[ columnName ] = matchColumns.findIndexOf { it.value == columnName }226 227 if( columnName != sampleNameName && columns[ columnName ] != -1 )228 dataMatches = true229 }230 231 println( "Columns: " + columns)232 233 // A column to match the sample name must be present234 if( columns[ sampleNameName ] == -1 ) {235 // Now delete the file, since we don't need it anymore236 _deleteUploadedFileFromSession()237 238 flash.error = "There must be a column present in the excel file that matches the sample name. Please try again."239 redirect( action: 'show', id: params.id)240 return241 }242 243 // A column with data should also be present244 if( !dataMatches ) {245 // Now delete the file, since we don't need it anymore246 _deleteUploadedFileFromSession()247 248 flash.error = "There are no data columns present in the excel file. No samples are updated."249 redirect( action: 'show', id: params.id)250 return251 }252 253 157 // Now loop through the excel sheet and update all samples with the specified data 254 158 File file = new File( fileService.getUploadDir(), session.filename ); 159 255 160 if( !file.exists() || !file.canRead() ) { 256 161 flash.error = "Excel file has been removed since previous step. Please try again." … … 258 163 return 259 164 } 260 261 def workbook = excelService.open( file ) 262 ArrayList data = excelService.readData( workbook, sheetIndex, dataStartsAtRow ) 263 264 // Check whether the excel file contains any data 265 if( data.size() == 0 ) { 266 // Now delete the file, since we don't need it anymore 267 _deleteUploadedFileFromSession() 268 269 flash.error = "The excel sheet contains no data to import. Please upload another excel file." 270 redirect( action: 'show', id: params.id) 271 272 return 273 } 274 275 def numSuccesful = 0 276 def failedRows = [] 277 278 // walk through all rows and fill the table with records 279 def assaySamples = assay.assaySamples 280 281 for( def i = 0; i < data.size(); i++ ) { 282 def rowData = data[ i ]; 283 284 String sampleName = rowData[ columns[ sampleNameName ] ] as String 285 286 // Find assay by sample name. Since sample names are unique within an assay (enforced by GSCF), 287 // this will always work. 288 AssaySample assaySample = assaySamples.find { it.sample.id == Sample.findByName( sampleName )?.id }; 289 290 // If no assaysample is found, add this row to the failed-row list 291 if( !assaySample ) { 292 failedRows << [ row: rowData, sampleName: sampleName ]; 293 continue; 294 } 295 296 columns.each { 297 if( it.value > -1 ) { 298 switch( it.key ) { 299 case tagSequenceName: assaySample.tagSequence = rowData[ it.value ]; break 300 case oligoNumberName: assaySample.oligoNumber = rowData[ it.value ]; break 301 } 302 } 303 } 304 305 assaySample.save() 306 307 numSuccesful++; 308 } 309 310 // Now delete the file, since we don't need it anymore 311 _deleteUploadedFileFromSession() 165 166 def excelData = sampleExcelService.updateTagsByExcel( matchColumns, session.possibleFields, file, assay.assaySamples ); 312 167 313 168 // Return a message to the user 314 if( numSuccesful == 0 ) { 315 flash.error = "None of the " + failedRows.size() + " row(s) could be imported, because none of the sample names matched. Have you provided the right excel file?" 169 if( !excelData.success ) { 170 flash.error = excelData.message 171 } else if( excelData.numSuccesful == 0 ) { 172 flash.error = "None of the " + excelData.failedRows.size() + " row(s) could be imported, because none of the sample names matched. Have you provided the right excel file?" 316 173 } else { 317 flash.message = numSuccesful + " samples have been updated. "318 319 if( failedRows.size() > 0 )320 flash.message += failedRows.size() + " row(s) could not be imported, because the sample names could not be found in the database."321 } 322 redirect( action: 'show', id: params.id )174 flash.message = excelData.numSuccesful + " samples have been updated. " 175 176 if( excelData.failedRows.size() > 0 ) 177 flash.message += excelData.failedRows.size() + " row(s) could not be imported, because the sample names could not be found in the database." 178 } 179 redirect( action: 'show', id: params.id ) 323 180 } 324 181 … … 327 184 */ 328 185 def updateTagsManually = { 329 // load study with id specified by param.id 330 def assay = Assay.get(params.id as Long) 331 332 if (!assay) { 333 flash.message = "No assay found with id: $params.id" 334 redirect('action': 'errorPage') 335 return 336 } 186 def assay = getAssay( params.id ); 187 if( !assay ) 188 return 337 189 338 190 // Loop through all assay samples and set data … … 342 194 assay.assaySamples.each { assaySample -> 343 195 def assaySampleParams = sampleParams.get( assaySample.id as String ); 196 println assaySampleParams 344 197 if( assaySampleParams ) { 345 assaySample.properties = assaySampleParams 198 assaySample.oligoNumber = assaySampleParams.oligoNumber 199 assaySample.tagSequence = assaySampleParams.tagSequence 200 201 try { 202 assaySample.run = Run.get( assaySampleParams.run as Long ); 203 } catch( Exception e ) {} 204 346 205 assaySample.save() 347 206 } … … 363 222 */ 364 223 def addExistingRuns = { 365 // load study with id specified by param.id 366 def assay = Assay.get(params.id as Long) 367 368 if (!assay) { 369 flash.message = "No assay found with id: $params.id" 370 redirect('action': 'errorPage') 371 return 372 } 224 def assay = getAssay( params.id ); 225 if( !assay ) 226 return 373 227 374 228 // Add checked runs to this assay … … 397 251 */ 398 252 def removeRun = { 399 // load study with id specified by param.id 400 def assay = Assay.get(params.id as Long) 401 402 if (!assay) { 403 flash.message = "No assay found with id: $params.id" 404 redirect('action': 'errorPage') 405 return 406 } 253 def assay = getAssay( params.id ); 254 if( !assay ) 255 return 407 256 408 257 if( !params.run_id ) { … … 449 298 session.filename = '' 450 299 } 300 301 protected Assay getAssay(def assayId) { 302 // load study with id specified by param.id 303 def assay 304 try { 305 assay = Assay.get(assayId as Long) 306 } catch( Exception e ) { 307 flash.error = "Incorrect id given: " + assayId 308 redirect(controller: 'study') 309 return null 310 } 311 312 if (!assay) { 313 flash.error = "No assay found with id: " + assayId 314 redirect(controller: 'study') 315 return null 316 } 317 318 if (!assay.study.canRead( session.user ) ) { 319 flash.error = "You don't have the right authorizaton to access assay " + assay.name 320 redirect(controller: 'study') 321 return null 322 } 323 324 return assay 325 } 326 451 327 452 328 } -
trunk/grails-app/controllers/nl/tno/metagenomics/AssaySampleController.groovy
r4 r7 14 14 } 15 15 16 [assaySample: assaySample] 16 if (!assaySample.assay.study.canRead( session.user ) ) { 17 flash.error = "You don't have the right authorizaton to access sample " + assaySample.sample.name 18 redirect(controller: 'study') 19 return null 20 } 21 22 23 [assaySample: assaySample, entityType: params.entityType] 17 24 } 18 25 } -
trunk/grails-app/controllers/nl/tno/metagenomics/FastaController.groovy
r5 r7 18 18 */ 19 19 def showProcessScreen = { 20 // load study with id specified by param.id 21 def assay = Assay.get(params.id as Long) 22 23 if (!assay) { 24 flash.message = "No assay found with id: $params.id" 25 redirect( controller: 'assay', action: 'errorPage') 26 return 27 } 20 def entityType = params.entityType 28 21 29 22 // Check whether files are given … … 32 25 if( !names ) { 33 26 flash.message = "No files uploaded for processing" 34 redirect( controller: 'assay', action: 'show', 'id': params.id)27 redirect( controller: params.entityType, action: 'show', 'id': params.id) 35 28 return 36 29 } … … 59 52 ] 60 53 61 [ assay: assay, filenames: names, url: createLink( action: 'showProcessResult', id: assay.id, params: [ selectedRun: params.selectedRun] ) ]54 [entityId: params.id, entityType: params.entityType, filenames: names, url: createLink( action: 'showProcessResult', id: params.id, params: [entityType: entityType] ) ] 62 55 } 63 56 … … 66 59 */ 67 60 def process = { 68 // load study with id specified by param.id 69 def assay = Assay.get(params.id as Long) 70 71 if (!assay) { 72 response.setStatus( 404, "No assay found with id: $params.id" ) 61 def entity 62 def assaySamples 63 64 switch( params.entityType ) { 65 case "run": 66 entity = getRun( params.id ); 67 assaySamples = entity.assaySamples; 68 break; 69 case "assay": 70 entity = getAssay( params.id ); 71 assaySamples = entity.assaySamples; 72 break; 73 default: 74 response.setStatus( 404, "No controller found" ); 75 render ""; 76 return; 77 } 78 79 if (!entity) { 80 response.setStatus( 404, flash.error ) 73 81 render ""; 74 82 return … … 113 121 session.processProgress.bytesProcessed = bytes; 114 122 } ); 123 124 // Check which assaySamples to use (only the ones visible to the user) 125 assaySamples = assaySamples.findAll { it.assay.study.canWrite( session.user ) } 115 126 116 127 // Match files with samples in the database 117 def matchedFiles = fastaService.matchFiles( parsedFiles.success, assay .assaySamples );128 def matchedFiles = fastaService.matchFiles( parsedFiles.success, assaySamples ); 118 129 119 130 // Sort files on filename … … 141 152 def showProcessResult = { 142 153 // load study with id specified by param.id 143 def assay = Assay.get(params.id as Long) 144 145 if (!assay) { 146 flash.message = "No assay found with id: $params.id" 147 redirect( controller: 'assay', action: 'errorPage') 148 return 149 } 150 154 def entity 155 156 switch( params.entityType ) { 157 case "run": 158 entity = getRun( params.id ) 159 break; 160 case "assay": 161 entity = getAssay( params.id ) 162 break; 163 default: 164 response.setStatus( 404, "No entity found" ); 165 render ""; 166 return; 167 } 168 169 if (!entity) { 170 response.setStatus( 404, flash.error ) 171 render ""; 172 return 173 } 174 151 175 if( !session.processedFiles ) { 152 176 flash.error = "Processing of files failed. Maybe the session timed out." … … 155 179 } 156 180 157 [ assay: assay, parsedFiles: session.processedFiles.parsed, matchedFiles: session.processedFiles.matched, selectedRun: params.selectedRun ]181 [entityType: params.entityType, entity: entity, id: params.id, parsedFiles: session.processedFiles.parsed, matchedFiles: session.processedFiles.matched, selectedRun: params.selectedRun ] 158 182 } 159 183 … … 162 186 */ 163 187 def saveProcessedFiles = { 164 // load study with id specified by param.id 165 def assay = Assay.get(params.id as Long) 166 167 if (!assay) { 168 flash.message = "No assay found with id: $params.id" 169 redirect( controller: 'assay', action: 'errorPage') 188 // load entity with id specified by param.id 189 def entity 190 191 switch( params.entityType ) { 192 case "run": 193 entity = getRun( params.id ); 194 break; 195 case "assay": 196 entity = getAssay( params.id ); 197 break; 198 default: 199 response.setStatus( 404, "No entity found" ); 200 render ""; 201 return; 202 } 203 204 if (!entity) { 205 response.setStatus( 404, flash.error ) 206 render ""; 170 207 return 171 208 } … … 176 213 if( !files ) { 177 214 flash.message = "No files were selected." 178 redirect( controller: 'assay', action: 'show', 'id': params.id)215 redirect( controller: params.entityType, action: 'show', 'id': params.id) 179 216 return 180 217 } … … 202 239 sd.numSequences = permanent.numSequences 203 240 sd.averageQuality = permanent.avgQuality 204 205 // Couple the data to the right run and sample206 def run = Run.get( filevalue.run )207 if( run )208 run.addToSequenceData( sd );209 241 210 242 def sample = AssaySample.get( filevalue.assaySample ); … … 251 283 } 252 284 253 redirect( controller: 'assay', action: "show", id: params.id )285 redirect( controller: params.entityType, action: "show", id: params.id ) 254 286 } 255 287 256 288 def deleteData = { 257 289 // load study with id specified by param.id 258 def sequenceData = SequenceData.get(params.id as Long) 290 def sequenceData 291 292 try { 293 sequenceData = SequenceData.get(params.id as Long) 294 } catch( Exception e ) {} 259 295 260 296 if (!sequenceData) { 261 297 flash.error = "No sequencedata found with id: $params.id" 262 redirect( controller: 'assay', action: 'errorPage') 263 return 264 } 265 266 def assayId = sequenceData.sample.assay.id; 298 redirect( controller: 'study' ) 299 return 300 } 301 302 def entityId 303 def entityType 304 305 switch( params.entityType ) { 306 case "run": 307 entityId = sequenceData.sample.run?.id; 308 entityType = "run" 309 break; 310 case "assay": 311 default: 312 entityType = "assay"; 313 entityId = sequenceData.sample.assay.id; 314 break; 315 } 316 267 317 def numFiles = sequenceData.numFiles(); 268 318 sequenceData.delete(); 269 319 270 320 flash.message = numFiles + " file" + (numFiles != 1 ? "s have" : " has" ) + " been deleted from this sample" 271 redirect( controller: 'assay', action: 'show', id: assayId ) 321 322 redirect( controller: entityType, action: 'show', id: entityId ) 323 } 324 325 protected Assay getAssay(def assayId) { 326 // load assay with id specified by param.id 327 def assay 328 try { 329 assay = Assay.get(assayId as Long) 330 } catch( Exception e ) { 331 flash.error = "Incorrect id given: " + assayId 332 return null 333 } 334 335 if (!assay) { 336 flash.error = "No assay found with id: " + assayId 337 return null 338 } 339 340 if (!assay.study.canRead( session.user ) ) { 341 flash.error = "You don't have the right authorizaton to access assay " + assay.name 342 return null 343 } 344 345 return assay 346 } 347 348 protected Run getRun(def runId) { 349 // load run with id specified by param.id 350 def run 351 try { 352 run = Run.get(runId as Long) 353 } catch( Exception e ) { 354 flash.error = "Incorrect id given: " + runId 355 return null 356 } 357 358 if (!run) { 359 flash.error = "No run found with id: " + runId 360 return null 361 } 362 363 return run 272 364 } 273 365 } -
trunk/grails-app/controllers/nl/tno/metagenomics/RunController.groovy
r4 r7 7 7 class RunController { 8 8 def fileService 9 10 /** 11 * Shows information about this run in dialog style 12 */ 9 def synchronizationService 10 def sampleExcelService 11 12 def index = { 13 [runs: Run.list()] 14 } 15 13 16 def show = { 14 Run run = Run.get( params.id as long ); 15 Assay assay = Assay.get( params.assayId as long ); 16 17 if( !run ) { 18 render "Run not found"; 19 return 20 } 21 22 if( !assay ) { 23 render "Assay not found"; 24 return 25 } 26 17 // load run with id specified by param.id 18 def run = getRun( params.id ); 19 20 if (!run) { 21 redirect(controller: 'study', action: 'index') 22 return 23 } 24 25 // Make sure the newest data is available 26 synchronizationService.sessionToken = session.sessionToken 27 synchronizationService.synchronizeStudies(); 28 29 // Determine runs not used in this assay 30 def otherAssays = Assay.list( sort: "name" ).findAll { !it.runs.contains( run ) } 31 32 // Send the assay information to the view 33 [run: run, otherAssays: otherAssays, editable: true] 34 } 35 36 /** 37 * Shows a form to edit the specified run in dialog mode 38 */ 39 def editForm = { 40 // load run with id specified by param.id 41 Run run = getRun( params.id ); 42 43 if (!run) { 44 render flash.error 45 return 46 } 47 48 Assay assay = getAssay( params.id ) 49 50 if( !assay ) { 51 render flash.error; 52 return 53 } 54 27 55 [assay: assay, run: run] 28 56 } 29 30 /** 31 * Shows a form to edit the specified run in dialog mode 32 */ 33 def editForm = { 34 Run run = Run.get( params.id as long ); 35 Assay assay = Assay.get( params.assayId as long ); 36 37 if( !run ) { 38 render "Run not found"; 39 return 40 } 41 42 if( !assay ) { 43 render "Assay not found"; 44 return 45 } 46 47 [assay: assay, run: run] 48 } 49 50 def create = { 51 Assay a = Assay.get( params.id as long ); 57 58 def create = { 59 Assay a = getAssay(params.id); 60 flash.error = ""; 52 61 53 62 // Create run based on given parameters 54 63 Run run = new Run(); 55 64 56 65 run.setPropertiesFromForm( params ); 57 66 58 a.addToRuns( run ); 67 if( a ) 68 a.addToRuns( run ); 59 69 60 70 if( !run.save() ) { … … 64 74 } 65 75 66 redirect( controller: "assay", action: "show", id: params.id ) 67 } 68 76 if( a ) 77 redirect( controller: "assay", action: "show", id: a.id ) 78 else 79 redirect( controller: 'run' ); 80 } 81 69 82 def update = { 70 83 if( !params.assayId ) { 71 84 flash.error = "No assay id given" 72 redirect(controller: 'assay', action: 'errorpage') 73 return 74 } 75 def assay = Assay.get(params.assayId as Long) 76 77 // load run with id specified by param.id 78 if (!assay) { 79 flash.message = "No assay found with id: ${params.assayId}" 80 redirect(controller: 'assay', 'action': 'errorPage') 81 return 82 } 83 84 85 def run 86 87 try { 88 run = Run.get( params.id as Long ); 89 } catch( Exception e ) { 90 throw e 91 flash.message = "Incorrect run id given: " 85 redirect(controller: 'study') 86 return 87 } 88 89 Assay assay = getAssay(params.assayId); 90 91 if( !a ) { 92 redirect( controller: 'study' ); 93 } 94 95 Run run = getRun( params.id ); 96 97 if( !run ) { 92 98 redirect(controller: 'assay', action: 'show', id: params.assayId) 93 99 return … … 106 112 redirect( controller: 'assay', action: 'show', id: params.assayId) 107 113 } 108 114 109 115 def delete = { 110 Run run = Run.get( params.id as long ); 116 Run run = getRun( params.id ); 117 118 if( !run ) { 119 redirect(controller: 'assay', action: 'show', id: params.assayId) 120 return 121 } 111 122 112 123 // Don't remove runs for which data exists … … 115 126 redirect( controller: "assay", action: "show", id: params.assayId ) 116 127 } 117 128 118 129 // Remove all associations 119 130 run.assays.each { 120 131 run.removeFromAssays( it ); 121 132 } 122 133 123 134 def name = run.name 124 135 run.delete(); … … 126 137 127 138 redirect( controller: "assay", action: "show", id: params.assayId ) 139 } 140 141 /************************************************************************** 142 * 143 * Methods for handling data about the samples in this run 144 * 145 *************************************************************************/ 146 147 /** 148 * Downloads an excel sheet with data about the assay samples, to enter data in excel 149 */ 150 def downloadTagsExcel = { 151 Run run = getRun( params.id ); 152 153 if( !run ) { 154 redirect(controller: 'study') 155 return 156 } 157 158 // Make it only possible to update samples writable by the user 159 def assaySamples = run.assaySamples.findAll { it.assay.study.canWrite( session.user ) } 160 161 def filename = "Run " + run.name + "_tags.xls" 162 def wb = sampleExcelService.downloadSampleExcel( assaySamples, false ); 163 164 // Make file downloadable 165 log.trace( "Creation for downloading the file " + filename ) 166 sampleExcelService.excelService.downloadFile( wb, filename, response ) 167 } 168 169 170 /** 171 * Parses an uploaded excel file and shows a form to match columns 172 */ 173 def parseTagExcel = { 174 Run run = getRun( params.id ); 175 176 if( !run ) { 177 redirect(controller: 'study') 178 return 179 } 180 181 def filename = params.filename 182 183 // Security check to prevent accessing files in other directories 184 if( !filename || filename.contains( '..' ) ) { 185 response.status = 500; 186 render "Invalid filename given"; 187 return; 188 } 189 190 // Check for existence and readability 191 File file = new File( fileService.getUploadDir(), filename) 192 193 if( !file.exists() || !file.canRead() ) { 194 response.status = 404; 195 render "The uploaded file doesn't exist or doesn't work as expected."; 196 return; 197 } 198 199 // Save the filename in session for later use 200 session.filename = filename; 201 def excelData; 202 try { 203 excelData = sampleExcelService.parseTagsExcel( file, false ); 204 } catch( Throwable e ) { // Catch a throwable here instead of an exception, since the apache poi stuff gives an Error on failure 205 // Couldn't create a workbook from this file. 206 response.status = 400 // Bad request 207 render "Uploaded file is not a valid excel file: " + e.getMessage() 208 return 209 } 210 session.possibleFields = excelData.possibleFields 211 212 [run: run, headers: excelData.headers, exampleData: excelData.exampleData, filename: filename, possibleFields: [ "Don't import" ] + excelData.possibleFields, bestMatches: excelData.bestMatches] 213 } 214 215 /** 216 * Updates the assay samples based on the given excel file and the column matches 217 */ 218 def updateTagsByExcel = { 219 Run run = getRun( params.id ); 220 221 if( !run ) { 222 // Now delete the file, since we don't need it anymore 223 _deleteUploadedFileFromSession() 224 225 redirect(controller: 'study') 226 return 227 } 228 229 if( !session.filename ) { 230 // Now delete the file, since we don't need it anymore 231 _deleteUploadedFileFromSession() 232 233 flash.error = "No excel file found because session timed out. Please try again." 234 redirect( action: 'show', id: params.id) 235 return 236 } 237 238 // Determine the match-columns 239 def matchColumns = params[ 'matches']; 240 241 // Now loop through the excel sheet and update all samples with the specified data 242 File file = new File( fileService.getUploadDir(), session.filename ); 243 244 if( !file.exists() || !file.canRead() ) { 245 flash.error = "Excel file has been removed since previous step. Please try again." 246 redirect( action: 'show', id: params.id) 247 return 248 } 128 249 250 // Make it only possible to update samples writable by the user 251 def assaySamples = run.assaySamples.findAll { it.assay.study.canWrite( session.user ) } 252 253 def excelData = sampleExcelService.updateTagsByExcel( matchColumns, session.possibleFields, file, assaySamples ); 254 255 // Return a message to the user 256 if( !excelData.success ) { 257 flash.error = excelData.message 258 } else if( excelData.numSuccesful == 0 ) { 259 flash.error = "None of the " + excelData.failedRows.size() + " row(s) could be imported, because none of the sample names matched or no samples are writable. Have you provided the right excel file?" 260 } else { 261 flash.message = excelData.numSuccesful + " samples have been updated. " 262 263 if( excelData.failedRows.size() > 0 ) 264 flash.message += excelData.failedRows.size() + " row(s) could not be imported, because the sample names could not be found in the database or you don't have the proper permissions to change them." 265 } 266 redirect( action: 'show', id: params.id ) 267 } 268 269 270 /** 271 * Update the properties of the assay samples manually 272 */ 273 def updateTagsManually = { 274 Run run = getRun( params.id ); 275 276 if( !run ) { 277 redirect(controller: 'study') 278 return 279 } 280 281 // Loop through all assay samples and set data 282 def sampleParams = params.assaySample; 283 284 if( sampleParams ) { 285 run.assaySamples.each { assaySample -> 286 def assaySampleParams = sampleParams.get( assaySample.id as String ); 287 if( assaySampleParams ) { 288 assaySample.oligoNumber = assaySampleParams.oligoNumber 289 assaySample.tagSequence = assaySampleParams.tagSequence 290 291 assaySample.save() 292 } 293 } 294 } 295 296 flash.message = "Data about samples is saved." 297 redirect( action: 'show', id: params.id ) 298 } 299 300 /************************************************************************** 301 * 302 * Methods for handling data about assays for this run 303 * 304 *************************************************************************/ 305 306 /** 307 * Adds existing assays to this run 308 */ 309 def addAssays = { 310 Run run = getRun( params.id ); 311 312 if( !run ) { 313 redirect(controller: 'study') 314 return 315 } 316 317 // Add checked runs to this assay 318 def assays = params.assays 319 if( assays instanceof String ) { 320 assays = [ assays ] 321 } 322 323 def numAdded = 0; 324 assays.each { assay_id -> 325 try { 326 def assay = Assay.findById( assay_id as Long ) 327 if( run.assays == null || !run.assays.contains( assay ) ) { 328 run.addToAssays( assay ); 329 numAdded++; 330 } 331 } catch( Exception e ) {} 332 } 333 334 flash.message = numAdded + " runs are added to this assay." 335 redirect( action: 'show', id: params.id) 336 } 337 338 /** 339 * Removes assay for this run 340 */ 341 def removeAssay = { 342 Run run = getRun( params.id ); 343 344 if( !run ) { 345 redirect(controller: 'study') 346 return 347 } 348 349 if( !params.assay_id ) { 350 flash.message = "No assay id given" 351 redirect(action: 'show', id: params.id) 352 return 353 } 354 355 def assay 356 357 try { 358 assay = Assay.findById( params.assay_id as Long ) 359 } catch( Exception e ) { 360 throw e 361 flash.message = "Incorrect assay id given: " 362 redirect(action: 'show', id: params.id) 363 return 364 } 365 366 if( run.assays.contains( assay ) ) { 367 run.removeFromAssays( assay ); 368 flash.message = "The assay has been removed from this run." 369 } else { 370 flash.message = "The given assay was not associated with this run." 371 } 372 373 redirect( action: 'show', id: params.id) 374 } 375 376 377 /** 378 * Deletes an uploaded file for which the filename is given in the session. 379 * @return 380 */ 381 def _deleteUploadedFileFromSession() { 382 if( !session.filename ) 383 return 384 385 // Now delete the file, since we don't need it anymore 386 fileService.delete( session.filename ) 387 session.filename = '' 388 } 389 390 protected Run getRun(def runId) { 391 // load study with id specified by param.id 392 def run 393 try { 394 run = Run.get(runId as Long) 395 } catch( Exception e ) { 396 flash.error = "Incorrect id given: " + runId 397 return null 398 } 399 400 if (!run) { 401 flash.error = "No run found with id: " + runId 402 return null 403 } 404 405 return run 406 } 407 408 protected Assay getAssay(def assayId) { 409 // load study with id specified by param.id 410 def assay 411 try { 412 assay = Assay.get(assayId as Long) 413 } catch( Exception e ) { 414 flash.error = "Incorrect id given: " + assayId 415 return null 416 } 417 418 if (!assay) { 419 flash.error = "No assay found with id: " + assayId 420 return null 421 } 422 423 if (!assay.study.canRead( session.user ) ) { 424 flash.error = "You don't have the right authorizaton to access assay " + assay.name 425 return null 426 } 427 428 return assay 129 429 } 130 430 } -
trunk/grails-app/controllers/nl/tno/metagenomics/integration/TrashController.groovy
r4 r7 53 53 redirect( action: "index" ); 54 54 } 55 55 println "Restore To: " + restoreSample 56 println "Original Sample: " + originalSample 56 57 trashService.restoreSample( restoreSample, originalSample ); 57 58 restoreSample.sample?.delete();
Note: See TracChangeset
for help on using the changeset viewer.