source: branches/port5/PROBE/PT_etc.cxx

Last change on this file was 5725, checked in by westram, 16 years ago
  • removed useless macros:
    • GB_STRDUP (easily taken for GB_strdup)
    • GB_MEMCPY + GB_MEMSET + GB_FREE
    • GB_DELETE (replaced by freeset(xx,NULL))
  • added macros:
    • freeset (= free + assign)
    • freedup (= free + assign strdup'ed)
    • reassign (= free + assign + clear source var)
    • nulldup (=strdup accepting NULL; replacement for GB_strdup in C++ code)
  • use these macros where applicable
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4// #include <malloc.h>
5#include <memory.h>
6#include <PT_server.h>
7#include <PT_server_prototypes.h>
8#include "probe.h"
9#include "pt_prototypes.h"
10#include <struct_man.h>
11
12/* get a weighted table for PT_N mismatches */
13void set_table_for_PT_N_mis()
14{
15    int i;
16    psg.w_N_mismatches[0] = 0;
17    psg.w_N_mismatches[1] = 0;
18    psg.w_N_mismatches[2] = 1;
19    psg.w_N_mismatches[3] = 2;
20    psg.w_N_mismatches[4] = 4;
21    psg.w_N_mismatches[5] = 5;
22    for (i=6; i<=PT_POS_TREE_HEIGHT; i++)
23        psg.w_N_mismatches[i] = i;
24}
25
26void pt_export_error(PT_local *locs, const char *error) {
27    freedup(locs->ls_error, error);
28}
29
30static const gene_struct *get_gene_struct_by_internal_gene_name(const char *gene_name) {
31    gene_struct to_search(gene_name, "", "");
32
33    gene_struct_index_internal::const_iterator found = gene_struct_internal2arb.find(&to_search);
34    return (found == gene_struct_internal2arb.end()) ? 0 : *found;
35}
36static const gene_struct *get_gene_struct_by_arb_species_gene_name(const char *species_gene_name) {
37    const char *slash = strchr(species_gene_name, '/');
38    if (!slash) {
39        fprintf(stderr, "Internal error: '%s' should be in format 'organism/gene'\n", species_gene_name);
40        return 0;
41    }
42
43    int   slashpos     = slash-species_gene_name;
44    char *organism     = strdup(species_gene_name);
45    organism[slashpos] = 0;
46
47    gene_struct to_search("", organism, species_gene_name+slashpos+1);
48    free(organism);
49
50    gene_struct_index_arb::const_iterator found = gene_struct_arb2internal.find(&to_search);
51    return (found == gene_struct_arb2internal.end()) ? 0 : *found;
52}
53
54static const char *arb2internal_name(const char *name) {
55    // convert arb name ('species/gene') into internal shortname
56    const gene_struct *found = get_gene_struct_by_arb_species_gene_name(name);
57    return found ? found->get_internal_gene_name() : 0;
58}
59
60/* get the name with a virtual function */
61extern "C" const char *virt_name(PT_probematch *ml)
62{
63    if (gene_flag) {
64        const gene_struct *gs = get_gene_struct_by_internal_gene_name(psg.data[ml->name].name);
65        return gs ? gs->get_arb_species_name() : "<cantResolveName>";
66    }
67    else {
68        pt_assert(psg.data[ml->name].name);
69        return psg.data[ml->name].name;
70    }
71}
72
73extern "C" const char *virt_fullname(PT_probematch * ml)
74{
75    if (gene_flag) {
76        const gene_struct *gs = get_gene_struct_by_internal_gene_name(psg.data[ml->name].name);
77        return gs ? gs->get_arb_gene_name() : "<cantResolveGeneFullname>";
78    }
79    else {
80        return psg.data[ml->name].fullname ?  psg.data[ml->name].fullname : "<undefinedFullname>";
81    }
82}
83
84/* copy one mismatch table to a new one allocating memory */
85int *table_copy(int *mis_table, int length)
86{
87    int *result_table;
88    int i;
89
90    result_table = (int *)calloc(length, sizeof(int));
91    for (i=0; i<length; i++)
92        result_table[i] = mis_table[i];
93    return result_table;
94}
95/* add the values of a source table to a destination table */
96void table_add(int *mis_tabled, int *mis_tables, int length)
97{
98    int i;
99    for (i=0; i<length; i++)
100        mis_tabled[i] += mis_tables[i];
101}
102
103#define MAX_LIST_PART_SIZE 50
104
105static const char *get_list_part(const char *list, int& offset) {
106    // scans strings with format "xxxx#yyyy#zzzz"
107    // your first call should be with offset == 0
108    //
109    // returns : static copy of each part or 0 when done
110    // offset is incremented by this function and set to -1 when all parts were returned
111
112    static char buffer[2][MAX_LIST_PART_SIZE+1];
113    static int  curr_buff = 0;  // toggle buffer to allow 2 parallel gets w/o invalidation
114
115    if (offset<0) return 0;     // already done
116    curr_buff ^= 1; // toggle buffer
117
118    const char *numsign = strchr(list+offset, '#');
119    int         num_offset;
120    if (numsign) {
121        num_offset = numsign-list;
122        pt_assert(list[num_offset] == '#');
123    }
124    else { // last list part
125        num_offset = offset+strlen(list+offset);
126        pt_assert(list[num_offset] == 0);
127    }
128
129    // now num_offset points to next '#' or to end-of-string
130
131    int len = num_offset-offset;
132    pt_assert(len <= MAX_LIST_PART_SIZE);
133
134    memcpy(buffer[curr_buff], list+offset, len);
135    buffer[curr_buff][len] = 0; // EOS
136
137    offset = (list[num_offset] == '#') ? num_offset+1 : -1; // set offset for next part
138
139    return buffer[curr_buff];
140}
141
142#undef MAX_LIST_PART_SIZE
143
144/* read the name list seperated by # and set the flag for the group members,
145   + returns a list of names which have not been found */
146
147char *ptpd_read_names(PT_local *locs, const char *names_list, const char *checksums, const char*& error) {
148    /* clear 'is_group' */
149    for (int i = 0; i < psg.data_count; i++) {
150        psg.data[i].is_group = 0; // Note: probes are designed for species with is_group == 1
151    }
152    locs->group_count = 0;
153    error             = 0;
154
155    if (!names_list) {
156        error = "Can't design probes for no species (species list is empty)";
157        return 0;
158    }
159
160    int noff = 0;
161    int coff = 0;
162
163    GBS_strstruct *not_found = 0;
164
165    while (noff >= 0) {
166        pt_assert(coff >= 0);   // otherwise 'checksums' contains less elements than 'names_list'
167        const char *arb_name      = get_list_part(names_list, noff);
168        const char *internal_name = arb_name; // differs only for gene pt server
169
170        if (arb_name[0] == 0) {
171            pt_assert(names_list[0] == 0);
172            break; // nothing marked
173        }
174
175        if (gene_flag) {
176            const char *slash = strchr(arb_name, '/');
177
178            if (!slash) {
179                // ARB has to send 'species/gene'.
180                // If it did not, user did not mark 'Gene probes ?' flag
181
182                error = GBS_global_string("Expected '/' in '%s' (this PT-server can only design probes for genes)", arb_name);
183                break;
184            }
185
186            internal_name = arb2internal_name(arb_name);
187            pt_assert(internal_name);
188        }
189
190        int  idx   = GBS_read_hash(psg.namehash, internal_name);
191        bool found = false;
192
193        if (idx) {
194            --idx;              // because 0 means not found!
195
196            if (checksums) {
197                const char *checksum = get_list_part(checksums, coff);
198                // if sequence checksum changed since pt server was updated -> not found
199                found                = atol(checksum) == psg.data[idx].checksum;
200            }
201            else {
202                found = true;
203            }
204
205            if (found) {
206                psg.data[idx].is_group = 1; // mark
207                locs->group_count++;
208            }
209        }
210
211        if (!found) { // name not found -> put into result
212            if (not_found == 0) not_found = GBS_stropen(1000);
213            else GBS_chrcat(not_found, '#');
214            GBS_strcat(not_found, arb_name);
215        }
216    }
217
218    char *result = not_found ? GBS_strclose(not_found) : 0;
219    if (error) freeset(result, 0);
220    return result;
221}
222
223extern "C" bytestring *PT_unknown_names(struct_PT_pdc *pdc){
224    static bytestring un = {0,0};
225    PT_local *locs = (PT_local*)pdc->mh.parent->parent;
226    delete un.data;
227
228    const char *error;
229    un.data = ptpd_read_names(locs,pdc->names.data,pdc->checksums.data, error);
230    if (un.data) {
231        un.size = strlen(un.data) + 1;
232        pt_assert(!error);
233    }
234    else {
235        un.data = strdup("");
236        un.size = 1;
237        if (error) pt_export_error(locs, error);
238    }
239    return &un;
240}
241
242/* compute clip max using the probe length */
243int get_clip_max_from_length(int length)
244{
245    int             data_size;
246    int             i;
247    double          hitperc_zero_mismatches;
248    double          half_mismatches;
249    data_size = psg.data_count * psg.max_size;
250    hitperc_zero_mismatches = (double)data_size;
251    for (i = 0; i < length; i++) {
252        hitperc_zero_mismatches *= .25;
253    }
254    for (half_mismatches = 0; half_mismatches < 100; half_mismatches++) {
255        if (hitperc_zero_mismatches > 1.0 / (3.0 * length))
256            break;
257        hitperc_zero_mismatches *= (3.0 * length);
258    }
259    return (int) (half_mismatches);
260}
261
262
263void PT_init_base_string_counter(char *str,char initval,int size)
264{
265    memset(str,initval,size+1);
266    str[size] = 0;
267}
268
269void PT_inc_base_string_count(char *str,char initval, char maxval, int size)
270{
271    int i;
272    if (!size) {
273        str[0]=255;
274        return;
275    }
276    for (i=size-1; i>=0; i--) {
277        str[i]++;
278        if (str[i] >= maxval) {
279            str[i] = initval;
280            if (!i) str[i]=255; /* end flag */
281        }else{
282            break;
283        }
284    }
285}
Note: See TracBrowser for help on using the repository browser.