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

Improved user interface and implemented basic export functionality

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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}
Note: See TracChangeset for help on using the changeset viewer.