Move alphabet type into SeqString
[mussa.git] / alg / motif_parser.cpp
1 #include "mussa_exceptions.hpp"
2 #include "alphabet.hpp"
3 #include "motif_parser.hpp"
4 #include "seq.hpp"
5
6 #include <boost/spirit/core.hpp>
7 #include <boost/spirit/actor/push_back_actor.hpp>
8 #include <boost/spirit/iterator/file_iterator.hpp>
9 #include <boost/spirit/utility/chset.hpp>
10 namespace spirit = boost::spirit;
11
12 #include <sstream>
13 #include <stdexcept>
14
15 motif_parser::push_channel::push_channel( motif_parser::ParsedMotifs *parsed_ ) :
16   parsed(parsed_)
17 {
18 }
19   
20 void motif_parser::push_channel::operator()(float f) const
21 {
22   parsed->channels.push_back(f);
23 }
24
25 motif_parser::push_sequence::push_sequence( ParsedMotifs *parsed_) :
26   parsed(parsed_)
27 {
28 }
29   
30 template<typename Iterator>
31 void motif_parser::push_sequence::operator()(
32   Iterator start,
33   Iterator end) const
34 {
35   std::copy(start, end, std::back_inserter(parsed->sequence));   
36 }
37
38 motif_parser::push_name::push_name( ParsedMotifs *parsed_) :
39   parsed(parsed_)
40 {
41 }
42
43 template<typename Iterator>
44 void motif_parser::push_name::operator()(
45   Iterator start,
46   Iterator end) const
47 {
48   std::copy(start, end, std::back_inserter(parsed->name));   
49 }
50
51 motif_parser::push_motif::push_motif( ParsedMotifs *parsed_) :
52   parsed(parsed_) {}
53     
54 template<typename Iterator>
55 void motif_parser::push_motif::operator()(
56   Iterator start,
57   Iterator end) const
58 {
59   float red, green, blue, alpha;
60   Sequence seq(parsed->sequence, nucleic_alphabet);
61   seq.set_fasta_header(parsed->name);
62   
63   alpha = 1.0;
64   switch (parsed->channels.size()) {
65     case 4:
66       alpha = parsed->channels[3];
67       // note fall through.
68   case 3:
69     red = parsed->channels[0];
70     green = parsed->channels[1];
71     blue = parsed->channels[2];
72     break;        
73   default:
74     throw std::runtime_error("wrong number of channels");
75     break;
76   }
77   Color c(red, green, blue, alpha);
78   std::string motif_subseq(seq.begin(), seq.end());
79   parsed->color_mapper->appendInstanceColor("motif", motif_subseq, c);
80   parsed->motifs.insert(seq);
81   
82   parsed->sequence.clear();
83   parsed->name.clear();
84   parsed->channels.clear();
85 }
86
87 motif_parser::ParsedMotifs::ParsedMotifs(
88   Mussa::motif_set& motifs_, 
89   boost::shared_ptr<AnnotationColors> color_mapper_) :
90   motifs(motifs_),
91   color_mapper(color_mapper_)
92 {
93 }
94
95 void motif_parser::ParsedMotifs::parse(const std::string &data)
96 {
97   const char *alphabet = Alphabet::nucleic_cstr;
98
99   // parse our string
100   spirit::parse_info<std::string::const_iterator> result;
101   result = spirit::parse(data.begin(), data.end(),
102      *(
103        ( 
104         (
105          (+spirit::chset<>(alphabet))[motif_parser::push_sequence(this)] >> 
106          +spirit::space_p
107         ) >>
108         !(
109           (
110             // names can either be letter followed by non-space characters
111             (spirit::alpha_p >> *spirit::graph_p)[motif_parser::push_name(this)]
112             |
113             // or a quoted string
114             (
115              spirit::ch_p('"') >> 
116                (+(~spirit::ch_p('"')))[motif_parser::push_name(this)] >>
117              spirit::ch_p('"')
118             )
119           ) >> +spirit::space_p
120         ) >>
121         spirit::real_p[motif_parser::push_channel(this)] >> +spirit::space_p >>
122         spirit::real_p[motif_parser::push_channel(this)] >> +spirit::space_p >>
123         spirit::real_p[motif_parser::push_channel(this)] >> +spirit::space_p >>
124         !(spirit::real_p[motif_parser::push_channel(this)] >> +spirit::space_p)
125        )[push_motif(this)]
126      ));
127   if (not result.full) {
128     std::stringstream msg;
129     msg << "Error at character " << result.length; 
130     // erase our potentially broken motif list
131     motifs.clear();
132     throw motif_load_error(msg.str());
133   }
134 }