source: branches/profile/PROBE/PT_etc.cxx

Last change on this file was 11060, checked in by westram, 10 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.3 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : PT_etc.cxx                                        //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "probe.h"
12
13#include <PT_server_prototypes.h>
14#include "pt_prototypes.h"
15
16#include <struct_man.h>
17#include <arb_strbuf.h>
18
19void pt_export_error(PT_local *locs, const char *error) {
20    freedup(locs->ls_error, error);
21}
22void pt_export_error_if(PT_local *locs, ARB_ERROR& error) {
23    if (error) pt_export_error(locs, error.deliver());
24    else error.expect_no_error();
25}
26
27static const gene_struct *get_gene_struct_by_internal_gene_name(const char *gene_name) {
28    gene_struct to_search(gene_name, "", "");
29
30    gene_struct_index_internal::const_iterator found = gene_struct_internal2arb.find(&to_search);
31    return (found == gene_struct_internal2arb.end()) ? 0 : *found;
32}
33static const gene_struct *get_gene_struct_by_arb_species_gene_name(const char *species_gene_name) {
34    const char *slash = strchr(species_gene_name, '/');
35    if (!slash) {
36        fprintf(stderr, "Internal error: '%s' should be in format 'organism/gene'\n", species_gene_name);
37        return 0;
38    }
39
40    int   slashpos     = slash-species_gene_name;
41    char *organism     = strdup(species_gene_name);
42    organism[slashpos] = 0;
43
44    gene_struct to_search("", organism, species_gene_name+slashpos+1);
45    free(organism);
46
47    gene_struct_index_arb::const_iterator found = gene_struct_arb2internal.find(&to_search);
48    return (found == gene_struct_arb2internal.end()) ? 0 : *found;
49}
50
51static const char *arb2internal_name(const char *name) {
52    // convert arb name ('species/gene') into internal shortname
53    const gene_struct *found = get_gene_struct_by_arb_species_gene_name(name);
54    return found ? found->get_internal_gene_name() : 0;
55}
56
57const char *virt_name(const PT_probematch *ml) 
58{
59    // get the name with a virtual function
60    if (gene_flag) {
61        const gene_struct *gs = get_gene_struct_by_internal_gene_name(psg.data[ml->name].get_shortname());
62        return gs ? gs->get_arb_species_name() : "<cantResolveName>";
63    }
64    else {
65        pt_assert(psg.data[ml->name].get_shortname());
66        return psg.data[ml->name].get_shortname();
67    }
68}
69
70const char *virt_fullname(const PT_probematch * ml) 
71{
72    if (gene_flag) {
73        const gene_struct *gs = get_gene_struct_by_internal_gene_name(psg.data[ml->name].get_shortname());
74        return gs ? gs->get_arb_gene_name() : "<cantResolveGeneFullname>";
75    }
76    else {
77        return psg.data[ml->name].get_fullname() ?  psg.data[ml->name].get_fullname() : "<undefinedFullname>";
78    }
79}
80
81#define MAX_LIST_PART_SIZE 50
82
83static const char *get_list_part(const char *list, int& offset) {
84    // scans strings with format "xxxx#yyyy#zzzz"
85    // your first call should be with offset == 0
86    //
87    // returns : static copy of each part or 0 when done
88    // offset is incremented by this function and set to -1 when all parts were returned
89
90    static char buffer[2][MAX_LIST_PART_SIZE+1];
91    static int  curr_buff = 0;  // toggle buffer to allow 2 parallel gets w/o invalidation
92
93    if (offset<0) return 0;     // already done
94    curr_buff ^= 1; // toggle buffer
95
96    const char *numsign = strchr(list+offset, '#');
97    int         num_offset;
98    if (numsign) {
99        num_offset = numsign-list;
100        pt_assert(list[num_offset] == '#');
101    }
102    else { // last list part
103        num_offset = offset+strlen(list+offset);
104        pt_assert(list[num_offset] == 0);
105    }
106
107    // now num_offset points to next '#' or to end-of-string
108
109    int len = num_offset-offset;
110    pt_assert(len <= MAX_LIST_PART_SIZE);
111
112    memcpy(buffer[curr_buff], list+offset, len);
113    buffer[curr_buff][len] = 0; // EOS
114
115    offset = (list[num_offset] == '#') ? num_offset+1 : -1; // set offset for next part
116
117    return buffer[curr_buff];
118}
119
120#undef MAX_LIST_PART_SIZE
121
122char *ptpd_read_names(PT_local *locs, const char *names_list, const char *checksums, ARB_ERROR& error) {
123    /* read the name list separated by '#' and set the flag for the group members,
124     + returns a list of names which have not been found
125     */
126
127    // clear 'is_group'
128    for (int i = 0; i < psg.data_count; i++) {
129        psg.data[i].set_group_state(0); // Note: probes are designed for species with is_group == 1
130    }
131    locs->group_count = 0;
132
133    error = 0;
134
135    if (!names_list) {
136        error = "Can't design probes for no species (species list is empty)";
137        return 0;
138    }
139
140    int noff = 0;
141    int coff = 0;
142
143    GBS_strstruct *not_found = 0;
144
145    while (noff >= 0) {
146        pt_assert(coff >= 0);   // otherwise 'checksums' contains less elements than 'names_list'
147        const char *arb_name      = get_list_part(names_list, noff);
148        const char *internal_name = arb_name; // differs only for gene pt server
149
150        if (arb_name[0] == 0) {
151            pt_assert(names_list[0] == 0);
152            break; // nothing marked
153        }
154
155        if (gene_flag) {
156            const char *slash = strchr(arb_name, '/');
157
158            if (!slash) {
159                // ARB has to send 'species/gene'.
160                // If it did not, user did not mark 'Gene probes ?' flag
161
162                error = GBS_global_string("Expected '/' in '%s' (this PT-server can only design probes for genes)", arb_name);
163                break;
164            }
165
166            internal_name = arb2internal_name(arb_name);
167            pt_assert(internal_name);
168        }
169
170        int  idx   = GBS_read_hash(psg.namehash, internal_name);
171        bool found = false;
172
173        if (idx) {
174            --idx;              // because 0 means not found!
175
176            if (checksums) {
177                const char *checksum = get_list_part(checksums, coff);
178                // if sequence checksum changed since pt server was updated -> not found
179                found                = atol(checksum) == psg.data[idx].get_checksum();
180            }
181            else {
182                found = true;
183            }
184
185            if (found) {
186                psg.data[idx].set_group_state(1); // mark
187                locs->group_count++;
188            }
189        }
190
191        if (!found) { // name not found -> put into result
192            if (not_found == 0) not_found = GBS_stropen(1000);
193            else GBS_chrcat(not_found, '#');
194            GBS_strcat(not_found, arb_name);
195        }
196    }
197
198    char *result = not_found ? GBS_strclose(not_found) : 0;
199    if (error) freenull(result);
200    return result;
201}
202
203bytestring *PT_unknown_names(const PT_pdc *pdc) {
204    PT_local *locs = (PT_local*)pdc->mh.parent->parent;
205    static bytestring unknown = { 0, 0 };
206    delete unknown.data;
207
208    ARB_ERROR error;
209    unknown.data = ptpd_read_names(locs, pdc->names.data, pdc->checksums.data, error);
210    if (unknown.data) {
211        unknown.size = strlen(unknown.data) + 1;
212        pt_assert(!error);
213    }
214    else {
215        unknown.data = strdup("");
216        unknown.size = 1;
217    }
218    pt_export_error_if(locs, error);
219    return &unknown;
220}
221
Note: See TracBrowser for help on using the repository browser.