Changeset 52 for trunk


Ignore:
Timestamp:
Apr 19, 2011, 3:27:02 PM (8 years ago)
Author:
robert@…
Message:
  • Updated a bug on production with org.apache.tools.zip
  • Added tooltips to all icons
Location:
trunk
Files:
1 added
2 deleted
33 edited

Legend:

Unmodified
Added
Removed
  • trunk/application.properties

    r35 r52  
    11#Grails Metadata file
    2 #Mon Feb 28 15:08:16 CET 2011
     2#Fri Apr 15 14:24:03 CEST 2011
    33app.build.display.info=0
     4app.version=0.1
     5plugins.tomcat=1.3.7
     6plugins.jquery=1.4.4.1
     7plugins.famfamfam=1.0.1
     8plugins.jquery-ui=1.8.7
     9app.servlet.version=2.4
     10plugins.hibernate=1.3.7
     11app.name=massSequencing
    412app.grails.version=1.3.7
    5 app.name=massSequencing
    6 app.servlet.version=2.4
    7 app.version=0.1
    8 plugins.db-util=0.4
    9 plugins.famfamfam=1.0.1
    10 plugins.hibernate=1.3.7
    11 plugins.jquery=1.4.4.1
    12 plugins.jquery-ui=1.8.7
    13 plugins.tomcat=1.3.7
  • trunk/grails-app/conf/BaseFilters.groovy

    r50 r52  
    186186                                        return true;
    187187                                       
     188                                if( !synchronizationService.performSynchronization() )
     189                                        return true;
     190                                       
    188191                                if( synchronizationService.timeForFullSynchronization() ) {
    189192                                        redirect( url: synchronizationService.urlForFullSynchronization( params ) );
  • trunk/grails-app/conf/Config.groovy

    r49 r52  
    112112    //}
    113113
     114        appenders {
     115                file name:'file', file:'/home/robert/tmp/profiler.log'
     116                file name:'sqlfile', file:'/home/robert/tmp/sql.log'
     117        }
     118       
    114119        trace   'grails.app'
    115120       
     
    125130           'org.hibernate',
    126131           'net.sf.ehcache.hibernate'
    127 
     132                   
    128133    warn   'org.mortbay.log'
     134       
     135        info    file: 'com.linkedin.grails'     
     136        //trace sqlfile: 'org.hibernate.SQL'
    129137}
    130138
  • trunk/grails-app/conf/DataSource.groovy

    r3 r52  
    44    username = "sa"
    55    password = ""
     6        //loggingSql = true
    67}
    78hibernate {
  • trunk/grails-app/conf/config-dbnptest.properties

    r36 r52  
    77# server URL
    88grails.serverURL=http://test.massSequencing.dbnp.org
     9
     10# Disable profiling on production environment
     11grails.profiler.disable=true
    912
    1013# DATABASE
  • trunk/grails-app/conf/config-development.properties

    r36 r52  
    2020gscf.baseURL=http://localhost:8080/gscf
    2121massSequencing.consumerID=http://localhost:8184/massSequencing
    22 massSequencing.synchronization = true
     22massSequencing.synchronization=false
    2323
    2424# File uploads
  • trunk/grails-app/controllers/nl/tno/massSequencing/AssayController.groovy

    r50 r52  
    3636                        return;
    3737                }
     38               
     39                // Find statistics for all assaySamples in order to improve performance
     40                AssaySample.initStats( assay.assaySamples?.toList() )
    3841               
    3942                // Determine runs not used in this assay
     
    409412                } catch( Exception e ) {
    410413                        log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." );
     414                        e.printStackTrace();
    411415                }
    412416        }
     
    440444                } catch( Exception e ) {
    441445                        log.error( "Exception occurred during export of metadata. Probably the user has cancelled the download." );
     446                        e.printStackTrace();
    442447                }
    443448        }
  • trunk/grails-app/controllers/nl/tno/massSequencing/AssaySampleController.groovy

    r49 r52  
    6262                } catch( Exception e ) {
    6363                        log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." );
     64                        e.printStackTrace();
    6465                }
    6566        }
  • trunk/grails-app/controllers/nl/tno/massSequencing/RunController.groovy

    r50 r52  
    3333                        redirect( url: synchronizationService.gscfService.urlAuthRemote(params, session.sessionToken) )
    3434                }
     35
     36                // Find statistics for all assaySamples in order to improve performance
     37                AssaySample.initStats( run.assaySamples?.toList() )
    3538
    3639                // Determine runs not used in this assay
     
    649652                } catch( Exception e ) {
    650653                        log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." );
     654                        e.printStackTrace();
    651655                }
    652656        }
     
    681685                        }
    682686                        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 ) ) {
    684689                                flash.error = "An error occurred while fetching sample data. Maybe the session has timed out.";
    685690                                response.setHeader( "Content-disposition", "" );
     
    689694                } catch( Exception e ) {
    690695                        log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." );
     696                        e.printStackTrace();
    691697                }
    692698        }
  • trunk/grails-app/controllers/nl/tno/massSequencing/SampleController.groovy

    r42 r52  
    3535           } catch( Exception e ) {
    3636                   log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." );
     37                        e.printStackTrace();
    3738           }
    3839   }
  • trunk/grails-app/controllers/nl/tno/massSequencing/StudyController.groovy

    r49 r52  
    6060                } catch( Exception e ) {
    6161                        log.error( "Exception occurred during export of sequences. Probably the user has cancelled the download." );
     62                        e.printStackTrace();
    6263                }
    6364        }
  • trunk/grails-app/controllers/nl/tno/massSequencing/integration/RestController.groovy

    r49 r52  
    414414                return [
    415415                        "# sequences": null, "# qual scores": null,
     416                        "run name": null,
    416417                        "forward oligo number":         "fwOligo",
    417418                        "forward mid name":             "fwMidName",
     
    654655                                                        case "# qual scores":
    655656                                                                value = assaySample.numQualScores(); break;
     657                                                        case "run name":
     658                                                                value = assaySample.run?.name; break;
    656659                                                }
    657660                                        } else {
  • trunk/grails-app/domain/nl/tno/massSequencing/Assay.groovy

    r42 r52  
    1717                }
    1818                assaySamples cascade: "all-delete-orphan"
     19                assaySamples batchSize: 10
    1920        }
    2021       
  • trunk/grails-app/domain/nl/tno/massSequencing/AssaySample.groovy

    r49 r52  
    88 */
    99class 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
    1114        private long _numSequences = -1;
    1215        private float _averageQuality = -1.0;
    1316        private long _numQualScores = -1;
    14 
     17        private long _numSequenceFiles = -1;
     18        private long _numQualityFiles = -1;
     19       
    1520        Integer numUniqueSequences      // Number of unique sequences / OTUs. Is only available after preprocessing
    1621
     
    5055                }
    5156                sequenceData cascade: "all-delete-orphan"
     57                sample fetch: 'join'
     58                assay fetch: 'join'
     59                run fetch: 'join'
    5260        }
    5361
     
    5967         */
    6068        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();
    6870        }
    6971
     
    7577         */
    7678        public int numSequenceFiles() {
     79                if( _numSequenceFiles > -1 )
     80                        return _numSequenceFiles;
     81
    7782                if( !sequenceData )
    7883                        return 0
     
    9499         */
    95100        public int numQualityFiles() {
     101                if( _numQualityFiles > -1 )
     102                        return _numQualityFiles;
     103               
    96104                if( !sequenceData )
    97105                        return 0
     
    183191                _numQualScores = -1;
    184192                _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                }
    185253        }
    186254       
  • trunk/grails-app/domain/nl/tno/massSequencing/Run.groovy

    r42 r52  
    2626                        name index:'runname_idx'
    2727                }
     28               
     29                assaySamples batchSize: 10
     30               
    2831        }
    2932        static constraints = {
  • trunk/grails-app/domain/nl/tno/massSequencing/Study.groovy

    r49 r52  
    3535                samples cascade: "all-delete-orphan"
    3636                auth cascade: "all-delete-orphan"
     37                auth lazy: false, batchSize: 10
    3738        }
    3839
  • trunk/grails-app/services/nl/tno/massSequencing/FastaService.groovy

    r49 r52  
    66import java.util.ArrayList;
    77import java.util.List;
    8 import java.util.zip.ZipEntry
    9 import java.util.zip.ZipOutputStream
    108import org.codehaus.groovy.grails.commons.ConfigurationHolder
     9import java.util.zip.*
    1110
    1211class FastaService {
     
    706705                zipFile.putNextEntry( new ZipEntry( name + ".xls" ) );
    707706                sampleExcelService.exportExcelSampleData( assaySamples, tags, zipFile );
     707                zipFile.flush();
    708708                zipFile.closeEntry();
    709709
  • trunk/grails-app/services/nl/tno/massSequencing/SampleExcelService.groovy

    r51 r52  
    303303                } catch( Exception e ) {
    304304                        log.error "Exception occurred while fetching sample data from gscf: " + e.getMessage();
     305                        e.printStackTrace()
    305306                        return false;
    306307                }
     
    367368                        }
    368369                       
     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                       
    369375                        data << row;
    370376                       
    371                 }
    372                
    373                 // Transpose data and create new headers
    374                 data = data.transpose();
    375                
    376                 // Add field names in front of the data
    377                 for( int i = 0; i < data.size(); i++ ) {
    378                         data[ i ] = [] + fields[ "descriptions" ][ "all" ][ i ] + data[ i ]
    379377                }
    380378               
     
    386384
    387385                // 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 );
    390388
    391389                // Auto resize columns (# columns = # samples + 1)
  • trunk/grails-app/services/nl/tno/massSequencing/files/ExcelService.groovy

    r50 r52  
    44import java.text.Format
    55import java.text.NumberFormat
    6 import org.apache.poi.hssf.usermodel.*
     6import org.apache.poi.xssf.usermodel.XSSFWorkbook;
     7import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    78import org.apache.poi.ss.usermodel.*
    89
  • trunk/grails-app/services/nl/tno/massSequencing/files/FileService.groovy

    r44 r52  
    1818import org.codehaus.groovy.grails.commons.ConfigurationHolder
    1919import java.io.File;
    20 import java.util.zip.*
     20import java.util.zip.GZIPInputStream
     21import java.util.zip.ZipEntry
     22import java.util.zip.ZipInputStream
    2123
    2224/**
  • trunk/grails-app/services/nl/tno/massSequencing/imports/FuzzySearchService.groovy

    r29 r52  
    1515         */
    1616        static def mostSimilarUnique( patterns, candidates, treshold ) {
     17                println "Patterns: " + patterns.findAll { it };
     18                println "Candidates: " + candidates;
     19               
    1720                def matches = []
    1821               
    1922                // Find the best matching candidate for each pattern
    20                 patterns.each { pattern ->
     23                patterns.findAll { it }.each { pattern ->
    2124                        def topScore = 0
    2225                        def bestFit = null
     
    2427                        candidates.each { candidate ->
    2528                                def score = stringSimilarity(pattern, candidate);
    26                                 if( score >= treshold )
     29                                if( !score.isNaN() && score >= treshold )
    2730                                        matches << [ 'pattern': pattern, 'candidate': candidate, 'score': score ];
    2831                        }
  • trunk/grails-app/services/nl/tno/massSequencing/integration/GscfService.groovy

    r50 r52  
    303303         * @param       restMethod Method to call on GSCF rest controller
    304304         * @param       restParams Parameters to provide to the GSCF rest method
     305         * @param       requestMethod   Request method to retrieve data
    305306         *
    306307         * @return      ArrayList
    307308         */
    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
    316315                restParams.each {parameter ->
    317316                        // If a list is given as value, the parameter should show up multiple times
    318317                        if( parameter.value instanceof Collection ) {
    319318                                parameter.value.each { value ->
    320                                         addr += "&${parameter.key}=" + value.toString().encodeAsURL()
     319                                        args += "&${parameter.key}=" + value.toString().encodeAsURL()
    321320                                }
    322321                        } else {
    323                                 addr += "&${parameter.key}=" + parameter.value.toString().encodeAsURL()
     322                                args += "&${parameter.key}=" + parameter.value.toString().encodeAsURL()
    324323                        }
    325324                }
    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               
    333364                } catch( Exception e ) {
    334365                        log.error("GSCF Call failed when calling service: ${addr}",e)
     
    336367                }
    337368               
     369                // Handle the response given by GSCF
     370                def gscfResponse = []
     371
    338372                switch( connection.responseCode ) {
    339373                        case 400:       // Bad request
     
    375409        }
    376410
    377 
    378411        /**
    379412         * Consumer ID for connection to of GSCF Rest Controller/API
  • trunk/grails-app/services/nl/tno/massSequencing/integration/SynchronizationService.groovy

    r50 r52  
    3131                        return true
    3232
    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                }
    3440        }
    3541       
     
    8894         */
    8995        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                }
    94102               
    95103                SynchronizationService.lastFullSynchronization = new Date();
     
    102110        public ArrayList<Study> synchronizeStudies() throws BadRequestException, NotAuthenticatedException, NotAuthorizedException, ResourceNotFoundException, Exception {
    103111                if( !performSynchronization() )
    104                         return Study.findAllWhereTrashcan(false)
     112                        return Study.findAllByTrashcan(false)
    105113
    106114                // When eager fetching is enabled, ask for all studies, otherwise only ask for studies marked dirty
     
    443451         */
    444452        public Auth synchronizeAuthorization(Study study) {
     453                if( !performSynchronization() )
     454                        return Auth.findByUserAndStudy( user, study )
     455               
    445456                // If the user is not set, we can't save anything to the database.
    446457                if( user == null ) {
  • trunk/grails-app/views/assay/index.gsp

    r49 r52  
    3333                                                                        <td><g:checkBox name="ids" value="${assay.id}" checked="${false}" onClick="updateCheckAll(this);" /></td>
    3434                                                               
    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>
    3636                                                                        <td><a href="${study.viewUrl()}">${study.name}</a></td>
    3737                                                                        <td>${assay.assaySamples?.size()}</td>
    3838                                                                        <td>
    3939                                                                                <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"/>
    4141                                                                                </g:if>
    4242                                                                                <g:else>
     
    4444                                                                                </g:else>
    4545                                                                        </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>
    4747                                                                        <td>
    4848                                                                                <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>
    5050                                                                                </g:if>
    5151                                                                                <g:else>
  • trunk/grails-app/views/assay/sequenceLengthHistogram.gsp

    r49 r52  
    33                <meta name="layout" content="main" />
    44                <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
    59        </head>
    610        <body>
    711                <h1>Sequence length histogram for assay ${assay.name}</h1>
    812                <p>
    9                         Total number of sequences: ${assay.numSequences()}
     13                        Total number of sequences: <g:formatNumber number="${assay.numSequences()}" format="###,###,##0" />
    1014                </p>
    1115                <div id="placeholder" style="width:600px;height:300px"></div>
     
    1317                <script type="text/javascript">
    1418                        $.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                    ]);
    2024                </script>
    2125        </body>
  • trunk/grails-app/views/assay/show.gsp

    r51 r52  
    5050        <label>Assay</label>: ${assay.name}<br />
    5151        <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 />
    5353        <label># files</label>: ${assay.numFiles()}<br />
    5454
    5555        <!-- Samples -->
    5656        <h2>Samples</h2>
     57
    5758        <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>
    6265        </g:if>
    6366        <g:else>
     
    7780                        </thead>                       
    7881                        <tbody>
    79                                 <% def assaySamples = assay.assaySamples.toList().sort { it.sample.name }; %>
     82                                <% def assaySamples = assay.assaySamples.toList() %>
    8083                                <g:each in="${assaySamples}" var="assaySample">
    8184                                        <tr>
    8285                                                <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>
    8487                                                <td>${assaySample.run?.name}</td>
    8588                                                <td>${assaySample.fwMidName}</td>
    8689                                                <td>
    8790                                                        <g:if test="${assaySample.numSequenceFiles() > 0}">
    88                                                                 ${assaySample.numSequences()}
     91                                                                <g:formatNumber number="${assaySample.numSequences()}" format="###,###,##0" />
    8992                                                        </g:if>
    9093                                                        <g:else>
     
    9497                                                <td>
    9598                                                        <g:if test="${assaySample.numQualityFiles() > 0}">
    96                                                                 ${assaySample.numQualScores()}
     99                                                                <g:formatNumber number="${assaySample.numQualScores()}" format="###,###,##0" />
    97100                                                        </g:if>
    98101                                                        <g:else>
     
    105108                                                        </g:if>
    106109                                                        <g:else>
    107                                                                 <a onClick="showEditSampleDialog(${assaySample.id}, 'assay', ${assay.id}); return false;" href="#"><img src="${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>
    108111                                                        </g:else>
    109112                                                </td>
    110113                                                <td class="button">
    111114                                                        <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>
    113116                                                        </g:if>
    114117                                                        <g:else>
    115118                                                                <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." />
    116119                                                        </g:else>
    117                                                 </td>                                           
     120                                                </td>
    118121                                        </tr>
    119122                                </g:each>
    120123                        </tbody>
    121124                </table>
     125               
    122126                <p class="options multiple">
    123127                        <g:if test="${editable}">
     
    181185                                <g:each in="${runs}" var="run">
    182186                                        <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>
    184188                                                <td><g:formatDate format="dd-MM-yyyy" date="${run.date}"/></td>
    185189                                                <td>${run.supplier}</td>
     
    197201                                                        </g:else>
    198202                                                </td>
    199                                                 <td class="button"><a href="#" onClick="showEditRunDialog( ${run.id} ); return false;"><img src="${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>
    200204                                                <td class="button">
    201205                                                        <g:if test="${run.samples(assay.id).size()}">
     
    203207                                                        </g:if>
    204208                                                        <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]}" ><img src="${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>
    206210                                                        </g:else>
    207211                                                </td>
  • trunk/grails-app/views/assaySample/sequenceLengthHistogram.gsp

    r49 r52  
    77                <h1>Sequence length histogram for sample ${assaySample.sample.name} (${assaySample.assay.study.name} / ${assaySample.assay.name})</h1>
    88                <p>
    9                         Total number of sequences: ${assaySample.numSequences()}
     9                        Total number of sequences: <g:formatNumber number="${assaySample.numSequences()}" format="###,###,##0" />
    1010                </p>
    1111                <div id="placeholder" style="width:600px;height:300px"></div>
  • trunk/grails-app/views/common/_topnav.gsp

    r15 r52  
    77                <li><g:link controller="run">Runs</g:link></li>
    88                <li><g:link controller="assay">Assays</g:link></li>
    9                 <li><g:link controller="study">Studies</g:link></li>
    109      </ul>
    1110    </li>
  • trunk/grails-app/views/layouts/main.gsp

    r49 r52  
    1818                <script type="text/javascript" src="${resource(dir: 'js', file: 'jquery.dataTables.min.js')}"></script>
    1919
     20                <!-- javascript charts using flot -->
    2021                <script type="text/javascript" src="${resource(dir: 'js', file: 'jquery.flot.min.js')}"></script>
    2122                <!--[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  
    4242                                                <tr>
    4343                                                        <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>
    4545                                                        <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>
    4848                                                        <td>
    4949                                                                <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>
    5151                                                                </g:if>
    5252                                                                <g:else>
     
    5656                                                        <td>
    5757                                                                <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>
    5959                                                                </g:if>
    6060                                                                <g:else>
  • trunk/grails-app/views/run/sequenceLengthHistogram.gsp

    r49 r52  
    77                <h1>Sequence length histogram for run ${run.name}</h1>
    88                <p>
    9                         Total number of sequences: ${run.numSequences()}
     9                        Total number of sequences: <g:formatNumber number="${run.numSequences()}" format="###,###,##0" />
    1010                </p>
    1111                <div id="placeholder" style="width:600px;height:300px"></div>
  • trunk/grails-app/views/run/show.gsp

    r51 r52  
    7878                </g:if>
    7979                <br />
    80                 <label># sequences</label>: ${run.numSequences()}<br />
     80                <label># sequences</label>: <g:formatNumber number="${run.numSequences()}" format="###,###,##0" /><br />
    8181                <label># files</label>: ${run.numFiles()}<br />
    8282        </div>
     
    8989        <% def assaySamples = run.assaySamples ? run.assaySamples.findAll { it.assay?.study.canRead( session.user ) }.toList().sort { it.sample.name } : []; %>
    9090        <g:if test="${assaySamples.size() == 0}">
    91                 No samples found in run.
     91                <p>No samples found in run.</p>
    9292        </g:if>
    9393        <g:else>
     
    112112                                        <tr>
    113113                                                <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>
    115115                                                <td>${assaySample.assay.study.name}</td>
    116116                                                <td>${assaySample.assay.name}</td>
     
    118118                                                <td>
    119119                                                        <g:if test="${assaySample.numSequenceFiles() > 0}">
    120                                                                 ${assaySample.numSequences()}
     120                                                                <g:formatNumber number="${assaySample.numSequences()}" format="###,###,##0" />
    121121                                                        </g:if>
    122122                                                        <g:else>
     
    126126                                                <td>
    127127                                                        <g:if test="${assaySample.numQualityFiles() > 0}">
    128                                                                 ${assaySample.numQualScores()}
     128                                                                <g:formatNumber number="${assaySample.numQualScores()}" format="###,###,##0" />
    129129                                                        </g:if>
    130130                                                        <g:else>
     
    137137                                                        </g:if>
    138138                                                        <g:else>
    139                                                                 <a onClick="showEditSampleDialog(${assaySample.id}, 'run', ${run.id});" href="#"><img src="${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>
    140140                                                        </g:else>
    141141                                                </td>
     
    145145                                                        </g:if>
    146146                                                        <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]}" ><img src="${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>
    148148                                                        </g:else>
    149149                                                </td>
    150150                                                <td class="button">
    151151                                                        <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>
    153153                                                        </g:if>
    154154                                                        <g:else>
     
    202202               
    203203                <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>
    205210                </p>
    206211               
     
    238243                                <g:each in="${assays}" var="assay">
    239244                                        <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>
    241246                                                <td>${assay.study?.name}</td>
    242247                                                <td>${assay.assaySamples?.size()}</td>
     
    248253                                                        <g:else>
    249254                                                                <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 />
    251256                                                                </g:each>
    252257                                                        </g:else>
     
    261266                                                                </g:if>
    262267                                                                <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>
    264269                                                                </g:else>
    265270                                                        </g:else>
  • trunk/web-app/js/forms.js

    r23 r52  
    3535        }
    3636       
     37        // Set form method to POST in order to be able to handle all items
     38        form.attr( 'method', 'POST' );
     39       
    3740        if( url != '' )
    3841                form.attr( 'action', url );
Note: See TracChangeset for help on using the changeset viewer.