Changeset 12 for trunk/grails-app/services/nl
- Timestamp:
- Feb 9, 2011, 9:04:29 AM (12 years ago)
- 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 1 1 package nl.tno.metagenomics 2 2 3 import java.io.BufferedWriter; 3 4 import java.io.File; 4 5 import java.util.ArrayList; 6 import java.util.zip.ZipEntry 7 import java.util.zip.ZipOutputStream 5 8 import org.codehaus.groovy.grails.commons.ConfigurationHolder 6 9 … … 53 56 for( int i = 0; i < filenames.size(); i++ ) { 54 57 def filename = filenames[ i ]; 55 58 56 59 if( fileService.isZipFile( filename ) ) { 57 60 // ZIP files are extracted and appended to the filenames list. 58 61 def newfiles = fileService.extractZipFile( filename, { files, bytes, totalFiles, totalBytes -> 59 60 61 62 62 filesProcessed += files; 63 bytesProcessed += bytes; 64 65 onProgress( filesProcessed, bytesProcessed, totalFiles, totalBytes ); 63 66 } ); 64 67 if( newfiles ) { … … 70 73 def file = fileService.get( filename ); 71 74 String filetype = fileService.determineFileType( file ); 72 75 73 76 if( !fileTypeValid( filetype ) ) { 74 77 // If files are not valid for parsing, delete them and return a message to the user … … 80 83 filesProcessed += files; 81 84 bytesProcessed += bytes; 82 85 83 86 onProgress( filesProcessed, bytesProcessed, 0, 0 ); 84 87 } ); 85 88 86 89 contents.filename = file.getName(); 87 90 contents.originalfilename = fileService.originalFilename( contents.filename ) 88 91 89 92 if( contents.success ) { 90 93 success << contents; … … 253 256 } 254 257 255 256 257 258 } 258 259 … … 396 397 } 397 398 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 } 399 700 400 701 } -
trunk/grails-app/services/nl/tno/metagenomics/files/FileService.groovy
r5 r12 147 147 directory = getUploadDir() 148 148 149 println "Moving " + file + " with originalname " + originalFilename + " to " + directory150 151 149 try { 152 150 if( file.exists() ) { … … 238 236 } 239 237 } 240 241 238 242 239 /** … … 274 271 275 272 /** 276 * Returns the absolute path for the given pathname. I tthe pathname is relative, it is taken relative to the web-app directory273 * Returns the absolute path for the given pathname. If the pathname is relative, it is taken relative to the web-app directory 277 274 * @param pathname 278 275 * @return … … 359 356 } 360 357 361 362 358 /********************************************************************************** 359 * 360 * Methods for handling zip files 361 * 362 **********************************************************************************/ 363 363 364 /** 364 365 * Determines whether a given file is a parsable zip file -
trunk/grails-app/services/nl/tno/metagenomics/integration/SynchronizationService.groovy
r9 r12 91 91 * @return ArrayList List of studies or null if the synchronization has failed 92 92 */ 93 public ArrayList<Study> synchronizeStudies() {93 public ArrayList<Study> synchronizeStudies() throws NotAuthenticatedException, Exception { 94 94 if( !performSynchronization() ) 95 95 return Study.findAllWhereTrashcan(false) … … 467 467 468 468 // Copy properties from gscf object 469 println "GSCF auth: " + gscfAuthorization470 471 469 if( gscfAuthorization.canRead instanceof Boolean ) 472 470 a.canRead = gscfAuthorization.canRead.booleanValue() … … 478 476 a.isOwner = gscfAuthorization.isOwner.booleanValue() 479 477 480 println "Saved auth: " + a.canRead.toString() + " - " + a.canWrite.toString() + " - " + a.isOwner.toString()481 482 478 a.save() 483 479
Note: See TracChangeset
for help on using the changeset viewer.