source: tags/arb_5.5/ARBDB/adGene.c

Last change on this file was 6100, checked in by westram, 16 years ago
  • fix warning "format not a string literal and no format arguments"
    • GB_export_error → GB_export_error/GB_export_errorf
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.7 KB
Line 
1/*  ====================================================================  */
2/*                                                                        */
3/*    File      : adGene.c                                                */
4/*    Purpose   : Basic gene access functions                             */
5/*                                                                        */
6/*                                                                        */
7/*  Coded by Ralf Westram (coder@reallysoft.de) in July 2002              */
8/*  Copyright Department of Microbiology (Technical University Munich)    */
9/*                                                                        */
10/*  Visit our web site at: http://www.arb-home.de/                        */
11/*                                                                        */
12/*                                                                        */
13/*  ====================================================================  */
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18
19#include "adGene.h"
20#include "arbdbt.h"
21
22//  -----------------------------------------------------------------
23//      bool GEN_is_genome_db(GBDATA *gb_main, int default_value)
24//  -----------------------------------------------------------------
25// default_value == 0 -> default to normal database
26//               == 1 -> default to GENOM database
27//               == -1 -> assume that type is already defined
28
29GB_BOOL GEN_is_genome_db(GBDATA *gb_main, int default_value) {
30    GBDATA *gb_genom_db = GB_entry(gb_main, GENOM_DB_TYPE);
31
32    if (!gb_genom_db) {         // no DB-type entry -> create one with default
33        GB_ERROR error = NULL;
34
35        assert_or_exit(default_value != -1); // first call to GEN_is_genome_db has to provide a 'default_value'
36
37        gb_genom_db             = GB_create(gb_main, GENOM_DB_TYPE, GB_INT);
38        if (!gb_genom_db) error = GB_await_error();
39        else error              = GB_write_int(gb_genom_db, default_value);
40
41        if (error) GBK_terminatef("Fatal in GEN_is_genome_db: %s", error);
42    }
43
44    return GB_read_int(gb_genom_db) != 0;
45}
46
47//  --------------
48//      genes:
49//  --------------
50
51GBDATA* GEN_findOrCreate_gene_data(GBDATA *gb_species) {
52    GBDATA *gb_gene_data = GB_search(gb_species, "gene_data", GB_CREATE_CONTAINER);
53    gb_assert(gb_gene_data);
54    return gb_gene_data;
55}
56
57GBDATA* GEN_find_gene_data(GBDATA *gb_species) {
58    return GB_search(gb_species, "gene_data", GB_FIND);
59}
60
61GBDATA* GEN_expect_gene_data(GBDATA *gb_species) {
62    GBDATA *gb_gene_data = GB_search(gb_species, "gene_data", GB_FIND);
63    gb_assert(gb_gene_data);
64    return gb_gene_data;
65}
66
67GBDATA* GEN_find_gene_rel_gene_data(GBDATA *gb_gene_data, const char *name) {
68    GBDATA *gb_name = GB_find_string(gb_gene_data, "name", name, GB_IGNORE_CASE, down_2_level); 
69
70    if (gb_name) return GB_get_father(gb_name); // found existing gene
71    return 0;
72}
73
74GBDATA* GEN_find_gene(GBDATA *gb_species, const char *name) {
75    // find existing gene. returns 0 if it does not exist.
76    GBDATA *gb_gene_data = GEN_find_gene_data(gb_species);
77    return gb_gene_data ? GEN_find_gene_rel_gene_data(gb_gene_data, name) : 0;
78}
79
80GBDATA* GEN_create_nonexisting_gene_rel_gene_data(GBDATA *gb_gene_data, const char *name) {
81    GB_ERROR  error   = GB_push_transaction(gb_gene_data);
82    GBDATA   *gb_gene = 0;
83
84    gb_assert(!GEN_find_gene_rel_gene_data(gb_gene_data, name)); // don't call this function if you are not sure that the gene does not exists!
85
86    if (!error) {
87        gb_gene = GB_create_container(gb_gene_data, "gene");
88        error   = gb_gene ? GBT_write_string(gb_gene, "name", name) : GB_await_error();
89    }
90
91    gb_assert(gb_gene || error);
92    error = GB_end_transaction(gb_gene_data, error);
93    if (error) GB_export_error(error);
94
95    return gb_gene;
96}
97
98GBDATA* GEN_create_nonexisting_gene(GBDATA *gb_species, const char *name) {
99    return GEN_create_nonexisting_gene_rel_gene_data(GEN_findOrCreate_gene_data(gb_species), name);
100}
101
102GBDATA* GEN_find_or_create_gene_rel_gene_data(GBDATA *gb_gene_data, const char *name) {
103    GBDATA *gb_gene = 0;
104
105    /* Search for a gene, when gene does not exist create it */
106    if (!name || !name[0]) {
107        GB_export_error("Missing gene name");
108    }
109    else {
110        GBDATA *gb_name = GB_find_string(gb_gene_data, "name", name, GB_IGNORE_CASE, down_2_level);
111
112        if (gb_name) {
113            gb_gene = GB_get_father(gb_name); // found existing gene
114        }
115        else {
116            GB_ERROR error = GB_push_transaction(gb_gene_data);
117
118            if (!error) {
119                gb_gene = GB_create_container(gb_gene_data, "gene");
120                error   = GBT_write_string(gb_gene, "name", name);
121            }
122            error = GB_end_transaction(gb_gene_data, error);
123            if (error) {
124                gb_gene = NULL;
125                GB_export_error(error);
126            }
127        }
128    }
129    return gb_gene;
130}
131
132GBDATA* GEN_find_or_create_gene(GBDATA *gb_species, const char *name) {
133    return GEN_find_or_create_gene_rel_gene_data(GEN_findOrCreate_gene_data(gb_species), name);
134}
135
136GBDATA* GEN_first_gene(GBDATA *gb_species) {
137    return GB_entry(GEN_expect_gene_data(gb_species), "gene");
138}
139
140GBDATA* GEN_first_gene_rel_gene_data(GBDATA *gb_gene_data) {
141    return GB_entry(gb_gene_data, "gene");
142}
143
144GBDATA* GEN_next_gene(GBDATA *gb_gene) {
145    gb_assert(GB_has_key(gb_gene, "gene"));
146    return GB_nextEntry(gb_gene);
147}
148
149GBDATA *GEN_first_marked_gene(GBDATA *gb_species) {
150    return GB_first_marked(GEN_expect_gene_data(gb_species), "gene");
151}
152GBDATA *GEN_next_marked_gene(GBDATA *gb_gene) {
153    return GB_next_marked(gb_gene,"gene");
154}
155
156/* ----------------------- */
157/*      gene position      */
158/* ----------------------- */
159
160static struct GEN_position *lastFreedPosition = 0;
161
162struct GEN_position *GEN_new_position(int parts, GB_BOOL joinable) {
163    struct GEN_position *pos;
164
165    size_t pos_size  = parts*sizeof(pos->start_pos[0]);
166    size_t comp_size = parts*sizeof(pos->complement[0]);
167    size_t data_size = 2*pos_size+3*comp_size;
168
169    gb_assert(parts>0);
170
171    if (lastFreedPosition && lastFreedPosition->parts == parts) {
172        pos               = lastFreedPosition;
173        lastFreedPosition = 0;
174        memset(pos->start_pos, 0, data_size);
175    }
176    else {
177        pos             = GB_calloc(1, sizeof(*pos));
178        pos->parts      = parts;
179        pos->start_pos  = GB_calloc(1, data_size);
180        pos->stop_pos   = pos->start_pos+parts;
181        pos->complement = (unsigned char*)(pos->stop_pos+parts);
182    }
183
184    pos->joinable        = joinable;
185    pos->start_uncertain = 0;
186    pos->stop_uncertain  = 0;
187
188    return pos;
189}
190
191void GEN_use_uncertainties(struct GEN_position *pos) {
192    if (pos->start_uncertain == 0) {
193        // space was already allocated in GEN_new_position
194        pos->start_uncertain = pos->complement+pos->parts;
195        pos->stop_uncertain  = pos->start_uncertain+pos->parts;
196
197        size_t comp_size = pos->parts*sizeof(pos->complement[0]);
198        memset(pos->start_uncertain, '=', 2*comp_size);
199    }
200}
201
202void GEN_free_position(struct GEN_position *pos) {
203    if (lastFreedPosition) {
204        free(lastFreedPosition->start_pos); // rest is allocated together with start_pos
205        free(lastFreedPosition);
206    }
207
208    lastFreedPosition = pos;
209}
210
211static void clearParseTable(char **parseTable, int parts) {
212    int p;
213    free(parseTable[0]);
214    for (p = 0; p<parts; p++) parseTable[p] = 0;
215}
216
217static GB_ERROR parseCSV(GBDATA *gb_gene, const char *field_name, int parts, char **parseTable) {
218    // reads a field and splits the content at ','
219    // results are put into parseTable (only first entry in parseTable is allocated, other entries
220    // are simply pointers into the same string)
221
222    GB_ERROR  error      = 0;
223    GBDATA   *gb_field   = GB_entry(gb_gene, field_name);
224    if (!gb_field) error = GBS_global_string("Expected entry '%s' missing", field_name);
225    else {
226        char *content       = GB_read_string(gb_field);
227        if (!content) error = GB_await_error();
228        else {
229            int   p;
230            char *pos = content;
231
232            clearParseTable(parseTable, parts);
233
234            for (p = 0; p<(parts-1) && !error; p++) {
235                char *comma = strchr(pos, ',');
236                if (comma) {
237                    comma[0]      = 0;
238                    parseTable[p] = pos;
239                    pos           = comma+1;
240                }
241                else {
242                    error = "comma expected";
243                }
244            }
245
246            if (!error) {
247                parseTable[p] = pos; // rest
248
249                if (strchr(pos, ',') != 0) error = "comma found where none expected";
250            }
251
252            if (error) {
253                error         = GBS_global_string("%s in '%s' (while parsing %i values from '%s')",
254                                                  error, pos, parts, GB_read_char_pntr(gb_field));
255                parseTable[0] = content; // ensure content gets freed
256            }
257        }
258    }
259
260    if (error) clearParseTable(parseTable, parts);
261    return error;
262}
263
264static GB_ERROR parsePositions(GBDATA *gb_gene, const char *field_name, int parts, size_t *results, char **parseTable) {
265    GB_ERROR error = parseCSV(gb_gene, field_name, parts, parseTable);
266    if (!error) {
267        int p;
268        for (p = 0; p<parts && !error; p++) {
269            char *end;
270            results[p] = strtol(parseTable[p], &end, 10);
271            if (end == parseTable[p]) { // error
272                error = GBS_global_string("can't convert '%s' to number (while parsing '%s')", parseTable[p], field_name);
273            }
274        }
275    }
276    return error;
277}
278
279struct GEN_position *GEN_read_position(GBDATA *gb_gene) {
280    int                  parts         = 1;
281    GB_BOOL              joinable      = GB_FALSE;
282    GBDATA              *gb_pos_joined = GB_entry(gb_gene, "pos_joined");
283    struct GEN_position *pos           = 0;
284    GB_ERROR             error         = 0;
285
286    if (gb_pos_joined) {
287        parts = GB_read_int(gb_pos_joined);
288        if (parts != 1) { // splitted
289            if (parts>1) joinable = GB_TRUE;
290            else if (parts<-1) parts = -parts; // neg value means "not joinable" (comes from feature location 'order(...)')
291            else error = GBS_global_string("Illegal value %i in 'pos_joined'", parts);
292        }
293    }
294
295    if (!error) {
296        pos = GEN_new_position(parts, joinable);
297
298        char **parseTable = GB_calloc(parts, sizeof(*parseTable));
299
300        error =             parsePositions(gb_gene, "pos_start", parts, pos->start_pos, parseTable);
301        if (!error) error = parsePositions(gb_gene, "pos_stop",  parts, pos->stop_pos,  parseTable);
302
303        int p;
304        if (!error) {
305            error = parseCSV(gb_gene, "pos_complement",  parts, parseTable);
306            for (p = 0; p<parts && !error; p++) {
307                const char *val = parseTable[p];
308                if ((val[0] != '0' && val[0] != '1') || val[1] != 0) {
309                    error = GBS_global_string("Invalid content '%s' in 'pos_complement' (expected: \"01\")", val);
310                }
311                else {
312                    pos->complement[p] = (unsigned char)atoi(val);
313                }
314            }
315        }
316
317        if (!error) {
318            GBDATA *gb_pos_certain = GB_entry(gb_gene, "pos_certain");
319
320            if (gb_pos_certain) {
321                error = parseCSV(gb_gene, "pos_certain",  parts, parseTable);
322                GEN_use_uncertainties(pos);
323                for (p = 0; p<parts && !error; p++) {
324                    const unsigned char *val = (unsigned char *)(parseTable[p]);
325                    int                  vp;
326
327                    for (vp = 0; vp<2; vp++) {
328                        unsigned char c = val[vp];
329                        if (c != '<' && c != '=' && c != '>' && (c != "+-"[vp])) {
330                            error = GBS_global_string("Invalid content '%s' in 'pos_certain' (expected 2 from \"<=>\")", val);
331                        }
332                    }
333                    if (!error) {
334                        pos->start_uncertain[p] = val[0];
335                        pos->stop_uncertain[p]  = val[1];
336                    }
337                }
338            }
339        }
340
341        clearParseTable(parseTable, parts);
342        free(parseTable);
343    }
344
345    gb_assert(error || pos);
346    if (error) {
347        GB_export_error(error);
348        if (pos) {
349            GEN_free_position(pos);
350            pos = 0;
351        }
352    }
353    return pos;
354}
355
356GB_ERROR GEN_write_position(GBDATA *gb_gene, const struct GEN_position *pos) {
357    GB_ERROR  error          = 0;
358    GBDATA   *gb_pos_joined  = GB_entry(gb_gene, "pos_joined");
359    GBDATA   *gb_pos_certain = GB_entry(gb_gene, "pos_certain");
360    GBDATA   *gb_pos_start;
361    GBDATA   *gb_pos_stop;
362    GBDATA   *gb_pos_complement;
363    int       p;
364
365    gb_assert(pos);
366
367    gb_pos_start             = GB_search(gb_gene, "pos_start", GB_STRING);
368    if (!gb_pos_start) error = GB_await_error();
369
370    if (!error) {
371        gb_pos_stop             = GB_search(gb_gene, "pos_stop", GB_STRING);
372        if (!gb_pos_stop) error = GB_await_error();
373    }
374    if (!error) {
375        gb_pos_complement             = GB_search(gb_gene, "pos_complement", GB_STRING);
376        if (!gb_pos_complement) error = GB_await_error();
377    }
378
379    if (!error) {
380        if (pos->start_uncertain) {
381            if (!gb_pos_certain) {
382                gb_pos_certain             = GB_search(gb_gene, "pos_certain", GB_STRING);
383                if (!gb_pos_certain) error = GB_await_error();
384            }
385        }
386        else {
387            if (gb_pos_certain) {
388                error          = GB_delete(gb_pos_certain);
389                gb_pos_certain = 0;
390            }
391        }
392    }
393
394#if defined(DEBUG)
395    /* test data */
396    if (!error) {
397        for (p = 0; p<pos->parts; ++p) {
398            char c;
399
400            c = pos->complement[p]; gb_assert(c == 0 || c == 1);
401            gb_assert(pos->start_pos[p] <= pos->stop_pos[p]);
402            if (pos->start_uncertain) {
403                c = pos->start_uncertain[p]; gb_assert(strchr("<=>+", c) != 0);
404                c = pos->stop_uncertain[p]; gb_assert(strchr("<=>-", c) != 0);
405            }
406        }
407    }
408#endif /* DEBUG */
409
410    if (!error) {
411        if (pos->parts == 1) {
412            if (gb_pos_joined) error = GB_delete(gb_pos_joined);
413           
414            if (!error) error = GB_write_string(gb_pos_start,      GBS_global_string("%zu", pos->start_pos[0]));
415            if (!error) error = GB_write_string(gb_pos_stop,       GBS_global_string("%zu", pos->stop_pos[0]));
416            if (!error) error = GB_write_string(gb_pos_complement, GBS_global_string("%c", pos->complement[0]+'0'));
417
418            if (!error && gb_pos_certain) {
419                error = GB_write_string(gb_pos_certain, GBS_global_string("%c%c", pos->start_uncertain[0], pos->stop_uncertain[0]));
420            }
421        }
422        else {
423            if (!gb_pos_joined) {
424                gb_pos_joined             = GB_search(gb_gene, "pos_joined", GB_INT);
425                if (!gb_pos_joined) error = GB_await_error();
426            }
427            if (!error) error = GB_write_int(gb_pos_joined, pos->parts * (pos->joinable ? 1 : -1)); // neg. parts means not joinable
428
429            if (!error) {
430                void *start      = GBS_stropen(12*pos->parts);
431                void *stop       = GBS_stropen(12*pos->parts);
432                void *complement = GBS_stropen(2*pos->parts);
433                void *uncertain  = GBS_stropen(3*pos->parts);
434
435                for (p = 0; p<pos->parts; ++p) {
436                    if (p>0) {
437                        GBS_chrcat(start, ',');
438                        GBS_chrcat(stop, ',');
439                        GBS_chrcat(complement, ',');
440                        GBS_chrcat(uncertain, ',');
441                    }
442                    GBS_strcat(start, GBS_global_string("%zu", pos->start_pos[p]));
443                    GBS_strcat(stop,  GBS_global_string("%zu", pos->stop_pos[p]));
444                    GBS_chrcat(complement, pos->complement[p]+'0');
445                    if (gb_pos_certain) {
446                        GBS_chrcat(uncertain, pos->start_uncertain[p]);
447                        GBS_chrcat(uncertain, pos->stop_uncertain[p]);
448                    }
449                }
450
451                char *sstart      = GBS_strclose(start);
452                char *sstop       = GBS_strclose(stop);
453                char *scomplement = GBS_strclose(complement);
454                char *suncertain  = GBS_strclose(uncertain);
455
456                error             = GB_write_string(gb_pos_start, sstart);
457                if (!error) error = GB_write_string(gb_pos_stop, sstop);
458                if (!error) error = GB_write_string(gb_pos_complement, scomplement);
459                if (!error && gb_pos_certain) error = GB_write_string(gb_pos_certain, suncertain);
460
461                free(suncertain);
462                free(scomplement);
463                free(sstop);
464                free(sstart);
465            }
466        }
467    }
468
469    return error;
470}
471
472static struct GEN_position *location2sort = 0;
473
474static int cmp_location_parts(const void *v1, const void *v2) {
475    int i1 = *(int*)v1;
476    int i2 = *(int*)v2;
477
478    int cmp = location2sort->start_pos[i1]-location2sort->start_pos[i2];
479    if (!cmp) {
480        cmp = location2sort->stop_pos[i1]-location2sort->stop_pos[i2];
481    }
482    return cmp;
483}
484
485void GEN_sortAndMergeLocationParts(struct GEN_position *location) {
486    // Note: makes location partly invalid (only start_pos + stop_pos are valid afterwards)
487    int  parts = location->parts;
488    int *idx   = (int*)malloc(parts*sizeof(*idx)); // idx[newpos] = oldpos
489    int  i, p;
490
491    for (p = 0; p<parts; ++p) idx[p] = p;
492
493    location2sort = location;
494    qsort(idx, parts, sizeof(*idx), cmp_location_parts);
495    location2sort = 0;
496
497    for (p = 0; p<parts; ++p) {
498        i = idx[p];
499
500#define swap(a, b, type) do { type tmp = (a); (a) = (b); (b) = (tmp); } while (0)
501
502        if (i != p) {
503            swap(location->start_pos[i],  location->start_pos[p],  size_t);
504            swap(location->stop_pos[i],   location->stop_pos[p],   size_t);
505            swap(idx[i], idx[p], int);
506        }
507    }
508
509#if defined(DEBUG) && 0
510    printf("Locations sorted:\n");
511    for (p = 0; p<parts; ++p) {
512        printf("  [%i] %i - %i %i\n", p, location->start_pos[p], location->stop_pos[p], (int)(location->complement[p]));
513    }
514#endif /* DEBUG */
515   
516    i = 0;
517    for (p = 1; p<parts; p++) {
518        if ((location->stop_pos[i]+1) >= location->start_pos[p]) {
519            // parts overlap or are directly consecutive
520
521            location->stop_pos[i]  = location->stop_pos[p];
522        }
523        else {
524            i++;
525            location->start_pos[i] = location->start_pos[p];
526            location->stop_pos[i]  = location->stop_pos[p];
527        }
528    }
529    location->parts = i+1;
530
531#if defined(DEBUG) && 0
532    parts = location->parts;
533    printf("Locations merged:\n");
534    for (p = 0; p<parts; ++p) {
535        printf("  [%i] %i - %i %i\n", p, location->start_pos[p], location->stop_pos[p], (int)(location->complement[p]));
536    }
537#endif /* DEBUG */
538
539    free(idx);
540}
541
542
543
544//  -----------------------------------------
545//      test if species is pseudo-species
546//  -----------------------------------------
547
548const char *GEN_origin_organism(GBDATA *gb_pseudo) {
549    GBDATA *gb_origin = GB_entry(gb_pseudo, "ARB_origin_species");
550    return gb_origin ? GB_read_char_pntr(gb_origin) : 0;
551}
552const char *GEN_origin_gene(GBDATA *gb_pseudo) {
553    GBDATA *gb_origin = GB_entry(gb_pseudo, "ARB_origin_gene");
554    return gb_origin ? GB_read_char_pntr(gb_origin) : 0;
555}
556
557GB_BOOL GEN_is_pseudo_gene_species(GBDATA *gb_species) {
558    return GEN_origin_organism(gb_species) != 0;
559}
560
561//  ------------------------------------------------
562//      find organism or gene for pseudo-species
563//  ------------------------------------------------
564
565GB_ERROR GEN_organism_not_found(GBDATA *gb_pseudo) {
566    GB_ERROR error = 0;
567
568    gb_assert(GEN_is_pseudo_gene_species(gb_pseudo));
569    gb_assert(GEN_find_origin_organism(gb_pseudo, 0) == 0);
570
571    error = GB_export_errorf("The gene-species '%s' refers to an unknown organism (%s)\n"
572                             "This occurs if you rename or delete the organism or change the entry\n"
573                             "'ARB_origin_species' and will most likely cause serious problems.",
574                             GBT_read_name(gb_pseudo),
575                             GEN_origin_organism(gb_pseudo));
576
577    return error;
578}
579
580// @@@ FIXME: missing: GEN_gene_not_found (like GEN_organism_not_found)
581
582/* ---------------------------------- */
583/*      searching pseudo species      */
584/* ---------------------------------- */
585
586static const char *pseudo_species_hash_key(const char *organism_name, const char *gene_name) {
587    return GBS_global_string("%s*%s", organism_name, gene_name);
588}
589
590GBDATA *GEN_read_pseudo_species_from_hash(GB_HASH *pseudo_hash, const char *organism_name, const char *gene_name) {
591    return (GBDATA*)GBS_read_hash(pseudo_hash, pseudo_species_hash_key(organism_name, gene_name));
592}
593
594void GEN_add_pseudo_species_to_hash(GBDATA *gb_pseudo, GB_HASH *pseudo_hash) {
595    const char *organism_name = GEN_origin_organism(gb_pseudo);
596    const char *gene_name     = GEN_origin_gene(gb_pseudo);
597
598    gb_assert(organism_name);
599    gb_assert(gene_name);
600
601    GBS_write_hash(pseudo_hash, pseudo_species_hash_key(organism_name, gene_name), (long)gb_pseudo);
602}
603
604GB_HASH *GEN_create_pseudo_species_hash(GBDATA *gb_main, int additionalSize) {
605    GB_HASH *pseudo_hash = GBS_create_hash(GBT_get_species_hash_size(gb_main)+2*additionalSize, GB_IGNORE_CASE);
606    GBDATA  *gb_pseudo;
607
608    for (gb_pseudo = GEN_first_pseudo_species(gb_main);
609         gb_pseudo;
610         gb_pseudo = GEN_next_pseudo_species(gb_pseudo))
611    {
612        GEN_add_pseudo_species_to_hash(gb_pseudo, pseudo_hash);
613    }
614
615    return pseudo_hash;
616}
617
618GBDATA *GEN_find_pseudo_species(GBDATA *gb_main, const char *organism_name, const char *gene_name, GB_HASH *pseudo_hash) {
619    // parameter pseudo_hash :
620    // 0 -> use slow direct search [if you only search one]
621    // otherwise it shall be a hash generated by GEN_create_pseudo_species_hash() [if you search several times]
622    // Note : use GEN_add_pseudo_species_to_hash to keep hash up-to-date
623    GBDATA *gb_pseudo;
624
625    if (pseudo_hash) {
626        gb_pseudo = GEN_read_pseudo_species_from_hash(pseudo_hash, organism_name, gene_name);
627    }
628    else {
629        for (gb_pseudo = GEN_first_pseudo_species(gb_main);
630             gb_pseudo;
631             gb_pseudo = GEN_next_pseudo_species(gb_pseudo))
632        {
633            const char *origin_gene_name = GEN_origin_gene(gb_pseudo);
634            if (strcmp(gene_name, origin_gene_name) == 0) {
635                const char *origin_species_name = GEN_origin_organism(gb_pseudo);
636                if (strcmp(organism_name, origin_species_name) == 0) {
637                    break; // found pseudo species
638                }
639            }
640        }
641    }
642    return gb_pseudo;
643}
644
645/* --------------------------- */
646/*      searching origins      */
647/* --------------------------- */
648
649GBDATA *GEN_find_origin_organism(GBDATA *gb_pseudo, GB_HASH *organism_hash) {
650    // parameter organism_hash:
651    // 0 -> use slow direct search [if you only search one or two]
652    // otherwise it shall be a hash generated by GBT_create_organism_hash() [if you search several times]
653    // Note : use GBT_add_item_to_hash() to keep hash up-to-date
654   
655    const char *origin_species_name;
656    GBDATA     *gb_organism = 0;
657    gb_assert(GEN_is_pseudo_gene_species(gb_pseudo));
658
659    origin_species_name = GEN_origin_organism(gb_pseudo);
660    if (origin_species_name) {
661        if (organism_hash) {
662            gb_organism = (GBDATA*)GBS_read_hash(organism_hash, origin_species_name);
663        }
664        else {
665            gb_organism = GBT_find_species_rel_species_data(GB_get_father(gb_pseudo), origin_species_name);
666        }
667    }
668
669    return gb_organism;
670}
671
672GBDATA *GEN_find_origin_gene(GBDATA *gb_pseudo, GB_HASH *organism_hash) {
673    const char *origin_gene_name;
674
675    gb_assert(GEN_is_pseudo_gene_species(gb_pseudo));
676
677    origin_gene_name = GEN_origin_gene(gb_pseudo);
678    if (origin_gene_name) {
679        GBDATA *gb_organism = GEN_find_origin_organism(gb_pseudo, organism_hash);
680        gb_assert(gb_organism);
681
682        return GEN_find_gene(gb_organism, origin_gene_name);
683    }
684    return 0;
685}
686
687//  --------------------------------
688//      find pseudo-species
689//  --------------------------------
690
691GBDATA* GEN_first_pseudo_species(GBDATA *gb_main) {
692    GBDATA *gb_species = GBT_first_species(gb_main);
693
694    if (!gb_species || GEN_is_pseudo_gene_species(gb_species)) return gb_species;
695    return GEN_next_pseudo_species(gb_species);
696}
697
698GBDATA* GEN_first_pseudo_species_rel_species_data(GBDATA *gb_species_data) {
699    GBDATA *gb_species = GBT_first_species_rel_species_data(gb_species_data);
700
701    if (!gb_species || GEN_is_pseudo_gene_species(gb_species)) return gb_species;
702    return GEN_next_pseudo_species(gb_species);
703}
704
705GBDATA* GEN_next_pseudo_species(GBDATA *gb_species) {
706    if (gb_species) {
707        while (1) {
708            gb_species = GBT_next_species(gb_species);
709            if (!gb_species || GEN_is_pseudo_gene_species(gb_species)) break;
710        }
711    }
712    return gb_species;
713}
714
715GBDATA *GEN_first_marked_pseudo_species(GBDATA *gb_main) {
716    GBDATA *gb_species = GBT_first_marked_species(gb_main);
717
718    if (!gb_species || GEN_is_pseudo_gene_species(gb_species)) return gb_species;
719    return GEN_next_marked_pseudo_species(gb_species);
720}
721
722GBDATA* GEN_next_marked_pseudo_species(GBDATA *gb_species) {
723    if (gb_species) {
724        while (1) {
725            gb_species = GBT_next_marked_species(gb_species);
726            if (!gb_species || GEN_is_pseudo_gene_species(gb_species)) break;
727        }
728    }
729    return gb_species;
730}
731
732
733
734/* ------------------------ */
735/*        organisms         */
736/* ------------------------ */
737
738GB_BOOL GEN_is_organism(GBDATA *gb_species) {
739    gb_assert(GEN_is_genome_db(GB_get_root(gb_species), -1)); /* assert this is a genome db */
740    /* otherwise it is an error to use GEN_is_organism (or its callers)!!!! */
741   
742    return GB_entry(gb_species, GENOM_ALIGNMENT) != 0;
743}
744
745GBDATA *GEN_find_organism(GBDATA *gb_main, const char *name) {
746    GBDATA *gb_orga = GBT_find_species(gb_main, name);
747    if (gb_orga) {
748        if (!GEN_is_organism(gb_orga)) {
749            fprintf(stderr, "ARBDB-warning: found unspecific species named '%s', but expected an 'organism' with that name\n", name);
750            gb_orga = 0;
751        }
752    }
753    return gb_orga;
754}
755
756GBDATA *GEN_first_organism(GBDATA *gb_main) {
757    GBDATA *gb_organism = GBT_first_species(gb_main);
758
759    if (!gb_organism || GEN_is_organism(gb_organism)) return gb_organism;
760    return GEN_next_organism(gb_organism);
761}
762GBDATA *GEN_next_organism(GBDATA *gb_organism) {
763    if (gb_organism) {
764        while (1) {
765            gb_organism = GBT_next_species(gb_organism);
766            if (!gb_organism || GEN_is_organism(gb_organism)) break;
767        }
768    }
769    return gb_organism;
770
771}
772
773long GEN_get_organism_count(GBDATA *gb_main) {
774    long    count       = 0;
775    GBDATA *gb_organism = GEN_first_organism(gb_main);
776    while (gb_organism) {
777        count++;
778        gb_organism = GEN_next_organism(gb_organism);
779    }
780    return count;
781}
782
783
784GBDATA *GEN_first_marked_organism(GBDATA *gb_main) {
785    GBDATA *gb_organism = GBT_first_marked_species(gb_main);
786
787    if (!gb_organism || GEN_is_organism(gb_organism)) return gb_organism;
788    return GEN_next_marked_organism(gb_organism);
789}
790GBDATA *GEN_next_marked_organism(GBDATA *gb_organism) {
791    if (gb_organism) {
792        while (1) {
793            gb_organism = GBT_next_marked_species(gb_organism);
794            if (!gb_organism || GEN_is_organism(gb_organism)) break;
795        }
796    }
797    return gb_organism;
798}
799
800char *GEN_global_gene_identifier(GBDATA *gb_gene, GBDATA *gb_organism) {
801    if (!gb_organism) {
802        gb_organism = GB_get_grandfather(gb_gene);
803        gb_assert(gb_organism);
804    }
805
806    return GBS_global_string_copy("%s/%s", GBT_read_name(gb_organism), GBT_read_name(gb_gene));
807}
Note: See TracBrowser for help on using the repository browser.