source: tags/arb-6.0/PROBE_DESIGN/probe_match_parser.cxx

Last change on this file was 8725, checked in by westram, 12 years ago
  • comments cleanup
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.0 KB
Line 
1//  ==================================================================== //
2//                                                                       //
3//    File      : probe_match_parser.cxx                                 //
4//    Purpose   : parse the results of a probe match                     //
5//                                                                       //
6//                                                                       //
7//  Coded by Ralf Westram (coder@reallysoft.de) in June 2004             //
8//  Copyright Department of Microbiology (Technical University Munich)   //
9//                                                                       //
10//  Visit our web site at: http://www.arb-home.de/                       //
11//                                                                       //
12//  ==================================================================== //
13
14#include "probe_match_parser.hxx"
15
16#include <arbdbt.h>
17#include <arb_defs.h>
18
19#include <cctype>
20#include <map>
21
22#define pm_assert(cond) arb_assert(cond)
23
24using namespace std;
25
26// ----------------
27//      column
28
29struct column {
30    const char *title;          // column title (pointer into ProbeMatch_impl::headline)
31    int         start_column, end_column;
32
33    column() : title(0), start_column(-1), end_column(-1) {}
34    column(const char *t, int sc, int ec) : title(t), start_column(sc), end_column(ec) {}
35};
36
37// -------------------------
38//      ProbeMatch_impl
39
40struct ltstr {
41    bool operator()(const char* s1, const char* s2) const {
42        return strcmp(s1, s2) < 0;
43    }
44};
45
46typedef map<const char*, column, ltstr> ColumnMap;
47
48class ProbeMatch_impl : virtual Noncopyable {
49    char      *headline;
50    ColumnMap  columns;
51    int probe_region_offset;    // left index of probe region
52
53
54public:
55    ProbeMatch_impl(const char *headline_, char **errPtr)
56        : headline(0)
57        , probe_region_offset(-1)
58    {
59        pm_assert(headline_);
60        headline = strdup(headline_);
61
62        for (char *tok_start = strtok(headline, " "); tok_start; tok_start = strtok(0, " ")) {
63            char *tok_end = strchr(tok_start, 0)-1;
64
65            int startPos = tok_start-headline;
66            int endPos   = tok_end-headline;
67
68            while (tok_end >= tok_start && tok_end[0] == '-') --tok_end;
69            while (tok_start <= tok_end && tok_start[0] == '-') ++tok_start;
70            pm_assert(tok_start <= tok_end); // otherwise column only contained '-'
71            tok_end[1] = 0;
72
73            columns[tok_start] = column(tok_start, startPos-2, endPos-2); // -2 because headline is 2 shorter than other lines
74        }
75
76        if (columns.empty()) *errPtr = strdup("No columns found");
77    }
78
79    ~ProbeMatch_impl() {
80        free(headline);
81    }
82
83    column *findColumn(const char *columntitle) {
84        ColumnMap::iterator ci = columns.find(columntitle);
85        if (ci == columns.end()) return 0;
86        return &(ci->second);
87    }
88
89    void set_probe_region_offset(int offset) { probe_region_offset = offset; }
90    int get_probe_region_offset() const { return probe_region_offset; }
91};
92
93// --------------------------
94//      ProbeMatchParser
95
96ProbeMatchParser::ProbeMatchParser(const char *probe_target, const char *headline)
97    : pimpl(0), init_error(0)
98{
99    if (!headline) {
100        init_error = strdup("No headline given");
101    }
102    else if (!probe_target) {
103        init_error = strdup("No probe target given.");
104    }
105    else {
106        pimpl = new ProbeMatch_impl(headline, &init_error);
107        if (!init_error) {
108            // modify target, so that it matches the target string in headline
109            char *probe_target_copy = GBS_global_string_copy("'%s'", probe_target); // add single quotes
110            for (int i = 0; probe_target_copy[i]; ++i) {
111                probe_target_copy[i] = toupper(probe_target_copy[i]);
112                if (probe_target_copy[i] == 'T') { // replace 'T' by 'U'
113                    probe_target_copy[i] = 'U';
114                }
115            }
116
117            // find that column and
118            column *target_found = pimpl->findColumn(probe_target_copy);
119            if (!target_found) {
120                char *probe_rev_compl = strdup(probe_target_copy);
121                GBT_reverseComplementNucSequence(probe_rev_compl, strlen(probe_rev_compl), 'U');
122                target_found          = pimpl->findColumn(probe_rev_compl);
123                free(probe_rev_compl);
124            }
125
126            if (target_found) {
127                int probe_region_offset = target_found->start_column - 9;
128                pimpl->set_probe_region_offset(probe_region_offset);
129            }
130            else {
131                init_error = GBS_global_string_copy("Probe match parser failed (Could not find target '%s' in headline)", probe_target_copy);
132            }
133            free(probe_target_copy);
134        }
135    }
136}
137
138ProbeMatchParser::~ProbeMatchParser() {
139    free(init_error);
140}
141
142bool ProbeMatchParser::getColumnRange(const char *columnName, int *startCol, int *endCol) const {
143    pm_assert(!init_error);
144    column *col = pimpl->findColumn(columnName);
145    if (!col) return false;
146
147    *startCol = col->start_column;
148    *endCol   = col->end_column;
149    return true;
150}
151
152bool ProbeMatchParser::is_gene_result() const {
153    pm_assert(!init_error);
154    return pimpl->findColumn("organism") && pimpl->findColumn("genename");
155}
156
157int ProbeMatchParser::get_probe_region_offset() const {
158    pm_assert(!init_error);
159    return pimpl->get_probe_region_offset();
160}
161
162// --------------------------
163//      ParsedProbeMatch
164
165ParsedProbeMatch::ParsedProbeMatch(const char *match_, const ProbeMatchParser& parser_)
166    : parser(parser_), match(0), error(0)
167{
168    if (match_) match = strdup(match_);
169    else error = "No match given";
170}
171
172ParsedProbeMatch::~ParsedProbeMatch() {
173    free(match);
174}
175
176inline char *strpartdup(const char *str, int c1, int c2) {
177    int len = c2-c1+1;
178
179    pm_assert(str);
180    pm_assert(c1 <= c2);
181    pm_assert((int)strlen(str) > c2);
182
183    char *buffer = (char*)malloc(len+1);
184    memcpy(buffer, str+c1, len);
185    buffer[len]  = 0;
186    return buffer;
187}
188
189int ParsedProbeMatch::get_position() const {
190    pm_assert(!error);
191    int c1, c2;
192    if (parser.getColumnRange("pos", &c1, &c2)) {
193        char *content = strpartdup(match, c1, c2);
194        int   pos     = bio2info(atoi(content));
195        free(content);
196        return pos;
197    }
198    error = "no such column: 'pos'";
199    return -1;
200}
201
202const char *ParsedProbeMatch::get_probe_region() const {
203    pm_assert(!error);
204    int pro      = parser.pimpl->get_probe_region_offset();
205    int matchlen = strlen(match);
206
207    if (pro<matchlen) {
208        return match+pro;
209    }
210
211    error = GBS_global_string("can't parse match info '%s'", match);
212    return 0;
213}
214
215char *ParsedProbeMatch::get_column_content(const char *columnName, bool chop_spaces) const {
216    pm_assert(!error);
217    int sc, ec;
218    if (parser.getColumnRange(columnName, &sc, &ec)) {
219        if (chop_spaces) {
220            while (sc<ec && match[sc] == ' ') ++sc;
221            while (sc<ec && match[ec] == ' ') --ec;
222        }
223        return strpartdup(match, sc, ec);
224    }
225    return 0;
226}
Note: See TracBrowser for help on using the repository browser.