Changeset 52
- Timestamp:
- Apr 19, 2011, 3:27:02 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 2 deleted
- 33 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/application.properties
r35 r52 1 1 #Grails Metadata file 2 # Mon Feb 28 15:08:16 CET 20112 #Fri Apr 15 14:24:03 CEST 2011 3 3 app.build.display.info=0 4 app.version=0.1 5 plugins.tomcat=1.3.7 6 plugins.jquery=1.4.4.1 7 plugins.famfamfam=1.0.1 8 plugins.jquery-ui=1.8.7 9 app.servlet.version=2.4 10 plugins.hibernate=1.3.7 11 app.name=massSequencing 4 12 app.grails.version=1.3.7 5 app.name=massSequencing6 app.servlet.version=2.47 app.version=0.18 plugins.db-util=0.49 plugins.famfamfam=1.0.110 plugins.hibernate=1.3.711 plugins.jquery=1.4.4.112 plugins.jquery-ui=1.8.713 plugins.tomcat=1.3.7 -
trunk/grails-app/conf/BaseFilters.groovy
r50 r52 186 186 return true; 187 187 188 if( !synchronizationService.performSynchronization() ) 189 return true; 190 188 191 if( synchronizationService.timeForFullSynchronization() ) { 189 192 redirect( url: synchronizationService.urlForFullSynchronization( params ) ); -
trunk/grails-app/conf/Config.groovy
r49 r52 112 112 //} 113 113 114 appenders { 115 file name:'file', file:'/home/robert/tmp/profiler.log' 116 file name:'sqlfile', file:'/home/robert/tmp/sql.log' 117 } 118 114 119 trace 'grails.app' 115 120 … … 125 130 'org.hibernate', 126 131 'net.sf.ehcache.hibernate' 127 132 128 133 warn 'org.mortbay.log' 134 135 info file: 'com.linkedin.grails' 136 //trace sqlfile: 'org.hibernate.SQL' 129 137 } 130 138 -
trunk/grails-app/conf/DataSource.groovy
r3 r52 4 4 username = "sa" 5 5 password = "" 6 //loggingSql = true 6 7 } 7 8 hibernate { -
trunk/grails-app/conf/config-dbnptest.properties
r36 r52 7 7 # server URL 8 8 grails.serverURL=http://test.massSequencing.dbnp.org 9 10 # Disable profiling on production environment 11 grails.profiler.disable=true 9 12 10 13 # DATABASE -
trunk/grails-app/conf/config-development.properties
r36 r52 20 20 gscf.baseURL=http://localhost:8080/gscf 21 21 massSequencing.consumerID=http://localhost:8184/massSequencing 22 massSequencing.synchronization = true22 massSequencing.synchronization=false 23 23 24 24 # File uploads -
trunk/grails-app/controllers/nl/tno/massSequencing/AssayController.groovy
r50 r52 36 36 return; 37 37 } 38 39 // Find statistics for all assaySamples in order to improve performance 40 AssaySample.initStats( assay.assaySamples?.toList() ) 38 41 39 42 // Determine runs not used in this assay … … 409 412 } catch( Exception e ) { 410 413 log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." ); 414 e.printStackTrace(); 411 415 } 412 416 } … … 440 444 } catch( Exception e ) { 441 445 log.error( "Exception occurred during export of metadata. Probably the user has cancelled the download." ); 446 e.printStackTrace(); 442 447 } 443 448 } -
trunk/grails-app/controllers/nl/tno/massSequencing/AssaySampleController.groovy
r49 r52 62 62 } catch( Exception e ) { 63 63 log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." ); 64 e.printStackTrace(); 64 65 } 65 66 } -
trunk/grails-app/controllers/nl/tno/massSequencing/RunController.groovy
r50 r52 33 33 redirect( url: synchronizationService.gscfService.urlAuthRemote(params, session.sessionToken) ) 34 34 } 35 36 // Find statistics for all assaySamples in order to improve performance 37 AssaySample.initStats( run.assaySamples?.toList() ) 35 38 36 39 // Determine runs not used in this assay … … 649 652 } catch( Exception e ) { 650 653 log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." ); 654 e.printStackTrace(); 651 655 } 652 656 } … … 681 685 } 682 686 response.setHeader "Content-disposition", "attachment; filename=${name}.xls" 683 if( !sampleExcelService.exportExcelSampleData( assaySamples.unique(), tags, response.getOutputStream() ) ) { 687 688 if( !sampleExcelService.exportExcelSampleData( assaySamples.unique(), tags, response.outputStream ) ) { 684 689 flash.error = "An error occurred while fetching sample data. Maybe the session has timed out."; 685 690 response.setHeader( "Content-disposition", "" ); … … 689 694 } catch( Exception e ) { 690 695 log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." ); 696 e.printStackTrace(); 691 697 } 692 698 } -
trunk/grails-app/controllers/nl/tno/massSequencing/SampleController.groovy
r42 r52 35 35 } catch( Exception e ) { 36 36 log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." ); 37 e.printStackTrace(); 37 38 } 38 39 } -
trunk/grails-app/controllers/nl/tno/massSequencing/StudyController.groovy
r49 r52 60 60 } catch( Exception e ) { 61 61 log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." ); 62 e.printStackTrace(); 62 63 } 63 64 } -
trunk/grails-app/controllers/nl/tno/massSequencing/integration/RestController.groovy
r49 r52 414 414 return [ 415 415 "# sequences": null, "# qual scores": null, 416 "run name": null, 416 417 "forward oligo number": "fwOligo", 417 418 "forward mid name": "fwMidName", … … 654 655 case "# qual scores": 655 656 value = assaySample.numQualScores(); break; 657 case "run name": 658 value = assaySample.run?.name; break; 656 659 } 657 660 } else { -
trunk/grails-app/domain/nl/tno/massSequencing/Assay.groovy
r42 r52 17 17 } 18 18 assaySamples cascade: "all-delete-orphan" 19 assaySamples batchSize: 10 19 20 } 20 21 -
trunk/grails-app/domain/nl/tno/massSequencing/AssaySample.groovy
r49 r52 8 8 */ 9 9 class AssaySample { 10 // To be computed in run time 10 // Grails datasource is used for executing custom SQL statement 11 def dataSource 12 13 // To be computed at run time 11 14 private long _numSequences = -1; 12 15 private float _averageQuality = -1.0; 13 16 private long _numQualScores = -1; 14 17 private long _numSequenceFiles = -1; 18 private long _numQualityFiles = -1; 19 15 20 Integer numUniqueSequences // Number of unique sequences / OTUs. Is only available after preprocessing 16 21 … … 50 55 } 51 56 sequenceData cascade: "all-delete-orphan" 57 sample fetch: 'join' 58 assay fetch: 'join' 59 run fetch: 'join' 52 60 } 53 61 … … 59 67 */ 60 68 public int numFiles() { 61 if( !sequenceData ) 62 return 0 63 64 int numFiles = 0; 65 sequenceData.each { numFiles += it.numFiles() } 66 67 return numFiles; 69 return numSequenceFiles() + numQualityFiles(); 68 70 } 69 71 … … 75 77 */ 76 78 public int numSequenceFiles() { 79 if( _numSequenceFiles > -1 ) 80 return _numSequenceFiles; 81 77 82 if( !sequenceData ) 78 83 return 0 … … 94 99 */ 95 100 public int numQualityFiles() { 101 if( _numQualityFiles > -1 ) 102 return _numQualityFiles; 103 96 104 if( !sequenceData ) 97 105 return 0 … … 183 191 _numQualScores = -1; 184 192 _averageQuality = -1; 193 194 _numSequenceFiles = -1; 195 _numQualityFiles = -1; 196 } 197 198 /** 199 * Fill statistics for multiple assaySamples at once. 200 * 201 * This method is used to improve performance. If multiple assaysamples are shown on the screen 202 * and all have to collect the statistics, it is done with n queries (where n is the number of assaysamples) 203 * This method reduces this number to 1 204 * 205 * @param assaySamples List of assaySamples to collect the statistics for 206 */ 207 public static void initStats( ArrayList<AssaySample> assaySamples ) { 208 if( !assaySamples ) 209 return; 210 211 // Order assaysamples by id 212 assaySamples.sort { it.id } 213 214 // Retrieve the datasource for these assaysamples 215 groovy.sql.Sql sql = new groovy.sql.Sql(assaySamples[0].dataSource) 216 217 // Execute a custom query 218 String ids = assaySamples.id*.toString().join( ', ' ); 219 String sqlStatement = """ 220 SELECT 221 a.id, 222 count( s.sequence_file ) AS numSequenceFiles, 223 count( s.quality_file ) AS numQualityFiles, 224 sum( s.num_sequences ) AS numSequences, 225 sum( CASE WHEN s.quality_file IS NOT NULL THEN s.num_sequences ELSE 0 END ) AS numQualScores 226 FROM assay_sample a 227 LEFT JOIN sequence_data s ON a.id = s.sample_id 228 WHERE a.id IN (${ids}) 229 GROUP BY a.id 230 ORDER BY a.id 231 """ 232 233 // For each assaysample, one row is returned. In order to prevent lookups in 234 // the asasySamples list, both lists are sorted by id. For that reason, we can just 235 // walk through both lists simultaneously 236 def listIndex = 0; 237 sql.eachRow( sqlStatement ) { 238 // Still, we perform a check to see whether the ids match. If they don't 239 // something went wrong in the database or in grails. We note an error, and 240 // skip the assignment. The variables will be filled later on anyhow, it 241 // will only be a little bit slower 242 if( it.id != assaySamples[ listIndex ]?.id ) { 243 log.error "ID of the database row and the domain object don't match. DB: " + it.id + ", Domain object: " + assaySamples[ listIndex ]?.id 244 } else { 245 assaySamples[ listIndex ]._numSequences = it.numSequences ?: 0; 246 assaySamples[ listIndex ]._numQualScores = it.numQualScores ?: 0; 247 assaySamples[ listIndex ]._numSequenceFiles = it.numSequenceFiles ?: 0; 248 assaySamples[ listIndex ]._numQualityFiles = it.numQualityFiles ?: 0; 249 } 250 251 listIndex++; 252 } 185 253 } 186 254 -
trunk/grails-app/domain/nl/tno/massSequencing/Run.groovy
r42 r52 26 26 name index:'runname_idx' 27 27 } 28 29 assaySamples batchSize: 10 30 28 31 } 29 32 static constraints = { -
trunk/grails-app/domain/nl/tno/massSequencing/Study.groovy
r49 r52 35 35 samples cascade: "all-delete-orphan" 36 36 auth cascade: "all-delete-orphan" 37 auth lazy: false, batchSize: 10 37 38 } 38 39 -
trunk/grails-app/services/nl/tno/massSequencing/FastaService.groovy
r49 r52 6 6 import java.util.ArrayList; 7 7 import java.util.List; 8 import java.util.zip.ZipEntry9 import java.util.zip.ZipOutputStream10 8 import org.codehaus.groovy.grails.commons.ConfigurationHolder 9 import java.util.zip.* 11 10 12 11 class FastaService { … … 706 705 zipFile.putNextEntry( new ZipEntry( name + ".xls" ) ); 707 706 sampleExcelService.exportExcelSampleData( assaySamples, tags, zipFile ); 707 zipFile.flush(); 708 708 zipFile.closeEntry(); 709 709 -
trunk/grails-app/services/nl/tno/massSequencing/SampleExcelService.groovy
r51 r52 303 303 } catch( Exception e ) { 304 304 log.error "Exception occurred while fetching sample data from gscf: " + e.getMessage(); 305 e.printStackTrace() 305 306 return false; 306 307 } … … 367 368 } 368 369 370 // Unfortunately the excel format can only contain max 256 columns 371 // If more than 256 columns are generated, the columns above 256 are disregarded 372 if( row.size() > 256 ) 373 row = row[0..255]; 374 369 375 data << row; 370 376 371 }372 373 // Transpose data and create new headers374 data = data.transpose();375 376 // Add field names in front of the data377 for( int i = 0; i < data.size(); i++ ) {378 data[ i ] = [] + fields[ "descriptions" ][ "all" ][ i ] + data[ i ]379 377 } 380 378 … … 386 384 387 385 // Put the headers on the first row 388 //excelService.writeHeader( wb, data[ 0], sheetIndex );389 excelService.writeData( wb, data, sheetIndex, 0);386 excelService.writeHeader( wb, fields[ "descriptions" ][ "all" ], sheetIndex ); 387 excelService.writeData( wb, data, sheetIndex, 1 ); 390 388 391 389 // Auto resize columns (# columns = # samples + 1) -
trunk/grails-app/services/nl/tno/massSequencing/files/ExcelService.groovy
r50 r52 4 4 import java.text.Format 5 5 import java.text.NumberFormat 6 import org.apache.poi.hssf.usermodel.* 6 import org.apache.poi.xssf.usermodel.XSSFWorkbook; 7 import org.apache.poi.hssf.usermodel.HSSFWorkbook; 7 8 import org.apache.poi.ss.usermodel.* 8 9 -
trunk/grails-app/services/nl/tno/massSequencing/files/FileService.groovy
r44 r52 18 18 import org.codehaus.groovy.grails.commons.ConfigurationHolder 19 19 import java.io.File; 20 import java.util.zip.* 20 import java.util.zip.GZIPInputStream 21 import java.util.zip.ZipEntry 22 import java.util.zip.ZipInputStream 21 23 22 24 /** -
trunk/grails-app/services/nl/tno/massSequencing/imports/FuzzySearchService.groovy
r29 r52 15 15 */ 16 16 static def mostSimilarUnique( patterns, candidates, treshold ) { 17 println "Patterns: " + patterns.findAll { it }; 18 println "Candidates: " + candidates; 19 17 20 def matches = [] 18 21 19 22 // Find the best matching candidate for each pattern 20 patterns. each { pattern ->23 patterns.findAll { it }.each { pattern -> 21 24 def topScore = 0 22 25 def bestFit = null … … 24 27 candidates.each { candidate -> 25 28 def score = stringSimilarity(pattern, candidate); 26 if( score >= treshold )29 if( !score.isNaN() && score >= treshold ) 27 30 matches << [ 'pattern': pattern, 'candidate': candidate, 'score': score ]; 28 31 } -
trunk/grails-app/services/nl/tno/massSequencing/integration/GscfService.groovy
r50 r52 303 303 * @param restMethod Method to call on GSCF rest controller 304 304 * @param restParams Parameters to provide to the GSCF rest method 305 * @param requestMethod Request method to retrieve data 305 306 * 306 307 * @return ArrayList 307 308 */ 308 private ArrayList callGSCF(String sessionToken, String restMethod, HashMap restParams = [:]) throws BadRequestException, NotAuthenticatedException, NotAuthorizedException, ResourceNotFoundException, Exception { 309 310 def gscfResponse = [] 311 312 //construct addr 313 def addr = "${this.restURL()}/${restMethod}?moduleURL=${this.moduleURL()}&consumer=${this.consumerID()}&token=${sessionToken}" 314 315 // concat all Rest Call specific arguments behind addr 309 private ArrayList callGSCF(String sessionToken, String restMethod, HashMap restParams = [:], String requestMethod = "GET" ) throws BadRequestException, NotAuthenticatedException, NotAuthorizedException, ResourceNotFoundException, Exception { 310 311 // Create a string of arguments to send to GSCF 312 def args = "moduleURL=${this.moduleURL()}&consumer=${this.consumerID()}&token=${sessionToken}"; 313 314 // concat all Rest Call specific arguments behind args 316 315 restParams.each {parameter -> 317 316 // If a list is given as value, the parameter should show up multiple times 318 317 if( parameter.value instanceof Collection ) { 319 318 parameter.value.each { value -> 320 a ddr+= "&${parameter.key}=" + value.toString().encodeAsURL()319 args += "&${parameter.key}=" + value.toString().encodeAsURL() 321 320 } 322 321 } else { 323 a ddr+= "&${parameter.key}=" + parameter.value.toString().encodeAsURL()322 args += "&${parameter.key}=" + parameter.value.toString().encodeAsURL() 324 323 } 325 324 } 326 327 // Open the connection 328 def connection; 329 330 try { 331 log.info("GSCF REST-CALL: ${addr}") 332 connection = addr.toURL().openConnection() 325 326 // construct GSCF address 327 def addr = "${this.restURL()}/${restMethod}" 328 def connection 329 330 // If the data to be sent is longer than appr 2000 characters, the GET method will fail 331 // For that reason, we switch to POST if needed 332 if( addr.size() + args.size() > 2000 && requestMethod != "POST" ) { 333 log.warn "Calling " + addr + " with request method POST instead of " + requestMethod + " because content length is too long: " + ( addr.size() + args.size() ) 334 requestMethod = "POST"; 335 } 336 337 // Call GSCF, depending on the requestmethod that is asked for 338 try { 339 log.info("GSCF REST-CALL (" + requestMethod + "): ${addr}") 340 341 switch( requestMethod.toUpperCase() ) { 342 case "GET": 343 def url = addr + "?" + args; 344 connection = url.toURL().openConnection(); 345 346 break 347 case "POST": 348 connection = addr.toURL().openConnection() 349 connection.setRequestMethod( "POST" ); 350 connection.doOutput = true 351 352 def writer = new OutputStreamWriter( connection.outputStream ) 353 writer.write( args ); 354 writer.flush() 355 writer.close() 356 357 connection.connect(); 358 359 break 360 default: 361 throw new Exception( "Unknown request method given. Use GET or POST" ) 362 } 363 333 364 } catch( Exception e ) { 334 365 log.error("GSCF Call failed when calling service: ${addr}",e) … … 336 367 } 337 368 369 // Handle the response given by GSCF 370 def gscfResponse = [] 371 338 372 switch( connection.responseCode ) { 339 373 case 400: // Bad request … … 375 409 } 376 410 377 378 411 /** 379 412 * Consumer ID for connection to of GSCF Rest Controller/API -
trunk/grails-app/services/nl/tno/massSequencing/integration/SynchronizationService.groovy
r50 r52 31 31 return true 32 32 33 return conf 33 // See http://jira.codehaus.org/browse/GRAILS-6515 34 if (conf.class == java.lang.Boolean) { 35 // because 'true.toBoolean() == false' !!! 36 return conf 37 } else { 38 return conf.toBoolean() 39 } 34 40 } 35 41 … … 88 94 */ 89 95 public void fullSynchronization() { 90 def previousEager = this.eager 91 this.eager = true 92 this.synchronizeStudies(); 93 this.eager = previousEager 96 if( performSynchronization() ) { 97 def previousEager = this.eager 98 this.eager = true 99 this.synchronizeStudies(); 100 this.eager = previousEager 101 } 94 102 95 103 SynchronizationService.lastFullSynchronization = new Date(); … … 102 110 public ArrayList<Study> synchronizeStudies() throws BadRequestException, NotAuthenticatedException, NotAuthorizedException, ResourceNotFoundException, Exception { 103 111 if( !performSynchronization() ) 104 return Study.findAll WhereTrashcan(false)112 return Study.findAllByTrashcan(false) 105 113 106 114 // When eager fetching is enabled, ask for all studies, otherwise only ask for studies marked dirty … … 443 451 */ 444 452 public Auth synchronizeAuthorization(Study study) { 453 if( !performSynchronization() ) 454 return Auth.findByUserAndStudy( user, study ) 455 445 456 // If the user is not set, we can't save anything to the database. 446 457 if( user == null ) { -
trunk/grails-app/views/assay/index.gsp
r49 r52 33 33 <td><g:checkBox name="ids" value="${assay.id}" checked="${false}" onClick="updateCheckAll(this);" /></td> 34 34 35 <td><g:link controller="assay" action="show" id="${assay.id}">${assay.name}</g:link></td>35 <td><g:link title="View assay" controller="assay" action="show" id="${assay.id}">${assay.name}</g:link></td> 36 36 <td><a href="${study.viewUrl()}">${study.name}</a></td> 37 37 <td>${assay.assaySamples?.size()}</td> 38 38 <td> 39 39 <g:if test="${assay.assaySamples?.size()}"> 40 <g:formatNumber number="${assay.numSequences() / assay.assaySamples?.size()}" format=" 0"/>40 <g:formatNumber number="${assay.numSequences() / assay.assaySamples?.size()}" format="###,###,##0"/> 41 41 </g:if> 42 42 <g:else> … … 44 44 </g:else> 45 45 </td> 46 <td><g:link controller="assay" action="show" id="${assay.id}"><img src="${fam.icon( name: 'application_form_magnify' )}" alt="view" title="view" /></g:link></td>46 <td><g:link title="View assay" controller="assay" action="show" id="${assay.id}"><img src="${fam.icon( name: 'application_form_magnify' )}" alt="View assay" title="View assay" /></g:link></td> 47 47 <td> 48 48 <g:if test="${assay.numSequences() > 0}"> 49 <g:link controller="assay" action="sequenceLengthHistogram" id="${assay.id}"><img src="${fam.icon( name: 'chart_bar' )}" alt="Sequence length histogram" title="Sequence length histogram" /></g:link>49 <g:link title="Sequence length histogram" controller="assay" action="sequenceLengthHistogram" id="${assay.id}"><img src="${fam.icon( name: 'chart_bar' )}" alt="Sequence length histogram" title="Sequence length histogram" /></g:link> 50 50 </g:if> 51 51 <g:else> -
trunk/grails-app/views/assay/sequenceLengthHistogram.gsp
r49 r52 3 3 <meta name="layout" content="main" /> 4 4 <title>Sequence length histogram for asasy ${assay.name} | Mass Sequencing | dbNP</title> 5 6 <script type="text/javascript" src="${resource(dir: 'jqplot/plugins', file: 'jqplot.barRenderer.min.js')}"></script> 7 <script type="text/javascript" src="${resource(dir: 'jqplot/plugins', file: 'jqplot.logAxisRenderer.min.js')}"></script> 8 5 9 </head> 6 10 <body> 7 11 <h1>Sequence length histogram for assay ${assay.name}</h1> 8 12 <p> 9 Total number of sequences: ${assay.numSequences()}13 Total number of sequences: <g:formatNumber number="${assay.numSequences()}" format="###,###,##0" /> 10 14 </p> 11 15 <div id="placeholder" style="width:600px;height:300px"></div> … … 13 17 <script type="text/javascript"> 14 18 $.plot($("#placeholder"), [ 15 {16 data: ${histogram},17 bars: {show: true, align: "center"}18 }19 19 { 20 data: ${histogram}, 21 bars: {show: true, align: "center"} 22 } 23 ]); 20 24 </script> 21 25 </body> -
trunk/grails-app/views/assay/show.gsp
r51 r52 50 50 <label>Assay</label>: ${assay.name}<br /> 51 51 <label># samples</label>: ${assay.assaySamples?.size()}<br /> 52 <label># sequences</label>: ${assay.numSequences()}<br />52 <label># sequences</label>: <g:formatNumber number="${assay.numSequences()}" format="###,###,##0" /><br /> 53 53 <label># files</label>: ${assay.numFiles()}<br /> 54 54 55 55 <!-- Samples --> 56 56 <h2>Samples</h2> 57 57 58 <g:if test="${assay.assaySamples == null || assay.assaySamples.size() == 0}"> 58 No samples found in assay. 59 <g:if test="${editable}"> 60 Associate samples with this assay in <a target="_top" href="${ assay.study.viewUrl() }">GSCF</a>. 61 </g:if> 59 <p> 60 No samples found in assay. 61 <g:if test="${editable}"> 62 Associate samples with this assay in <a target="_top" href="${ assay.study.viewUrl() }">GSCF</a>. 63 </g:if> 64 </p> 62 65 </g:if> 63 66 <g:else> … … 77 80 </thead> 78 81 <tbody> 79 <% def assaySamples = assay.assaySamples.toList() .sort { it.sample.name };%>82 <% def assaySamples = assay.assaySamples.toList() %> 80 83 <g:each in="${assaySamples}" var="assaySample"> 81 84 <tr> 82 85 <td><g:checkBox name="ids" value="${assaySample.id}" checked="${false}" onClick="updateCheckAll(this);" /></td> 83 <td><a href="#" onClick="showSample(${assaySample.id}, 'assay'); return false;">${assaySample.sample.name}</a></td>86 <td><a title="Show assay" href="#" onClick="showSample(${assaySample.id}, 'assay'); return false;">${assaySample.sample.name}</a></td> 84 87 <td>${assaySample.run?.name}</td> 85 88 <td>${assaySample.fwMidName}</td> 86 89 <td> 87 90 <g:if test="${assaySample.numSequenceFiles() > 0}"> 88 ${assaySample.numSequences()}91 <g:formatNumber number="${assaySample.numSequences()}" format="###,###,##0" /> 89 92 </g:if> 90 93 <g:else> … … 94 97 <td> 95 98 <g:if test="${assaySample.numQualityFiles() > 0}"> 96 ${assaySample.numQualScores()}99 <g:formatNumber number="${assaySample.numQualScores()}" format="###,###,##0" /> 97 100 </g:if> 98 101 <g:else> … … 105 108 </g:if> 106 109 <g:else> 107 <a onClick="showEditSampleDialog(${assaySample.id}, 'assay', ${assay.id}); return false;" href="#" ><imgsrc="${fam.icon(name: 'pencil')}" /></a>110 <a onClick="showEditSampleDialog(${assaySample.id}, 'assay', ${assay.id}); return false;" href="#" title="Edit sample data"><img title="Edit sample data" src="${fam.icon(name: 'pencil')}" /></a> 108 111 </g:else> 109 112 </td> 110 113 <td class="button"> 111 114 <g:if test="${assaySample.numSequences() > 0}"> 112 <g:link controller="assaySample" action="sequenceLengthHistogram" id="${assaySample.id}" ><img src="${fam.icon( name: 'chart_bar' )}" alt="Sequence length histogram" title="Sequence length histogram" /></g:link>115 <g:link controller="assaySample" action="sequenceLengthHistogram" id="${assaySample.id}" title="Sequence length histogram"><img src="${fam.icon( name: 'chart_bar' )}" alt="Sequence length histogram" title="Sequence length histogram" /></g:link> 113 116 </g:if> 114 117 <g:else> 115 118 <img src="${fam.icon( name: 'chart_bar' )}" class="disabled" alt="No histogram available because no sequences are uploaded." title="No histogram available because no sequences are uploaded." /> 116 119 </g:else> 117 </td> 120 </td> 118 121 </tr> 119 122 </g:each> 120 123 </tbody> 121 124 </table> 125 122 126 <p class="options multiple"> 123 127 <g:if test="${editable}"> … … 181 185 <g:each in="${runs}" var="run"> 182 186 <tr> 183 <td><g:link controller="run" action="show" id="${run.id}">${run.name}</g:link></td>187 <td><g:link title="Show run" controller="run" action="show" id="${run.id}">${run.name}</g:link></td> 184 188 <td><g:formatDate format="dd-MM-yyyy" date="${run.date}"/></td> 185 189 <td>${run.supplier}</td> … … 197 201 </g:else> 198 202 </td> 199 <td class="button"><a href="#" onClick="showEditRunDialog( ${run.id} ); return false;" ><imgsrc="${fam.icon(name: 'application_edit')}" /></a></td>203 <td class="button"><a href="#" onClick="showEditRunDialog( ${run.id} ); return false;" title="Edit run properties"><img title="Edit run properties" src="${fam.icon(name: 'application_edit')}" /></a></td> 200 204 <td class="button"> 201 205 <g:if test="${run.samples(assay.id).size()}"> … … 203 207 </g:if> 204 208 <g:else> 205 <g:link onClick="return confirm( 'Are you sure you want to remove the selected run from this assay?' );" controller="assay" action="removeRun" id="${assay.id}" params="${[run_id: run.id]}" ><imgsrc="${fam.icon(name: 'application_delete')}" /></g:link>209 <g:link onClick="return confirm( 'Are you sure you want to remove the selected run from this assay?' );" controller="assay" action="removeRun" id="${assay.id}" params="${[run_id: run.id]}" title="Remove run from assay"><img title="Remove run from assay" src="${fam.icon(name: 'application_delete')}" /></g:link> 206 210 </g:else> 207 211 </td> -
trunk/grails-app/views/assaySample/sequenceLengthHistogram.gsp
r49 r52 7 7 <h1>Sequence length histogram for sample ${assaySample.sample.name} (${assaySample.assay.study.name} / ${assaySample.assay.name})</h1> 8 8 <p> 9 Total number of sequences: ${assaySample.numSequences()}9 Total number of sequences: <g:formatNumber number="${assaySample.numSequences()}" format="###,###,##0" /> 10 10 </p> 11 11 <div id="placeholder" style="width:600px;height:300px"></div> -
trunk/grails-app/views/common/_topnav.gsp
r15 r52 7 7 <li><g:link controller="run">Runs</g:link></li> 8 8 <li><g:link controller="assay">Assays</g:link></li> 9 <li><g:link controller="study">Studies</g:link></li>10 9 </ul> 11 10 </li> -
trunk/grails-app/views/layouts/main.gsp
r49 r52 18 18 <script type="text/javascript" src="${resource(dir: 'js', file: 'jquery.dataTables.min.js')}"></script> 19 19 20 <!-- javascript charts using flot --> 20 21 <script type="text/javascript" src="${resource(dir: 'js', file: 'jquery.flot.min.js')}"></script> 21 22 <!--[if lte IE 8]><script language="javascript" type="text/javascript" src="${resource(dir: 'js', file: 'excanvas.min.js')}"></script><![endif]--> -
trunk/grails-app/views/run/index.gsp
r49 r52 42 42 <tr> 43 43 <td><g:checkBox name="ids" value="${run.id}" checked="${false}" onClick="updateCheckAll(this);" /></td> 44 <td><g:link controller="run" action="show" id="${run.id}">${run.name}</g:link></td>44 <td><g:link title="View run" controller="run" action="show" id="${run.id}">${run.name}</g:link></td> 45 45 <td>${run.assaySamples?.size()}</td> 46 <td> ${run.numSequences()}</td>47 <td><g:link controller="run" action="show" id="${run.id}"><img src="${fam.icon( name: 'application_form_magnify' )}" alt="view" title="view" /></g:link></td>46 <td><g:formatNumber number="${run.numSequences()}" format="###,###,##0" /></td> 47 <td><g:link title="View run" controller="run" action="show" id="${run.id}"><img src="${fam.icon( name: 'application_form_magnify' )}" alt="View run" title="View run" /></g:link></td> 48 48 <td> 49 49 <g:if test="${run.deletable(user)}"> 50 <g:link onClick="return confirm( 'Are you sure you want to delete this run?' );" controller="run" action="deleteRun" id="${run.id}"><img src="${fam.icon( name: 'delete' )}" alt="delete" title="delete" /></g:link>50 <g:link title="Delete run" onClick="return confirm( 'Are you sure you want to delete this run?' );" controller="run" action="deleteRun" id="${run.id}"><img src="${fam.icon( name: 'delete' )}" alt="Delete run" title="Delete run" /></g:link> 51 51 </g:if> 52 52 <g:else> … … 56 56 <td> 57 57 <g:if test="${run.numSequences() > 0}"> 58 <g:link controller="run" action="sequenceLengthHistogram" id="${run.id}"><img src="${fam.icon( name: 'chart_bar' )}" alt="Sequence length histogram" title="Sequence length histogram" /></g:link>58 <g:link controller="run" action="sequenceLengthHistogram" title="Sequence length histogram" id="${run.id}"><img src="${fam.icon( name: 'chart_bar' )}" alt="Sequence length histogram" title="Sequence length histogram" /></g:link> 59 59 </g:if> 60 60 <g:else> -
trunk/grails-app/views/run/sequenceLengthHistogram.gsp
r49 r52 7 7 <h1>Sequence length histogram for run ${run.name}</h1> 8 8 <p> 9 Total number of sequences: ${run.numSequences()}9 Total number of sequences: <g:formatNumber number="${run.numSequences()}" format="###,###,##0" /> 10 10 </p> 11 11 <div id="placeholder" style="width:600px;height:300px"></div> -
trunk/grails-app/views/run/show.gsp
r51 r52 78 78 </g:if> 79 79 <br /> 80 <label># sequences</label>: ${run.numSequences()}<br />80 <label># sequences</label>: <g:formatNumber number="${run.numSequences()}" format="###,###,##0" /><br /> 81 81 <label># files</label>: ${run.numFiles()}<br /> 82 82 </div> … … 89 89 <% def assaySamples = run.assaySamples ? run.assaySamples.findAll { it.assay?.study.canRead( session.user ) }.toList().sort { it.sample.name } : []; %> 90 90 <g:if test="${assaySamples.size() == 0}"> 91 No samples found in run.91 <p>No samples found in run.</p> 92 92 </g:if> 93 93 <g:else> … … 112 112 <tr> 113 113 <td><g:checkBox name="ids" value="${assaySample.id}" checked="${false}" onClick="updateCheckAll(this);" /></td> 114 <td><a href="#" onClick="showSample(${assaySample.id}, 'run'); return false;">${assaySample.sample.name}</a></td>114 <td><a title="Show sample details" href="#" onClick="showSample(${assaySample.id}, 'run'); return false;">${assaySample.sample.name}</a></td> 115 115 <td>${assaySample.assay.study.name}</td> 116 116 <td>${assaySample.assay.name}</td> … … 118 118 <td> 119 119 <g:if test="${assaySample.numSequenceFiles() > 0}"> 120 ${assaySample.numSequences()}120 <g:formatNumber number="${assaySample.numSequences()}" format="###,###,##0" /> 121 121 </g:if> 122 122 <g:else> … … 126 126 <td> 127 127 <g:if test="${assaySample.numQualityFiles() > 0}"> 128 ${assaySample.numQualScores()}128 <g:formatNumber number="${assaySample.numQualScores()}" format="###,###,##0" /> 129 129 </g:if> 130 130 <g:else> … … 137 137 </g:if> 138 138 <g:else> 139 <a onClick="showEditSampleDialog(${assaySample.id}, 'run', ${run.id});" href="#"><imgsrc="${fam.icon(name: 'pencil')}" /></a>139 <a title="Edit sample" onClick="showEditSampleDialog(${assaySample.id}, 'run', ${run.id});" href="#"><img title="Edit sample" src="${fam.icon(name: 'pencil')}" /></a> 140 140 </g:else> 141 141 </td> … … 145 145 </g:if> 146 146 <g:else> 147 <g:link onClick="return confirm( 'Are you sure you want to remove the selected sample from this run?' );" controller="run" action="removeSample" id="${run.id}" params="${[assaySampleId: assaySample.id]}" ><imgsrc="${fam.icon(name: 'application_delete')}" /></g:link>147 <g:link title="Remove sample from run" onClick="return confirm( 'Are you sure you want to remove the selected sample from this run?' );" controller="run" action="removeSample" id="${run.id}" params="${[assaySampleId: assaySample.id]}" ><img title="Remove sample from run" src="${fam.icon(name: 'application_delete')}" /></g:link> 148 148 </g:else> 149 149 </td> 150 150 <td class="button"> 151 151 <g:if test="${assaySample.numSequences() > 0}"> 152 <g:link controller="assaySample" action="sequenceLengthHistogram" id="${assaySample.id}" ><img src="${fam.icon( name: 'chart_bar' )}" alt="Sequence length histogram" title="Sequence length histogram" /></g:link>152 <g:link controller="assaySample" action="sequenceLengthHistogram" id="${assaySample.id}" title="Sequence length histogram"><img src="${fam.icon( name: 'chart_bar' )}" alt="Sequence length histogram" title="Sequence length histogram" /></g:link> 153 153 </g:if> 154 154 <g:else> … … 202 202 203 203 <p class="options multiple"> 204 <a class="fasta" href="#" onClick="submitPaginatedForm( $( '#sampleForm' ), '<g:createLink controller="assaySample" action="exportAsFasta" />', '#samples', 'Please select one or more samples to export' ); return false;">Export as fasta</a><br /> 204 <g:if test="${assaySamples.size() > 0}"> 205 <a class="fasta" href="#" onClick="submitPaginatedForm( $( '#sampleForm' ), '<g:createLink controller="assaySample" action="exportAsFasta" />', '#samples', 'Please select one or more samples to export' ); return false;">Export as fasta</a><br /> 206 </g:if> 207 <g:else> 208 <a class="fasta disabled" href="#" onClick="return false;">Export as fasta</a><br /> 209 </g:else> 205 210 </p> 206 211 … … 238 243 <g:each in="${assays}" var="assay"> 239 244 <tr> 240 <td><g:link controller="assay" action="show" id="${assay.id}">${assay.name}</g:link></td>245 <td><g:link title="Show assay" controller="assay" action="show" id="${assay.id}">${assay.name}</g:link></td> 241 246 <td>${assay.study?.name}</td> 242 247 <td>${assay.assaySamples?.size()}</td> … … 248 253 <g:else> 249 254 <g:each in="${assay.runs - run}" var="otherRun"> 250 <g:link action="show" id="${otherRun.id}">${otherRun.name}</g:link><br />255 <g:link title="Show other run" action="show" id="${otherRun.id}">${otherRun.name}</g:link><br /> 251 256 </g:each> 252 257 </g:else> … … 261 266 </g:if> 262 267 <g:else> 263 <g:link onClick="return confirm( 'Are you sure you want to remove the selected assay from this run?' );" controller="run" action="removeAssay" id="${run.id}" params="${[assay_id: assay.id]}" ><img src="${fam.icon(name: 'application_delete')}" /></g:link>268 <g:link onClick="return confirm( 'Are you sure you want to remove the selected assay from this run?' );" controller="run" action="removeAssay" id="${run.id}" params="${[assay_id: assay.id]}" title="Remove assay from run" ><img src="${fam.icon(name: 'application_delete')}" title="Remove assay from run" /></g:link> 264 269 </g:else> 265 270 </g:else> -
trunk/web-app/js/forms.js
r23 r52 35 35 } 36 36 37 // Set form method to POST in order to be able to handle all items 38 form.attr( 'method', 'POST' ); 39 37 40 if( url != '' ) 38 41 form.attr( 'action', url );
Note: See TracChangeset
for help on using the changeset viewer.