Changeset 9


Ignore:
Timestamp:
Jan 28, 2011, 12:30:39 PM (9 years ago)
Author:
robert@…
Message:
 
Location:
trunk
Files:
2 added
3 deleted
25 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/conf/BaseFilters.groovy

    r6 r9  
    1515 */
    1616import grails.converters.*
     17import javax.servlet.http.HttpServletResponse
    1718import org.codehaus.groovy.grails.commons.ConfigurationHolder
    1819
     
    3637                                        return false
    3738                                }
     39
    3840                               
     41                                // We are handling the Rest controller as a special case. The rest calls are made
     42                                // outside of the users browser session, so it should always contain a session token.
     43                                // Moreover, it should never redirect the user, but instead send a 403 error
     44                                if( controllerName == 'rest' ) {
     45                                        if (!params.sessionToken && !session.sessionToken ){
     46                                                response.setStatus( HttpServletResponse.SC_BAD_REQUEST, "No sessiontoken given" );
     47                                                render "No sessiontoken given"
     48                                                return false
     49                                        }
     50                                       
     51                                        if( params.sessionToken )
     52                                                session.sessionToken = params.sessionToken
     53                                               
     54                                        try {
     55                                                def user = gscfService.getUser( session.sessionToken );
     56                                               
     57                                                if( user ) {
     58                                                        session.user = User.findByIdentifierAndUsername( user.id, user.username );
     59                                                        if( !session.user) {
     60                                                                session.user = new User( identifier: user.id, username: user.username ).save( flush: true );
     61                                                        }
     62                                                } else {
     63                                                        response.setStatus( HttpServletResponse.SC_UNAUTHORIZED, "No user logged in" );
     64                                                        render "No user logged in"
     65                                                        return false;
     66                                                }
     67                                        } catch( Exception e ) {
     68                                                log.error( "Unable to fetch user from GSCF", e );
     69                                                response.setStatus( HttpServletResponse.SC_BAD_REQUEST, "Unable to fetch user from GSCF" );
     70                                                render "Unable to fetch user from GSCF"
     71                                                return false;
     72                                        }
     73                                       
     74                                        return true;
     75                                }
     76                                                               
    3977                                // enable to inject a session from the outside...
    4078                                if (params.sessionToken){
  • trunk/grails-app/controllers/nl/tno/metagenomics/AssayController.groovy

    r7 r9  
    8383
    8484                def filename = assay.study.name + "_" + assay.name + "_tags.xls"
    85                 excelService.downloadSampleExcel( assay.assaySamples );
     85                def wb = sampleExcelService.downloadSampleExcel( assay.assaySamples );
    8686
    8787                // Make file downloadable
     
    196196                                println assaySampleParams
    197197                                if( assaySampleParams ) {
     198                                        assaySample.tagName = assaySampleParams.tagName
    198199                                        assaySample.oligoNumber = assaySampleParams.oligoNumber
    199200                                        assaySample.tagSequence = assaySampleParams.tagSequence
  • trunk/grails-app/controllers/nl/tno/metagenomics/RunController.groovy

    r7 r9  
    3131
    3232                // Send the assay information to the view
    33                 [run: run, otherAssays: otherAssays, editable: true]
     33                [run: run, allRuns: Run.list(), otherAssays: otherAssays, editable: true]
    3434        }
    3535
     
    4545                        return
    4646                }
    47 
    48                 Assay assay = getAssay( params.id )
    49 
    50                 if( !assay ) {
    51                         render flash.error;
    52                         return
     47               
     48                Assay assay = null
     49                if( params.assayId ) {
     50                        assay = getAssay( params.assayId )
     51       
     52                        if( !assay ) {
     53                                render flash.error;
     54                                return
     55                        }
    5356                }
    5457
     
    8184
    8285        def update = {
    83                 if( !params.assayId ) {
    84                         flash.error = "No assay 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 
    9586                Run run = getRun( params.id );
    9687
     
    10293                // Set properties to the run
    10394                params.parameterFile = params.editParameterFile
     95               
     96                println "Edit run: " + params
    10497                run.setPropertiesFromForm( params );
    10598
     
    109102                        flash.error = "Run could not be saved: " + run.getErrors();
    110103                }
    111 
    112                 redirect( controller: 'assay', action: 'show', id: params.assayId)
     104               
     105                Assay assay = getAssay(params.assayId);
     106                flash.error = "";
     107               
     108                if( assay ) {
     109                        redirect( controller: 'assay', action: 'show', id: assay.id)
     110                } else {
     111                        redirect( controller: 'run', action: 'show', id: run.id )
     112                }
    113113        }
    114114
     
    286286                                def assaySampleParams = sampleParams.get( assaySample.id as String );
    287287                                if( assaySampleParams ) {
     288                                        assaySample.tagName = assaySampleParams.tagName
    288289                                        assaySample.oligoNumber = assaySampleParams.oligoNumber
    289290                                        assaySample.tagSequence = assaySampleParams.tagSequence
  • trunk/grails-app/controllers/nl/tno/metagenomics/integration/RestController.groovy

    r4 r9  
    3838        /****************************************************************/
    3939        private getMeasurementTypes() {
    40                 return [ "# sequences", "average quality" ]
     40                return [ "# sequences" ]
    4141        }
    4242
     
    274274        def notifyStudyChange = {
    275275                def studyToken = params.studyToken
    276                
     276
    277277                if( !studyToken ) {
    278278                        response.sendError(400, "No studyToken given" )
    279279                        return
    280280                }
    281                
     281
    282282                // Search for the changed study
    283283                def study = Study.findByStudyToken( studyToken );
    284                
     284
    285285                // If the study is not found, it is added in GSCF. Add a dummy (dirty) study, in order to
    286286                // update it immediately when asked for
     
    288288                        log.info( "METAGENOMICS: GSCF notification for new study " + studyToken );
    289289                        study = new Study(
    290                                 name: "",
    291                                 studyToken: studyToken,
    292                                 isDirty: true
    293                         )
     290                                        name: "",
     291                                        studyToken: studyToken,
     292                                        isDirty: true
     293                                        )
    294294                } else {
    295295                        log.info( "METAGENOMICS: GSCF notification for existing study " + studyToken );
     
    297297                }
    298298                study.save(flush:true);
    299                
     299
    300300                def jsonData = [ 'studyToken': studyToken, message: "Notify succesful" ];
    301                
     301
    302302                render jsonData as JSON
    303303        }
    304        
     304
    305305        /**
    306306         * Return URL to view an assay.
     
    322322                // If the assay is not found, try synchronizing
    323323                synchronizationService.sessionToken = session.sessionToken
    324                
     324
    325325                if( !assay ) {
    326326                        synchronizationService.synchronizeStudies()
    327327                        assay = Assay.findByAssayToken( assayToken );
    328                        
     328
    329329                        if( !assay ) {
    330330                                response.sendError(404, "Not Found" )
     
    338338                                return
    339339                        }
    340                        
     340
    341341                        def url = [ 'url' : ConfigurationHolder.config.grails.serverURL + '/assay/show/' + assay.id.toString() ]
    342342
     
    344344                }
    345345        }
    346        
     346
    347347        /***************************************************/
    348348        /* REST resources related to the querying in GSCF  */
    349349        /***************************************************/
     350
     351        /**
     352         * Retrieves a list of fields that could be queried when searching for a specific entity.
     353         *
     354         * The module is allowed to return different fields when the user searches for different entities
     355         *
     356         * Example call:                [moduleurl]/rest/getQueryableFields?entity=Study&entity=Sample
     357         * Example response:    { "Study": [ "# sequences" ], "Sample": [ "# sequences", "# bacteria" ] }
     358         *
     359         * @param       params.entity   Entity that is searched for. Might be more than one. If no entity is given,
     360         *                                                      a list of searchable fields for all entities is given
     361         * @return      JSON                    List with the names of the fields
     362         */
     363        def getQueryableFields = {
     364                // We don't really care about the entity. The only thing is that this module
     365                // is only aware of studies, assays and samples, but doesn't know anything about
     366                // subjects or events. If the user searches for those entities (maybe in the future)
     367                // this module doesn't have anything to search for.
     368
     369                def entities = params.entity ?: []
     370               
     371                if( entities instanceof String )
     372                        entities = [entities]
     373                else
     374                        entities = entities.toList()
     375
     376                if( !entities )
     377                        entities = [ "Study", "Assay", "Sample" ]
     378                       
     379
     380                def fields = [:];
     381                entities.unique().each { entity ->
     382                        switch( entity ) {
     383                                case "Study":
     384                                case "Assay":
     385                                case "Sample":
     386                                        fields[ entity ] = [ "# sequences" ]
     387                                        break;
     388                                default:
     389                                        // Do nothing
     390                                        break;
     391                        }
     392                }
     393               
     394                render fields as JSON
     395        }
     396
     397        /**
     398         * Returns data for the given field and entities.
     399         *
     400         * Example call:                [moduleurl]/rest/getQueryableFieldData?entity=Study&tokens=abc1&tokens=abc2&fields=# sequences&fields=# bacteria
     401         * Example response:    { "abc1": { "# sequences": 141, "# bacteria": 0 }, "abc2": { "#sequences": 412 } }
     402         *
     403         * @param       params.entity   Entity that is searched for
     404         * @param       params.tokens   One or more tokens of the entities that the data should be returned for
     405         * @param       params.fields   One or more field names of the data to be returned.
     406         * @return      JSON                    Map with keys being the entity tokens and the values being maps with entries [field] = [value]. Not all
     407         *                                                      fields and tokens that are asked for have to be returned by the module (e.g. when a specific entity can
     408         *                                                      not be found, or a value is not present for an entity)
     409         */
     410        def getQueryableFieldData = {
     411                def entity = params.entity;
     412                def tokens = params.tokens ?: []
     413                def fields = params.fields ?: []
     414
     415                if( tokens instanceof String )
     416                        tokens = [tokens]
     417                else
     418                        tokens = tokens.toList();
     419
     420                if( fields instanceof String )
     421                        fields = [fields]
     422                else
     423                        fields = fields.toList();
     424
     425                // Only search for unique tokens and fields
     426                tokens = tokens.unique()
     427                fields = fields.unique()
     428
     429                // Without tokens or fields we can only return an empty list
     430                def map = [:]
     431                if( tokens.size() == 0 || fields.size() == 0 ) {
     432                        log.trace "Return empty string for getQueryableFieldData: #tokens: " + tokens.size() + " #fields: " + fields.size()
     433                        render map as JSON
     434                        return;
     435                }
     436
     437                tokens.each { token ->
     438                        def object = getQueryableObject( entity, token );
     439                        if( object ) {
     440                                map[ token ] = [:]
     441                                fields.each { field ->
     442                                        def v = getQueryableFieldValue( entity, object, field );
     443                                        if( v != null )
     444                                                map[ token ][ field ] = v
     445                                }
     446                        } else {
     447                                log.trace "No " + entity + " with token " + token + " found."
     448                        }
     449                }
     450               
     451                render map as JSON
     452        }
     453
     454        /**
     455         * Searches for a specific entity
     456         *
     457         * @param entity                Entity to search in
     458         * @param token         Token of the entity to search in
     459         * @return
     460         */
     461        protected def getQueryableObject( def entity, def token ) {
     462                switch( entity ) {
     463                        case "Study":
     464                                return Study.findByStudyToken( token );
     465                        case "Assay":
     466                                return Assay.findByAssayToken( token );
     467                        case "Sample":
     468                                return Sample.findBySampleToken( token );
     469                        default:
     470                        // Other entities can't be handled
     471                                return null;
     472                }
     473        }
     474
     475        /**
     476         * Searches for the value of a specific field in a specific entity
     477         *
     478         * @param entity        Entity of the given object
     479         * @param object        Object to search in
     480         * @param field         Field value to retrieve         
     481         * @return
     482         */
     483        protected def getQueryableFieldValue( def entity, def object, def field ) {
     484                if( !entity || !object || !field )
     485                        return null;
     486                       
     487                switch( entity ) {
     488                        case "Study":
     489                                switch( field ) {
     490                                        // Returns the total number of sequences in this study
     491                                        case "# sequences":
     492                                                def assaySamples = object.assays*.assaySamples;
     493                                                if( assaySamples ) {
     494                                                        assaySamples = assaySamples.flatten()
     495                                                        return assaySamples.collect { it.numSequences() }.sum();
     496                                                } else {
     497                                                        return null;
     498                                                }
     499                                        // Other fields are not handled
     500                                        default:
     501                                                return null;
     502                                }
     503                        case "Assay":
     504                                switch( field ) {
     505                                        // Returns the total number of sequences in this study
     506                                        case "# sequences":
     507                                                def assaySamples = assay.assaySamples;
     508                                                if( assaySamples ) {
     509                                                        return assaySamples.collect { it.numSequences() }.sum();
     510                                                } else {
     511                                                        return null;
     512                                                }
     513                                        // Other fields are not handled
     514                                        default:
     515                                                return null;
     516                                }
     517                        case "Sample":
     518                                switch( field ) {
     519                                        // Returns the total number of sequences in this study
     520                                        case "# sequences":
     521                                                def assaySamples = sample.assaySamples;
     522                                                if( assaySamples ) {
     523                                                        return assaySamples.collect { it.numSequences() }.sum();
     524                                                } else {
     525                                                        return null;
     526                                                }
     527                                        // Other fields are not handled
     528                                        default:
     529                                                return null;
     530                                }
     531                        default:
     532                        // Other entities can't be handled
     533                                return null;
     534                }
     535        }
    350536
    351537        /**
  • trunk/grails-app/domain/nl/tno/metagenomics/AssaySample.groovy

    r7 r9  
    1616        String oligoNumber              // Oligonumber used to identify the sample
    1717        String tagSequence              // Tag originally used to identify the sample
     18        String tagName                  // Tag name
    1819
    1920        static belongsTo  = [ assay: Assay, sample: Sample, run: Run ]
     
    2324                numUniqueSequences(nullable: true)
    2425                oligoNumber(nullable: true)
     26               
     27                /*
     28                , validator: { value, obj, errors ->
     29                        // When one oligoNumber is used in different assaysamples,
     30                        // they must also have the same tagSequences and tagNames
     31                       
     32                        // Check whether this oligoNumber exists in the database
     33                        def otherAssaySamples = AssaySample.findAllByOligoNumber( value )
     34                        if( !otherAssaySamples || otherAssaySamples.size() == 0 ) {
     35                                return true;
     36                        }
     37                       
     38                        // Loop through the other assaysamples with this oligonumber
     39                        otherAssaySamples.each { otherAS ->
     40                                // Only check other objects, don't compare with itself (because that
     41                                // way it wouldn't be possible anymore to edit an object)
     42                                if( otherAS.id != obj.id ) {
     43                                        if( otherAS.tagSequence != obj.tagSequence || otherAS.tagName != obj.tagName ) {
     44                                                return false;
     45                                        }
     46                                }
     47                        }
     48                       
     49                        return true
     50                }
     51                 */
    2552                tagSequence(nullable: true)
     53                tagName(nullable:true)
    2654                run(nullable: true);
    2755        }
     
    150178         */
    151179        public boolean containsData() {
    152                 return tagSequence || oligoNumber || numFiles() > 0;
     180                return tagSequence || tagName || oligoNumber || numFiles() > 0;
    153181        }
    154182       
     
    164192                otherAssaySample.tagSequence = tagSequence;
    165193                otherAssaySample.oligoNumber = oligoNumber;
     194                otherAssaySample.tagName         = tagName;
    166195                otherAssaySample.run         = run;
    167196               
  • trunk/grails-app/domain/nl/tno/metagenomics/Run.groovy

    r7 r9  
    5656
    5757                // Enter filename if needed
    58                 if( params.parameterFile ) {
     58                if( params.parameterFile && params.parameterFile != this.parameterFile ) {
    5959                        this.parameterFile = fileService.handleUploadedFile(
    6060                                        fileService.get( params.parameterFile ),
  • trunk/grails-app/domain/nl/tno/metagenomics/Sample.groovy

    r7 r9  
    88class Sample {
    99        String  sampleToken             // Unique within a study
    10         String  name                   
     10        String  name
     11        String  subject
     12        String  event
    1113       
    1214        static belongsTo    = [ study: Study ]
     
    1820                assaySamples cascade: "all-delete-orphan"
    1921        }
     22        static constraints = {
     23                subject(nullable: true)
     24                event(nullable: true)
     25        }
     26       
     27        public static cloneSample( Sample otherSample, String newSampleToken, Study otherStudy ) {
     28                return new Sample(
     29                        sampleToken: newSampleToken,
     30                        name: otherSample.name,
     31                        subject: otherSample.subject,
     32                        event: otherSample.event,
     33                        study: otherStudy
     34                );
     35        }
    2036}
  • trunk/grails-app/services/nl/tno/metagenomics/SampleExcelService.groovy

    r7 r9  
    1010        def sampleNameName = "Sample name"
    1111        def runName = "Run"
     12        def tagNameName = "Tag name"
    1213        def tagSequenceName = "Tag sequence"
    1314        def oligoNumberName = "Oligo number"
    14         def possibleFields = [sampleNameName, runName, tagSequenceName, oligoNumberName]
     15        def possibleFields = [sampleNameName, runName, tagNameName, tagSequenceName, oligoNumberName]
    1516       
    1617    def downloadSampleExcel( def assaySamples, boolean includeRun = true ) {
     
    3940                                rowData << assaySample.run?.name
    4041                       
     42                        rowData << assaySample.tagName
    4143                        rowData << assaySample.tagSequence
    4244                        rowData << assaySample.oligoNumber
     
    156158                                if( it.value > -1 ) {
    157159                                        switch( it.key ) {
     160                                                case tagNameName:               assaySample.tagName = rowData[ it.value ]; break
    158161                                                case tagSequenceName:   assaySample.tagSequence = rowData[ it.value ]; break
    159162                                                case oligoNumberName:   assaySample.oligoNumber = rowData[ it.value ]; break
  • trunk/grails-app/services/nl/tno/metagenomics/integration/GscfService.groovy

    r6 r9  
    6161   }
    6262
     63   /**
     64   * Retrieves the currently logged in user from GSCF
     65   *
     66   * @param sessionToken String
     67   *
     68   * @return Map
     69   */
     70  public Map getUser(String sessionToken) {
     71          def user = [:]
     72          this.callGSCF(sessionToken, "getUser").each {
     73                  user[ it.key ] = it.value;
     74          }
     75          return user
     76  }
     77   
    6378        /**
    6479         * Retrieve a list of Studies from the GSCF
  • trunk/grails-app/services/nl/tno/metagenomics/integration/SynchronizationService.groovy

    r7 r9  
    7979         */
    8080        public void fullSynchronization() {
    81                 if( !timeForFullSynchronization() )
    82                         return
    83 
    8481                def previousEager = this.eager
    8582                this.eager = true
     
    630627
    631628                                        // Update the sample object if necessary
    632                                         if( sampleFound.name != gscfSample.name ) {
    633                                                 sampleFound.name = gscfSample.name
    634                                                 sampleFound.save();
    635                                         }
     629                                        sampleFound.name = gscfSample.name
     630                                        sampleFound.subject = gscfSample.subject
     631                                        sampleFound.event = gscfSample.event + ( gscfSample.startTime ? " (" + gscfSample.startTime + ")" : "" )
     632                                        sampleFound.save();
    636633                                } else {
    637634                                        log.trace( "AssaySample not found in assay" )
     
    644641
    645642                                                // Update the sample object if necessary
    646                                                 if( sampleFound.name != gscfSample.name ) {
    647                                                         sampleFound.name = gscfSample.name
    648                                                         sampleFound.save();
    649                                                 }
     643                                                sampleFound.name = gscfSample.name
     644                                                sampleFound.subject = gscfSample.subject
     645                                                sampleFound.event = gscfSample.event + ( gscfSample.startTime ? " (" + gscfSample.startTime + ")" : "" )
     646                                                sampleFound.save();
    650647                                        } else {
    651648                                                log.trace( "Sample " + gscfSample.sampleToken + " not found in database. Creating a new object." )
     
    653650                                                // If it doesn't exist, create a new object
    654651                                                sampleFound = new Sample( sampleToken: gscfSample.sampleToken, name: gscfSample.name, study: assay.study );
     652                                                sampleFound.subject = gscfSample.subject
     653                                                sampleFound.event = gscfSample.event + ( gscfSample.startTime ? " (" + gscfSample.startTime + ")" : "" )
    655654                                                assay.study.addToSamples( sampleFound );
    656655                                                sampleFound.save();
  • trunk/grails-app/services/nl/tno/metagenomics/integration/TrashService.groovy

    r7 r9  
    1919               
    2020                def l = []
    21                 l += study.auth
    22                
    23                 l.each { auth ->
    24                         auth.user.removeFromAuth( auth );
    25                         study.removeFromAuth( auth );
     21                if( study.auth ) {
     22                        l += study.auth
     23                       
     24                        l.each { auth ->
     25                                auth.user?.removeFromAuth( auth );
     26                                study.removeFromAuth( auth );
     27                        }
    2628                }
    2729               
     
    5052               
    5153                l = []
    52                 l += assay.assaySamples
    53                
    54                 l.each {
    55                         it.sample.removeFromAssaySamples( it );
    56                         assay.removeFromAssaySamples( it );
     54                if( assay.assaySamples ) {
     55                        l += assay.assaySamples
     56                       
     57                        l.each {
     58                                it.sample.removeFromAssaySamples( it );
     59                                assay.removeFromAssaySamples( it );
     60                        }
    5761                }
    5862
     
    6165                        study.removeFromAssays( assay );
    6266                }
    63                
    64                 /*
    65                 def assaySamples = assay.assaySamples.toList();
    66                 assaySamples.each {
    67                         it.assay = null
    68 
    69                         assay.removeFromAssaySamples( it );
    70                         it.sample.removeFromAssaySamples( it );
    71                         it.sample = null;
    72                         it.delete( flush: true );
    73                 }
    74 
    75                 assay.study.removeFromAssays( assay );
    76                 assay.study.save();
    77                 //assay.study = null
    78                 //assay.delete(flush:true);
    79                  */
    8067        }
    8168
     
    8976                // Remove associations
    9077                def l = []
    91                 l += sample.assaySamples
    92                
    93                 l.each {
    94                         it.assay.removeFromAssaySamples( it );
    95                         sample.removeFromAssaySamples( it );
     78                if( sample.assaySamples ) {
     79                        l += sample.assaySamples
     80                       
     81                        l.each {
     82                                it.assay.removeFromAssaySamples( it );
     83                                sample.removeFromAssaySamples( it );
     84                        }
    9685                }
    9786               
     
    122111           
    123112           def l = []
    124            l += assaySample.sequenceData
    125            
    126            l.each {
    127                    if( it ) {
    128                                 assaySample.removeFromSequenceData( it );
     113           if( assaySample.sequenceData ) {
     114                   l += assaySample.sequenceData
     115                   
     116                   l.each {
     117                           if( it ) {
     118                                        assaySample.removeFromSequenceData( it );
     119                           }
    129120                   }
    130121           }
     
    181172                                // Create dummy sample
    182173                                String newSampleToken = 'TrashSample ' + new Date().format( 'yyyyMMddHHmmssSSS') + ( Math.random() * 10000 );
    183                                 Sample dummySample = new Sample( sampleToken: newSampleToken, name: sample.name, study: trashcan );
     174                                Sample dummySample = Sample.cloneSample( sample, newSampleToken, trashcan );
    184175                                trashcan.addToSamples( dummySample );
    185176                                dummySample.save()
     
    218209                        // Create dummy sample
    219210                        String newSampleToken = 'TrashSample ' + new Date().format( 'yyyyMMddHHmmssSSS') + ( Math.random() * 10000 );
    220                         Sample dummySample = new Sample( sampleToken: newSampleToken, name: sample.name, study: trashcan );
     211                        Sample dummySample = Sample.cloneSample( sample, newSampleToken, trashcan );
    221212                        trashcan.addToSamples( dummySample );
    222213                        dummySample.save()
     
    264255                   // Create dummy sample
    265256                   String newSampleToken = 'TrashSample ' + new Date().format( 'yyyyMMddHHmmssSSS') + ( Math.random() * 10000 );
    266                    Sample dummySample = new Sample( sampleToken: newSampleToken, name: assaySample.sample.name, study: trashcan );
     257                   Sample dummySample = Sample.cloneSample( assaySample.sample, newSampleToken, trashcan );
    267258                   trashcan.addToSamples( dummySample );
    268259                   dummySample.save()
     
    336327                                        for( def j = numSamples - 1; j >= 0; j-- ) {
    337328                                                def s = sampleList[ j ];
    338                                                 if( !s.tagSequence && !s.oligoNumber && s.numSequences() == 0 ) {
     329                                                if( !s.containsData() ) {
    339330                                                        assayList[ i ].removeFromAssaySamples( s );
    340331                                                        s.sample?.delete();
  • trunk/grails-app/taglib/nl/tno/metagenomics/UploadTagLib.groovy

    r4 r9  
    2626                out << '    fileUploadField( "' + attrs.name + '", ' + ( multiple ? 'true' : 'false' ) + ( attrs.onUpload ? ', function(params) { ' + attrs.onUpload + '(params); }' : '' ) + ( attrs.onDelete ? ', function(params) { ' + attrs.onDelete + '(params); }' : '' ) + ');';
    2727                out << '    if( filename != "" ) {';
    28                 out << '      $("#' + attrs.name + 'Delete").show();';
     28                out << '      $("#' + attrs.name + 'DeleteExisting").show();';
    2929                out << '      $("#' + attrs.name + 'Example").html("Current file: " + createFileHTML( filename ) )';
    3030                out << '    }';
  • trunk/grails-app/views/assay/_enterTagsDialog.gsp

    r7 r9  
    1616                                                        <th>Sample</th>
    1717                                                        <th>Run</th>
     18                                                        <th>Tag name</th>
    1819                                                        <th>Tag sequence</th>
    1920                                                        <th>Oligo number</th>
     
    2425                                                        <td>${assaySample.sample?.name}</td>
    2526                                                        <td><g:select name="assaySample.${assaySample.id}.run" from="${assaySample.assay.runs}" value="${assaySample.run?.id}" optionKey="id" optionValue="name" /></td>
     27                                                        <td><g:textField name="assaySample.${assaySample.id}.tagName" value="${assaySample.tagName}" /></td>
    2628                                                        <td><g:textField name="assaySample.${assaySample.id}.tagSequence" value="${assaySample.tagSequence}" /></td>
    2729                                                        <td><g:textField name="assaySample.${assaySample.id}.oligoNumber" value="${assaySample.oligoNumber}" /></td>
  • trunk/grails-app/views/assay/show.gsp

    r7 r9  
    88               
    99                <g:javascript src="jquery.ui.tabbeddialog.js" />
    10                 <g:javascript src="assay.show.addFilesDialog.js" />
    1110                <g:javascript src="assay.show.enterTagsDialog.js" />
    1211                <g:javascript src="assay.show.runDialogs.js" />
     12                <g:javascript src="assay.show.showRunDialog.js" />
     13
    1314                <g:javascript src="showSampleDialog.js" />
    14                 <g:javascript src="assay.show.showRunDialog.js" />
     15                <g:javascript src="addFilesDialog.js" />
    1516
    1617                <g:javascript src="fileuploader.new.js" />
     
    6566                                        <th nowrap>name</th>
    6667                                        <th nowrap>run</th>
    67                                         <th nowrap>tag sequence</th>
     68                                        <th nowrap>subject</th>
     69                                        <th nowrap>event</th>
    6870                                        <th nowrap># sequences</th>
    69                                         <th nowrap># unique sequences</th>
    7071                                </tr>
    7172                        </thead>                       
     
    7677                                                <td><a href="#" onClick="showSample(${assaySample.id}, 'assay'); return false;">${assaySample.sample.name}</a></td>
    7778                                                <td>${assaySample.run?.name}</td>
    78                                                 <td>${assaySample.tagSequence}</td>
     79                                                <td>${assaySample.sample.subject}</td>
     80                                                <td>${assaySample.sample.event}</td>
    7981                                                <td>${assaySample.numSequences()}</td>
    80                                                 <td>
    81                                                         <g:if test="${assaySample.numUniqueSequences > 0}">
    82                                                                 ${assaySample.numUniqueSequences}
    83                                                         </g:if>
    84                                                         <g:else>
    85                                                                 -
    86                                                         </g:else>
    87                                                 </td>
    8882                                        </tr>
    8983                                </g:each>
     
    138132                                                        </g:else>
    139133                                                </td>
    140                                                 <td class="button"><a href="#" onClick="showEditRunDialog( ${run.id}, '${run.name?.encodeAsJavaScript()}', '${run.date ? run.date.format( 'yyyy-mm-dd' ).encodeAsJavaScript() : ''}', '${run.machine?.encodeAsJavaScript()}', '${run.supplier?.encodeAsJavaScript()}', '${run.parameterFile?.encodeAsJavaScript()}' ); return false;"><img src="${fam.icon(name: 'application_edit')}" /></a></td>
     134                                                <td class="button"><a href="#" onClick="showEditRunDialog( ${run.id} ); return false;"><img src="${fam.icon(name: 'application_edit')}" /></a></td>
    141135                                                <td class="button">
    142136                                                        <g:if test="${run.samples(assay.id).size()}">
  • trunk/grails-app/views/assaySample/show.gsp

    r7 r9  
    55        <li><label>Assay</label><span class="value">${assaySample.assay?.name}</span></li>
    66        <li><label>Sample</label><span class="value">${assaySample.sample?.name}</span></li>
     7        <li><label>Subject</label><span class="value">${assaySample.sample?.subject}</span></li>
     8        <li><label>Event</label><span class="value">${assaySample.sample?.event}</span></li>
    79        <li><label>Run</label><span class="value">${assaySample.run?.name}</span></li>
    810</ul>   
     
    1113
    1214<ul>
     15        <li><label>Tag name</label><span class="value">${assaySample.tagName}</span></li>
    1316        <li><label>Tag sequence</label><span class="value">${assaySample.tagSequence}</span></li>
    1417        <li><label>Oligo number</label><span class="value">${assaySample.oligoNumber}</span></li>
    1518        <li><label># sequences</label><span class="value">${assaySample.numSequences() ?: '-'}</span></li>
    16         <li><label>Average quality</label><span class="value">${assaySample.averageQuality() ?: '-'}</span></li>
    1719        <li><label># unique sequences</label><span class="value">${assaySample.numUniqueSequences ?: '-'}</span></li>
    1820</ul>
  • trunk/grails-app/views/common/_topnav.gsp

    r7 r9  
    33     <li><g:link controller="study">Home</g:link></li>
    44        <li>
    5       <a href="#">View</a>
     5      <a href="#" onClick="return false;">View</a>
    66      <ul class="subnav">
    77                <li><g:link controller="run">Runs</g:link></li>
     
    1010    </li>
    1111        <li>
    12       <a href="${org.codehaus.groovy.grails.commons.ConfigurationHolder.config.gscf.baseURL}">GSCF</a>
     12      <a href="#" onClick="return false;">GSCF</a>
     13      <ul class="subnav">
     14                <li><g:link url="${org.codehaus.groovy.grails.commons.ConfigurationHolder.config.gscf.baseURL}">Go to GSCF</g:link></li>
     15                <li><g:link controller="synchronize" action="full">Synchronize</g:link></li>
     16      </ul>
    1317    </li>
    1418        <g:if env="development">
  • trunk/grails-app/views/run/_enterTagsDialog.gsp

    r7 r9  
    1515                                                <tr>
    1616                                                        <th>Sample</th>
     17                                                        <th>Tag name</th>
    1718                                                        <th>Tag sequence</th>
    1819                                                        <th>Oligo number</th>
     
    2223                                                <tr>
    2324                                                        <td>${assaySample.sample?.name}</td>
     25                                                        <td><g:textField name="assaySample.${assaySample.id}.tagName" value="${assaySample.tagName}" /></td>
    2426                                                        <td><g:textField name="assaySample.${assaySample.id}.tagSequence" value="${assaySample.tagSequence}" /></td>
    2527                                                        <td><g:textField name="assaySample.${assaySample.id}.oligoNumber" value="${assaySample.oligoNumber}" /></td>
  • trunk/grails-app/views/run/editForm.gsp

    r4 r9  
    11<h2>Edit run</h2>
    22<p>
    3         Please enter data about the run below. Only the date is required.
     3        Please enter data about the run below. Only the name is required.
    44</p>
    55<% /* Test whether this run is used in other assays */ %>
    6 <g:if test="${run.assays.size() > 1}">
     6<g:if test="${assay && run.assays.size() > 1}">
    77        <p>
    88                <strong>Caution</strong>: other assays are also associated with this run. Your changes will
     
    1111</g:if>
    1212       
    13 <g:form name="editRun" controller="run" action="update" id="${run.id}" params="[assayId:assay.id]">
     13<g:form name="editRun" controller="run" action="update" id="${run.id}" params="[assayId:assay?.id]">
    1414        <g:hiddenField name="run_id" value="${run.id}" id="edit_run_id" /><br />
    1515        <label for="name">Name</label><g:textField name="run.name" value="${run.name}" id="edit_run_name" /><br />
  • trunk/grails-app/views/run/show.gsp

    r7 r9  
    88               
    99                <g:javascript src="jquery.ui.tabbeddialog.js" />
    10                 <g:javascript src="assay.show.addFilesDialog.js" />
     10                <g:javascript src="addFilesDialog.js" />
    1111
    1212                <g:javascript src="run.show.enterTagsDialog.js" />
    1313                <g:javascript src="run.show.assayDialog.js" />
     14                <g:javascript src="run.show.runDialog.js" />
    1415                <g:javascript src="showSampleDialog.js" />
    1516
     
    2324                        var numOtherAssays = ${otherAssays.size()};
    2425
     26                        // Create a variable with assay names to check for existing names
     27                        var runNames = [];
     28                        <g:each in="${allRuns}" var="currentrun">
     29                                runNames[ runNames.length ] = {id: ${currentrun.id}, name: '${currentrun.name}', alreadyAdded: false };
     30                        </g:each>
     31                       
    2532                        function initializeUploadedFiles( selector ) {
    2633                                if( selector == undefined )
     
    4148        </h1>
    4249       
    43         <label>Run</label>: ${run.name}<br />
    44         <label># samples</label>: ${run.assaySamples?.size()}
    45         <% def numHidden = run.assaySamples?.findAll { !it.assay?.study.canRead( session.user ) }.size() ; %>
    46         <g:if test="${numHidden}">
    47                 (${numHidden}
    48                 <a href="#" onClick="alert( '${numHidden} samples from this run are hidden because you don\'t have the right permissions to view them.' ); return false;">
    49                 hidden</a>)
    50         </g:if>
    51         <br />
    52         <label># sequences</label>: ${run.numSequences()}<br />
    53         <label># files</label>: ${run.numFiles()}<br />
    54 
     50        <div id="editRunDialog" class="dialog"></div>
     51        <div class="blok_data">
     52                <label>Run</label>: ${run.name}<br />
     53                <label>Date</label>: <g:formatDate format="dd-MM-yyyy" date="${run.date}"/><br />
     54                <label>Supplier</label>: ${run.supplier}<br />
     55                <label>Machine</label>: ${run.machine}<br />
     56                <label>Parameters</label>: <g:uploadedFile value="${run.parameterFile}" /><br />
     57                <a href="#" onClick="showEditRunDialog( ${run.id} ); return false;">Edit run</a>
     58        </div>
     59        <div class="blok_data">
     60                <label># assays</label>: ${run.assays?.size()}
     61                <% def numHidden = run.assays?.findAll { !it.study.canRead( session.user ) }.size() ; %>
     62                <g:if test="${numHidden}">
     63                        (${numHidden}
     64                        <a href="#" onClick="alert( '${numHidden} assay(s) from this run are hidden because you don\'t have the right permissions to view them.' ); return false;">
     65                        hidden</a>)
     66                </g:if>
     67                <br />
     68       
     69                <label># samples</label>: ${run.assaySamples?.size()}
     70                <% numHidden = run.assaySamples?.findAll { !it.assay?.study.canRead( session.user ) }.size() ; %>
     71                <g:if test="${numHidden}">
     72                        (${numHidden}
     73                        <a href="#" onClick="alert( '${numHidden} sample(s) from this run are hidden because you don\'t have the right permissions to view them.' ); return false;">
     74                        hidden</a>)
     75                </g:if>
     76                <br />
     77                <label># sequences</label>: ${run.numSequences()}<br />
     78                <label># files</label>: ${run.numFiles()}<br />
     79        </div>
     80       
    5581        <!-- Samples -->
    5682        <h2>Samples</h2>
     
    6490                                        <th nowrap>name</th>
    6591                                        <th nowrap>assay</th>
    66                                         <th nowrap>tag sequence</th>
     92                                        <th nowrap>subject</th>
     93                                        <th nowrap>event</th>
    6794                                        <th nowrap># sequences</th>
    68                                         <th nowrap># unique sequences</th>
    6995                                </tr>
    7096                        </thead>                       
     
    75101                                                <td><a href="#" onClick="showSample(${assaySample.id}, 'run'); return false;">${assaySample.sample.name}</a></td>
    76102                                                <td>${assaySample.assay.study.name} - ${assaySample.assay.name}</td>
    77                                                 <td>${assaySample.tagSequence}</td>
     103                                                <td>${assaySample.sample.subject}</td>
     104                                                <td>${assaySample.sample.event}</td>
    78105                                                <td>${assaySample.numSequences()}</td>
    79                                                 <td>
    80                                                         <g:if test="${assaySample.numUniqueSequences > 0}">
    81                                                                 ${assaySample.numUniqueSequences}
    82                                                         </g:if>
    83                                                         <g:else>
    84                                                                 -
    85                                                         </g:else>
    86                                                 </td>
    87106                                        </tr>
    88107                                </g:each>
  • trunk/test/integration/nl/tno/metagenomics/integration/SynchronizationServiceTests.groovy

    r7 r9  
    7272
    7373                gscf.setRestResponse( "getSamples", "1a", [
    74                         [ sampleToken: "S1", name: "sample 1" ],
    75                         [ sampleToken: "S2", name: "sample 2" ],
    76                         [ sampleToken: "S3", name: "sample 3" ]
     74                        [ sampleToken: "S1", name: "sample 1", subject: "subject 1", event: "blood extraction", startTime: "0s" ],
     75                        [ sampleToken: "S2", name: "sample 2", subject: "subject 2", event: "blood extraction" ],
     76                        [ sampleToken: "S3", name: "sample 3", subject: "subject 3", event: "blood extraction" ]
    7777                ] as JSON );
    7878
    7979                gscf.setRestResponse( "getSamples", "1b", [
    80                         [ sampleToken: "S1", name: "sample 1" ],
    81                         [ sampleToken: "S3", name: "sample 3" ]
     80                        [ sampleToken: "S1", name: "sample 1", subject: "subject 1", event: "blood extraction", startTime: "0s" ],
     81                        [ sampleToken: "S3", name: "sample 3", subject: "subject 3", event: "blood extraction" ]
    8282                ] as JSON );
    8383
     
    118118                assert s1.samples*.name.contains( "sample 2" );
    119119                assert s1.samples*.name.contains( "sample 3" );
     120
     121                def testsample = s1.samples.find { it.name == "sample 1" }
     122                assert testsample.subject == "subject 1";
     123                assert testsample.event == "blood extraction (0s)"
     124
     125                testsample = s1.samples.find { it.name == "sample 2" }
     126                assert testsample.subject == "subject 2";
     127                assert testsample.event == "blood extraction"
    120128
    121129                def a1 = s1.assays.find { it.name == "assay 1a" }
  • trunk/test/unit/nl/tno/metagenomics/integration/TrashServiceTests.groovy

    r7 r9  
    4747               
    4848                // Create four samples
    49                 Sample sa1 = new Sample( id: 1, name: "Sample 1a", sampleToken: "sample1a", study: s );
    50                 Sample sa2 = new Sample( id: 2, name: "Sample 1b", sampleToken: "sample1b", study: s );
    51                 Sample sa3 = new Sample( id: 3, name: "Sample 2a", sampleToken: "sample2a", study: s );
    52                 Sample sa4 = new Sample( id: 4, name: "Sample 2b", sampleToken: "sample2b", study: s );
    53                 Sample sa5 = new Sample( id: 5, name: "Sample 3a", sampleToken: "sample3a", study: s );
     49                Sample sa1 = new Sample( id: 1, name: "Sample 1a", subject: "S1", event: "event", sampleToken: "sample1a", study: s );
     50                Sample sa2 = new Sample( id: 2, name: "Sample 1b", subject: "S2", event: "event", sampleToken: "sample1b", study: s );
     51                Sample sa3 = new Sample( id: 3, name: "Sample 2a", subject: "S3", event: "event", sampleToken: "sample2a", study: s );
     52                Sample sa4 = new Sample( id: 4, name: "Sample 2b", subject: "S4", event: "event", sampleToken: "sample2b", study: s );
     53                Sample sa5 = new Sample( id: 5, name: "Sample 3a", subject: "S5", event: "event", sampleToken: "sample3a", study: s );
    5454                def samples = [sa1, sa2, sa3, sa4, sa5]
    5555               
     
    6464                // Create desired combinations of samples and assays
    6565                // Such that: assay1 has 2 samples with data, assay2 has 1 sample with data and assay3 has no samples with data
    66            AssaySample as1a = new AssaySample( oligoNumber: "123", tagSequence: "abc", sample: sa1, assay: a1 );
    67            AssaySample as1b = new AssaySample( oligoNumber: "200", tagSequence: "def", sample: sa2, assay: a1 );
    68            AssaySample as2a = new AssaySample( oligoNumber: "300", tagSequence: "ghi", sample: sa3, assay: a2 );
     66           AssaySample as1a = new AssaySample( oligoNumber: "123", tagSequence: "abc", tagName: "L391", sample: sa1, assay: a1 );
     67           AssaySample as1b = new AssaySample( oligoNumber: "200", tagSequence: "def", tagName: "L397", sample: sa2, assay: a1 );
     68           AssaySample as2a = new AssaySample( oligoNumber: "300", tagSequence: "ghi", tagName: "L421", sample: sa3, assay: a2 );
    6969           AssaySample as2b = new AssaySample( id: 12, sample: sa4, assay: a2);
    7070           AssaySample as3a = new AssaySample( sample: sa5, assay: a3);
     
    118118               
    119119                // Create three samples, two originally also present in assay 1, the other one isn't
    120                 Sample sa1 = new Sample( id: 101, name: "Sample 1a", sampleToken: "tsample1a", study: trash );
    121                 Sample sa2 = new Sample( id: 102, name: "Sample 1b", sampleToken: "tsample1b", study: trash );
    122                 Sample sa3 = new Sample( id: 103, name: "Sample 2a", sampleToken: "tsample2a", study: trash );
     120                Sample sa1 = new Sample( id: 101, name: "Sample 1a", sampleToken: "tsample1a", subject: "fromtrash: S1", event: "fromtrash: event", study: trash );
     121                Sample sa2 = new Sample( id: 102, name: "Sample 1b", sampleToken: "tsample1b", subject: "fromtrash: S2", event: "fromtrash: event", study: trash );
     122                Sample sa3 = new Sample( id: 103, name: "Sample 2a", sampleToken: "tsample2a", subject: "fromtrash: S3", event: "fromtrash: event", study: trash );
    123123                def samples = [sa1, sa2, sa3]
    124124               
     
    192192                assert assaySample.oligoNumber == "123"
    193193                assert assaySample.tagSequence == "abc"
     194                assert assaySample.sample.subject == "S1"
     195                assert assaySample.sample.event == "event"
    194196                assert assaySample.sequenceData.size() == 2
    195197
     
    198200                assert assaySample.oligoNumber == "200"
    199201                assert assaySample.tagSequence == "def"
     202                assert assaySample.sample.subject == "S2"
     203                assert assaySample.sample.event == "event"
    200204                assert assaySample.sequenceData.size() == 1
    201205
     
    204208                assert assaySample.oligoNumber == "300"
    205209                assert assaySample.tagSequence == "ghi"
     210                assert assaySample.sample.subject == "S3"
     211                assert assaySample.sample.event == "event"
    206212                assert !assaySample.sequenceData || assaySample.sequenceData.size() == 0
    207213
     
    281287                assert assaySample.oligoNumber == "123"
    282288                assert assaySample.tagSequence == "abc"
     289                assert assaySample.sample.subject == "S1"
     290                assert assaySample.sample.event == "event"
    283291                assert assaySample.sequenceData.size() == 2
    284292
     
    287295                assert assaySample.oligoNumber == "200"
    288296                assert assaySample.tagSequence == "def"
     297                assert assaySample.sample.subject == "S2"
     298                assert assaySample.sample.event == "event"
    289299                assert assaySample.sequenceData.size() == 1
    290300
     
    364374                assert assaySample.oligoNumber == "123"
    365375                assert assaySample.tagSequence == "abc"
     376                assert assaySample.sample.subject == "S1"
     377                assert assaySample.sample.event == "event"
    366378                assert assaySample.sequenceData.size() == 2
    367379
     
    419431                assert s.oligoNumber == "fromtrash: 1";
    420432                assert s.tagSequence == "fromtrash: abc";
     433               
     434                // Sample data shouldn't be copied, so remains the same
     435                assert s.sample.subject == "S1"
     436                assert s.sample.event == "event"
     437               
    421438                assert s.sequenceData?.size() == 4
    422439               
     
    468485                assert restoredTo.sequenceData?.size() == 2
    469486               
     487                // Sample data shouldn't be copied, so remains the same
     488                assert restoredTo.sample.subject == "S4"
     489                assert restoredTo.sample.event == "event"
     490               
    470491                assert restoredTo.numSequences() == 600
    471492                def sequenceFiles = restoredTo.sequenceData.sequenceFile;
  • trunk/web-app/css/metagenomics.css

    r7 r9  
    487487
    488488/* Makes sure the filenames in the dialog don't exceed 200px */
    489 .dataTables_wrapper .uploadedFile { display: inline-block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: 190px; height: 15px; }
    490                                        
     489.dataTables_wrapper .uploadedFile { display: inline-block; zoom: 1; *display: inline; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: 190px; height: 15px; }
     490.blok_data { display: inline-block; zoom: 1; *display: inline; width: 350px; vertical-align: top;}                                     
  • trunk/web-app/js/assay.show.enterTagsDialog.js

    r2 r9  
    22        $( "#enterTagsDialog" ).tabbedDialog({
    33                height: 450,
    4                 width: 620,
     4                width: 750,
    55                modal: true,
    66                autoOpen: false,
  • trunk/web-app/js/assay.show.runDialogs.js

    r4 r9  
    5959 * Shows the dialog to edit a run
    6060 * @param id                            ID of the run to edit
    61  * @param name                          Name of the run to edit
    62  * @param date                          Date of the run to edit
    63  * @param machine                       Machine of the run to edit
    64  * @param supplier                      Supplier of the run to edit
    65  * @param parameterFile         ParameterFile of the run to edit
    6661 */
    67 function showEditRunDialog(id, name, date, machine, supplier, parameterFile) {
     62function showEditRunDialog(id) {
    6863        $( "#editRunDialog" ).load( baseUrl + "/run/editForm/" + id + "?assayId=" + assayId, [], function() {
    6964                // Initialize date picker for add run dialog
  • trunk/web-app/js/run.show.enterTagsDialog.js

    r7 r9  
    22        $( "#enterTagsDialog" ).tabbedDialog({
    33                height: 450,
    4                 width: 620,
     4                width: 750,
    55                modal: true,
    66                autoOpen: false,
Note: See TracChangeset for help on using the changeset viewer.