BamInterface.cpp

00001 /*
00002  *  Copyright (C) 2010  Regents of the University of Michigan
00003  *
00004  *   This program is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   This program is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 
00018 #include "BamInterface.h"
00019 #include "CharBuffer.h"
00020 
00021 BamInterface::BamInterface()
00022 {
00023 }
00024 
00025 
00026 BamInterface::~BamInterface()
00027 {
00028 }
00029 
00030 
00031 // Read a BAM file's header.
00032 SamStatus::Status BamInterface::readHeader(IFILE filePtr, SamFileHeader& header)
00033 {
00034     if(filePtr == NULL)
00035     {
00036         // File is not open, return false.
00037         return(SamStatus::FAIL_ORDER);
00038     }
00039 
00040     // Clear the passed in header.
00041     header.resetHeader();
00042 
00043     SamStatus::Status status = header.setHeaderFromBamFile(filePtr);
00044     if(status != SamStatus::SUCCESS)
00045     {
00046         return(status);
00047     }
00048 
00049     int referenceCount;
00050     // Read the number of references sequences.
00051     ifread(filePtr, &referenceCount, sizeof(int));
00052 
00053 //     header.referenceContigs.Dimension(referenceCount);
00054 //     header.referenceLengths.Dimension(referenceCount);
00055     CharBuffer refName;
00056 
00057     // Read each reference sequence
00058     for (int i = 0; i < referenceCount; i++)
00059     {
00060         int nameLength;
00061         int rc;
00062         // Read the length of the reference name.
00063         rc = ifread(filePtr, &nameLength, sizeof(int));
00064         if(rc != sizeof(int)) {
00065             return SamStatus::FAIL_IO;
00066         }
00067       
00068         // Read the name.
00069         refName.readFromFile(filePtr, nameLength);
00070 
00071         // Read the length of the reference sequence.
00072         int32_t refLen;
00073         rc = ifread(filePtr, &refLen, sizeof(int));
00074 
00075         if(rc != sizeof(int)) {
00076             return SamStatus::FAIL_IO;
00077         }
00078 
00079         header.addReferenceInfo(refName.c_str(), refLen);
00080     }
00081 
00082     // Successfully read the file.
00083     return(SamStatus::SUCCESS);
00084 }
00085 
00086 
00087 SamStatus::Status BamInterface::writeHeader(IFILE filePtr, 
00088                                             SamFileHeader& header)
00089 {
00090     if((filePtr == NULL) || (filePtr->isOpen() == false))
00091     {
00092         // File is not open, return failure.
00093         return(SamStatus::FAIL_ORDER);
00094     }
00095 
00096     char magic[4];
00097     magic[0] = 'B';
00098     magic[1] = 'A';
00099     magic[2] = 'M';
00100     magic[3] = 1;
00101 
00102     // Write magic to the file.
00103     ifwrite(filePtr, magic, 4);
00104 
00105     ////////////////////////////////
00106     // Write the header to the file.
00107     ////////////////////////////////
00108     // Construct a string containing the entire header.
00109     std::string headerString = "";
00110     header.getHeaderString(headerString);
00111 
00112     int32_t headerLen = headerString.length();
00113     int numWrite = 0;
00114     
00115     // Write the header length.
00116     numWrite = ifwrite(filePtr, &headerLen, sizeof(int32_t));
00117     if(numWrite != sizeof(int32_t))
00118     {
00119         return(SamStatus::FAIL_IO);
00120     }
00121    
00122     // Write the header to the file.
00123     numWrite = ifwrite(filePtr, headerString.c_str(), headerLen);
00124     if(numWrite != headerLen)
00125     {
00126         return(SamStatus::FAIL_IO);
00127     }
00128     
00129     ////////////////////////////////////////////////////////
00130     // Write the Reference Information.
00131     const SamReferenceInfo* refInfo = header.getReferenceInfo();
00132     if(refInfo == NULL)
00133     {
00134         // Failed to get the reference info.
00135         return(SamStatus::INVALID);
00136     }
00137 
00138     // Get the number of sequences.    
00139     int32_t numSeq = refInfo->getNumEntries();
00140 
00141     // Check to see if the reference info has not yet been set.
00142     // If not, check for the SQ header.
00143     if(numSeq == 0)
00144     {
00145         header.generateReferenceInfo();
00146         numSeq = refInfo->getNumEntries();
00147     }
00148     ifwrite(filePtr, &numSeq, sizeof(int32_t));
00149 
00150     // Write each reference sequence
00151     for (int i = 0; i < numSeq; i++)
00152     {
00153         const char* refName = refInfo->getReferenceName(i);
00154         // Add one for the null value.
00155         int32_t nameLength = strlen(refName) + 1;
00156         // Write the length of the reference name.
00157         ifwrite(filePtr, &nameLength, sizeof(int32_t));
00158       
00159         // Write the name.
00160         ifwrite(filePtr, refName, nameLength);
00161         // Write the length of the reference sequence.
00162         int32_t refLen = refInfo->getReferenceLength(i);
00163         ifwrite(filePtr, &refLen, sizeof(int32_t));
00164     }
00165 
00166     return(SamStatus::SUCCESS);
00167 }
00168 
00169 
00170 void BamInterface::readRecord(IFILE filePtr, SamFileHeader& header,
00171                               SamRecord& record, 
00172                               SamStatus& samStatus)
00173 {
00174     // TODO - need to validate there are @SQ lines in both sam/bam - MAYBE!
00175 
00176     // SetBufferFromFile will reset the record prior to reading a new one.
00177     if(record.setBufferFromFile(filePtr, header) != SamStatus::SUCCESS)
00178     {
00179         // Failed, so add the error message.
00180         samStatus.addError(record.getStatus());
00181     }
00182 }
00183 
00184 SamStatus::Status BamInterface::writeRecord(IFILE filePtr, 
00185                                             SamFileHeader& header,
00186                                             SamRecord& record,
00187                                             SamRecord::SequenceTranslation translation)
00188 {
00189     // Write the file, returning the status.
00190     return(record.writeRecordBuffer(filePtr, translation));
00191 }
00192 
00193 
Generated on Tue Sep 6 17:51:59 2011 for libStatGen Software by  doxygen 1.6.3