Ignore:
Timestamp:
Feb 9, 2011, 9:04:29 AM (10 years ago)
Author:
robert@…
Message:

Implemented basic exporting functionality

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

Legend:

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

    r5 r12  
    11package nl.tno.metagenomics
    22
     3import java.io.BufferedWriter;
    34import java.io.File;
    45import java.util.ArrayList;
     6import java.util.zip.ZipEntry
     7import java.util.zip.ZipOutputStream
    58import org.codehaus.groovy.grails.commons.ConfigurationHolder
    69
     
    5356                for( int i = 0; i < filenames.size(); i++ ) {
    5457                        def filename = filenames[ i ];
    55                        
     58
    5659                        if( fileService.isZipFile( filename ) ) {
    5760                                // ZIP files are extracted and appended to the filenames list.
    5861                                def newfiles = fileService.extractZipFile( filename, { files, bytes, totalFiles, totalBytes ->
    59                                                         filesProcessed += files;
    60                                                         bytesProcessed += bytes;
    61        
    62                                                         onProgress( filesProcessed, bytesProcessed, totalFiles, totalBytes );
     62                                        filesProcessed += files;
     63                                        bytesProcessed += bytes;
     64
     65                                        onProgress( filesProcessed, bytesProcessed, totalFiles, totalBytes );
    6366                                } );
    6467                                if( newfiles ) {
     
    7073                                def file = fileService.get( filename );
    7174                                String filetype = fileService.determineFileType( file );
    72        
     75
    7376                                if( !fileTypeValid( filetype ) ) {
    7477                                        // If files are not valid for parsing, delete them and return a message to the user
     
    8083                                                        filesProcessed += files;
    8184                                                        bytesProcessed += bytes;
    82        
     85
    8386                                                        onProgress( filesProcessed, bytesProcessed, 0, 0 );
    8487                                                } );
    85        
     88
    8689                                                contents.filename = file.getName();
    8790                                                contents.originalfilename = fileService.originalFilename( contents.filename )
    88        
     91
    8992                                                if( contents.success ) {
    9093                                                        success << contents;
     
    253256                        }
    254257
    255 
    256 
    257258                }
    258259
     
    396397        }
    397398
    398 
     399        /**
     400         * Exports the fasta data of a list of assaysamples
     401         * @param assaySamples  Assaysamples to export
     402         * @param outStream             Outputstream to send the data to
     403         * @return
     404         */
     405        public def export( List assaySamples, OutputStream outStream, String name ) {
     406                if( !assaySamples || assaySamples.size() == 0 )
     407                        return false;
     408
     409                // Determine the directory the uploaded files are stored in
     410                File permanentDirectory = fileService.absolutePath( ConfigurationHolder.config.metagenomics.fileDir );
     411
     412                // First check whether qual files should be exported or not
     413                // It is only exported if qual scores are available for all sequences
     414                def exportQual = ( assaySamples*.numSequences().sum() == assaySamples*.numQualScores().sum() );
     415
     416                // First create tags for every sample
     417                def tags = [];
     418
     419                // Determine new tag length. Since we can use 4 characters per
     420                // tag position, we only have to use 4log( #samples)
     421                int tagLength = Math.ceil( Math.log( assaySamples.size() ) / Math.log( 4 ) )
     422                int tagNumber = 0;
     423
     424                assaySamples.each { assaySample ->
     425                        if( assaySample.numSequences() > 0 ) {
     426                                // Create a new tag for this assaysample
     427                                def tag = createTag( tagLength, tagNumber++);
     428
     429                                // Save the tag for exporting
     430                                tags << [assaySampleId: assaySample.id, sampleName: assaySample.sample.name, assayName: assaySample.assay.name, tag: tag]
     431                        }
     432                }
     433
     434                // Now create zip file for fasta and qual files
     435                ZipOutputStream zipFile = new ZipOutputStream( new BufferedOutputStream( outStream ) );
     436                BufferedWriter zipWriter = new BufferedWriter( new OutputStreamWriter( zipFile ) );
     437               
     438                // We have to loop twice through the sequenceData, since we can't write part of the sequence
     439                // file and part of the qual files mixed. We have to write the full sequence file first.
     440                try {
     441                        zipFile.putNextEntry( new ZipEntry( name + ".fasta" ) );
     442                       
     443                        assaySamples.each { assaySample ->
     444                                if( assaySample.numSequences() > 0 ) {
     445                                        def currentTag = tags.find { it.assaySampleId == assaySample.id };
     446
     447                                        assaySample.sequenceData.each { sequenceData ->
     448                                                copyFastaFileForExport( fileService.get( sequenceData.sequenceFile, permanentDirectory ), currentTag.tag, zipWriter)
     449                                        }
     450                                }
     451                        }
     452                        zipWriter.flush();
     453                        zipFile.closeEntry();
     454
     455                        if( exportQual ) {
     456                                zipFile.putNextEntry( new ZipEntry( name + ".qual" ) );
     457
     458                                assaySamples.each { assaySample ->
     459                                        if( assaySample.numSequences() > 0 ) {
     460                                                def currentTag = tags.find { it.assaySampleId == assaySample.id };
     461
     462                                                assaySample.sequenceData.each { sequenceData ->
     463                                                        copyQualFileForExport( fileService.get( sequenceData.qualityFile, permanentDirectory ), currentTag.tag, zipWriter)
     464                                                }
     465                                        }
     466                                }
     467                               
     468                                zipWriter.flush();
     469                                zipFile.closeEntry();
     470                        }
     471
     472                } catch( Exception e ) {
     473                        log.error "Error while writing to fastafile or qualfile: " + e.getMessage();
     474                } finally {
     475                        // Always close zip entry
     476                        try {
     477                                zipFile.closeEntry();
     478                        } catch( Exception e ) {
     479                                log.error "Error while closing zip entry for fasta and qual: " + e.getMessage();
     480                        }
     481                }
     482               
     483                zipFile.close();
     484
     485                // Export a tab delimited file with tags
     486                //exportSampleTagFile( tags );
     487        }
     488
     489        /**
     490         * Creates a unique tag for the given number
     491         * @param length
     492         * @param tagNumber
     493         * @return
     494         */
     495        public String createTag( int length, int tagNumber ) {
     496                def chars = ["C", "A", "G", "T"];
     497                def numChars = chars.size();
     498
     499                if( tagNumber > numChars ** length )
     500                        throw new Exception( "Given tag number (" + tagNumber + ") is too large for the specified length (" + length + ")")
     501
     502                String tag = "";
     503
     504                for( def i = 0; i < length; i++ ) {
     505                        int currentChar = tagNumber % numChars
     506
     507                        tag = chars[ currentChar ] + tag;
     508
     509                        tagNumber = Math.floor( tagNumber / numChars );
     510                }
     511
     512                return tag
     513        }
     514
     515        /**
     516         * Copies the contents of the given sequence file to the output file and prepends the tag to every sequences
     517         * @param inFile        Filename of the file to be read
     518         * @param tag           
     519         * @param outWriter
     520         * @return
     521         */
     522        protected boolean copyFastaFileForExport( File inFile, String tag, BufferedWriter outWriter ) {
     523                // Walk through the lines in the file, starting with '>'
     524                // (and where the following line contains a character other than '>')
     525
     526                try {
     527                        BufferedReader inReader = new BufferedReader( new FileReader( inFile ) );
     528
     529                        String line = null
     530                        String newLine = null
     531                        String sequence = "";
     532
     533                        def lengthPattern = ~/length=(\d+)/
     534                        def lengthMatches
     535                        int length = 0;
     536                        int tagLength = tag.size();
     537
     538                        while( ( line = inReader.readLine()) != null) {
     539                                if( line.size() == 0 ) {
     540                                        // Print the sequence we collected, before writing the empty line
     541                                        printSequence( outWriter, sequence, tag );
     542                                        sequence = "";
     543
     544                                        // Empty line
     545                                        outWriter.newLine();
     546                                } else if( line[ 0 ] == '>' ) {
     547                                        // Print the sequence we collected, before writing the new comments tag
     548                                        printSequence( outWriter, sequence, tag );
     549                                        sequence = "";
     550
     551                                        // Comments line: replace length=### with the
     552                                        // updated length, and put the line in the
     553                                        lengthMatches = ( line =~ lengthPattern );
     554                                        if( lengthMatches ) {
     555                                                length = Integer.valueOf( lengthMatches[0][1] ) + tagLength;
     556                                                newLine = lengthMatches.replaceAll( "length=" + length );
     557                                        }
     558
     559                                        outWriter.write(newLine);
     560                                        outWriter.newLine();
     561                                } else {
     562                                        // This is part of the sequence. We collect the whole sequence and
     563                                        // determine in the end how to write it to the file
     564                                        sequence += line;
     565                                }
     566                        }
     567
     568                        // Print the sequence we collected, before ending the file
     569                        printSequence( outWriter, sequence, tag );
     570                        sequence = "";
     571
     572                } catch( Exception e ) {
     573                        log.error( "An error occurred while copying contents from " + inFile.getName() + ": " + e.getMessage() );
     574                        return false;
     575                }
     576        }
     577
     578        /**
     579         * Prints a sequence to the output file
     580         * @param outWriter
     581         * @param sequence
     582         * @param tag
     583         */
     584        private void printSequence( BufferedWriter outWriter, String sequence, String tag, int maxWidth = 60 ) {
     585                // If no sequence is given, also don't prepend it with the tag
     586                if( sequence.size() == 0 )
     587                        return
     588
     589                // Prepend the tag to the sequence
     590                sequence = tag + sequence;
     591
     592                // Write the sequence with a width of maxWidth characters per line
     593                while( sequence ) {
     594                        if( sequence.size() > maxWidth ) {
     595                                outWriter.write( sequence[0..maxWidth-1] );
     596                                sequence = sequence[maxWidth..-1]
     597                        } else {
     598                                outWriter.write( sequence );
     599                                sequence = null;
     600                        }
     601                        outWriter.newLine();
     602                }
     603        }
     604
     605        /**
     606         * Copies the contents of the given qual file to the output file and prepends the tag quality score to every sequence.
     607         * For every tag character '40' is prepended to the qual scores
     608         *
     609         * @param inFile        Filename of the file to be read
     610         * @param tag
     611         * @param outWriter
     612         * @return
     613         */
     614        protected boolean copyQualFileForExport( File inFile, String tag, BufferedWriter outWriter ) {
     615                // Walk through the lines in the file, starting with '>'
     616                // (and where the following line contains a character other than '>')
     617                try {
     618                        BufferedReader inReader = new BufferedReader( new FileReader( inFile ) );
     619
     620                        String line = null
     621                        String newLine = null
     622                        List<Integer> qualScores = []
     623
     624                        def lengthPattern = ~/length=(\d+)/
     625                        def lengthMatches
     626                        int length = 0;
     627                        int tagLength = tag.size();
     628
     629                        while( ( line = inReader.readLine()) != null) {
     630                                if( line.size() == 0 ) {
     631                                        // Print the quality scores we collected, before writing the empty line
     632                                        printQualScore( outWriter, qualScores, tagLength );
     633                                        qualScores = [];
     634
     635                                        // Empty line
     636                                        outWriter.newLine();
     637                                } else if( line[ 0 ] == '>' ) {
     638                                        // Print the quality scores we collected, before writing the empty line
     639                                        printQualScore( outWriter, qualScores, tagLength );
     640                                        qualScores = [];
     641
     642                                        // Comments line: replace length=### with the
     643                                        // updated length, and put the line in the
     644                                        lengthMatches = ( line =~ lengthPattern );
     645                                        if( lengthMatches ) {
     646                                                length = Integer.valueOf( lengthMatches[0][1] ) + tagLength;
     647                                                newLine = lengthMatches.replaceAll( "length=" + length );
     648                                        }
     649
     650                                        outWriter.write(newLine);
     651                                        outWriter.newLine();
     652                                } else {
     653                                        // This is part of the quality score. We collect the whole set of quality
     654                                        // scores and determine in the end how to write it to the file
     655                                        qualScores += line.split( " " ).collect {
     656                                                if( !it.isInteger() )
     657                                                        return 0;
     658                                                else
     659                                                        return Integer.parseInt( it );
     660                                        };
     661                                }
     662                        }
     663
     664                        // Print the quality scores we collected, before ending the file
     665                        printQualScore( outWriter, qualScores, tagLength );
     666                        qualScores = [];
     667
     668                } catch( Exception e ) {
     669                        log.error( "An error occurred while copying contents from " + inFile.getName() + ": " + e.getMessage() );
     670                        return false;
     671                }
     672        }
     673
     674        /**
     675         * Prints a sequence to the output file
     676         * @param outWriter
     677         * @param sequence
     678         * @param tag
     679         */
     680        private void printQualScore( BufferedWriter outWriter, List<Integer> qualScores, int tagLength, int maxWidth = 60 ) {
     681                // If no qualScores are given, also don't prepend it with the tag
     682                if( qualScores.size() == 0 )
     683                        return
     684
     685                // Prepend the tag to the sequence
     686                qualScores = Collections.nCopies( tagLength, 40 ) + qualScores;
     687
     688                // Write the sequence with a width of maxWidth characters per line
     689                while( qualScores ) {
     690                        if( qualScores.size() > maxWidth ) {
     691                                outWriter.write( qualScores[0..maxWidth-1].join( " " ) );
     692                                qualScores = qualScores[maxWidth..-1]
     693                        } else {
     694                                outWriter.write( qualScores.join( " " ) );
     695                                qualScores = null;
     696                        }
     697                        outWriter.newLine();
     698                }
     699        }
    399700
    400701}
  • trunk/grails-app/services/nl/tno/metagenomics/files/FileService.groovy

    r5 r12  
    147147                directory = getUploadDir()
    148148
    149                 println "Moving " + file + " with originalname " + originalFilename + " to " + directory
    150 
    151149                try {
    152150                        if( file.exists() ) {
     
    238236                }
    239237        }
    240 
    241238
    242239        /**
     
    274271
    275272        /**
    276          * Returns the absolute path for the given pathname. It the pathname is relative, it is taken relative to the web-app directory
     273         * Returns the absolute path for the given pathname. If the pathname is relative, it is taken relative to the web-app directory
    277274         * @param pathname
    278275         * @return
     
    359356        }
    360357
    361 
    362 
     358        /**********************************************************************************
     359         *
     360         * Methods for handling zip files
     361         *
     362         **********************************************************************************/
     363       
    363364        /**
    364365         * Determines whether a given file is a parsable zip file
  • trunk/grails-app/services/nl/tno/metagenomics/integration/SynchronizationService.groovy

    r9 r12  
    9191         * @return      ArrayList       List of studies or null if the synchronization has failed
    9292         */
    93         public ArrayList<Study> synchronizeStudies() {
     93        public ArrayList<Study> synchronizeStudies() throws NotAuthenticatedException, Exception {
    9494                if( !performSynchronization() )
    9595                        return Study.findAllWhereTrashcan(false)
     
    467467
    468468                // Copy properties from gscf object
    469                 println "GSCF auth: " + gscfAuthorization
    470                
    471469                if( gscfAuthorization.canRead instanceof Boolean  )
    472470                        a.canRead = gscfAuthorization.canRead.booleanValue()
     
    478476                        a.isOwner = gscfAuthorization.isOwner.booleanValue()
    479477                       
    480                 println "Saved auth: " + a.canRead.toString() + " - " + a.canWrite.toString() + " - " + a.isOwner.toString()
    481 
    482478                a.save()
    483479
Note: See TracChangeset for help on using the changeset viewer.