Ignore:
Timestamp:
Feb 10, 2011, 5:03:02 PM (9 years ago)
Author:
robert@…
Message:

Improved user interface and implemented basic export functionality

Location:
trunk/grails-app/services/nl/tno/metagenomics
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/services/nl/tno/metagenomics/FastaService.groovy

    r12 r13  
    33import java.io.BufferedWriter;
    44import java.io.File;
     5import java.io.Writer;
    56import java.util.ArrayList;
    67import java.util.zip.ZipEntry
     
    1112        def fileService
    1213        def fuzzySearchService
     14        def sampleExcelService
    1315
    1416        static transactional = true
     
    428430
    429431                                // Save the tag for exporting
    430                                 tags << [assaySampleId: assaySample.id, sampleName: assaySample.sample.name, assayName: assaySample.assay.name, tag: tag]
     432                                tags << [assaySampleId: assaySample.id, sampleName: assaySample.sample.name, assayName: assaySample.assay.name, studyName: assaySample.assay.study.name, tag: tag]
    431433                        }
    432434                }
     
    481483                }
    482484               
     485                // Export a tab delimited file with tags
     486                zipFile.putNextEntry( new ZipEntry( name + "_sample-tag.tab" ) );
     487                exportSampleTagFile( tags, zipWriter );
     488                zipWriter.flush();
     489                zipFile.closeEntry();
     490
     491                // Export an excel file with information about the samples
     492                zipFile.putNextEntry( new ZipEntry( name + ".xls" ) );
     493                sampleExcelService.exportExcelSampleData( assaySamples, tags, zipFile );
     494                zipFile.closeEntry();
     495               
    483496                zipFile.close();
    484 
    485                 // Export a tab delimited file with tags
    486                 //exportSampleTagFile( tags );
     497        }
     498       
     499        /**
     500         * Creates a tab delimited file with two columns and column headers "Sequence" and "Samplename"
     501         * @param tags          Map with newly created tags
     502         * @param zipWriter     Writer to write the data to
     503         */
     504        protected void exportSampleTagFile( List tags, Writer zipWriter ) {
     505                zipWriter.write( "Sequence" + "\t" + "Samplename" + "\n" );
     506               
     507                // Check whether the sample names are unique. If they aren't, the assay and study names
     508                // are appended to the sample name
     509                def sampleNames = tags*.sampleNames;
     510                if( sampleNames.unique().size() < sampleNames.size() ) {
     511                        tags.each {
     512                                it.uniqueName = it.sampleName + " (" + it.assayName + " / " + it.studyName + ")";
     513                        }
     514                } else {
     515                        tags.each {
     516                                it.uniqueName = it.sampleName;
     517                        }
     518                }
     519               
     520                tags.each {
     521                        zipWriter.write( it.tag + "\t" + it.uniqueName + "\n" );
     522                }
    487523        }
    488524
  • trunk/grails-app/services/nl/tno/metagenomics/SampleExcelService.groovy

    r9 r13  
    11package nl.tno.metagenomics
     2
     3import org.springframework.web.context.request.RequestContextHolder;
    24
    35class SampleExcelService {
    46        def excelService
    57        def fuzzySearchService
     8        def gscfService
    69       
    710    static transactional = true
     
    1518        def possibleFields = [sampleNameName, runName, tagNameName, tagSequenceName, oligoNumberName]
    1619       
    17     def downloadSampleExcel( def assaySamples, boolean includeRun = true ) {
     20    /**
     21     * Download a sample excel file with information about the metagenomics data of the assaySamples (i.e. all assaySample properties)
     22     * @param assaySamples      AssaySamples for which the information should be exported
     23     * @param includeRun        Whether to include a column with run name or not
     24     * @return
     25     */
     26        def downloadSampleExcel( def assaySamples, boolean includeRun = true ) {
    1827                def sheetIndex = 0;
    1928               
     
    5059                excelService.autoSizeColumns( wb, sheetIndex, 0..2)
    5160
    52                 return wb;             
     61                return wb;
    5362    }
    5463       
     64        /**
     65         * Parses a given excel file and tries to match the column names with assaySample properties
     66         * @param file 
     67         * @return
     68         */
    5569        def parseTagsExcel( File file, boolean includeRun = true ) {
    5670                def sheetIndex = 0
     
    8195        }
    8296       
     97        /**
     98         * Updates given assay samples with data from the excel file
     99         * @param matchColumns          Indicated which columns from the excel file should go into which field of the assaySample
     100         * @param possibleFields        List with possible fields to enter
     101         * @param file                          Excel file with the data
     102         * @param assaySamples          Assay Samples to be updated
     103         * @return
     104         */
    83105        def updateTagsByExcel( def matchColumns, def possibleFields, File file, def assaySamples ) {
    84106                def sheetIndex = 0
     
    187209                }
    188210        }
     211       
     212        /**
     213         * Exports all known data about the samples to an excel file
     214         * @param assaySamples  Assaysamples to export information about
     215         * @param tags                  Tags associated with the assay samples
     216         * @param stream                Outputstream to write the data to       
     217         * @return
     218         */
     219        def exportExcelSampleData( List<AssaySample> assaySamples, def tags, OutputStream stream ) {
     220                if( assaySamples == null )
     221                        assaySamples = []
     222
     223                // Gather data from GSCF.
     224                def sampleTokens = assaySamples*.sample.unique()*.sampleToken;
     225                def sessionToken = RequestContextHolder.currentRequestAttributes().getSession().sessionToken
     226                def gscfData
     227                try {
     228                        gscfData = gscfService.getSamples( sessionToken, sampleTokens );
     229                } catch( Exception e ) {
     230                        log.error "Exception occurred while fetching sample data from gscf: " + e.getMessage();
     231                        return;
     232                }
     233               
     234                // Determine which fields to show from the GSCF data
     235                def gscfFields = []
     236                def subjectFields = []
     237                def eventFields = []
     238                def moduleFields = [ "Sample name", "Assay name", "Study name", "Run name", "# sequences", "Artificial tag sequence", "Original tag sequence", "Tag name", "Oligo number" ]
     239                gscfData.each { sample ->
     240                        sample.each { key, value ->
     241                                if( key == "subjectObject" ) {
     242                                        value.each { subjectKey, subjectValue ->
     243                                                if( subjectValue && !value.isNull( subjectKey ) && !subjectFields.contains( subjectKey ) )
     244                                                        subjectFields << subjectKey
     245                                        }
     246                                } else if( key == "eventObject" ) {
     247                                        value.each { eventKey, eventValue ->
     248                                                if( eventValue && !value.isNull( eventKey ) && !eventFields.contains( eventKey ) )
     249                                                        eventFields << eventKey
     250                                        }
     251                                } else if( value && !sample.isNull( key ) && !gscfFields.contains( key ) ) {
     252                                        gscfFields << key
     253                                }
     254                        }
     255                }
     256               
     257                // Handle specific fields and names in GSCF
     258                def fields = handleSpecificFields( [ "module": moduleFields, "gscf": gscfFields, "subject": subjectFields, "event": eventFields ] );
     259
     260                // Put the module data in the right format (and sorting the samples by name)
     261                def data = []
     262                assaySamples.toList().sort { it.sample.name }.each { assaySample ->
     263                        // Lookup the tag for this assaySample
     264                        def currentTag = tags.find { it.assaySampleId == assaySample.id };
     265                       
     266                        // First add the module data
     267                        def row = [
     268                                assaySample.sample.name,
     269                                assaySample.assay.name,
     270                                assaySample.assay.study.name,
     271                                assaySample.run?.name,
     272                                assaySample.numSequences(),
     273                                currentTag?.tag,
     274                                assaySample.tagName,
     275                                assaySample.tagSequence,
     276                                assaySample.oligoNumber
     277                        ]
     278                       
     279                        // Afterwards add the gscfData including subject and event data
     280                        def gscfRow = gscfData.find { it.sampleToken == assaySample.sample.sampleToken };
     281                        if( gscfRow ) {
     282                                fields[ "names" ][ "gscf" ].each { field ->
     283                                        row << prepare( gscfRow, field );
     284                                }
     285                                fields[ "names" ][ "subject" ].each { field ->
     286                                        row << prepare( gscfRow.optJSONObject( "subjectObject" ), field );
     287                                }
     288                                fields[ "names" ][ "event" ].each { field ->
     289                                        row << prepare( gscfRow.optJSONObject( "eventObject" ), field );
     290                                }
     291                        }
     292                       
     293                        data << row;
     294                       
     295                }
     296               
     297                // Create excel file
     298                def sheetIndex = 0;
     299                       
     300                // Create an excel sheet
     301                def wb = excelService.create();
     302
     303                // Put the headers on the first row
     304                excelService.writeHeader( wb, fields[ "descriptions" ][ "all" ], sheetIndex );
     305                excelService.writeData( wb, data, sheetIndex, 1 );
     306
     307                // Auto resize columns
     308                excelService.autoSizeColumns( wb, sheetIndex, 0..fields[ "names" ][ "all" ].size()-1)
     309
     310                // Write the data to the output stream
     311                wb.write( stream );
     312        }
     313       
     314        protected String prepare( def object, def fieldName ) {
     315                if( object.isNull( fieldName ) )
     316                        return "";
     317               
     318                // If the field is a object, return the 'name' property
     319                def obj = object.optJSONObject( fieldName )
     320                if( obj )
     321                        return obj.optString( "name" )
     322                else
     323                        return object.optString( fieldName );
     324        }
     325       
     326        protected handleSpecificFields( def inputFields ) {
     327                def fields = [
     328                        "names": [
     329                                "all": []
     330                        ],
     331                        "descriptions": [
     332                                "all": []
     333                        ]
     334                ]
     335               
     336                inputFields.each { key, value ->
     337                        def names = [];
     338                        def descriptions = []
     339                        switch( key ) {
     340                                case "gscf":
     341                                        value.each {
     342                                                if( it != "sampleToken" && it != "name" ) {
     343                                                        names << it;
     344                                                        if( it == "startTime" )
     345                                                                descriptions << "Event start time";
     346                                                        else
     347                                                                descriptions << it
     348                                                }
     349                                        }
     350                                        break;
     351                                case "subject":
     352                                        value.each {
     353                                                if( it != "name" ) {
     354                                                        names << it;
     355                                                        descriptions << it
     356                                                }
     357                                        }
     358                                        break;
     359                                case "event":
     360                                        value.each {
     361                                                if( it != "startTime" ) {
     362                                                        names << it;
     363                                                        descriptions << it
     364                                                }
     365                                        }
     366                                        break;
     367                                default:
     368                                        names = value; descriptions = value;
     369                                        break;
     370                        }
     371                       
     372                        fields[ "names" ][ key ] = names;
     373                        fields[ "names" ][ "all" ] += names;
     374                        fields[ "descriptions" ][ key ] = descriptions;
     375                        fields[ "descriptions" ][ "all" ] += descriptions;
     376                }       
     377               
     378                return fields;
     379
     380        }
     381       
    189382}
  • trunk/grails-app/services/nl/tno/metagenomics/files/FileService.groovy

    r12 r13  
    100100
    101101                if( !uploadDir )
    102                 uploadDir = "fileuploads"
     102                        uploadDir = "fileuploads"
    103103
    104104                return absolutePath( uploadDir );
  • trunk/grails-app/services/nl/tno/metagenomics/integration/GscfService.groovy

    r9 r13  
    1212 */
    1313class GscfService {
    14 
    1514        def config = ConfigurationHolder.config
    1615
    1716        static transactional = true
    18 
    19 
    2017
    2118        /**
     
    5148                return "${config.gscf.baseURL}/study/showByToken/" + studyToken
    5249        }
    53        
    54         /**
    55         * Returns the url to add a new study in GSCF
    56         *
    57         * @return                       URL to redirect the user to
    58         */
    59    public String urlAddStudy( String studyToken ) {
    60            return config.gscf.baseURL + config.gscf.addStudyPath
    61    }
    62 
    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    
     50
     51        /**
     52         * Returns the url to add a new study in GSCF
     53         *
     54         * @return                      URL to redirect the user to
     55         */
     56        public String urlAddStudy( String studyToken ) {
     57                return config.gscf.baseURL + config.gscf.addStudyPath
     58        }
     59
     60        /**
     61        * Retrieves the currently logged in user from GSCF
     62        *
     63        * @param sessionToken String
     64        *
     65        * @return Map
     66        */
     67        public Map getUser(String sessionToken) {
     68                def user = [:]
     69                this.callGSCF(sessionToken, "getUser").each {
     70                        user[ it.key ] = it.value;
     71                }
     72                return user
     73        }
     74
    7875        /**
    7976         * Retrieve a list of Studies from the GSCF
     
    8784        }
    8885
    89        
     86
    9087        /**
    9188         * Retrieve a list of Studies from the GSCF
     
    116113                } catch( ResourceNotFoundException e ) {
    117114                        throw new ResourceNotFoundException( "Study with token " + studyToken + " not found in GSCF" )
    118                         throw e // Other exceptions are thrown as they appear
    119                 }
     115                } // Other exceptions are thrown as they appear
    120116
    121117                // Return only the first element of the list, since we are only interested in one study
    122                 if( list.size() == 0 ) {
     118                if( list?.size() ) {
     119                        return list[0];
     120                } else {
    123121                        return []
    124                 } else {
    125                         return list[0];
    126122                }
    127123        }
     
    172168        }
    173169
    174         /**
    175          * Retrieve a list of Samples from the GSCF
    176          *
    177          * @param sessionToken String
    178          * @param assay Assay (parameter assay is optional, only used when you want to limit the list of samples of an Assay within a Study)
    179          *
    180          * @return ArrayList
    181          */
    182         public ArrayList getSamples(String sessionToken, String assayToken) throws NotAuthorizedException, ResourceNotFoundException {
    183                 // Samples of a Study limited to a single Assay
    184                 try {
    185                         return this.callGSCF(sessionToken, "getSamples", ["assayToken":assayToken])
    186                 } catch( NotAuthorizedException e ) {
    187                         throw new NotAuthorizedException( "User is not authorized to access study for assay with token " + assayToken )
    188                 } catch( ResourceNotFoundException e ) {1
    189                         throw new ResourceNotFoundException( "Assay with token " + assayToken + " not found in GSCF" )
    190                 } // Other exceptions are thrown as they appear
    191 
    192         }
    193 
     170       
    194171        /**
    195172         * Retrieve a single Sample from the GSCF
    196          * 
     173         *
    197174         * @param sessionToken String
    198175         * @param assay Assay
    199          * @param sample Sample 
    200          * 
    201          * @return ArrayList 
     176         * @param sample Sample
     177         *
     178         * @return ArrayList
    202179         */
    203180        public def getSample(String sessionToken, String assayToken, String sampleToken) throws NotAuthorizedException, ResourceNotFoundException {
     
    219196
    220197        }
     198       
     199        /**
     200         * Retrieve a list of Samples from the GSCF
     201         *
     202         * @param sessionToken String
     203         * @param assay Assay (parameter assay is optional, only used when you want to limit the list of samples of an Assay within a Study)
     204         *
     205         * @return ArrayList
     206         */
     207        public ArrayList getSamples(String sessionToken, String assayToken) throws NotAuthorizedException, ResourceNotFoundException {
     208                // Samples of a Study limited to a single Assay
     209                try {
     210                        return this.callGSCF(sessionToken, "getSamples", ["assayToken":assayToken])
     211                } catch( NotAuthorizedException e ) {
     212                        throw new NotAuthorizedException( "User is not authorized to access study for assay with token " + assayToken )
     213                } catch( ResourceNotFoundException e ) {1
     214                        throw new ResourceNotFoundException( "Assay with token " + assayToken + " not found in GSCF" )
     215                } // Other exceptions are thrown as they appear
     216
     217        }
     218
     219        /**
     220         * Retrieve a list of samples from the GSCF
     221         *
     222         * @param sessionToken String
     223         * @param sampleTokens List of sampleTokens
     224         *
     225         * @return ArrayList
     226         */
     227        public def getSamples(String sessionToken, List sampleTokens) throws NotAuthorizedException, ResourceNotFoundException {
     228                def list
     229
     230                try {
     231                        list = this.callGSCF(sessionToken, "getSamples", ["sampleToken": sampleTokens])
     232                } catch( NotAuthorizedException e ) {
     233                        throw new NotAuthorizedException( "User is not authorized to access samples" )
     234                } catch( ResourceNotFoundException e ) {
     235                        throw new ResourceNotFoundException( "Samples with token " + sampleTokens + " not found in GSCF" )
     236                } // Other exceptions are thrown as they appear
     237
     238                // Return only the first element of the list, since we are only interested in one sample
     239                return list
     240        }
     241
    221242
    222243        /**
     
    273294
    274295                // concat all Rest Call specific arguments behind addr
    275                 restParams.each {parameter -> 
     296                restParams.each {parameter ->
    276297                        // If a list is given as value, the parameter should show up multiple times
    277298                        if( parameter.value instanceof Collection ) {
     
    281302                        } else {
    282303                                addr += "&${parameter.key}=" + parameter.value.toString().encodeAsURL()
    283                         } 
     304                        }
    284305                }
    285306
  • trunk/grails-app/services/nl/tno/metagenomics/integration/SynchronizationService.groovy

    r12 r13  
    261261                        // Can't retrieve data. Maybe sessionToken has expired or invalid. Anyway, stop
    262262                        // synchronizing and return null
     263                        e.printStackTrace()
    263264                        log.error( "Exception occurred when fetching study " + study.studyToken + ": " + e.getMessage() )
    264265                        throw new Exception( "Error while fetching study " + study.studyToken, e)
Note: See TracChangeset for help on using the changeset viewer.