source: tags/ms_r16q3/PROBE_DESIGN/probe_match_parser.cxx

Last change on this file was 15176, checked in by westram, 8 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(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
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(0)
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(0, " ")) {
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 0;
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(0), init_error(0)
92{
93    if (!headline) {
94        init_error = ARB_strdup("No headline given");
95    }
96    else if (!probe_target) {
97        init_error = ARB_strdup("No probe target given.");
98    }
99    else {
100        pimpl = new ProbeMatch_impl(headline, &init_error);
101        if (!init_error) {
102            // modify target, so that it matches the target string in headline
103            char *probe_target_copy = GBS_global_string_copy("'%s'", probe_target); // add single quotes
104            for (int i = 0; probe_target_copy[i]; ++i) {
105                probe_target_copy[i] = toupper(probe_target_copy[i]);
106                if (probe_target_copy[i] == 'T') { // replace 'T' by 'U'
107                    probe_target_copy[i] = 'U';
108                }
109            }
110
111            // find that column and
112            column *target_found = pimpl->findColumn(probe_target_copy);
113            if (!target_found) {
114                char *probe_rev_compl = ARB_strdup(probe_target_copy);
115                GBT_reverseComplementNucSequence(probe_rev_compl, strlen(probe_rev_compl), 'U');
116                target_found          = pimpl->findColumn(probe_rev_compl);
117                free(probe_rev_compl);
118            }
119
120            if (target_found) {
121                int probe_region_offset = target_found->start_column - 9;
122                pimpl->set_probe_region_offset(probe_region_offset);
123            }
124            else {
125                init_error = GBS_global_string_copy("Probe match parser failed (Could not find target '%s' in headline)", probe_target_copy);
126            }
127            free(probe_target_copy);
128        }
129    }
130}
131
132ProbeMatchParser::~ProbeMatchParser() {
133    free(init_error);
134    delete pimpl;
135}
136
137bool ProbeMatchParser::getColumnRange(const char *columnName, int *startCol, int *endCol) const {
138    pm_assert(!init_error);
139    column *col = pimpl->findColumn(columnName);
140    if (!col) return false;
141
142    *startCol = col->start_column;
143    *endCol   = col->end_column;
144    return true;
145}
146
147bool ProbeMatchParser::is_gene_result() const {
148    pm_assert(!init_error);
149    return pimpl->findColumn("organism") && pimpl->findColumn("genename");
150}
151
152int ProbeMatchParser::get_probe_region_offset() const {
153    pm_assert(!init_error);
154    return pimpl->get_probe_region_offset();
155}
156
157// --------------------------
158//      ParsedProbeMatch
159
160ParsedProbeMatch::ParsedProbeMatch(const char *match_, const ProbeMatchParser& parser_)
161    : parser(parser_), match(0), error(0)
162{
163    if (match_) match = ARB_strdup(match_);
164    else error = "No match given";
165}
166
167ParsedProbeMatch::~ParsedProbeMatch() {
168    free(match);
169}
170
171inline char *strpartdup(const char *str, int c1, int c2) {
172    int len = c2-c1+1;
173
174    pm_assert(str);
175    pm_assert(c1 <= c2);
176    pm_assert((int)strlen(str) > c2);
177
178    return ARB_strndup(str+c1, len);
179}
180
181int ParsedProbeMatch::get_position() const {
182    pm_assert(!error);
183    int c1, c2;
184    if (parser.getColumnRange("pos", &c1, &c2)) {
185        char *content = strpartdup(match, c1, c2);
186        int   pos     = bio2info(atoi(content));
187        free(content);
188        return pos;
189    }
190    error = "no such column: 'pos'";
191    return -1;
192}
193
194const char *ParsedProbeMatch::get_probe_region() const {
195    pm_assert(!error);
196    int pro      = parser.pimpl->get_probe_region_offset();
197    int matchlen = strlen(match);
198
199    if (pro<matchlen) {
200        return match+pro;
201    }
202
203    error = GBS_global_string("can't parse match info '%s'", match);
204    return 0;
205}
206
207char *ParsedProbeMatch::get_column_content(const char *columnName, bool chop_spaces) const {
208    pm_assert(!error);
209    int sc, ec;
210    if (parser.getColumnRange(columnName, &sc, &ec)) {
211        if (chop_spaces) {
212            while (sc<ec && match[sc] == ' ') ++sc;
213            while (sc<ec && match[ec] == ' ') --ec;
214        }
215        return strpartdup(match, sc, ec);
216    }
217    return 0;
218}
Note: See TracBrowser for help on using the repository browser.