Ignore:
Timestamp:
Mar 23, 2011, 1:24:24 PM (12 years ago)
Author:
robert@…
Message:

Improved export of fasta files and added properties to assaysamples

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

Legend:

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

    r13 r24  
    405405         * @return
    406406         */
    407         public def export( List assaySamples, OutputStream outStream, String name ) {
     407        public def export( List assaySamples, OutputStream outStream, String name = null ) {
    408408                if( !assaySamples || assaySamples.size() == 0 )
    409409                        return false;
     410               
     411                // Retrieve the filename from configuration, if none is given
     412                if( !name )
     413                        name = ConfigurationHolder.config.metagenomics.exportFilename
    410414
    411415                // Determine the directory the uploaded files are stored in
     
    421425                // Determine new tag length. Since we can use 4 characters per
    422426                // tag position, we only have to use 4log( #samples)
    423                 int tagLength = Math.ceil( Math.log( assaySamples.size() ) / Math.log( 4 ) )
     427                // The minimum number of characters used is 10, to ensure the correct working of the other
     428                // programs.
     429                int tagLength = Math.max( 10, Math.ceil( Math.log( assaySamples.size() ) / Math.log( 4 ) ) );
    424430                int tagNumber = 0;
    425431
     
    430436
    431437                                // Save the tag for exporting
    432                                 tags << [assaySampleId: assaySample.id, sampleName: assaySample.sample.name, assayName: assaySample.assay.name, studyName: assaySample.assay.study.name, tag: tag]
     438                                tags << [       assaySampleId: assaySample.id, sampleName: assaySample.sample.name,
     439                                                        assayName: assaySample.assay.name, studyName: assaySample.assay.study.name,
     440                                                        forwardPrimer: assaySample.fwPrimerSeq, reversePrimer: assaySample.revPrimerSeq,
     441                                                        tag: tag
     442                                ];
    433443                        }
    434444                }
     
    441451                // file and part of the qual files mixed. We have to write the full sequence file first.
    442452                try {
    443                         zipFile.putNextEntry( new ZipEntry( name + ".fasta" ) );
     453                        zipFile.putNextEntry( new ZipEntry( name + ".fna" ) );
    444454                       
    445455                        assaySamples.each { assaySample ->
     
    484494               
    485495                // Export a tab delimited file with tags
    486                 zipFile.putNextEntry( new ZipEntry( name + "_sample-tag.tab" ) );
    487                 exportSampleTagFile( tags, zipWriter );
     496                zipFile.putNextEntry( new ZipEntry( name + ".tab" ) );
     497                exportTabDelimitedSampleTagFile( tags, zipWriter );
    488498                zipWriter.flush();
    489499                zipFile.closeEntry();
    490500
     501                // Export a mothur file with tags
     502                zipFile.putNextEntry( new ZipEntry( name + ".oligos" ) );
     503                exportMothurSampleTagFile( tags, zipWriter );
     504                zipWriter.flush();
     505                zipFile.closeEntry();
     506               
    491507                // Export an excel file with information about the samples
    492508                zipFile.putNextEntry( new ZipEntry( name + ".xls" ) );
     
    498514       
    499515        /**
    500          * Creates a tab delimited file with two columns and column headers "Sequence" and "Samplename"
     516         * Creates an oligos file for Mothur that represents the connection between samples
     517         * and the artificial tags.
     518         *
     519         * @see http://www.mothur.org/wiki/Trim.seqs#allfiles
    501520         * @param tags          Map with newly created tags
    502521         * @param zipWriter     Writer to write the data to
    503522         */
    504         protected void exportSampleTagFile( List tags, Writer zipWriter ) {
    505                 zipWriter.write( "Sequence" + "\t" + "Samplename" + "\n" );
     523        protected void exportMothurSampleTagFile( List tags, Writer zipWriter ) {
     524                // Add the forward and reverse primers, as found in the assaysamples
     525                // The primers are already cut off, so they are not relevant anymore
     526                // For that reason, a '#' is prepended to each line.
     527                def fwPrimers = tags.collect { it.forwardPrimer }.findAll { it }.unique();
     528                def revPrimers = tags.collect { it.reversePrimer }.findAll { it }.unique();
     529               
     530                fwPrimers.each { zipWriter.write( "#forward\t" + it + "\n" )    }
     531                revPrimers.each { zipWriter.write( "#reverse\t" + it + "\n" ) }
    506532               
    507533                // Check whether the sample names are unique. If they aren't, the assay and study names
     
    519545               
    520546                tags.each {
    521                         zipWriter.write( it.tag + "\t" + it.uniqueName + "\n" );
    522                 }
    523         }
    524 
     547                        zipWriter.write( "barcode\t" + it.tag + "\t" + it.uniqueName + "\n" );
     548                }
     549        }
     550
     551        /**
     552        * Creates a tab delimited file with two columns and column headers "Sequence" and "Samplename"
     553        * @param tags           Map with newly created tags
     554        * @param zipWriter      Writer to write the data to
     555        */
     556   protected void exportTabDelimitedSampleTagFile( List tags, Writer zipWriter ) {
     557           zipWriter.write( "Sequence" + "\t" + "Samplename" + "\n" );
     558           
     559           // Check whether the sample names are unique. If they aren't, the assay and study names
     560           // are appended to the sample name
     561           def sampleNames = tags*.sampleNames;
     562           if( sampleNames.unique().size() < sampleNames.size() ) {
     563                   tags.each {
     564                           it.uniqueName = it.sampleName + " (" + it.assayName + " / " + it.studyName + ")";
     565                   }
     566           } else {
     567                   tags.each {
     568                           it.uniqueName = it.sampleName;
     569                   }
     570           }
     571           
     572           tags.each {
     573                   zipWriter.write( it.tag + "\t" + it.uniqueName + "\n" );
     574           }
     575   }
     576
     577       
    525578        /**
    526579         * Creates a unique tag for the given number
     
    541594                        int currentChar = tagNumber % numChars
    542595
    543                         tag = chars[ currentChar ] + tag;
     596                        // Append the new character to the end of the tag, to ensure that the first part of the tag is
     597                        // the most volatile. This way it is easy to find the end of the tag and the beginning of the real
     598                        // sequence on first sight.
     599                        tag = tag + chars[ currentChar ];
    544600
    545601                        tagNumber = Math.floor( tagNumber / numChars );
    546602                }
    547603
    548                 return tag
     604                return tag;
    549605        }
    550606
  • trunk/grails-app/services/nl/tno/metagenomics/SampleExcelService.groovy

    r21 r24  
    1111
    1212        // Fields to be edited using excel file and manually
     13        def variableFields = [
     14                'fwOligo':              'Forward oligo number',
     15                'fwMidName':    'Forward mid name',
     16                'fwTotalSeq':   'Total forward sequence',
     17                'fwMidSeq':             'Forward mid sequence',
     18                'fwPrimerSeq':  'Forward primer sequence',
     19                'revOligo':     'Reverse oligo number',
     20                'revMidName':   'Reverse mid name',
     21                'revTotalSeq':  'Total reverse sequence',
     22                'revMidSeq':    'Reverse mid sequence',
     23                'revPrimerSeq': 'Reverse primer sequence',
     24
     25        ]
     26       
    1327        def sampleNameName = "Sample name"
    1428        def runName = "Run"
    15         def tagNameName = "Tag name"
    16         def tagSequenceName = "Tag sequence"
    17         def oligoNumberName = "Oligo number"
    18         def possibleFields = [sampleNameName, runName, tagNameName, tagSequenceName, oligoNumberName]
     29        def possibleFields = [sampleNameName, runName] + variableFields.keySet().toList();
     30        def possibleFieldNames = [sampleNameName, runName ] + variableFields.values();
    1931       
    2032    /**
     
    3547                def wb = excelService.create();
    3648
    37                 def fields = possibleFields
     49                def fields = possibleFieldNames
    3850                if( !includeRun )
    3951                        fields = fields - runName
     
    4961                                rowData << assaySample.run?.name
    5062                       
    51                         rowData << assaySample.tagName
    52                         rowData << assaySample.tagSequence
    53                         rowData << assaySample.oligoNumber
     63                        variableFields.each { k, v ->
     64                                rowData << assaySample[ k ];
     65                        }
     66                       
    5467                        data << rowData;
    5568                }
     
    5770
    5871                // Auto resize columns
    59                 excelService.autoSizeColumns( wb, sheetIndex, 0..2)
     72                excelService.autoSizeColumns( wb, sheetIndex, 0..fields.size())
    6073
    6174                return wb;
     
    8295                // Try to guess best matches between the excel file and the column names
    8396                def bestMatches = [:]
    84                 def fields = possibleFields
     97                def fields = possibleFieldNames
    8598                if( !includeRun )
    8699                        fields = fields - runName
    87                
    88100                       
    89101                // Do matching using fuzzy search. The 0.8 treshold makes sure that no match if chosen if
    90102                // there is actually no match at all.
    91                 def matches = fuzzySearchService.mostSimilarUnique( headers, possibleFields, 0.8 );
     103                def matches = fuzzySearchService.mostSimilarUnique( headers, fields, 0.8 );
    92104               
    93105                headers.eachWithIndex { header, idx ->
     
    121133                def columns = [:]
    122134                def dataMatches = false;
    123                 possibleFields.each { columnName ->
     135                possibleFieldNames.each { columnName ->
    124136                        def foundColumn = matchColumns.find { it.value == columnName };
    125137                       
     
    130142                }
    131143
    132                 println columns
    133                
    134144                // A column to match the sample name must be present
    135145                if( columns[ sampleNameName ] == -1 ) {
     
    188198                        columns.each {
    189199                                if( it.value > -1 ) {
    190                                         switch( it.key ) {
    191                                                 case tagNameName:               assaySample.tagName = rowData[ it.value ]; break
    192                                                 case tagSequenceName:   assaySample.tagSequence = rowData[ it.value ]; break
    193                                                 case oligoNumberName:   assaySample.oligoNumber = rowData[ it.value ]; break
    194                                                 case runName:                   assaySample.run = Run.findByName( rowData[ it.value ] ); break
     200                                        if( it.key == runName ) {
     201                                                assaySample.run = Run.findByName( rowData[ it.value ] );
     202                                        } else {
     203                                                def field = variableFields.find { variableField -> variableField.value == it.key };
     204                                                if( field ) {
     205                                                        assaySample[ field.key ] = rowData[ it.value ];
     206                                                }
    195207                                        }
    196208                                }
     
    245257                def subjectFields = []
    246258                def eventFields = []
    247                 def moduleFields = [ "Sample name", "Assay name", "Study name", "Run name", "# sequences", "Artificial tag sequence", "Original tag sequence", "Tag name", "Oligo number" ]
     259                def moduleFields = [ "Sample name", "Assay name", "Study name", "Run name", "# sequences", "Artificial tag sequence" ] + variableFields.values();
    248260                gscfData.each { sample ->
    249261                        sample.each { key, value ->
     
    281293                                assaySample.numSequences(),
    282294                                currentTag?.tag,
    283                                 assaySample.tagName,
    284                                 assaySample.tagSequence,
    285                                 assaySample.oligoNumber
    286295                        ]
     296                       
     297                        // Add the variable fields for all assaysamples
     298                        variableFields.each { k, v ->
     299                                row << assaySample[ k ];
     300                        }
    287301                       
    288302                        // Afterwards add the gscfData including subject and event data
     
    322336                excelService.writeData( wb, data, sheetIndex, 0 );
    323337
    324                 // Auto resize columns
    325                 excelService.autoSizeColumns( wb, sheetIndex, 0..fields[ "names" ][ "all" ].size()-1)
     338                // Auto resize columns (# columns = # samples + 1)
     339                excelService.autoSizeColumns( wb, sheetIndex, 0..assaySamples?.size())
    326340
    327341                // Write the data to the output stream
  • trunk/grails-app/services/nl/tno/metagenomics/files/ExcelService.groovy

    r20 r24  
    185185         * @return
    186186         */
    187         public Workbook autoSizeColumns( Workbook book, int sheetIndex = 0,def columns = 0 ) {
     187        public Workbook autoSizeColumns( Workbook book, int sheetIndex = 0, def columns = 0 ) {
    188188                if( book == null )
    189189                        throw new Exception( "No workbook given." );
  • trunk/grails-app/services/nl/tno/metagenomics/integration/SynchronizationService.groovy

    r16 r24  
    634634                                        // Update the sample object if necessary
    635635                                        sampleFound.name = gscfSample.name
    636                                         sampleFound.subject = gscfSample.subject.toString()
    637                                         sampleFound.event = gscfSample.event.toString() + ( gscfSample.startTime ? " (" + gscfSample.startTime + ")" : "" )
     636                                        setSubjectAndEventFromGSCF( sampleFound, gscfSample );
    638637                                        sampleFound.save();
    639638                                } else {
     
    648647                                                // Update the sample object if necessary
    649648                                                sampleFound.name = gscfSample.name
    650                                                 sampleFound.subject = gscfSample.subject.toString()
    651                                                 sampleFound.event = gscfSample.event.toString() + ( gscfSample.startTime ? " (" + gscfSample.startTime + ")" : "" )
     649                                                setSubjectAndEventFromGSCF( sampleFound, gscfSample );
    652650                                                sampleFound.save();
    653651                                        } else {
     
    656654                                                // If it doesn't exist, create a new object
    657655                                                sampleFound = new Sample( sampleToken: gscfSample.sampleToken, name: gscfSample.name, study: assay.study );
    658                                                 sampleFound.subject = gscfSample.subject.toString()
    659                                                 sampleFound.event = gscfSample.event.toString() + ( gscfSample.startTime ? " (" + gscfSample.startTime + ")" : "" )
     656                                                setSubjectAndEventFromGSCF( sampleFound, gscfSample );
    660657                                                assay.study.addToSamples( sampleFound );
    661658                                                sampleFound.save();
     
    673670                        }
    674671                }
     672        }
     673       
     674        /**
     675         * Copies the subject and event properties from the gscf sample to the local sample
     676         * @param sample                Sample object to update
     677         * @param gscfSample    Map with properties about the gscf sample ('subject', 'event' and 'startTime' are used)
     678         */
     679        private void setSubjectAndEventFromGSCF( sample, gscfSample ) {
     680                sample.subject = gscfSample.subject && gscfSample.subject != "null" ? gscfSample.subject.toString() : ""
     681
     682                sample.event = gscfSample.event && gscfSample.event != "null" ? gscfSample.event.toString() : ""
     683               
     684                if( gscfSample.startTime && gscfSample.startTime != "null" )
     685                        sample.event += " (" + gscfSample.startTime + ")";
    675686        }
    676687
Note: See TracChangeset for help on using the changeset viewer.