00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef CGA_TOOLS_SAM_READER_HPP_
00016 #define CGA_TOOLS_SAM_READER_HPP_ 1
00017
00019
00020 #include "cgatools/core.hpp"
00021 #include "cgatools/util/Exception.hpp"
00022 #include "cgatools/util/DelimitedLineParser.hpp"
00023
00024 #include <map>
00025
00026 namespace cgatools { namespace mapping {
00027
00028 class SamTag
00029 {
00030 friend std::ostream& operator<< (std::ostream& ost, const SamTag& r);
00031 public:
00032 void parse(const char* first, const char* last);
00033
00034 std::string name_;
00035 char type_;
00036 std::string value_;
00037 };
00038
00039 class SamHeaderTag
00040 {
00041 friend std::ostream& operator<< (std::ostream& ost, const SamHeaderTag& r);
00042 public:
00043 void parse(const char* first, const char* last);
00044
00045 std::string name_;
00046 std::string value_;
00047 };
00048
00049 template <class SamTag>
00050 class SamTags
00051 {
00052 public:
00053 typedef typename std::map<std::string, SamTag> SamTagMap;
00054
00055 bool hasTag(const std::string& t) const
00056 {
00057 return samTags_.find(t) != samTags_.end();
00058 }
00059
00060 const SamTag& getTag(const std::string& t) const
00061 {
00062 typename SamTagMap::const_iterator it = samTags_.find(t);
00063 CGA_ASSERT_MSG(it!=samTags_.end(), "The tag '" << t << "' not found.");
00064 return it->second;
00065 }
00066
00067 void addTag(const SamTag& t)
00068 {
00069 samTags_[t.name_] = t;
00070 }
00071
00072 void print(std::ostream& ost) const
00073 {
00074 for (typename SamTagMap::const_iterator it=samTags_.begin(),
00075 itEnd = samTags_.end(); it!=itEnd; ++it)
00076 {
00077 if (it != samTags_.begin())
00078 ost << '\t';
00079 ost << it->second;
00080 }
00081 }
00082
00083 void clear() {samTags_.clear();}
00084
00085 SamTagMap samTags_;
00086 };
00087
00088 template <class SamTag>
00089 class SamTagField : public util::DelimitedFieldParser
00090 {
00091 public:
00092
00093
00094
00095 SamTagField(const std::string& name, SamTags<SamTag>& samTags, bool isFirst)
00096 : DelimitedFieldParser(name),
00097 isFirst_(isFirst),
00098 samTags_(samTags)
00099 {
00100 }
00101
00102 void parse(const char* first, const char* last) {
00103 CGA_ASSERT_MSG((!isFirst_) || samTags_.samTags_.empty(), "samTags map was not cleaned");
00104 SamTag tag;
00105 tag.parse(first, last);
00106 samTags_.addTag(tag);
00107 }
00108
00109 private:
00110 bool isFirst_;
00111 SamTags<SamTag>& samTags_;
00112 };
00113
00114 class SamFileRecord
00115 {
00116 friend std::ostream& operator<< (std::ostream& ost, const SamFileRecord& r);
00117
00118 public:
00119 SamFileRecord() : flag_(-1), pos_(-1), mapq_(-1), pnext_(-1), tlen_(-1) {}
00120
00121 void bindToParser(util::DelimitedLineParser &parser);
00122
00123
00124 bool isConsistent() const {return (flag_ & 0x2) > 0;}
00125
00126
00127 bool isUnmapped() const {return (flag_ & 0x4) > 0;}
00128
00129
00130 bool isMateUnmapped() const {return (flag_ & 0x8) > 0;}
00131
00132
00133 bool isReverseComplemented() const {return (flag_ & 0x10) > 0;}
00134
00135
00136 bool isMateReverseComplemented() const {return (flag_ & 0x20) > 0;}
00137
00138
00139 bool isFirstMate() const {return (flag_ & 0x40) > 0;}
00140
00141
00142 bool isLastMate() const {return (flag_ & 0x80) > 0;}
00143
00144
00145 int getSide() const {return (flag_&0x40)>0 ? 0:((flag_&0x80)>0 ? 1:-1);}
00146
00147
00148 bool isSecondary() const {return (flag_ & 0x100) > 0;}
00149
00150 void parseQName(std::string& slide, std::string& lane, size_t& batchNo, size_t& offset) const;
00151
00152 std::string qname_;
00153 uint32_t flag_;
00154 std::string rname_;
00155 uint32_t pos_;
00156 uint32_t mapq_;
00157 std::string cigar_;
00158 std::string rnext_;
00159 uint32_t pnext_;
00160 int32_t tlen_;
00161 std::string seq_;
00162 std::string qual_;
00163
00164 SamTags<SamTag> samTags_;
00165 };
00166
00167 class SamFileHeader
00168 {
00169 public:
00170 class Record
00171 {
00172 friend std::ostream& operator<< (std::ostream& ost, const Record& r);
00173
00174 public:
00175 void bindToParser(util::DelimitedLineParser &parser);
00176
00177 std::string id_;
00178 SamTags<SamHeaderTag> tags_;
00179 };
00180
00181 typedef std::vector<Record> Records;
00182 typedef std::map<std::string, Records> RecordMap;
00183
00184 typedef std::map<std::string, const Record *> HeaderRecordIndex;
00185
00186 SamFileHeader()
00187 : dl_(true)
00188 {
00189 samHeaderRecord_.bindToParser(dl_);
00190 }
00191
00192 bool hasRecords(const std::string& section) const
00193 {
00194 return recordMap_.find(section)!=recordMap_.end();
00195 }
00196
00197 const Records& getRecords(const std::string& section) const
00198 {
00199 RecordMap::const_iterator it = recordMap_.find(section);
00200 CGA_ASSERT_MSG(it!=recordMap_.end(), "Section is missing: " << section);
00201 return it->second;
00202 }
00203
00204 Records& getRecords(const std::string& section)
00205 {
00206 return recordMap_[section];
00207 }
00208
00209 void addLine(const std::string& headerLine);
00210
00211 RecordMap recordMap_;
00212
00213 bool hasReadGroup(const std::string& rgId) const;
00214 const Record& getReadGroup(const std::string& rgId) const;
00215
00216 void initMetadata();
00217
00218 protected:
00219 Record samHeaderRecord_;
00220 util::DelimitedLineParser dl_;
00221
00222 HeaderRecordIndex readGroups_;
00223 };
00224
00225 class SamFileParser {
00226 public:
00227 SamFileParser(std::istream& in, const std::string& fileName)
00228 : isInitialised_(false), in_(in), fileName_(fileName),lineNo_(0), dl_(true)
00229 {
00230 samFileRecord_.bindToParser(dl_);
00231 }
00232
00233 bool next();
00234
00235 const SamFileRecord & getRecord() const {return samFileRecord_;}
00236
00237 void initMetadata();
00238
00239 SamFileHeader header_;
00240
00241 protected:
00242 bool isInitialised_;
00243
00244 std::istream& in_;
00245 std::string fileName_;
00246
00247 std::string line_;
00248 size_t lineNo_;
00249 SamFileRecord samFileRecord_;
00250 util::DelimitedLineParser dl_;
00251 };
00252
00253 } }
00254
00255 #endif // CGA_TOOLS_SAM_READER_HPP_
00256