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         // Read the length of the reference name.
00062         ifread(filePtr, &nameLength, sizeof(int));
00063       
00064         // Read the name.
00065         refName.readFromFile(filePtr, nameLength);
00066 
00067         // Read the length of the reference sequence.
00068         int32_t refLen;
00069         ifread(filePtr, &refLen, sizeof(int));
00070 
00071         header.addReferenceInfo(refName.c_str(), refLen);
00072     }
00073 
00074     // Successfully read the file.
00075     return(SamStatus::SUCCESS);
00076 }
00077 
00078 
00079 SamStatus::Status BamInterface::writeHeader(IFILE filePtr, 
00080                                             SamFileHeader& header)
00081 {
00082     if((filePtr == NULL) || (filePtr->isOpen() == false))
00083     {
00084         // File is not open, return failure.
00085         return(SamStatus::FAIL_ORDER);
00086     }
00087 
00088     char magic[4];
00089     magic[0] = 'B';
00090     magic[1] = 'A';
00091     magic[2] = 'M';
00092     magic[3] = 1;
00093 
00094     // Write magic to the file.
00095     ifwrite(filePtr, magic, 4);
00096 
00097     ////////////////////////////////
00098     // Write the header to the file.
00099     ////////////////////////////////
00100     // Construct a string containing the entire header.
00101     std::string headerString = "";
00102     header.getHeaderString(headerString);
00103 
00104     int32_t headerLen = headerString.length();
00105     int numWrite = 0;
00106     
00107     // Write the header length.
00108     numWrite = ifwrite(filePtr, &headerLen, sizeof(int32_t));
00109     if(numWrite != sizeof(int32_t))
00110     {
00111         return(SamStatus::FAIL_IO);
00112     }
00113    
00114     // Write the header to the file.
00115     numWrite = ifwrite(filePtr, headerString.c_str(), headerLen);
00116     if(numWrite != headerLen)
00117     {
00118         return(SamStatus::FAIL_IO);
00119     }
00120     
00121     ////////////////////////////////////////////////////////
00122     // Write the Reference Information.
00123     const SamReferenceInfo* refInfo = header.getReferenceInfo();
00124     if(refInfo == NULL)
00125     {
00126         // Failed to get the reference info.
00127         return(SamStatus::INVALID);
00128     }
00129 
00130     // Get the number of sequences.    
00131     int32_t numSeq = refInfo->getNumEntries();
00132 
00133     // Check to see if the reference info has not yet been set.
00134     // If not, check for the SQ header.
00135     if(numSeq == 0)
00136     {
00137         header.generateReferenceInfo();
00138         numSeq = refInfo->getNumEntries();
00139     }
00140     ifwrite(filePtr, &numSeq, sizeof(int32_t));
00141 
00142     // Write each reference sequence
00143     for (int i = 0; i < numSeq; i++)
00144     {
00145         const char* refName = refInfo->getReferenceName(i);
00146         // Add one for the null value.
00147         int32_t nameLength = strlen(refName) + 1;
00148         // Write the length of the reference name.
00149         ifwrite(filePtr, &nameLength, sizeof(int32_t));
00150       
00151         // Write the name.
00152         ifwrite(filePtr, refName, nameLength);
00153         // Write the length of the reference sequence.
00154         int32_t refLen = refInfo->getReferenceLength(i);
00155         ifwrite(filePtr, &refLen, sizeof(int32_t));
00156     }
00157 
00158     return(SamStatus::SUCCESS);
00159 }
00160 
00161 
00162 void BamInterface::readRecord(IFILE filePtr, SamFileHeader& header,
00163                               SamRecord& record, 
00164                               SamStatus& samStatus)
00165 {
00166     // TODO - need to validate there are @SQ lines in both sam/bam - MAYBE!
00167 
00168     // Reset the record prior to reading a new one.
00169     record.resetRecord();
00170 
00171     if(record.setBufferFromFile(filePtr, header) != SamStatus::SUCCESS)
00172     {
00173         // Failed, so add the error message.
00174         samStatus.addError(record.getStatus());
00175     }
00176 }
00177 
00178 SamStatus::Status BamInterface::writeRecord(IFILE filePtr, 
00179                                             SamFileHeader& header,
00180                                             SamRecord& record)
00181 {
00182     // Write the file, returning the status.
00183     return(record.writeRecordBuffer(filePtr));
00184 }
00185 
00186 
Generated on Wed Nov 17 15:38:27 2010 for StatGen Software by  doxygen 1.6.3