source: tags/arb-6.0.4/PROBE/probe.h

Last change on this file was 11159, checked in by westram, 10 years ago
  • dynamically allocate table for N-match→mismatch calculation
    • fixes #410 (buffer-overflow)

Thanks to Paavo Jumppanen

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.1 KB
Line 
1#ifndef PROBE_H
2#define PROBE_H
3
4#ifndef __LIST__
5#include <list>
6#endif
7#ifndef __SET__
8#include <set>
9#endif
10
11#ifndef ARBDB_H
12#include <arbdb.h>
13#endif
14#ifndef PT_COM_H
15#include <PT_com.h>
16#endif
17#ifndef AISC_GEN_SERVER_INCLUDED
18#include <PT_server.h>
19#endif
20#ifndef PT_TOOLS_H
21#include "PT_tools.h"
22#endif
23#ifndef CACHE_H
24#include <cache.h>
25#endif
26
27#define PT_SERVER_MAGIC   0x32108765                // pt server identifier
28#define PT_SERVER_VERSION 3                         // version of pt server database (no versioning till 2009/05/13)
29
30#if defined(DEBUG)
31// # define PTM_DEBUG_NODES
32# define PTM_DEBUG_STAGE_ASSERTIONS
33// # define PTM_DEBUG_VALIDATE_CHAINS
34#endif // DEBUG
35
36#define CALCULATE_STATS_ON_QUERY
37
38#if defined(PTM_DEBUG_STAGE_ASSERTIONS)
39#define pt_assert_stage(s) pt_assert(psg.get_stage() == (s))
40#else // !defined(PTM_DEBUG_STAGE_ASSERTIONS)
41#define pt_assert_stage(s)
42#endif
43
44#if defined(PTM_DEBUG_VALIDATE_CHAINS)
45#define pt_assert_valid_chain_stage1(node) pt_assert(PT_chain_has_valid_entries<ChainIteratorStage1>(node))
46#else // !defined(PTM_DEBUG_VALIDATE_CHAINS)
47#define pt_assert_valid_chain_stage1(node)
48#endif
49
50typedef unsigned long ULONG;
51typedef unsigned int  UINT;
52typedef unsigned char uchar;
53
54#define PT_MAX_PARTITION_DEPTH 4
55
56#define PT_POS_TREE_HEIGHT 20
57#define PT_MIN_TREE_HEIGHT PT_MAX_PARTITION_DEPTH
58
59#define MIN_PROBE_LENGTH 2
60
61enum PT_MATCH_TYPE {
62    PT_MATCH_TYPE_INTEGER           = 0,
63    PT_MATCH_TYPE_WEIGHTED_PLUS_POS = 1,
64    PT_MATCH_TYPE_WEIGHTED          = -1
65};
66
67
68
69#define MATCHANSWER  50                             // private msg type: match result answer
70#define CREATEANSWER 51                             // private msg type: create result answer
71#define FINDANSWER   52                             // private msg type: find result answer
72
73extern int gene_flag;           // if 'gene_flag' == 1 -> we are a gene pt server
74struct Hs_struct;
75
76enum type_types {
77    t_int    = 1,
78    t_string = 0,
79    t_float  = 2
80};
81
82enum PT_base {
83    PT_QU = 0,
84    PT_N  = 1,
85    PT_A,
86    PT_C,
87    PT_G,
88    PT_T,
89    PT_BASES,
90    PT_B_UNDEF,
91};
92
93inline bool is_std_base(char b) { return b >= PT_A && b <= PT_T; }
94inline bool is_ambig_base(char b) { return b == PT_QU || b == PT_N; }
95inline bool is_valid_base(char b) { return b >= PT_QU && b < PT_BASES; }
96
97inline char base_2_readable(char base) {
98    static char table[] = ".NACGU";
99    return base<PT_BASES ? table[safeCharIndex(base)] : base;
100}
101
102inline char *probe_2_readable(char *id_string, int len) {
103    //! translate a string containing PT_base into readable characters.
104    // caution if 'id_string' contains PT_QU ( == zero == EOS).
105    // (see also: probe_compress_sequence)
106    for (int i = 0; i<len; ++i) {
107        id_string[i] = base_2_readable(id_string[i]);
108    }
109    return id_string;
110}
111
112inline void reverse_probe(char *seq, int len) {
113    int i = 0;
114    int j = len-1;
115
116    while (i<j) std::swap(seq[i++], seq[j--]);
117}
118
119struct POS_TREE1;
120struct POS_TREE2;
121
122enum Stage { STAGE1, STAGE2 };
123
124// ---------------------
125//      Probe search
126
127class probe_input_data : virtual Noncopyable { // every taxa's own data
128    int     size;       // @@@ misleading (contains 1 if no bases in sequence)
129    GBDATA *gb_species;
130    bool    group;      // probe_design: whether species is in group
131
132    typedef SmartArrayPtr(int) SmartIntPtr;
133
134    mutable cache::CacheHandle<SmartCharPtr> seq;
135    mutable cache::CacheHandle<SmartIntPtr>  rel2abs;
136
137    static cache::Cache<SmartCharPtr> seq_cache;
138    static cache::Cache<SmartIntPtr>  rel2abs_cache;
139
140    SmartCharPtr loadSeq() const {
141        GB_transaction ta(gb_species);
142        GBDATA *gb_compr = GB_entry(gb_species, "compr");
143        return SmartCharPtr(GB_read_bytes(gb_compr));
144    }
145
146public:
147
148    probe_input_data()
149        : size(0),
150          gb_species(0),
151          group(false)
152    {}
153    ~probe_input_data() {
154        seq.release(seq_cache);
155        rel2abs.release(rel2abs_cache);
156    }
157
158    static void set_cache_sizes(size_t seq_cache_size, size_t abs_cache_size) {
159        seq_cache.resize(seq_cache_size);
160        rel2abs_cache.resize(abs_cache_size);
161    }
162
163    GB_ERROR init(GBDATA *gb_species_);
164
165    SmartCharPtr get_dataPtr() const {
166        if (!seq.is_cached()) seq.assign(loadSeq(), seq_cache);
167        return seq.access(seq_cache);
168    }
169
170    const char *get_shortname() const {
171        GB_transaction ta(gb_species);
172
173        GBDATA *gb_name = GB_entry(gb_species, "name");
174        pt_assert(gb_name);
175        return GB_read_char_pntr(gb_name);
176    }
177    const char *get_fullname() const {
178        GB_transaction ta(gb_species);
179
180        GBDATA *gb_full = GB_entry(gb_species, "full_name");
181        return gb_full ? GB_read_char_pntr(gb_full) : "";
182    }
183    long get_checksum() const { // @@@ change return-type -> uint32_t
184        GB_transaction ta(gb_species);
185        GBDATA *gb_cs = GB_entry(gb_species, "cs");
186        pt_assert(gb_cs);
187        uint32_t csum = uint32_t(GB_read_int(gb_cs));
188        return csum;
189    }
190    int get_size() const { return size; }
191
192    bool valid_rel_pos(int rel_pos) const { // returns true if rel_pos is inside sequence
193        return rel_pos >= 0 && rel_pos<get_size();
194    }
195
196    bool inside_group() const { return group; }
197    bool outside_group() const { return !group; }
198
199    void set_group_state(bool isGroupMember) { group = isGroupMember; }
200
201    long get_geneabspos() const {
202        pt_assert(gene_flag); // only legal in gene-ptserver
203        GBDATA *gb_pos = GB_entry(gb_species, "abspos");
204        if (gb_pos) return GB_read_int(gb_pos);
205        return -1;
206    }
207
208    void preload_rel2abs() const {
209        if (!rel2abs.is_cached()) {
210            GB_transaction ta(gb_species);
211
212            GBDATA *gb_baseoff = GB_entry(gb_species, "baseoff");
213            pt_assert(gb_baseoff);
214
215            const GB_CUINT4 *baseoff = GB_read_ints_pntr(gb_baseoff);
216
217            int *r2a = new int[size];
218
219            int abs = 0;
220            for (int rel = 0; rel<size; ++rel) {
221                abs      += baseoff[rel];
222                r2a[rel]  = abs;
223            }
224
225            rel2abs.assign(r2a, rel2abs_cache);
226        }
227    }
228    size_t get_abspos(size_t rel_pos) const {
229        pt_assert(rel2abs.is_cached()); // you need to call preload_rel2abs
230        return (&*rel2abs.access(rel2abs_cache))[rel_pos]; // @@@ brute-forced
231    }
232
233    size_t calc_relpos(int abs_pos) const { // expensive
234        preload_rel2abs();
235        SmartIntPtr  rel2abs_ptr = rel2abs.access(rel2abs_cache);
236        const int   *r2a     = &*rel2abs_ptr;
237
238        int l = 0;
239        int h = get_size()-1;
240
241        if (r2a[l] == abs_pos) return l;
242        if (r2a[h] == abs_pos) return h;
243
244        while (l<h) {
245            int m = (l+h)/2;
246            if (r2a[m]<abs_pos) {
247                l = m;
248            }
249            else if (r2a[m]>abs_pos) {
250                h = m;
251            }
252            else {
253                return m;
254            }
255        }
256        return l;
257    }
258};
259
260struct probe_statistic_struct {
261    // common
262    int cut_offs;                                   // statistic of chains
263    int single_node;
264    int short_node;
265    int long_node;
266    int longs;
267    int shorts;
268    int shorts2;
269    int chars;
270
271#ifdef ARB_64
272    // 64bit specials
273    int  int_node;
274    int  ints;
275    int  ints2;
276    long maxdiff;
277#endif
278
279    void setup();
280};
281
282class BI_ecoli_ref;
283
284class MostUsedPos : virtual Noncopyable {
285    int pos;
286    int used;
287
288    MostUsedPos *next;
289
290    void swapWith(MostUsedPos *other) {
291        std::swap(pos, other->pos);
292        std::swap(used, other->used);
293    }
294
295public:
296    MostUsedPos() : pos(0), used(0), next(NULL) { }
297    MostUsedPos(int p) : pos(p), used(1), next(NULL) { }
298    ~MostUsedPos() { delete next; }
299
300    void clear() {
301        pos  = 0;
302        used = 0;
303        delete next;
304        next = NULL;
305    }
306
307    void announce(int p) {
308        if (p == pos) used++;
309        else {
310            if (next) next->announce(p);
311            else next = new MostUsedPos(p);
312            if (next->used>used) swapWith(next);
313        }
314    }
315
316
317    int get_most_used() const { return pos; }
318};
319
320class probe_struct_global {
321    Stage stage;
322
323    union {
324        POS_TREE1 *p1;
325        POS_TREE2 *p2;
326    } pt;
327
328public:
329    GB_shell *gb_shell;
330    GBDATA   *gb_main;                              // ARBDB interface
331    char     *alignment_name;
332    GB_HASH  *namehash;                             // name to int
333
334    int                      data_count;
335    struct probe_input_data *data;                  // the internal database
336
337    char         *ecoli;                            // the ecoli sequenz
338    BI_ecoli_ref *bi_ecoli;
339
340    int  max_size;                                  // maximum sequence len
341    long char_count;                                // number of all 'acgtuACGTU'
342
343    int reversed;                                   // tell the matcher whether probe is reversed
344
345    double *pos_to_weight;                          // position to weight
346
347    MostUsedPos abs_pos;
348
349    int sort_by;
350
351    char *main_probe;
352
353    char      *server_name;                         // name of this server
354    aisc_com  *link;
355    T_PT_MAIN  main;
356    Hs_struct *com_so;                              // the communication socket
357
358    probe_statistic_struct stat;
359
360    bool big_db; // STAGE2 only (true -> uses 8 bit pointers)
361
362    void setup();
363    void cleanup();
364
365    void enter_stage(Stage stage_);
366    Stage get_stage() const { return stage; }
367
368    POS_TREE1*& TREE_ROOT1() { pt_assert(stage == STAGE1); return pt.p1; }
369    POS_TREE2*& TREE_ROOT2() { pt_assert(stage == STAGE2); return pt.p2; }
370};
371
372extern probe_struct_global psg;
373
374class gene_struct {
375    char       *gene_name;
376    const char *arb_species_name; // pointers into 'gene_name'
377    const char *arb_gene_name;
378
379    void init(const char *gene_name_, const char *arb_species_name_, const char *arb_gene_name_) {
380        int gene_name_len        = strlen(gene_name_);
381        int arb_species_name_len = strlen(arb_species_name_);
382        int arb_gene_name_len    = strlen(arb_gene_name_);
383
384        int fulllen      = gene_name_len+1+arb_species_name_len+1+arb_gene_name_len+1;
385        gene_name        = new char[fulllen];
386        strcpy(gene_name, gene_name_);
387        arb_species_name = gene_name+(gene_name_len+1);
388        strcpy((char*)arb_species_name, arb_species_name_);
389        arb_gene_name    = arb_species_name+(arb_species_name_len+1);
390        strcpy((char*)arb_gene_name, arb_gene_name_);
391    }
392
393public:
394    gene_struct(const char *gene_name_, const char *arb_species_name_, const char *arb_gene_name_) {
395        init(gene_name_, arb_species_name_, arb_gene_name_);
396    }
397    gene_struct(const gene_struct& other) {
398        if (&other != this) {
399            init(other.get_internal_gene_name(), other.get_arb_species_name(), other.get_arb_gene_name());
400        }
401    }
402    gene_struct& operator = (const gene_struct& other) {
403        if (&other != this) {
404            delete [] gene_name;
405            init(other.get_internal_gene_name(), other.get_arb_species_name(), other.get_arb_gene_name());
406        }
407        return *this;
408    }
409
410    ~gene_struct() {
411        delete [] gene_name;
412    }
413
414    const char *get_internal_gene_name() const { return gene_name; }
415    const char *get_arb_species_name() const { return arb_species_name; }
416    const char *get_arb_gene_name() const { return arb_gene_name; }
417};
418
419struct ltByArbName {
420    bool operator()(const gene_struct *gs1, const gene_struct *gs2) const {
421        int cmp           = strcmp(gs1->get_arb_species_name(), gs2->get_arb_species_name());
422        if (cmp == 0) { cmp = strcmp(gs1->get_arb_gene_name(), gs2->get_arb_gene_name()); }
423        return cmp<0;
424    }
425};
426struct ltByInternalName {
427    bool operator()(const gene_struct *gs1, const gene_struct *gs2) const {
428        int cmp = strcmp(gs1->get_internal_gene_name(), gs2->get_internal_gene_name());
429        return cmp<0;
430    }
431};
432
433typedef std::list<gene_struct>                          gene_struct_list;
434typedef std::set<const gene_struct *, ltByInternalName> gene_struct_index_internal;
435typedef std::set<const gene_struct *, ltByArbName>      gene_struct_index_arb;
436
437extern gene_struct_index_arb      gene_struct_arb2internal; // sorted by arb species+gene name
438extern gene_struct_index_internal gene_struct_internal2arb; // sorted by internal name
439
440#else
441#error probe.h included twice
442#endif
443
Note: See TracBrowser for help on using the repository browser.