source: branches/help/PROBE_DESIGN/probe_match_parser.cxx

Last change on this file was 16763, checked in by westram, 7 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 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(NULp), 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
40typedef map<const char*, column, charpLess> ColumnMap;
41
42class ProbeMatch_impl : virtual Noncopyable {
43    char      *headline;
44    ColumnMap  columns;
45    int probe_region_offset;    // left index of probe region
46
47
48public:
49    ProbeMatch_impl(const char *headline_, char **errPtr) :
50        headline(NULp),
51        probe_region_offset(-1)
52    {
53        pm_assert(headline_);
54        headline = ARB_strdup(headline_);
55
56        for (char *tok_start = strtok(headline, " "); tok_start; tok_start = strtok(NULp, " ")) {
57            char *tok_end = strchr(tok_start, 0)-1;
58
59            int startPos = tok_start-headline;
60            int endPos   = tok_end-headline;
61
62            while (tok_end >= tok_start && tok_end[0] == '-') --tok_end;
63            while (tok_start <= tok_end && tok_start[0] == '-') ++tok_start;
64            pm_assert(tok_start <= tok_end); // otherwise column only contained '-'
65            tok_end[1] = 0;
66
67            columns[tok_start] = column(tok_start, startPos-2, endPos-2); // -2 because headline is 2 shorter than other lines
68        }
69
70        if (columns.empty()) *errPtr = ARB_strdup("No columns found");
71    }
72
73    ~ProbeMatch_impl() {
74        free(headline);
75    }
76
77    column *findColumn(const char *columntitle) {
78        ColumnMap::iterator ci = columns.find(columntitle);
79        if (ci == columns.end()) return NULp;
80        return &(ci->second);
81    }
82
83    void set_probe_region_offset(int offset) { probe_region_offset = offset; }
84    int get_probe_region_offset() const { return probe_region_offset; }
85};
86
87// --------------------------
88//      ProbeMatchParser
89
90ProbeMatchParser::ProbeMatchParser(const char *probe_target, const char *headline) :
91    pimpl(NULp),
92    init_error(NULp)
93{
94    if (!headline) {
95        init_error = ARB_strdup("No headline given");
96    }
97    else if (!probe_target) {
98        init_error = ARB_strdup("No probe target given.");
99    }
100    else {
101        pimpl = new ProbeMatch_impl(headline, &init_error);
102        if (!init_error) {
103            // modify target, so that it matches the target string in headline
104            char *probe_target_copy = GBS_global_string_copy("'%s'", probe_target); // add single quotes
105            for (int i = 0; probe_target_copy[i]; ++i) {
106                probe_target_copy[i] = toupper(probe_target_copy[i]);
107                if (probe_target_copy[i] == 'T') { // replace 'T' by 'U'
108                    probe_target_copy[i] = 'U';
109                }
110            }
111
112            // find that column and
113            column *target_found = pimpl->findColumn(probe_target_copy);
114            if (!target_found) {
115                char *probe_rev_compl = ARB_strdup(probe_target_copy);
116                GBT_reverseComplementNucSequence(probe_rev_compl, strlen(probe_rev_compl), 'U');
117                target_found          = pimpl->findColumn(probe_rev_compl);
118                free(probe_rev_compl);
119            }
120
121            if (target_found) {
122                int probe_region_offset = target_found->start_column - 9;
123                pimpl->set_probe_region_offset(probe_region_offset);
124            }
125            else {
126                init_error = GBS_global_string_copy("Probe match parser failed (Could not find target '%s' in headline)", probe_target_copy);
127            }
128            free(probe_target_copy);
129        }
130    }
131}
132
133ProbeMatchParser::~ProbeMatchParser() {
134    free(init_error);
135    delete pimpl;
136}
137
138bool ProbeMatchParser::getColumnRange(const char *columnName, int *startCol, int *endCol) const {
139    pm_assert(!init_error);
140    column *col = pimpl->findColumn(columnName);
141    if (!col) return false;
142
143    *startCol = col->start_column;
144    *endCol   = col->end_column;
145    return true;
146}
147
148bool ProbeMatchParser::is_gene_result() const {
149    pm_assert(!init_error);
150    return pimpl->findColumn("organism") && pimpl->findColumn("genename");
151}
152
153int ProbeMatchParser::get_probe_region_offset() const {
154    pm_assert(!init_error);
155    return pimpl->get_probe_region_offset();
156}
157
158// --------------------------
159//      ParsedProbeMatch
160
161ParsedProbeMatch::ParsedProbeMatch(const char *match_, const ProbeMatchParser& parser_) :
162    parser(parser_),
163    match(NULp),
164    error(NULp)
165{
166    if (match_) match = ARB_strdup(match_);
167    else error = "No match given";
168}
169
170ParsedProbeMatch::~ParsedProbeMatch() {
171    free(match);
172}
173
174inline char *strpartdup(const char *str, int c1, int c2) {
175    int len = c2-c1+1;
176
177    pm_assert(str);
178    pm_assert(c1 <= c2);
179    pm_assert((int)strlen(str) > c2);
180
181    return ARB_strndup(str+c1, len);
182}
183
184int ParsedProbeMatch::get_position() const {
185    pm_assert(!error);
186    int c1, c2;
187    if (parser.getColumnRange("pos", &c1, &c2)) {
188        char *content = strpartdup(match, c1, c2);
189        int   pos     = bio2info(atoi(content));
190        free(content);
191        return pos;
192    }
193    error = "no such column: 'pos'";
194    return -1;
195}
196
197const char *ParsedProbeMatch::get_probe_region() const {
198    pm_assert(!error);
199    int pro      = parser.pimpl->get_probe_region_offset();
200    int matchlen = strlen(match);
201
202    if (pro<matchlen) {
203        return match+pro;
204    }
205
206    error = GBS_global_string("can't parse match info '%s'", match);
207    return NULp;
208}
209
210char *ParsedProbeMatch::get_column_content(const char *columnName, bool chop_spaces) const {
211    pm_assert(!error);
212    int sc, ec;
213    if (parser.getColumnRange(columnName, &sc, &ec)) {
214        if (chop_spaces) {
215            while (sc<ec && match[sc] == ' ') ++sc;
216            while (sc<ec && match[ec] == ' ') --ec;
217        }
218        return strpartdup(match, sc, ec);
219    }
220    return NULp;
221}
Note: See TracBrowser for help on using the repository browser.