source: tags/ms_r16q2/ARB_GDE/GDE_event.cxx

Last change on this file was 14433, checked in by westram, 8 years ago
  • use typed callbacks in ARB_GDE
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.6 KB
Line 
1#include "GDE_extglob.h"
2#include "GDE_awars.h"
3
4#include <awt_filter.hxx>
5#include <aw_window.hxx>
6#include <aw_root.hxx>
7#include <aw_question.hxx>
8#include <aw_awar.hxx>
9#include <aw_msg.hxx>
10#include <aw_file.hxx>
11#include <arb_progress.h>
12#include <AP_filter.hxx>
13
14#include <set>
15#include <string>
16
17#include <unistd.h>
18
19using namespace std;
20
21extern adfiltercbstruct *agde_filter;
22
23/*
24  ReplaceArgs():
25  Replace all command line arguments with the appropriate values
26  stored for the chosen menu item.
27
28  Copyright (c) 1989-1990, University of Illinois board of trustees.  All
29  rights reserved.  Written by Steven Smith at the Center for Prokaryote Genome
30  Analysis.  Design and implementation guidance by Dr. Gary Olsen and Dr.
31  Carl Woese.
32
33  Copyright (c) 1990,1991,1992 Steven Smith at the Harvard Genome Laboratory.
34  All rights reserved.
35
36*/
37
38
39static char *ReplaceArgs(AW_root *awr, char *Action, GmenuItem *gmenuitem, int number)
40{
41    /*
42     *  The basic idea is to replace all of the symbols in the method
43     *  string with the values picked in the dialog box.  The method
44     *  is the general command line structure.  All arguments have two
45     *  parts : a label and a value.  Values are the
46     *  associated arguments that some flags require.  All symbols that
47     *  require argvalue replacement should have a '$' infront of the symbol
48     *  name in the itemmethod definition.
49     *
50     *  If '$symbol' is prefixed by '!' ARB_GDE does a label replacement, i.e. insert
51     *  the value visible in GUI. Only works for argchoice arguments!
52     *  This is intended for informational use (e.g. to write used settings
53     *  into the comment of a generated tree).
54     *
55     *  An example command line replacement would be:
56     *
57     *       itemmethod=>        "lpr -P $arg1 $arg2"
58     *
59     *       arglabel arg1=>     "To printer?"
60     *       argvalue arg1=>     "lw"
61     *
62     *       arglabel arg2=>     "File name?"
63     *       argvalue arg2=>     "foobar"
64     *
65     *   final command line:
66     *
67     *       lpr -P lw foobar
68     *
69     */
70
71    char       *textvalue  = 0;
72    const char *labelvalue = 0;
73
74    const GmenuItemArg& currArg = gmenuitem->arg[number];
75
76    const char *symbol = currArg.symbol;
77    int         type   = currArg.type;
78
79    if (type == SLIDER) {
80        char *awarname = GDE_makeawarname(gmenuitem, number);
81        textvalue      = awr->awar(awarname)->read_as_string();
82        free(awarname);
83    }
84    else if (type == FILE_SELECTOR) {
85        char *awar_base = GDE_maketmpawarname(gmenuitem, number);
86        textvalue  = AW_get_selected_fullname(awr, awar_base);
87        free(awar_base);
88    }
89    else if (type == CHOOSER ||
90             type == CHOICE_TREE ||
91             type == CHOICE_SAI ||
92             type == CHOICE_MENU ||
93             type == CHOICE_LIST ||
94             type == CHOICE_WEIGHTS ||
95             type == TEXTFIELD)
96    {
97        char *awarname = GDE_makeawarname(gmenuitem, number);
98        textvalue      = awr->awar(awarname)->read_string();
99
100        if (currArg.choice) {
101            for (int c = 0; c<currArg.numchoices && !labelvalue; ++c) {
102                GargChoice& choice = currArg.choice[c];
103                if (choice.method) {
104                    if (strcmp(choice.method, textvalue) == 0) {
105                        labelvalue = choice.label;
106                    }
107                }
108            }
109        }
110    }
111
112    if (textvalue == NULL)  textvalue=(char *)calloc(1, sizeof(char));
113    if (symbol == NULL)     symbol="";
114
115    set<string>warned_about;
116    int conversion_warning = 0;
117   
118    for (int i, j = 0; (i=Find2(Action+j, symbol)) != -1;) {
119        i += j;
120        ++j;
121        if (i>0 && Action[i-1] == '$') {
122            const char *replaceBy = textvalue;
123            int         skip      = 1;
124
125            if (i>1 && Action[i-2] == '!') { // use label (if available)
126                if (labelvalue) {
127                    replaceBy = labelvalue;
128                    skip = 2; // skip '!'
129                }
130                else {
131                    aw_message(GBS_global_string("[ARB_GDE]: Cannot access label of '%s'\n", symbol));
132                    return NULL; // @@@ ignores resources (should only occur during development)
133                }
134            }
135
136            int   repLen = strlen(replaceBy);
137            int   symLen = strlen(symbol);
138            int   newlen = strlen(Action)-skip-symLen+repLen+1;
139            char *temp   = (char *)calloc(newlen, 1);
140
141            strncat(temp, Action, i-skip);
142            strncat(temp, replaceBy, repLen);
143            strcat(temp, &(Action[i+symLen]));
144            freeset(Action, temp);
145        }
146        else {
147            if (warned_about.find(symbol) == warned_about.end()) {
148                fprintf(stderr,
149                        "old arb version converted '%s' to '%s' (now only '$%s' is converted)\n",
150                        symbol, textvalue, symbol);
151                conversion_warning++;
152                warned_about.insert(symbol);
153            }
154        }
155    }
156
157    if (conversion_warning) {
158        fprintf(stderr,
159                "Conversion warnings occurred in Action:\n'%s'\n",
160                Action);
161    }
162
163    free(textvalue);
164    return (Action);
165}
166
167static char *ReplaceFile(char *Action, GfileFormat file)
168{
169    char *symbol, *method, *temp;
170    int i, newlen;
171    symbol = file.symbol;
172    method = file.name;
173
174    for (; (i=Find2(Action, symbol)) != -1;)
175    {
176        newlen = strlen(Action)-strlen(symbol) + strlen(method)+1;
177        temp = (char *)calloc(newlen, 1);
178        strncat(temp, Action, i);
179        strncat(temp, method, strlen(method));
180        strcat(temp, &(Action[i+strlen(symbol)]));
181        freeset(Action, temp);
182    }
183    return (Action);
184}
185
186static char *ReplaceString(char *Action, const char *old, const char *news)
187{
188    const char *symbol;
189    const char *method;
190    char *temp;
191    int i, newlen;
192
193    symbol = old;
194    method = news;
195
196    for (; (i=Find2(Action, symbol)) != -1;)
197    {
198        newlen = strlen(Action)-strlen(symbol) + strlen(method)+1;
199        temp = (char *)calloc(newlen, 1);
200        strncat(temp, Action, i);
201        strncat(temp, method, strlen(method));
202        strcat(temp, &(Action[i+strlen(symbol)]));
203        freeset(Action, temp);
204    }
205    return (Action);
206}
207
208static void GDE_freesequ(NA_Sequence *sequ) {
209    if (sequ) {
210        freenull(sequ->comments);
211        freenull(sequ->baggage);
212        freenull(sequ->sequence);
213    }
214}
215
216NA_Alignment::NA_Alignment(GBDATA *gb_main_)
217    : id(NULL),
218      description(NULL),
219      authority(NULL),
220      numelements(0),
221      maxnumelements(0),
222      maxlen(0),
223      rel_offset(0),
224      element(NULL),
225      numgroups(0),
226      group(NULL),
227      format(0),
228      gb_main(gb_main_)
229{
230    GB_transaction ta(gb_main);
231    alignment_name = GBT_get_default_alignment(gb_main);
232    alignment_type = GBT_get_alignment_type(gb_main, alignment_name);
233}
234
235NA_Alignment::~NA_Alignment() {
236    free(id);
237    free(description);
238    free(authority);
239    free(alignment_name);
240
241    for (unsigned long i=0; i<numelements; i++) {
242        GDE_freesequ(element+i);
243    }
244}
245
246static GB_ERROR write_sequence_autoinc_alisize(GBDATA *gb_data, long& ali_len, const char *sequence, int seq_len) {
247    /* writes sequence data.
248     * Specials things done:
249     * - cuts content beyond 'ali_len' if nothing relevant there
250     * - increments alignment length (stored in DB and parameter)
251     */
252
253    GB_ERROR error    = 0;
254    int      part_len = seq_len; // size that will be written
255    if (seq_len > ali_len) { // sequence longer than alignment
256        // check whether it can be cutoff w/o loosing anything relevant
257        int oversize          = seq_len-ali_len;
258        int irrelevant        = strspn(sequence+ali_len, "-.nN"); // @@@ this has to be different for AA!
259        int relevant_oversize = oversize-irrelevant;
260
261        part_len = ali_len+relevant_oversize;
262
263        if (relevant_oversize) { // got some relevant data behind alignment length -> increase alignment length
264            int         new_ali_len = part_len;
265            GBDATA     *gb_main     = GB_get_root(gb_data);
266            const char *ali_name    = GB_read_key_pntr(GB_get_father(gb_data));
267
268            gde_assert(GBT_get_alignment_len(gb_main, ali_name) == ali_len);
269
270            error   = GBT_set_alignment_len(gb_main, ali_name, new_ali_len);
271            ali_len = new_ali_len;
272        }
273    }
274
275    if (!error) {
276        if (part_len<seq_len) {
277            char *seq_part = GB_strndup(sequence, part_len);
278            error = GB_write_string(gb_data, seq_part);
279            free(seq_part);
280        }
281        else {
282            gde_assert(part_len == seq_len);
283            error = GB_write_string(gb_data, sequence);
284        }
285    }
286
287    return error;
288}
289
290inline bool isgap(char c) { return c == '.' || c == '-'; }
291inline bool isTU(char c) { return c == 'T' || c == 'U'; }
292
293inline char eatgaps(const char *seq, int& index) {
294    /*! increments index forward to next base (or EOS)
295     * @return first gap char seen or 0
296     */
297    if (isgap(seq[index])) {
298        char gap = seq[index++];
299        while (isgap(seq[index])) ++index;
300        return gap;
301    }
302    return 0;
303}
304
305static char *fix_aligned_data(const char *old_seq, const char *new_seq, GB_alignment_type ali_type) {
306    char *fixed = strdup(new_seq);
307
308    int o = 0;
309    int n = 0;
310    int f = 0;
311
312    bool fixTU = ali_type == GB_AT_RNA || ali_type == GB_AT_DNA;
313    char TU    = ali_type == GB_AT_RNA ? 'U' : 'T';
314    char tu    = tolower(TU);
315
316    while (old_seq[o]) {
317        char og = eatgaps(old_seq, o);
318        char ng = eatgaps(new_seq, n);
319
320        if (og && ng && og != ng) memset(fixed+f, og, n-f);
321        f = n;
322
323        char oc = old_seq[o++];
324        char nc = new_seq[n++];
325        if (!nc) break;
326
327        char oC = toupper(oc);
328        char nC = toupper(nc);
329
330        if (fixTU && isTU(nC) && isTU(oC)) fixed[f] = (oc == oC) ? TU : tu;
331        else if (oc != nc && oC == nC)     fixed[f] = oc;
332
333        f++;
334    }
335
336    return fixed;
337}
338
339static void export_to_DB(NA_Alignment& dataset, size_t oldnumelements, bool aligned_data) {
340    /*! (re-)import data into arb DB
341     * @param dataset normally has been read from file (which was created by external tool)
342     * @param oldnumelements start index into dataset
343     * @param aligned_data if true => only import sequences; expect checksums did not change; repair some minor, unwanted changes (case, T<>U, gaptype)
344     */
345    if (dataset.numelements == oldnumelements) return;
346    gde_assert(dataset.numelements > oldnumelements); // otherwise this is a noop
347
348    GBDATA     *gb_main     = db_access.gb_main;
349    GB_ERROR    error       = GB_begin_transaction(gb_main);
350    const char *ali_name    = dataset.alignment_name;
351    long        maxalignlen = GBT_get_alignment_len(gb_main, ali_name);
352
353    if (maxalignlen <= 0 && !error) {
354        error = GB_await_error();
355    }
356
357    long lotyp = 0;
358    if (!error) {
359        GB_alignment_type at = GBT_get_alignment_type(gb_main, ali_name);
360
361        switch (at) {
362            case GB_AT_DNA:     lotyp = DNA;     break;
363            case GB_AT_RNA:     lotyp = RNA;     break;
364            case GB_AT_AA:      lotyp = PROTEIN; break;
365            case GB_AT_UNKNOWN: lotyp = DNA;     break;
366        }
367    }
368
369    unsigned long i;
370    const long    oldalignlen = maxalignlen;
371    bool          auto_format = false;
372
373    AW_repeated_question overwrite_question;
374    AW_repeated_question checksum_change_question;
375
376    arb_progress progress("importing", dataset.numelements-oldnumelements+1); // +1 avoids zero-progress
377    for (i = oldnumelements; !error && i < dataset.numelements; i++) {
378        NA_Sequence *sequ = dataset.element+i;
379        int seqtyp, issame = 0;
380
381        seqtyp = sequ->elementtype;
382        if ((seqtyp == lotyp) || ((seqtyp == DNA) && (lotyp == RNA)) || ((seqtyp == RNA) && (lotyp == DNA))) {
383            issame = 1;
384        }
385        else {
386            aw_message(GBS_global_string("Warning: sequence type of species '%s' changed", sequ->short_name));
387        }
388
389        if (sequ->tmatrix) {
390            for (long j = 0; j < sequ->seqlen; j++) {
391                sequ->sequence[j] = (char)sequ->tmatrix[sequ->sequence[j]];
392            }
393            sequ->sequence[sequ->seqlen] = 0;
394        }
395
396        char *savename = GBS_string_2_key(sequ->short_name);
397
398        sequ->gb_species = 0;
399
400        const char *new_seq     = (const char *)sequ->sequence;
401        int         new_seq_len = sequ->seqlen;
402
403        gde_assert(new_seq[new_seq_len] == 0);
404        gde_assert((int)strlen(new_seq) == new_seq_len);
405
406        if (!issame) {          // save as extended
407            GBDATA *gb_extended = GBT_find_or_create_SAI(gb_main, savename);
408
409            if (!gb_extended) error = GB_await_error();
410            else {
411                sequ->gb_species = gb_extended;
412                GBDATA *gb_data  = GBT_add_data(gb_extended, ali_name, "data", GB_STRING);
413
414                if (!gb_data) error = GB_await_error();
415                else {
416                    error = write_sequence_autoinc_alisize(gb_data, maxalignlen, new_seq, new_seq_len);
417                    if (new_seq_len<maxalignlen) auto_format = true;
418                }
419            }
420        }
421        else {                  // save as sequence
422            GBDATA *gb_species_data     = GBT_get_species_data(gb_main);
423            if (!gb_species_data) error = GB_await_error();
424            else {
425                GBDATA *gb_species       = GBT_find_species_rel_species_data(gb_species_data, savename);
426                bool    fix_data_changes = false;
427
428                GB_push_my_security(gb_main);
429
430                if (gb_species) {   // new element that already exists !!!!
431                    enum ReplaceMode { REPLACE_SPEC = 0, REIMPORT_SEQ = 1, SKIP_IMPORT  = 2 } replace_mode;
432
433                    if (aligned_data) {
434                        replace_mode = REIMPORT_SEQ;
435                    }
436                    else {
437                        const char *question =
438                            GBS_global_string("You are (re-)importing a species '%s'.\n"
439                                              "That species already exists in your database!\n"
440                                              "\n"
441                                              "Possible actions:\n"
442                                              "\n"
443                                              "       - overwrite existing species (all fields)\n"
444                                              "       - overwrite the sequence (does not change other fields)\n"
445                                              "       - skip import of the species\n",
446                                              savename);
447
448                        replace_mode = (ReplaceMode)overwrite_question.get_answer("GDE_overwrite", question, "Overwrite species,Overwrite sequence only,Skip entry", "all", false);
449                    }
450
451                    switch (replace_mode) {
452                        case SKIP_IMPORT:
453                            gb_species = 0;
454                            break;
455                        case REPLACE_SPEC:
456                            error      = GB_delete(gb_species);
457                            gb_species = NULL;
458                            if (error) break;
459                            // fall-through
460                        case REIMPORT_SEQ:
461                            gb_species = GBT_find_or_create_species_rel_species_data(gb_species_data, savename);
462                            if (!gb_species) error = GB_await_error();
463                            break;
464                    }
465
466                    fix_data_changes = replace_mode == REIMPORT_SEQ;
467                }
468                else {
469                    if (aligned_data) {
470                        aw_message(GBS_global_string("Warning: new species '%s' has been created (unexpected; possible naming problems)", savename));
471                    }
472                    gb_species             = GBT_find_or_create_species_rel_species_data(gb_species_data, savename);
473                    if (!gb_species) error = GB_await_error();
474                }
475
476                if (gb_species) {
477                    gde_assert(!error);
478                    sequ->gb_species = gb_species;
479
480                    GBDATA *gb_data     = GBT_add_data(gb_species, ali_name, "data", GB_STRING); // does only add if not already existing
481                    if (!gb_data) error = GB_await_error();
482                    else {
483                        GBDATA *gb_old_data   = GBT_find_sequence(gb_species, ali_name);
484                        bool    writeSequence = true;
485                        if (gb_old_data) {          // we already have data -> compare checksums
486                            const char *old_seq = GB_read_char_pntr(gb_old_data);
487
488                            long old_checksum    = 0;
489                            long new_checksum    = 0;
490                            bool calcStdChecksum = true;
491                            if (fix_data_changes) {
492                                char *new_seq_fixed = fix_aligned_data(old_seq, new_seq, dataset.alignment_type);  // apply some fixes to (realigned) data
493
494                                switch (dataset.alignment_type) {
495                                    case GB_AT_DNA:
496                                    case GB_AT_RNA: {
497                                        char *old_TU = GBS_string_eval(old_seq,       ":T=U:t=u", NULL);
498                                        char *new_TU = GBS_string_eval(new_seq_fixed, ":T=U:t=u", NULL);
499
500                                        old_checksum = GBS_checksum(old_TU, 1, "-.");
501                                        new_checksum = GBS_checksum(new_TU, 1, "-.");
502
503                                        free(new_TU);
504                                        free(old_TU);
505                                        break;
506                                    }
507                                    case GB_AT_AA:
508                                    case GB_AT_UNKNOWN:
509                                        old_checksum = GBS_checksum(old_seq,       1, "-.");
510                                        new_checksum = GBS_checksum(new_seq_fixed, 1, "-.");
511                                        break;
512                                }
513
514                                if (new_checksum == old_checksum) { // fix succeeded
515                                    free(sequ->sequence);
516                                    sequ->sequence  = (NA_Base*)new_seq_fixed;
517                                    new_seq         = new_seq_fixed;
518                                    calcStdChecksum = false;
519                                }
520                                else {
521                                    fprintf(stderr, "Checksum changed for '%s':\nold='%s'\nfix='%s' (failed)\nnew='%s'\n", savename, old_seq, new_seq_fixed, new_seq);
522                                    free(new_seq_fixed);
523                                }
524                            }
525                            if (calcStdChecksum) {
526                                old_checksum = GBS_checksum(old_seq, 1, "-.");
527                                new_checksum = GBS_checksum(new_seq, 1, "-.");
528                            }
529
530                            if (old_checksum != new_checksum) {
531                                if (!fix_data_changes) { // already dumped above
532                                    fprintf(stderr, "Checksum changed for '%s':\nold='%s'\nnew='%s'\n", savename, old_seq, new_seq);
533                                }
534
535                                char *question = GBS_global_string_copy("Warning: Sequence checksum of '%s' has changed!\n"
536                                                                        "This should NOT happen if you aligned sequences!\n"
537                                                                        "(see console for changes to sequence)", savename);
538
539                                const char *questionID = aligned_data ? "GDE_accept_aligner_seqchange" : "GDE_accept_seqchange";
540
541                                enum ChangeMode {
542                                    ACCEPT_CHANGE = 0,
543                                    REJECT_CHANGE = 1,
544                                } change_mode = (ChangeMode)checksum_change_question.get_answer(questionID, question, "Accept change,Reject", "all", false);
545
546                                if (change_mode == REJECT_CHANGE) writeSequence = false;
547
548                                aw_message(GBS_global_string("Warning: Sequence checksum for '%s' has changed (%s)",
549                                                             savename, writeSequence ? "accepted" : "rejected"));
550                                free(question);
551                            }
552                        }
553                        if (writeSequence) {
554                            error = write_sequence_autoinc_alisize(gb_data, maxalignlen, new_seq, new_seq_len);
555                            if (new_seq_len<maxalignlen) auto_format = true;
556                        }
557                    }
558                }
559                GB_pop_my_security(gb_main);
560            }
561        }
562        free(savename);
563        progress.inc_and_check_user_abort(error);
564    }
565
566    if (!auto_format) auto_format = oldalignlen != maxalignlen;
567
568    if (auto_format) {
569        if (db_access.format_ali) {
570            GB_push_my_security(gb_main);
571            error = db_access.format_ali(gb_main, ali_name);
572            GB_pop_my_security(gb_main);
573        }
574    }
575
576    progress.done();
577
578    GB_end_transaction_show_error(db_access.gb_main, error, aw_message);
579}
580
581static char *preCreateTempfile(const char *name) {
582    // creates a tempfile and returns heapcopy of fullpath
583    // exits in case of error
584    char *fullname = GB_create_tempfile(name);
585
586    if (!fullname) aw_message(GBS_global_string("[ARB_GDE]: %s", GB_await_error()));
587    return fullname;
588}
589
590void GDE_startaction_cb(AW_window *aw, GmenuItem *gmenuitem) {
591    gde_assert(!GB_have_error());
592
593    AW_root   *aw_root      = aw->get_root();
594    GmenuItem *current_item = gmenuitem;
595
596    GapCompression compress = static_cast<GapCompression>(aw_root->awar(AWAR_GDE_COMPRESSION)->read_int());
597    arb_progress   progress(current_item->label);
598    NA_Alignment   DataSet(db_access.gb_main);
599    int            stop     = 0;
600
601    if (current_item->numinputs>0) {
602        TypeInfo typeinfo = UNKNOWN_TYPEINFO;
603        {
604            for (int j=0; j<current_item->numinputs; j++) {
605                if (j == 0) { typeinfo = current_item->input[j].typeinfo; }
606                else if (current_item->input[j].typeinfo != typeinfo) {
607                    aw_message("'intyped' must be same for all inputs (config error in GDE menu file)");
608                    stop = 1;
609                }
610            }
611        }
612        gde_assert(typeinfo != UNKNOWN_TYPEINFO);
613
614        if (!stop) {
615            AP_filter *filter2 = awt_get_filter(agde_filter);
616            gde_assert(gmenuitem->seqtype != '-'); // inputs w/o seqtype? impossible!
617            {
618                GB_ERROR error = awt_invalid_filter(filter2);
619                if (error) {
620                    aw_message(error);
621                    stop = 1;
622                }
623            }
624
625            if (!stop) {
626                GB_transaction ta(DataSet.gb_main);
627                progress.subtitle("reading database");
628
629                long cutoff_stop_codon = aw_root->awar(AWAR_GDE_CUTOFF_STOPCODON)->read_int();
630                bool marked            = (aw_root->awar(AWAR_GDE_SPECIES)->read_int() != 0);
631
632                if (db_access.get_sequences) {
633                    stop = ReadArbdb2(DataSet, filter2, compress, cutoff_stop_codon, typeinfo);
634                }
635                else {
636                    stop = ReadArbdb(DataSet, marked, filter2, compress, cutoff_stop_codon, typeinfo);
637                }
638            }
639            delete filter2;
640        }
641
642        if (!stop && DataSet.numelements==0) {
643            aw_message("no sequences selected");
644            stop = 1;
645        }
646    }
647
648    if (!stop) {
649        int select_mode = (current_item->numinputs>0) ? ALL : NONE;
650        int pid         = getpid();
651
652        static int fileindx = 0;
653        for (int j=0; j<current_item->numinputs; j++) {
654            GfileFormat& gfile = current_item->input[j];
655
656            char buffer[GBUFSIZ];
657            sprintf(buffer, "gde%d_%d", pid, fileindx++);
658            gfile.name = preCreateTempfile(buffer);
659
660            switch (gfile.format) {
661                case GENBANK: WriteGen    (DataSet, gfile.name, select_mode); break;
662                case NA_FLAT: WriteNA_Flat(DataSet, gfile.name, select_mode); break;
663                case GDE:     WriteGDE    (DataSet, gfile.name, select_mode); break;
664                default: break;
665            }
666        }
667
668        for (int j=0; j<current_item->numoutputs; j++) {
669            char buffer[GBUFSIZ];
670            sprintf(buffer, "gde%d_%d", pid, fileindx++);
671            current_item->output[j].name = preCreateTempfile(buffer);
672        }
673
674        // Create the command line for external the function call
675        char *Action = strdup(current_item->method);
676
677        while (1) {
678            char *oldAction = strdup(Action);
679
680            for (int j=0; j<current_item->numargs; j++) Action = ReplaceArgs(aw_root, Action, gmenuitem, j);
681            bool changed = strcmp(oldAction, Action) != 0;
682            free(oldAction);
683
684            if (!changed) break;
685        }
686
687        for(int j=0; j<current_item->numinputs;  j++) Action = ReplaceFile(Action, current_item->input[j]);
688        for(int j=0; j<current_item->numoutputs; j++) Action = ReplaceFile(Action, current_item->output[j]);
689
690        if (Find(Action, "$FILTER") == true) {
691            char *filter_name = AWT_get_combined_filter_name(aw_root, AWAR_PREFIX_GDE_TEMP);
692            Action            = ReplaceString(Action, "$FILTER", filter_name);
693            free(filter_name);
694        }
695
696        // call and go...
697        progress.subtitle("calling external program");
698        aw_message_if(GBK_system(Action));
699        free(Action);
700
701        size_t oldnumelements = DataSet.numelements;
702
703        for (int j=0; j<current_item->numoutputs; j++) {
704            switch (current_item->output[j].format) {
705                case GENBANK:
706                case NA_FLAT:
707                case GDE:
708                    LoadData(current_item->output[j].name, DataSet);
709                    break;
710                default:
711                    gde_assert(0);
712                    break;
713            }
714        }
715        for (int j=0; j<current_item->numoutputs; j++) {
716            if (!current_item->output[j].save) {
717                unlink(current_item->output[j].name);
718            }
719        }
720
721        for (int j=0; j<current_item->numinputs; j++) {
722            if (!current_item->input[j].save) {
723                unlink(current_item->input[j].name);
724            }
725        }
726
727        export_to_DB(DataSet, oldnumelements, current_item->aligned);
728    }
729
730    gde_assert(!GB_have_error());
731}
732
733// --------------------------------------------------------------------------------
734
735#ifdef UNIT_TESTS
736#ifndef TEST_UNIT_H
737#include <test_unit.h>
738#endif
739
740static arb_test::match_expectation fixed_as(GB_alignment_type ali_type, const char *old, const char *expected_fix, const char *aligned) {
741    using namespace    arb_test;
742    char              *fixed = fix_aligned_data(old, aligned, ali_type);
743    match_expectation  e     = that(fixed).is_equal_to(expected_fix);
744    free(fixed);
745    return e;
746}
747
748#define TEST_FIX_ALIGNED(t,o,f,a)             TEST_EXPECTATION(fixed_as(t,o,f,a))
749#define TEST_FIX_ALIGNED__BROKEN(t,o,fw,fg,a) TEST_EXPECTATION__BROKEN(fixed_as(t,o,fw,a), fixed_as(t,o,fg,a))
750
751void TEST_fix_aligned_data() {
752    TEST_FIX_ALIGNED(GB_AT_RNA,
753                     "...A---CG..G--U.....", // old
754                     "..AC--G..GU...",       // fixed: gaps corrected; T->U
755                     "--AC--G--GT---");      // aligned
756
757    TEST_FIX_ALIGNED(GB_AT_RNA,
758                     "A---CG..G--U",         // old (no gaps at border)
759                     "--AC--G..GU---",       // fixed: gaps corrected; T->U
760                     "--AC--G--GT---");      // aligned
761
762    TEST_FIX_ALIGNED(GB_AT_RNA,
763                     "...A---CG..G--U.....", // old
764                     "AC--G..GU",            // fixed: gaps corrected; T->U
765                     "AC--G--GT");           // aligned (no gaps at border)
766
767    TEST_FIX_ALIGNED(GB_AT_RNA,
768                     "A---CG..G--U", // old
769                     "AC-----GT",    // not fixed
770                     "AC-----GT");   // aligned (bases changed!)
771
772    TEST_FIX_ALIGNED(GB_AT_DNA,
773                     "A---cTUu..G--t", // old
774                     "AcT--Tt..Gt",    // fixed: case restored; U's convert to T's
775                     "ACT--UT--GU");   // aligned
776
777    TEST_FIX_ALIGNED(GB_AT_RNA,
778                     "A---cTUu..G--t", // old
779                     "AcU--Uu..Gu",    // fixed: case restored; T's convert to U's
780                     "ACT--UT--GU");   // aligned
781}
782
783#endif // UNIT_TESTS
784
785// --------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.