root/trunk/ARB_GDE/GDE_arbdb_io.cxx

Revision 8516, 15.4 KB (checked in by westram, 2 months ago)
  • replace other uses of literal main-container-names
  • arb_gene_probe generates species_data with correct protection
    • updated test result
  • fixed locals in arb_prm_read()
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include "GDE_def.h"
2#include "GDE_proto.h"
3
4#include <aw_msg.hxx>
5#include <arb_progress.h>
6#include <AW_rename.hxx>
7#include <AP_filter.hxx>
8#include <aw_awar_defs.hxx>
9
10// AISC_MKPT_PROMOTE:#ifndef GDE_EXTGLOB_H
11// AISC_MKPT_PROMOTE:#include "GDE_extglob.h"
12// AISC_MKPT_PROMOTE:#endif
13
14typedef unsigned int UINT;
15
16static int Arbdb_get_curelem(NA_Alignment *dataset)
17{
18    int curelem;
19    curelem = dataset->numelements++;
20    if (curelem == 0) {
21        dataset->element = (NA_Sequence *) Calloc(5, sizeof(NA_Sequence));
22        dataset->maxnumelements = 5;
23    }
24    else if (curelem == dataset->maxnumelements) {
25        (dataset->maxnumelements) *= 2;
26        dataset->element = (NA_Sequence *) Realloc((char *)dataset->element,
27                                                   dataset->maxnumelements * sizeof(NA_Sequence));
28    }
29    return curelem;
30}
31
32extern int Default_PROColor_LKUP[], Default_NAColor_LKUP[];
33
34static void set_constant_fields(NA_Sequence *this_elem) {
35    this_elem->attr            = DEFAULT_X_ATTR;
36    this_elem->comments        = strdup("no comments");
37    this_elem->comments_maxlen = 1 + (this_elem->comments_len = strlen(this_elem->comments));
38    this_elem->elementtype     = TEXT;
39    this_elem->rmatrix         = NULL;
40    this_elem->tmatrix         = NULL;
41    this_elem->col_lut         = Default_PROColor_LKUP;
42}
43
44static void AppendNA_and_free(NA_Sequence *this_elem, uchar *& sequfilt) {
45    AppendNA((NA_Base *)sequfilt, strlen((const char *)sequfilt), this_elem);
46    freenull(sequfilt);
47}
48
49static int InsertDatainGDE(NA_Alignment *dataset, GBDATA **the_species, unsigned char **the_names,
50                           unsigned char **the_sequences, unsigned long numberspecies,
51                           unsigned long maxalignlen, const AP_filter *filter, GapCompression compress,
52                           bool cutoff_stop_codon)
53{
54    GBDATA      *gb_species;
55    GBDATA      *gbd;
56    NA_Sequence *this_elem;
57    AP_filter   *allocatedFilter = 0;
58
59    gde_assert(contradicted(the_species, the_names));
60
61    if (filter==0) {
62        allocatedFilter = new AP_filter(maxalignlen);
63        filter          = allocatedFilter;
64    }
65    else {
66        size_t fl = filter->get_length();
67        if (fl < maxalignlen) {
68            aw_message("Warning: Your filter is shorter than the alignment len");
69            maxalignlen = fl;
70        }
71    }
72
73    size_t *seqlen=(size_t *)calloc((unsigned int)numberspecies, sizeof(size_t));
74    // sequences may have different length
75    {
76        unsigned long i;
77        for (i=0; i<numberspecies; i++) {
78            seqlen[i] = strlen((char *)the_sequences[i]);
79        }
80    }
81
82    if (cutoff_stop_codon) {
83        unsigned long i;
84        fputs("[CUTTING STOP CODONS]\n", stdout);
85        for (i=0; i<numberspecies; i++) {
86            uchar *seq        = the_sequences[i];
87            uchar *stop_codon = (uchar*)strchr((char*)seq, '*');
88            if (stop_codon) {
89                long pos     = stop_codon-seq;
90                long restlen = maxalignlen-pos;
91                memset(stop_codon, '.', restlen);
92            }
93        }
94    }
95
96    // store (compressed) sequence data in array:
97    uchar **sequfilt = (uchar**)calloc((unsigned int)numberspecies+1, sizeof(uchar*));
98
99    if (compress==COMPRESS_ALL) { // compress all gaps and filter positions
100        long          len = filter->get_filtered_length();
101        unsigned long i;
102
103        for (i=0; i<numberspecies; i++) {
104            sequfilt[i]   = (uchar*)calloc((unsigned int)len+1, sizeof(uchar));
105            long newcount = 0;
106            for (unsigned long col=0; (col<maxalignlen); col++) {
107                char c = the_sequences[i][col];
108                if (!c) break;
109                if ((filter->use_position(col)) && (c!='-') && (c!='.')) {
110                    sequfilt[i][newcount++] = c;
111                }
112            }
113        }
114    }
115    else {
116        if (compress==COMPRESS_VERTICAL_GAPS || // compress vertical gaps (and '.')
117            compress == COMPRESS_NONINFO_COLUMNS) // and additionally all columns containing no info (only N or X)
118        {
119            size_t i;
120            bool   isInfo[256];
121
122            for (i=0; i<256; i++) isInfo[i] = true;
123            isInfo[UINT('-')] = false;
124            isInfo[UINT('.')] = false;
125            if (compress == COMPRESS_NONINFO_COLUMNS) {
126                GB_alignment_type type = GBT_get_alignment_type(dataset->gb_main, dataset->alignment_name);
127                switch (type) {
128                    case GB_AT_RNA:
129                    case GB_AT_DNA:
130                        isInfo[UINT('N')] = false;
131                        isInfo[UINT('n')] = false;
132                        break;
133                    case GB_AT_AA:
134                        isInfo[UINT('X')] = false;
135                        isInfo[UINT('x')] = false;
136                        break;
137                    default:
138                        gde_assert(0);
139                        break;
140                }
141            }
142
143            bool  modified     = false;
144            char *filterString = filter->to_string();
145
146            for (i=0; i<maxalignlen; i++) {
147                if (filter->use_position(i)) {
148                    bool wantColumn = false;
149
150                    for (size_t n=0; n<numberspecies; n++) {
151                        if (i < seqlen[n]) {
152                            if (isInfo[UINT(the_sequences[n][i])]) {
153                                wantColumn = true; // have info -> take column
154                                break;
155                            }
156                        }
157                    }
158                    if (!wantColumn) {
159                        filterString[i] = '0';
160                        modified        = true;
161                    }
162                }
163            }
164
165            if (modified) {
166                size_t len = filter->get_length();
167
168                delete allocatedFilter;
169                filter = allocatedFilter = new AP_filter(filterString, NULL, len);
170            }
171
172            free(filterString);
173        }
174
175        long   len = filter->get_filtered_length();
176        size_t i;
177
178        for (i=0; i<numberspecies; i++) {
179            int  c;
180            long newcount = 0;
181
182            sequfilt[i]      = (uchar*)malloc((unsigned int)len+1);
183            sequfilt[i][len] = 0;
184            memset(sequfilt[i], '.', len); // Generate empty sequences
185
186            const uchar *simplify = filter->get_simplify_table();
187            for (size_t col=0; (col<maxalignlen) && (c=the_sequences[i][col]); col++) {
188                if (filter->use_position(col)) {
189                    sequfilt[i][newcount++] = simplify[c];
190                }
191            }
192        }
193    }
194
195    {
196        GB_transaction  dummy(db_access.gb_main);
197        char           *str   = filter->to_string();
198        GB_ERROR        error = GBT_write_string(db_access.gb_main, AWAR_GDE_EXPORT_FILTER, str);
199        free(str);
200
201        if (error) aw_message(error);
202    }
203
204    free(seqlen);
205
206    long number    = 0;
207    int  curelem;
208    int  bad_names = 0;
209
210    arb_progress progress("Read data from DB", numberspecies);
211    GB_ERROR     error = 0;
212    if (the_species) {
213        for (gb_species = the_species[number]; gb_species && !error; gb_species = the_species[++number]) {
214            curelem   = Arbdb_get_curelem(dataset);
215            this_elem = &(dataset->element[curelem]);
216
217            InitNASeq(this_elem, RNA);
218            this_elem->gb_species = gb_species;
219
220#define GET_FIELD_CONTENT(fieldname,buffer,bufsize) do {                \
221                gbd = GB_entry(gb_species, fieldname);                  \
222                if (gbd) {                                              \
223                    const char *val = GB_read_char_pntr(gbd);           \
224                    strncpy_terminate(buffer, val, bufsize);            \
225                }                                                       \
226                else buffer[0] = 0;                                     \
227            } while(0)
228
229            GET_FIELD_CONTENT("name",      this_elem->short_name, SIZE_SHORT_NAME);
230            GET_FIELD_CONTENT("author",    this_elem->authority,  SIZE_AUTHORITY);
231            GET_FIELD_CONTENT("full_name", this_elem->seq_name,   SIZE_SEQ_NAME);
232            GET_FIELD_CONTENT("acc",       this_elem->id,         SIZE_ID);
233
234            if (AWTC_name_quality(this_elem->short_name) != 0) bad_names++;
235            AppendNA_and_free(this_elem, sequfilt[number]);
236            set_constant_fields(this_elem);
237            progress.inc_and_check_user_abort(error);
238        }
239    }
240    else {      // use the_names
241        unsigned char *species_name;
242
243        for (species_name=the_names[number]; species_name && !error; species_name=the_names[++number]) {
244            curelem   = Arbdb_get_curelem(dataset);
245            this_elem = &(dataset->element[curelem]);
246
247            InitNASeq(this_elem, RNA);
248            this_elem->gb_species = 0;
249
250            strncpy(this_elem->short_name, (char*)species_name, SIZE_SHORT_NAME);
251            this_elem->authority[0] = 0;
252            this_elem->seq_name[0]  = 0;
253            this_elem->id[0]        = 0;
254
255            if (AWTC_name_quality(this_elem->short_name) != 0) bad_names++;
256            AppendNA_and_free(this_elem, sequfilt[number]);
257            set_constant_fields(this_elem);
258            progress.inc_and_check_user_abort(error);
259        }
260    }
261
262    if (!error) {
263        if (bad_names) {
264            aw_message(GBS_global_string("Problematic names found: %i\n"
265                                         "External program call may fail or produce invalid results.\n"
266                                         "You might want to use 'Generate new names' and read the associated help.",
267                                         bad_names));
268        }
269
270        {
271            unsigned long i;
272            for (i=0; i<dataset->numelements; i++) {
273                dataset->maxlen = MAX(dataset->maxlen,
274                                      dataset->element[i].seqlen+dataset->element[i].offset);
275            }
276            for (i=0; i<numberspecies; i++)
277            {
278                delete sequfilt[i];
279            }
280            free(sequfilt);
281        }
282    }
283
284    delete allocatedFilter;
285    if (error) {
286        aw_message(error);
287        return 1; // = aborted
288    }
289    return 0;
290
291}
292
293void ReadArbdb_plain(char */*filename*/, NA_Alignment *dataset, int /*type*/) {
294    ReadArbdb(dataset, true, NULL, COMPRESS_NONE, false);
295}
296
297int ReadArbdb2(NA_Alignment *dataset, AP_filter *filter, GapCompression compress, bool cutoff_stop_codon) {
298    dataset->gb_main = db_access.gb_main;
299
300    GBDATA **the_species;
301    long     maxalignlen;
302    long     numberspecies = 0;
303    uchar  **the_sequences;
304    uchar  **the_names;
305    char    *error         = db_access.get_sequences(db_access.client_data,
306                                                     the_species, the_names, the_sequences,
307                                                     numberspecies, maxalignlen);
308
309    gde_assert(contradicted(the_species, the_names));
310
311    if (error) {
312        aw_message(error);
313        return 1;
314    }
315
316    InsertDatainGDE(dataset, 0, the_names, (unsigned char **)the_sequences, numberspecies, maxalignlen, filter, compress, cutoff_stop_codon);
317    long i;
318    for (i=0; i<numberspecies; i++) {
319        delete the_sequences[i];
320    }
321    delete the_sequences;
322    if (the_species) delete the_species;
323    else delete the_names;
324
325    return 0;
326}
327
328
329
330int ReadArbdb(NA_Alignment *dataset, bool marked, AP_filter *filter, GapCompression compress, bool cutoff_stop_codon) {
331    dataset->gb_main = db_access.gb_main;
332
333    // Alignment choosen ?
334
335    GBDATA  *gb_species_data = GBT_get_species_data(dataset->gb_main);
336    long     maxalignlen     = GBT_get_alignment_len(db_access.gb_main, dataset->alignment_name);
337    GBDATA **the_species;
338    long     numberspecies   = 0;
339    long     missingdata     = 0;
340
341    GBDATA *gb_species;
342    if (marked) gb_species = GBT_first_marked_species_rel_species_data(gb_species_data);
343    else gb_species        = GBT_first_species_rel_species_data(gb_species_data);
344
345    while (gb_species) {
346        if (GBT_read_sequence(gb_species, dataset->alignment_name)) numberspecies++;
347        else missingdata++;
348
349        if (marked) gb_species = GBT_next_marked_species(gb_species);
350        else gb_species        = GBT_next_species(gb_species);
351    }
352
353    if (missingdata) {
354        aw_message(GBS_global_string("Skipped %li species which did not contain data in '%s'", missingdata, dataset->alignment_name));
355    }
356
357    the_species   = (GBDATA**)calloc((unsigned int)numberspecies+1, sizeof(GBDATA*));
358    numberspecies = 0;
359
360    if (marked) gb_species = GBT_first_marked_species_rel_species_data(gb_species_data);
361    else gb_species        = GBT_first_species_rel_species_data(gb_species_data);
362
363    while (gb_species) {
364        if (GBT_read_sequence(gb_species, dataset->alignment_name)) {
365            the_species[numberspecies]=gb_species;
366            numberspecies++;
367        }
368
369        if (marked) gb_species = GBT_next_marked_species(gb_species);
370        else gb_species        = GBT_next_species(gb_species);
371    }
372
373    maxalignlen = GBT_get_alignment_len(db_access.gb_main, dataset->alignment_name);
374
375    char **the_sequences = (char**)calloc((unsigned int)numberspecies+1, sizeof(char*));
376
377    long i;
378    for (i=0; the_species[i]; i++) {
379        the_sequences[i] = (char *)malloc((size_t)maxalignlen+1);
380        the_sequences[i][maxalignlen] = 0;
381        memset(the_sequences[i], '.', (size_t)maxalignlen);
382        const char *data = GB_read_char_pntr(GBT_read_sequence(the_species[i], dataset->alignment_name));
383        int size = strlen(data);
384        if (size > maxalignlen) size = (int)maxalignlen;
385        strncpy_terminate(the_sequences[i], data, size+1);
386    }
387    InsertDatainGDE(dataset, the_species, 0, (unsigned char **)the_sequences, numberspecies, maxalignlen, filter, compress, cutoff_stop_codon);
388    for (i=0; i<numberspecies; i++) {
389        free(the_sequences[i]);
390    }
391    free(the_sequences);
392    free(the_species);
393
394    return 0;
395}
396
397int getelem(NA_Sequence *a, int b) {
398    if (a->seqlen == 0) return -1;
399
400    if (b<a->offset || (b>a->offset+a->seqlen)) {
401        switch (a->elementtype) {
402            case DNA:
403            case RNA:  return 0;
404            case PROTEIN:
405            case TEXT: return '~';
406            case MASK: return '0';
407            default:   return '-';
408        }
409    }
410
411    return a->sequence[b-a->offset];
412}
413
414void putelem(NA_Sequence *a, int b, NA_Base c) {
415    int      j;
416    NA_Base *temp;
417
418    if (b>=(a->offset+a->seqmaxlen)) {
419        Warning("Putelem:insert beyond end of sequence space ignored");
420    }
421    else if (b >= (a->offset)) {
422        a->sequence[b-(a->offset)] = c;
423    }
424    else {
425        temp = (NA_Base*)Calloc(a->seqmaxlen+a->offset-b, sizeof(NA_Base));
426        switch (a->elementtype) {
427            // Pad out with gap characters fron the point of insertion to the offset
428            case MASK:
429                for (j=b; j<a->offset; j++) temp[j-b]='0';
430                break;
431            case DNA:
432            case RNA:
433                for (j=b; j<a->offset; j++) temp[j-b]='\0';
434                break;
435            case PROTEIN:
436                for (j=b; j<a->offset; j++) temp[j-b]='-';
437                break;
438            case TEXT:
439            default:
440                for (j=b; j<a->offset; j++) temp[j-b]=' ';
441                break;
442        }
443
444        for (j=0; j<a->seqmaxlen; j++) temp[j+a->offset-b] = a->sequence[j];
445        Cfree((char*)a->sequence);
446
447        a->sequence     = temp;
448        a->seqlen      += (a->offset - b);
449        a->seqmaxlen   += (a->offset - b);
450        a->offset       = b;
451        a->sequence[0]  = c;
452    }
453}
Note: See TracBrowser for help on using the browser.