source: tags/svn.1.5.4/PARSIMONY/PARS_main.cxx

Last change on this file was 8360, checked in by westram, 12 years ago
  • renamed menu separator functions
  • removed macro AWMIMT
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 63.6 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : PARS_main.cxx                                     //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "pars_main.hxx"
12#include "pars_dtree.hxx"
13#include "pars_klprops.hxx"
14#include "ap_tree_nlen.hxx"
15
16#include <aw_awars.hxx>
17#include <aw_preset.hxx>
18#include <aw_msg.hxx>
19
20#include <awt.hxx>
21#include <ColumnStat.hxx>
22#include <nds.h>
23#include <awt_sel_boxes.hxx>
24#include <awt_filter.hxx>
25#include <arb_progress.h>
26#include <aw_root.hxx>
27#include <aw_question.hxx>
28#include <gui_aliview.hxx>
29
30#include <TreeCallbacks.hxx>
31
32#include <list>
33
34#if defined(DEBUG)
35# define TESTMENU
36#endif // DEBUG
37
38using namespace std;
39
40AW_HEADER_MAIN
41
42#define AWAR_COLUMNSTAT_BASE "tmp/pars/colstat"
43#define AWAR_COLUMNSTAT_NAME AWAR_COLUMNSTAT_BASE "/name"
44
45GBDATA *GLOBAL_gb_main;                             // global gb_main for arb_pars
46
47#if defined(WARN_TODO)
48#warning make GLOBAL_PARS static!
49#endif
50PARS_global *GLOBAL_PARS;
51
52// waaah more globals :(
53AP_main *ap_main;
54
55static void pars_saveNrefresh_changed_tree(AWT_canvas *ntw) {
56    ap_assert((AWT_TREE(ntw) == GLOBAL_PARS->tree));
57
58    GB_ERROR error = GLOBAL_PARS->tree->save(ntw->gb_main, 0, 0, 0);
59    if (error) aw_message(error);
60
61    ntw->zoom_reset_and_refresh();
62}
63
64static void pars_export_tree() {
65    GB_ERROR error = GLOBAL_PARS->tree->save(0, 0, 0, 0);
66    if (error) aw_message(error);
67}
68
69STATIC_ATTRIBUTED(__ATTR__NORETURN, void pars_exit(AW_window *aww)) {
70    aww->get_root()->unlink_awars_from_DB(GLOBAL_gb_main);
71#if defined(DEBUG)
72    AWT_browser_forget_db(GLOBAL_gb_main);
73#endif // DEBUG
74    GB_close(GLOBAL_gb_main);
75    exit(0);
76}
77
78static void PARS_export_cb(AW_window *aww, AWT_canvas *, AW_CL mode) {
79    if (mode &1) {      // export tree
80        pars_export_tree();
81    }
82    if (mode &2) {
83        // quit
84        pars_exit(aww);
85    }
86}
87
88static void AP_user_push_cb(AW_window *aww, AWT_canvas *)
89{
90    ap_main->user_push();
91    aww->get_root()->awar(AWAR_STACKPOINTER)->write_int(ap_main->get_user_push_counter());
92}
93
94static void AP_user_pop_cb(AW_window *aww, AWT_canvas *ntw)
95{
96    if (ap_main->get_user_push_counter()<=0) {
97        aw_message("No tree on stack.");
98        return;
99    }
100    ap_main->user_pop();
101    rootNode()->compute_tree(GLOBAL_gb_main);
102    ASSERT_VALID_TREE(rootNode());
103    aww->get_root()->awar(AWAR_STACKPOINTER)->write_int(ap_main->get_user_push_counter());
104
105    pars_saveNrefresh_changed_tree(ntw);
106
107    if (ap_main->get_user_push_counter() <= 0) { // last tree was popped => push again
108        AP_user_push_cb(aww, ntw);
109    }
110}
111
112class InsertData {
113    int  abort_flag;
114    long currentspecies;
115   
116    arb_progress progress;
117
118public:
119
120    bool quick_add_flag;
121    InsertData(bool quick, long spec_count)
122        : abort_flag(false),
123          currentspecies(0),
124          progress(GBS_global_string("Inserting %li species", spec_count), spec_count), 
125          quick_add_flag(quick)
126    {
127    }
128
129    bool every_sixteenth() { return (currentspecies & 0xf) == 0; }
130
131    bool aborted() const { return abort_flag; }
132    void set_aborted(bool aborted_) { abort_flag = aborted_; }
133
134    void inc() {
135        ++currentspecies;
136        progress.inc();
137        abort_flag = progress.aborted();
138    }
139};
140
141static long insert_species_in_tree_test(const char *key, long val, void *cd_isits) {
142    if (!val) return val;
143
144    InsertData *isits = (InsertData*)cd_isits;
145    if (isits->aborted()) return val;
146
147    GBDATA  *gb_node = (GBDATA *)val;
148
149#if defined(WARN_TODO)
150#warning following code could be a method ..
151    // ARB_tree *ARB_tree_root::create_linked_leaf(GBDATA *gb_species, const char *name)
152#endif
153
154    AP_tree *tree = rootNode();
155    AP_tree *leaf = tree->dup();
156    leaf->gb_node = gb_node;
157    leaf->name    = strdup(key);
158    leaf->is_leaf = true;
159
160    leaf->set_seq(leaf->get_tree_root()->get_seqTemplate()->dup());
161    GB_ERROR error = leaf->get_seq()->bind_to_species(gb_node);
162
163    if (error) {
164        aw_message(error);
165        return val;
166    }
167
168    if (leaf->get_seq()->weighted_base_count() < MIN_SEQUENCE_LENGTH) {
169        aw_message(GBS_global_string("Species %s has too short sequence (%f, minimum is %i)",
170                                     key,
171                                     leaf->get_seq()->weighted_base_count(),
172                                     MIN_SEQUENCE_LENGTH));
173        delete leaf;
174        return val;
175    }
176
177    isits->inc();
178
179    {
180        AP_FLOAT best_val = 9999999999999.0;
181        AP_FLOAT this_val;
182        int      cnt      = 0;
183
184        while (cnt<2) {
185            this_val = rootEdge()->nni_rek(-1, false, AP_BL_NNI_ONLY, NULL);
186            if (this_val<best_val) {
187                best_val = this_val;
188                cnt      = 0;
189            }
190            else if (this_val==best_val) {
191                cnt++;
192            }
193            else {
194                cnt = 0;
195            }
196        }
197    }
198
199    rootEdge()->dumpNNI=2;
200
201    AP_tree      **blist;
202    AP_tree_nlen  *bl, *blf;
203    long           bsum    = 0;
204    long           counter = 0;
205
206    tree->buildBranchList(blist, bsum, true, -1); // get all branches
207
208#if defined(DEBUG)
209    long prevCombineCount = AP_sequence::combine_count();
210#endif // DEBUG
211
212    AP_tree *bestposl = tree->get_leftson();
213    AP_tree *bestposr = tree->get_rightson();
214    leaf->insert(bestposl);
215    AP_FLOAT best_parsimony, akt_parsimony;
216    best_parsimony = akt_parsimony = rootNode()->costs();
217
218    for (counter = 0; !isits->aborted() && blist[counter]; counter += 2)
219    {
220        bl = (AP_tree_nlen *)blist[counter];
221        blf = (AP_tree_nlen *)blist[counter+1];
222        if (blf->father == bl)
223        {
224            bl = (AP_tree_nlen *)blist[counter+1];
225            blf = (AP_tree_nlen *)blist[counter];
226        }
227
228        if (bl->father) bl->set_root();
229
230        leaf->moveTo(bl, 0.5);
231        akt_parsimony = rootNode()->costs();
232
233        if (akt_parsimony<best_parsimony)
234        {
235            best_parsimony = akt_parsimony;
236            bestposl = bl;
237            bestposr = blf;
238        }
239    }
240    delete blist;
241    blist = 0;
242    if (bestposl->father != bestposr) bestposl = bestposr;
243    leaf->moveTo(bestposl, 0.5);
244
245    // calculate difference in father-sequence
246
247    int baseDiff = 0;
248
249    {
250        AP_tree_nlen *fath = ((AP_tree_nlen*)bestposl)->get_father()->get_father();
251
252        char *seq_with_leaf;
253        char *seq_without_leaf;
254        long  i;
255
256        // Note: removed sequence length code here,
257        // cause "sequence_len" is always filter-length (i.e. constant until filter changes)
258        // ralf 10/2009
259
260        seq_with_leaf = fath->getSequenceCopy();
261
262        ap_main->push();
263
264        leaf->remove();
265        seq_without_leaf = fath->getSequenceCopy();
266
267        ap_main->pop();
268
269        for (i=0; seq_with_leaf[i]; i++) {
270            if (seq_with_leaf[i]!=seq_without_leaf[i]) {
271                baseDiff++;
272            }
273
274        }
275
276        delete [] seq_with_leaf;
277        delete [] seq_without_leaf;
278    }
279
280    rootEdge()->countSpecies();
281
282#if defined(DEBUG)
283    printf("Combines: %li\n", AP_sequence::combine_count()-prevCombineCount);
284#endif // DEBUG
285
286    if (!isits->quick_add_flag) {
287        int           deep    = -1;
288        AP_tree_nlen *bestpos = (AP_tree_nlen*)bestposl;
289        AP_tree_edge *e       = bestpos->edgeTo(bestpos->get_father());
290
291        if (isits->every_sixteenth())  deep = -1;
292
293        arb_progress progress("optimization");
294        e->dumpNNI          = 1;
295        e->distInsertBorder = e->distanceToBorder(INT_MAX, (AP_tree_nlen*)leaf);
296        e->basesChanged     = baseDiff;
297        e->nni_rek(deep, false, AP_BL_NNI_ONLY, NULL);
298        e->dumpNNI          = 0;
299    }
300
301    return val;
302}
303
304static int sort_sequences_by_length(const char*, long leaf0_ptr, const char*, long leaf1_ptr) {
305    AP_tree *leaf0 = (AP_tree*)leaf0_ptr;
306    AP_tree *leaf1 = (AP_tree*)leaf1_ptr;
307
308    AP_FLOAT len0 = leaf0->get_seq()->weighted_base_count();
309    AP_FLOAT len1 = leaf1->get_seq()->weighted_base_count();
310
311    return len0<len1 ? 1 : (len0>len1 ? -1 : 0); // longest sequence first
312}
313
314static long transform_gbd_to_leaf(const char *key, long val, void *) {
315    if (!val) return val;
316
317#if defined(WARN_TODO)
318#warning use create_linked_leaf() when impl
319#endif
320
321    GBDATA       *gb_node = (GBDATA *)val;
322    AP_tree_root *troot   = ap_main->get_tree_root()->tree_static;
323    AP_tree_nlen *leaf    = DOWNCAST(AP_tree_nlen*, troot->get_nodeTemplate()->dup());
324
325    leaf->gb_node = gb_node;
326    leaf->name    = strdup(key);
327    leaf->is_leaf = true;
328
329    leaf->set_seq(troot->get_seqTemplate()->dup());
330    GB_ERROR error = leaf->get_seq()->bind_to_species(gb_node);
331    if (error) {
332        aw_message(error);
333        delete leaf; leaf = 0;
334    }
335    return (long)leaf;
336}
337
338static AP_tree_nlen *insert_species_in_tree(const char *key, AP_tree_nlen *leaf, InsertData *isits) {
339    if (!leaf) return leaf;
340    if (isits->aborted()) return leaf;
341
342    AP_tree_nlen *tree = rootNode();
343
344    if (leaf->get_seq()->weighted_base_count() < MIN_SEQUENCE_LENGTH) {
345        aw_message(GBS_global_string("Species %s has too short sequence (%f, minimum is %i)",
346                                     key,
347                                     leaf->get_seq()->weighted_base_count(),
348                                     MIN_SEQUENCE_LENGTH));
349        delete leaf;
350        return 0;
351    }
352
353    if (!tree) {                                    // no tree yet
354        static AP_tree_nlen *last_inserted = NULL; // @@@ move 'last_inserted' into 'InsertData'
355
356        if (!last_inserted) {                       // store 1st leaf
357            last_inserted = leaf;
358        }
359        else {                                      // 2nd leaf -> create initial tree
360            AP_tree_root *troot = ap_main->get_tree_root()->tree_static;
361            leaf->insert(last_inserted);
362            last_inserted       = NULL;
363
364            AP_tree *initial_tree = leaf->get_father();
365            troot->change_root(NULL, initial_tree);
366
367            ASSERT_VALID_TREE(troot->get_root_node());
368        }
369    }
370    else {
371        ASSERT_VALID_TREE(tree);
372
373        AP_tree_nlen **branchlist;
374        long           bsum = 0;
375
376        {
377            AP_tree **blist;
378            tree->buildBranchList(blist, bsum, true, -1); // get all branches
379            branchlist = (AP_tree_nlen**)blist;
380        }
381
382        AP_tree_nlen *bestposl = tree->get_leftson();
383        AP_tree_nlen *bestposr = tree->get_rightson();
384
385        ap_assert(tree == rootNode());
386        leaf->insert(bestposl);
387        tree = NULL;                                // tree may have changed
388
389        {
390            AP_FLOAT curr_parsimony = rootNode()->costs();
391            AP_FLOAT best_parsimony = curr_parsimony;
392
393            ASSERT_VALID_TREE(rootNode());
394
395            for (long counter = 0; !isits->aborted() && branchlist[counter]; counter += 2) {
396                AP_tree_nlen *bl  = branchlist[counter];
397                AP_tree_nlen *blf = branchlist[counter+1];
398
399                if (blf->father == bl) {
400                    bl  = branchlist[counter+1];
401                    blf = branchlist[counter];
402                }
403
404                if (bl->father) {
405                    bl->set_root();
406                }
407
408                ASSERT_VALID_TREE(rootNode());
409
410                leaf->moveTo(bl, 0.5);
411                ASSERT_VALID_TREE(rootNode());
412
413                curr_parsimony = rootNode()->costs();
414                ASSERT_VALID_TREE(rootNode());
415
416                if (curr_parsimony < best_parsimony) {
417                    best_parsimony = curr_parsimony;
418                    bestposl = bl;
419                    bestposr = blf;
420                }
421
422            }
423        }
424        delete branchlist; branchlist = 0;
425        if (bestposl->father != bestposr) {
426            bestposl = bestposr;
427        }
428
429        ASSERT_VALID_TREE(rootNode());
430
431        leaf->moveTo(bestposl, 0.5);
432
433        ASSERT_VALID_TREE(rootNode());
434
435        if (!isits->quick_add_flag) {
436            int deep                           = 5;
437            if (isits->every_sixteenth()) deep = -1;
438           
439            arb_progress progress("optimization");
440            bestposl->get_father()->nn_interchange_rek(deep, AP_BL_NNI_ONLY, true);
441            ASSERT_VALID_TREE(rootNode());
442        }
443        AP_tree_nlen *brother = leaf->get_brother();
444        if (brother->is_leaf && leaf->father->father) {
445            bool brother_is_short = 2 * brother->get_seq()->weighted_base_count() < leaf->get_seq()->weighted_base_count();
446
447            if (brother_is_short) {
448                brother->remove();
449                leaf->remove();
450
451                for (int firstUse = 1; firstUse >= 0; --firstUse) {
452                    AP_tree_nlen *to_insert = firstUse ? leaf : brother;
453                    const char   *format    = firstUse ? "2:%s" : "shortseq:%s";
454
455                    char *label = GBS_global_string_copy(format, to_insert->name);
456                    insert_species_in_tree(label, to_insert, isits);
457                    free(label);
458                }
459            }
460        }
461
462        ASSERT_VALID_TREE(rootNode());
463    }
464
465    return leaf;
466}
467
468static long hash_insert_species_in_tree(const char *key, long leaf, void *cd_isits) {
469    InsertData *isits  = (InsertData*)cd_isits;
470    long        result = (long)insert_species_in_tree(key, (AP_tree_nlen*)leaf, isits);
471    isits->inc();
472    return result;
473}
474
475static long count_hash_elements(const char *, long val, void *cd_count) {
476    if (val) {
477        long *count = (long*)cd_count;
478        (*count)++;
479    }
480    return val;
481}
482
483enum AddWhat {
484    NT_ADD_MARKED,
485    NT_ADD_SELECTED,
486};
487
488static void nt_add(AW_window *, AWT_canvas *ntw, AddWhat what, bool quick, int test)
489{
490    GB_ERROR  error = 0;
491
492    AP_tree *oldrootleft  = NULL;
493    AP_tree *oldrootright = NULL;
494    {
495        AP_tree *root = rootNode();
496        if (root) {
497            oldrootleft  = root->get_leftson();
498            oldrootright = root->get_rightson();
499        }
500    }
501
502    GB_HASH *hash = 0;
503    {
504        GB_transaction ta(GLOBAL_gb_main);
505        switch (what) {
506            case NT_ADD_SELECTED: {
507                char *name = GBT_readOrCreate_string(GLOBAL_gb_main, AWAR_SPECIES_NAME, "");
508                if (name && strlen(name)) {
509                    GBDATA *gb_species = GBT_find_species(GLOBAL_gb_main, name);
510                    if (gb_species) {
511                        hash = GBS_create_hash(1, GB_MIND_CASE);
512                        GBS_write_hash(hash, name, (long)gb_species);
513                    }
514                    else error = GBS_global_string("Selected Species (%s) not found", name);
515                }
516                else error = "Please select a species";
517                free(name);
518                break;
519            }
520            case NT_ADD_MARKED: {
521                hash = GBT_create_marked_species_hash(GLOBAL_gb_main);
522                break;
523            }
524        }
525    }
526
527    if (!error) {
528        ap_assert(hash);
529
530        NT_remove_species_in_tree_from_hash(rootNode(), hash);
531
532        long       max_species = 0;
533        GBS_hash_do_loop(hash, count_hash_elements, &max_species);
534        InsertData isits(quick, max_species);
535
536        if (test) {
537            GBS_hash_do_loop(hash, insert_species_in_tree_test, &isits);
538        }
539        else {
540            GB_begin_transaction(GLOBAL_gb_main);
541            GBS_hash_do_loop(hash, transform_gbd_to_leaf, NULL);
542            GB_commit_transaction(GLOBAL_gb_main);
543            GBS_hash_do_sorted_loop(hash, hash_insert_species_in_tree, sort_sequences_by_length, &isits);
544        }
545        if (!quick) {
546            rootEdge()->nni_rek(-1, false, AP_BL_NNI_ONLY, NULL);
547        }
548
549        if (rootNode()) {
550            rootEdge()->calc_branchlengths();
551
552            ASSERT_VALID_TREE(rootNode());
553            rootNode()->compute_tree(GLOBAL_gb_main);
554
555            if (oldrootleft) {
556                if (oldrootleft->father == oldrootright) oldrootleft->set_root();
557                else                                     oldrootright->set_root();
558            }
559            else {
560                ARB_edge innermost = rootNode()->get_tree_root()->find_innermost_edge();
561                DOWNCAST(AP_tree*, innermost.son())->set_root();
562            }
563        }
564        else {
565            error = "Tree lost (no leafs left)";
566        }
567    }
568
569    if (hash) GBS_free_hash(hash);
570    if (error) aw_message(error);
571
572    AWT_TREE(ntw)->resort_tree(0);
573    pars_saveNrefresh_changed_tree(ntw);
574}
575
576// -----------------------------------------
577//      Adding partial sequences to tree
578// -----------------------------------------
579
580class PartialSequence { 
581    GBDATA               *gb_species;
582    mutable AP_tree_nlen *self;                     // self converted to leaf (ready for insertion)
583    const AP_tree_nlen   *best_full_match;          // full sequence position which matched best
584    long                  overlap;                  // size of overlapping region
585    long                  penalty;                  // weighted mismatches
586    bool                  released;
587    bool                  multi_match;
588    string                multi_list;               // list of equal-rated insertion-points (not containing self)
589
590    AP_tree_nlen *get_self() const {
591        if (!self) {
592            ap_assert(!released); // request not possible, because leaf has already been released!
593
594            self = (AP_tree_nlen*)transform_gbd_to_leaf(GBT_read_name(gb_species), (long)gb_species, NULL);
595            ap_assert(self);
596        }
597        return self;
598    }
599
600public:
601    PartialSequence(GBDATA *gb_species_)
602        : gb_species(gb_species_), self(0), best_full_match(0)
603        , overlap(0),  penalty(LONG_MAX), released(false), multi_match(false)
604    {
605    }
606    PartialSequence(const PartialSequence& other)
607        : gb_species(other.gb_species),
608          self(other.self),
609          best_full_match(other.best_full_match),
610          overlap(other.overlap),
611          penalty(other.penalty),
612          released(other.released),
613          multi_match(other.multi_match),
614          multi_list(other.multi_list)
615    {
616        ap_assert(self == 0); // copying self not implemented
617    }
618    DECLARE_ASSIGNMENT_OPERATOR(PartialSequence);
619    ~PartialSequence() { ap_assert(self == 0); }
620
621    GBDATA *get_species() const { return gb_species; }
622    const AP_tree_nlen *get_best_match() const { return best_full_match; }
623    AP_FLOAT get_branchlength() const { return AP_FLOAT(penalty)/overlap; }
624    void test_match(const AP_tree_nlen *leaf_full);
625    bool is_multi_match() const { return multi_match; }
626
627    const char *get_name() const {
628        const char *name = get_self()->name;
629        ap_assert(name);
630        return name;
631    }
632
633    string get_multilist() const {
634        ap_assert(is_multi_match());
635        return string(best_full_match->name)+multi_list;
636    }
637
638    AP_tree_nlen *release() {
639        AP_tree_nlen *s = self;
640        self            = 0;
641        released        = true;
642        return s;
643    }
644
645    void dump() const {
646        printf("best match for '%s' is '%s' (overlap=%li penalty=%li)\n",
647               get_name(), best_full_match->name,
648               overlap, penalty);
649    }
650
651};
652
653void PartialSequence::test_match(const AP_tree_nlen *leaf_full) {
654    long curr_overlap;
655    long curr_penalty;
656
657    leaf_full->get_seq()->partial_match(get_self()->get_seq(), &curr_overlap, &curr_penalty);
658
659    bool better = false;
660
661    if (curr_overlap > overlap) {
662        better = true;
663    }
664    else if (curr_overlap == overlap) {
665        if (curr_penalty<penalty) {
666            better = true;
667        }
668        else if (curr_penalty == penalty) {
669            // found two equal-rated insertion points -> store data for warning
670#if defined(DEBUG)
671            if (!multi_match) dump();
672            printf("Another equal match is against '%s' (overlap=%li penalty=%li)\n", leaf_full->name, curr_overlap, curr_penalty);
673#endif // DEBUG
674
675            multi_match  = true;
676            multi_list.append(1, '/');
677            multi_list.append(leaf_full->name);
678        }
679    }
680
681    if (better) {
682        overlap         = curr_overlap;
683        penalty         = curr_penalty;
684        best_full_match = leaf_full;
685        multi_match     = false;
686        multi_list      = "";
687    }
688}
689
690static GB_ERROR nt_best_partial_match_rek(list<PartialSequence>& partial, const AP_tree_nlen *tree) {
691    GB_ERROR error = 0;
692
693    if (tree) {
694        if (tree->is_leaf && tree->name) {
695            if (tree->gb_node) {
696                int is_partial = GBT_is_partial(tree->gb_node, 0, true); // marks undef as 'full sequence'
697                if (is_partial == 0) { // do not consider other partial sequences
698                    list<PartialSequence>::iterator i = partial.begin();
699                    list<PartialSequence>::iterator e = partial.end();
700                    for (;  i != e; ++i) {
701                        i->test_match(tree);
702                    }
703                }
704                else if (is_partial == -1) {
705                    error = GB_await_error();
706                }
707            }
708        }
709        else {
710            error             = nt_best_partial_match_rek(partial, tree->get_leftson());
711            if (!error) error = nt_best_partial_match_rek(partial, tree->get_rightson());
712        }
713    }
714    return error;
715}
716
717static void count_partial_and_full(const AP_tree_nlen *at, int *partial, int *full, int *zombies, int default_value, int define_if_undef) {
718    if (at->is_leaf) {
719        if (at->gb_node) {
720            int is_partial = GBT_is_partial(at->gb_node, default_value, define_if_undef);
721            if (is_partial) ++(*partial);
722            else ++(*full);
723        }
724        else {
725            ++(*zombies);
726        }
727    }
728    else {
729        count_partial_and_full(at->get_leftson(),  partial, full, zombies, default_value, define_if_undef);
730        count_partial_and_full(at->get_rightson(), partial, full, zombies, default_value, define_if_undef);
731    }
732}
733
734static const AP_tree_nlen *find_least_deep_leaf(const AP_tree_nlen *at, int depth, int *min_depth) {
735    if (depth >= *min_depth) {
736        return 0; // already found better or equal
737    }
738
739    if (at->is_leaf) {
740        if (at->gb_node) {
741            *min_depth = depth;
742            return at;
743        }
744        return 0;
745    }
746
747    const AP_tree_nlen *left  = find_least_deep_leaf(at->get_leftson(), depth+1, min_depth);
748    const AP_tree_nlen *right = find_least_deep_leaf(at->get_rightson(), depth+1, min_depth);
749
750    return right ? right : left;
751}
752inline AP_tree_nlen *find_least_deep_leaf(AP_tree_nlen *at, int depth, int *min_depth) {
753    return const_cast<AP_tree_nlen*>(find_least_deep_leaf(const_cast<const AP_tree_nlen*>(at), depth, min_depth));
754}
755
756static long push_partial(const char *, long val, void *cd_partial) {
757    list<PartialSequence> *partial = reinterpret_cast<list<PartialSequence> *>(cd_partial);
758    partial->push_back(PartialSequence((GBDATA*)val));
759    return val;
760}
761
762static void nt_add_partial(AW_window * /* aww */, AWT_canvas *ntw) {
763    GB_begin_transaction(GLOBAL_gb_main);
764    GB_ERROR error                    = 0;
765    int      full_marked_sequences    = 0;
766    int      partial_marked_sequences = 0;
767    int      no_data                  = 0; // no data in alignment
768
769    arb_progress("Adding partial sequences");
770
771    {
772        list<PartialSequence> partial;
773        {
774            GB_HASH *partial_hash = GBS_create_hash(GBT_get_species_count(GLOBAL_gb_main), GB_MIND_CASE);
775            int      marked_found = 0;
776
777            for (GBDATA *gb_marked = GBT_first_marked_species(GLOBAL_gb_main);
778                 !error && gb_marked;
779                 gb_marked = GBT_next_marked_species(gb_marked))
780            {
781                ++marked_found;
782
783                if (GBT_read_sequence(gb_marked, ap_main->get_aliname())) { // species has sequence in alignment
784                    const char *name = GBT_read_name(gb_marked);
785
786                    switch (GBT_is_partial(gb_marked, 1, true)) { // marks undef as 'partial sequence'
787                        case 0: { // full sequences
788                            aw_message(GBS_global_string("'%s' is a full sequence (cannot add partial)", name));
789                            ++full_marked_sequences;
790                            break;
791                        }
792                        case 1:     // partial sequences
793                            ++partial_marked_sequences;
794                            GBS_write_hash(partial_hash, name, (long)gb_marked);
795                            break;
796                        case -1:    // error
797                            error = GB_await_error();
798                            break;
799                        default:
800                            ap_assert(0);
801                            break;
802                    }
803                }
804                else {
805                    no_data++;
806                }
807            }
808
809            if (!error && !marked_found) error = "There are no marked species";
810
811            if (!error) {
812                NT_remove_species_in_tree_from_hash(rootNode(), partial_hash); // skip all species which are in tree
813                GBS_hash_do_loop(partial_hash, push_partial, &partial); // build partial list from hash
814
815                int partials_already_in_tree = partial_marked_sequences - partial.size();
816
817                if (no_data>0) aw_message(GBS_global_string("%i marked species have no data in '%s'", no_data, ap_main->get_aliname()));
818                if (full_marked_sequences>0) aw_message(GBS_global_string("%i marked species are declared full sequences", full_marked_sequences));
819                if (partials_already_in_tree>0) aw_message(GBS_global_string("%i marked species are already in tree", partials_already_in_tree));
820
821                if (partial.empty()) error = "No species left to add";
822            }
823        }
824
825        if (!error) {
826            // find best matching full sequence for each partial sequence
827            error = nt_best_partial_match_rek(partial, rootNode());
828
829            list<PartialSequence>::iterator i = partial.begin();
830            list<PartialSequence>::iterator e = partial.end();
831
832            arb_progress part_insert_progress(partial.size());
833
834#if defined(DEBUG)
835            // show results :
836            for (; i != e; ++i) i->dump();
837            i = partial.begin();
838#endif // DEBUG
839
840            for (; i != e && !error; ++i) {
841                const char *name = i->get_name();
842
843                if (i->is_multi_match()) {
844                    aw_message(GBS_global_string("Insertion of '%s' is ambiguous.\n"
845                                                 "(took first of equal scored insertion points: %s)",
846                                                 name, i->get_multilist().c_str()));
847                }
848
849                AP_tree_nlen *part_leaf  = i->release();
850                AP_tree_nlen *full_seq   = const_cast<AP_tree_nlen*>(i->get_best_match());
851                AP_tree_nlen *brother    = full_seq->get_brother();
852                int           is_partial = 0;
853                AP_tree_nlen *target     = 0;
854
855                if (brother->is_leaf) {
856                    if (brother->gb_node) {
857                        is_partial = GBT_is_partial(brother->gb_node, 0, 1);
858
859                        if (is_partial) { // brother is partial sequence
860                            target = brother; // insert as brother of brother
861                        }
862                        else {
863                            target = full_seq; // insert as brother of full_seq
864                        }
865                    }
866                    else {
867                        error = "There are zombies in your tree - please remove them";
868                    }
869                }
870                else {
871                    int partial_count = 0;
872                    int full_count    = 0;
873                    int zombie_count  = 0;
874
875                    count_partial_and_full(brother, &partial_count, &full_count, &zombie_count, 0, 1);
876
877                    if (zombie_count) {
878                        error = "There are zombies in your tree - please remove them";
879                    }
880                    else if (full_count) {
881                        // brother is a subtree containing full sequences
882                        // -> add new brother to full_seq found above
883                        target = full_seq;
884                    }
885                    else {      // brother subtree only contains partial sequences
886                        // find one of the least-deep leafs
887                        int depth  = INT_MAX;
888                        target     = find_least_deep_leaf(brother, 0, &depth);
889                        is_partial = 1;
890                    }
891                }
892
893
894                if (!error) {
895#if defined(DEBUG)
896                    printf("inserting '%s'\n", name);
897#endif // DEBUG
898                    part_leaf->insert(target);
899
900                    // we need to create the sequence of the father node!
901                    AP_tree_nlen *father = part_leaf->get_father();
902                    father->costs();
903
904                    // ensure full-sequence is always on top
905                    if (father->rightson == target) {
906                        father->swap_sons();
907                    }
908
909                    if (!error) {
910                        // now correct the branch lengths.
911                        // First calc the original branchlen
912                        GBT_LEN orglen = father->get_branchlength()+target->get_branchlength();
913
914                        if (is_partial) { // we now have a subtree of partial sequences
915                            brother->set_branchlength(orglen); // each partial sequence has it's branchlength.
916                            father->set_branchlength(0); // all father branches are zero length
917                        }
918                        else { // we have a subtree of one full+one partial sequence
919                            father->set_branchlength(orglen); // father branch represents original length (w/o partial seq)
920                            full_seq->set_branchlength(0); // full seq has no sub-branch length
921                        }
922                        part_leaf->set_branchlength(i->get_branchlength());
923                        printf("Adding with branchlength=%f\n", i->get_branchlength());
924                    }
925                }
926                else {
927                    delete part_leaf;
928                }
929
930                part_insert_progress.inc_and_check_user_abort(error);
931            }
932        }
933    }
934
935    if (full_marked_sequences) {
936        aw_message(GBS_global_string("%i marked full sequences were not added", full_marked_sequences));
937    }
938
939    if (error) {
940        aw_message(error);
941        GB_abort_transaction(GLOBAL_gb_main);
942    }
943    else {
944        GB_commit_transaction(GLOBAL_gb_main);
945    }
946
947    pars_saveNrefresh_changed_tree(ntw);
948}
949
950// -----------------------------
951//      add marked / selected
952// -----------------------------
953
954// normal versions :
955
956static void NT_add      (AW_window * aww, AWT_canvas *ntw, AddWhat what) { nt_add(aww, ntw, what, false, 0); }
957static void NT_quick_add(AW_window * aww, AWT_canvas *ntw, AddWhat what) { nt_add(aww, ntw, what, true, 0); }
958
959// test versions :
960
961#if defined(TESTMENU)
962static void TESTMENU_add      (AW_window * aww, AWT_canvas *ntw, AddWhat what) { nt_add(aww, ntw, what, false, 1); }
963static void TESTMENU_quick_add(AW_window * aww, AWT_canvas *ntw, AddWhat what) { nt_add(aww, ntw, what, true, 1); }
964#endif // TESTMENU
965
966// -----------------------------------------
967//      remove and add marked / selected
968// -----------------------------------------
969
970static void NT_radd_internal(AW_window * aww, AWT_canvas *ntw, AddWhat what, bool quick, int test) {
971    AW_awar *awar_best_pars = aww->get_root()->awar(AWAR_BEST_PARSIMONY);
972    int      oldparsval     = awar_best_pars->read_int();
973
974    AWT_graphic_tree *agt = AWT_TREE(ntw);
975    if (agt->get_root_node()) {
976        agt->tree_static->remove_leafs(AWT_REMOVE_BUT_DONT_FREE|AWT_REMOVE_MARKED);
977    }
978
979    // restore old parsimony value (otherwise the state where species were removed would count) :
980    awar_best_pars->write_int(oldparsval);
981
982    nt_add(aww, ntw, what, quick, test);
983}
984
985// normal versions :
986
987static void NT_radd      (AW_window * aww, AWT_canvas *ntw, AddWhat what) { NT_radd_internal(aww, ntw, what, false, 0); }
988static void NT_rquick_add(AW_window * aww, AWT_canvas *ntw, AddWhat what) { NT_radd_internal(aww, ntw, what, true, 0); }
989
990// test versions :
991
992#if defined(TESTMENU)
993static void TESTMENU_radd           (AW_window * aww, AWT_canvas *ntw, AddWhat what) { NT_radd_internal(aww, ntw, what, false, 1); }
994static void TESTMENU_rquick_add_test(AW_window * aww, AWT_canvas *ntw, AddWhat what) { NT_radd_internal(aww, ntw, what, true, 1); }
995#endif // TESTMENU
996
997// --------------------------------------------------------------------------------
998// Add Partial sequences
999// --------------------------------------------------------------------------------
1000
1001
1002static void NT_partial_add(AW_window *aww, AW_CL cl_ntw, AW_CL) {
1003    AWT_canvas *ntw = (AWT_canvas*)cl_ntw;
1004    nt_add_partial(aww, ntw);
1005}
1006
1007// --------------------------------------------------------------------------------
1008
1009static void NT_branch_lengths(AW_window *, AWT_canvas *ntw) {
1010    arb_progress progress("Calculating Branch Lengths");
1011    rootEdge()->calc_branchlengths();
1012    AWT_TREE(ntw)->resort_tree(0);
1013    pars_saveNrefresh_changed_tree(ntw);
1014}
1015
1016static void NT_bootstrap(AW_window *, AWT_canvas *ntw, AW_CL limit_only) {
1017    arb_progress progress("Calculating Bootstrap Limit");
1018    AP_BL_MODE mode       = AP_BL_MODE((limit_only ? AP_BL_BOOTSTRAP_LIMIT : AP_BL_BOOTSTRAP_ESTIMATE)|AP_BL_BL_ONLY);
1019    rootEdge()->nni_rek(-1, false, mode, NULL);
1020    AWT_TREE(ntw)->resort_tree(0);
1021    AWT_TREE(ntw)->tree_root_display = AWT_TREE(ntw)->get_root_node();
1022    pars_saveNrefresh_changed_tree(ntw);
1023}
1024
1025static void NT_optimize(AW_window *, AWT_canvas *ntw) {
1026    arb_progress progress("Optimizing Tree");
1027    PARS_optimizer_cb(rootNode(), progress);
1028    ASSERT_VALID_TREE(rootNode());
1029    rootEdge()->calc_branchlengths();
1030    AWT_TREE(ntw)->resort_tree(0);
1031    rootNode()->compute_tree(GLOBAL_gb_main);
1032    pars_saveNrefresh_changed_tree(ntw);
1033}
1034
1035static void NT_recursiveNNI(AW_window *, AWT_canvas *ntw) {
1036    arb_progress progress("Recursive NNI");
1037    AP_FLOAT orgPars = rootNode()->costs();
1038    AP_FLOAT prevPars = orgPars;
1039    progress.subtitle(GBS_global_string("Old parsimony: %.1f", orgPars));
1040    while (!progress.aborted()) {
1041        AP_FLOAT currPars = rootEdge()->nni_rek(-1, true, AP_BL_NNI_ONLY, NULL);
1042        if (currPars == prevPars) break; // no improvement -> abort
1043        progress.subtitle(GBS_global_string("New parsimony: %.1f (gain: %.1f)", currPars, orgPars-currPars));
1044        prevPars = currPars;
1045    }
1046    rootEdge()->calc_branchlengths();
1047    AWT_TREE(ntw)->resort_tree(0);
1048    rootNode()->compute_tree(GLOBAL_gb_main);
1049    pars_saveNrefresh_changed_tree(ntw);
1050}
1051
1052static AW_window *NT_create_tree_setting(AW_root *aw_root)
1053{
1054    static AW_window_simple *aws = 0;
1055    if (aws) return (AW_window *)aws;
1056
1057    aws = new AW_window_simple;
1058    aws->init(aw_root, "SAVE_DB", "SAVE ARB DB");
1059    aws->load_xfig("awt/tree_settings.fig");
1060
1061    aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
1062    aws->create_button("CLOSE", "CLOSE", "C");
1063
1064    aws->at("help"); aws->callback(AW_POPUP_HELP, (AW_CL)"nt_tree_settings.hlp");
1065    aws->create_button("HELP", "HELP", "H");
1066
1067    aws->at("button");
1068    aws->auto_space(10, 10);
1069    aws->label_length(30);
1070
1071    aws->label("Base Line Width");
1072    aws->create_input_field(AWAR_DTREE_BASELINEWIDTH, 4);
1073    aws->at_newline();
1074
1075    aws->label("Relative vert. Dist");
1076    aws->create_input_field(AWAR_DTREE_VERICAL_DIST, 4);
1077    aws->at_newline();
1078
1079    aws->label("Auto Jump (list tree)");
1080    aws->create_toggle(AWAR_DTREE_AUTO_JUMP);
1081    aws->at_newline();
1082
1083
1084    return (AW_window *)aws;
1085
1086}
1087
1088static void PA_focus_cb(AW_window *, GBDATA *gb_main_par)
1089{
1090    GB_transaction dummy(gb_main_par);
1091}
1092
1093// -----------------------
1094//      test functions
1095
1096#if defined(TESTMENU)
1097static void refreshTree(AWT_canvas *ntw) {
1098    GB_transaction gb_dummy(ntw->gb_main);
1099
1100    AWT_TREE(ntw)->check_update(ntw->gb_main);
1101    GB_ERROR error = AWT_TREE(ntw)->save(ntw->gb_main, 0, 0, 0);
1102    if (error) aw_message(error);
1103    ntw->zoom_reset_and_refresh();
1104}
1105#endif // TESTMENU
1106
1107static void setBranchlens(AP_tree_nlen *node, double newLen)
1108{
1109    node->setBranchlen(newLen, newLen);
1110
1111    if (!node->is_leaf)
1112    {
1113        setBranchlens(node->get_leftson(), newLen);
1114        setBranchlens(node->get_rightson(), newLen);
1115    }
1116}
1117#if defined(TESTMENU)
1118static void TESTMENU_setBranchlen(AW_window *, AWT_canvas *ntw)
1119{
1120    AP_tree_nlen *root = rootNode();
1121
1122    setBranchlens(root, 1.0);
1123    refreshTree(ntw);
1124}
1125
1126static void TESTMENU_treeStats(AW_window *, AWT_canvas *) {
1127    ARB_tree_info tinfo;
1128    AP_tree_nlen *root = rootNode();
1129
1130    {
1131        GB_transaction ta(root->get_tree_root()->get_gb_main());
1132        root->calcTreeInfo(tinfo);
1133    }
1134
1135    puts("Tree stats:");
1136
1137    printf("nodes      =%6zu\n", tinfo.nodes());
1138    printf(" inner     =%6zu\n", tinfo.innerNodes);
1139    printf("  groups   =%6zu\n", tinfo.groups);
1140    printf(" leafs     =%6zu\n", tinfo.leafs);
1141    printf("  unlinked =%6zu (zombies?)\n", tinfo.unlinked);
1142    printf("  linked   =%6zu\n", tinfo.linked());
1143    printf("   marked  =%6zu\n", tinfo.marked);
1144}
1145
1146static void TESTMENU_mixTree(AW_window *, AWT_canvas *ntw)
1147{
1148    rootEdge()->mixTree(100);
1149    refreshTree(ntw);
1150}
1151
1152static void TESTMENU_sortTreeByName(AW_window *, AWT_canvas *ntw)
1153{
1154    AP_tree_nlen *root = rootNode();
1155
1156    root->sortByName();
1157    refreshTree(ntw);
1158}
1159
1160static void TESTMENU_buildAndDumpChain(AW_window *, AWT_canvas *)
1161{
1162    AP_tree_nlen *root = rootNode();
1163
1164    root->get_leftson()->edgeTo(root->get_rightson())->testChain(2);
1165    root->get_leftson()->edgeTo(root->get_rightson())->testChain(3);
1166    root->get_leftson()->edgeTo(root->get_rightson())->testChain(4);
1167    root->get_leftson()->edgeTo(root->get_rightson())->testChain(5);
1168    root->get_leftson()->edgeTo(root->get_rightson())->testChain(6);
1169    root->get_leftson()->edgeTo(root->get_rightson())->testChain(7);
1170    root->get_leftson()->edgeTo(root->get_rightson())->testChain(8);
1171    root->get_leftson()->edgeTo(root->get_rightson())->testChain(9);
1172    root->get_leftson()->edgeTo(root->get_rightson())->testChain(10);
1173    root->get_leftson()->edgeTo(root->get_rightson())->testChain(11);
1174    root->get_leftson()->edgeTo(root->get_rightson())->testChain(-1);
1175}
1176
1177static void init_TEST_menu(AW_window_menu_modes *awm, AWT_canvas *ntw)
1178{
1179    awm->create_menu("Test[debug]", "T", AWM_ALL);
1180
1181    awm->insert_menu_topic(0, "Mix tree",           "M", "", AWM_ALL, (AW_CB)TESTMENU_mixTree,           (AW_CL)ntw, 0);
1182    awm->insert_menu_topic(0, "Tree statistics",    "s", "", AWM_ALL, (AW_CB)TESTMENU_treeStats,         (AW_CL)ntw, 0);
1183    awm->insert_menu_topic(0, "Set branchlens",     "b", "", AWM_ALL, (AW_CB)TESTMENU_setBranchlen,      (AW_CL)ntw, 0);
1184    awm->insert_menu_topic(0, "Sort tree by name",  "o", "", AWM_ALL, (AW_CB)TESTMENU_sortTreeByName,    (AW_CL)ntw, 0);
1185    awm->insert_menu_topic(0, "Build & dump chain", "c", "", AWM_ALL, (AW_CB)TESTMENU_buildAndDumpChain, (AW_CL)ntw, 0);
1186    awm->sep______________();
1187    awm->insert_menu_topic(0, "Add marked species",          "A", "pa_quick.hlp", AWM_ALL, (AW_CB)TESTMENU_quick_add,       (AW_CL)ntw, NT_ADD_MARKED);
1188    awm->insert_menu_topic(0, "Add marked species + NNI",    "N", "pa_add.hlp",   AWM_ALL, (AW_CB)TESTMENU_add,             (AW_CL)ntw, NT_ADD_MARKED);
1189    awm->insert_menu_topic(0, "Remove & add marked species", "o", "pa_add.hlp",   AWM_ALL, (AW_CB)TESTMENU_rquick_add_test, (AW_CL)ntw, NT_ADD_MARKED);
1190    awm->insert_menu_topic(0, "Remove & add marked + NNI",   "v", "pa_add.hlp",   AWM_ALL, (AW_CB)TESTMENU_radd,            (AW_CL)ntw, NT_ADD_MARKED);
1191    awm->sep______________();
1192    awm->insert_menu_topic(0, "Add selected species",       "l", "pa_quick_sel.hlp", AWM_ALL, (AW_CB)TESTMENU_quick_add, (AW_CL)ntw, NT_ADD_SELECTED);
1193    awm->insert_menu_topic(0, "Add selected species + NNI", "I", "pa_add_sel.hlp",   AWM_ALL, (AW_CB)TESTMENU_add,       (AW_CL)ntw, NT_ADD_SELECTED);
1194}
1195#endif // TESTMENU
1196
1197static GB_ERROR pars_check_size(AW_root *awr) {
1198    char *tree_name = awr->awar(AWAR_TREE)->read_string();
1199    char *filter = awr->awar(AWAR_FILTER_FILTER)->read_string();
1200    GB_ERROR error = 0;
1201    long ali_len = 0;
1202    if (strlen(filter)) {
1203        int i;
1204        for (i=0; filter[i]; i++) {
1205            if (filter[i] != '0') ali_len++;
1206        }
1207    }
1208    else {
1209        char *ali_name = awr->awar(AWAR_ALIGNMENT)->read_string();
1210        ali_len = GBT_get_alignment_len(GLOBAL_gb_main, ali_name);
1211        delete ali_name;
1212    }
1213
1214    long tree_size = GBT_size_of_tree(GLOBAL_gb_main, tree_name);
1215    if (tree_size == -1) {
1216        error = "Please select an existing tree";
1217    }
1218    else {
1219        unsigned long expected_memuse = (ali_len * tree_size * 4 / 1000);
1220        if (expected_memuse > GB_get_physical_memory()) {
1221            error  = GBS_global_string("Estimated memory usage (%s) exceeds physical memory (will swap)\n"
1222                                       "(did you specify a filter?)",
1223                                       GBS_readable_size(expected_memuse, "b"));
1224        }
1225    }
1226    free(filter);
1227    free(tree_name);
1228    return error;
1229}
1230
1231static void pars_reset_optimal_parsimony(AW_window *aww, AW_CL *cl_ntw) {
1232    AW_root *awr = aww->get_root();
1233    awr->awar(AWAR_BEST_PARSIMONY)->write_int(awr->awar(AWAR_PARSIMONY)->read_int());
1234
1235    AWT_canvas *ntw = (AWT_canvas*)cl_ntw;
1236    ntw->refresh();
1237}
1238
1239
1240static void pars_start_cb(AW_window *aw_parent, AW_CL cd_weightedFilter, AW_CL cl_cmds) {
1241    WeightedFilter *wfilt = (WeightedFilter*)cd_weightedFilter;
1242    PARS_commands  *cmds  = (PARS_commands*)cl_cmds;
1243    AW_root        *awr   = aw_parent->get_root();
1244    GB_begin_transaction(GLOBAL_gb_main);
1245    {
1246        GB_ERROR warning = pars_check_size(awr);
1247        if (warning) {
1248            char *question = GBS_global_string_copy("%s\nDo you want to continue?", warning);
1249            bool  cont     = aw_ask_sure("swap_warning", question);
1250            free(question);
1251
1252            if (!cont) {
1253                GB_commit_transaction(GLOBAL_gb_main);
1254                return;
1255            }
1256        }
1257    }
1258
1259
1260    AW_window_menu_modes *awm = new AW_window_menu_modes();
1261    awm->init(awr, "ARB_PARSIMONY", "ARB_PARSIMONY", 400, 200);
1262
1263    AW_gc_manager aw_gc_manager = 0;
1264
1265    GLOBAL_PARS->tree = PARS_generate_tree(awr, wfilt);
1266
1267    AWT_canvas *ntw;
1268    {
1269        AP_tree_sort  old_sort_type = GLOBAL_PARS->tree->tree_sort;
1270        GLOBAL_PARS->tree->set_tree_type(AP_LIST_SIMPLE, NULL); // avoid NDS warnings during startup
1271        ntw = new AWT_canvas(GLOBAL_gb_main, (AW_window *)awm, GLOBAL_PARS->tree, aw_gc_manager, AWAR_TREE);
1272        GLOBAL_PARS->tree->set_tree_type(old_sort_type, ntw);
1273    }
1274
1275    {
1276        GB_ERROR error = 0;
1277        arb_progress progress("loading tree");
1278        NT_reload_tree_event(awr, ntw, 0);             // load tree (but do not expose - first zombies need to be removed)
1279        if (!GLOBAL_PARS->tree->get_root_node()) {
1280            error = "I cannot load the selected tree";
1281        }
1282        else {
1283            AP_tree_edge::initialize(rootNode());   // builds edges
1284            long removed = GLOBAL_PARS->tree->tree_static->remove_leafs(AWT_REMOVE_DELETED);
1285
1286            PARS_tree_init(GLOBAL_PARS->tree);
1287            removed += GLOBAL_PARS->tree->tree_static->remove_leafs(AWT_REMOVE_DELETED | AWT_REMOVE_NO_SEQUENCE);
1288
1289            if (!GLOBAL_PARS->tree->get_root_node()) {
1290                const char *aliname = GLOBAL_PARS->tree->tree_static->get_aliview()->get_aliname();
1291                error               = GBS_global_string("Less than 2 species contain data in '%s'\n"
1292                                                        "Tree vanished", aliname);
1293            }
1294            else if (removed) {
1295                aw_message(GBS_global_string("Removed %li leafs (zombies or species w/o data in alignment)", removed));
1296            }
1297
1298            error = GB_end_transaction(ntw->gb_main, error);
1299            if (!error) {
1300                progress.subtitle("Calculating inner nodes");
1301                GLOBAL_PARS->get_root_node()->costs();
1302            }
1303        }
1304        if (error) aw_popup_exit(error);
1305    }
1306
1307    awr->awar(AWAR_COLOR_GROUPS_USE)->add_callback((AW_RCB)NT_recompute_cb, (AW_CL)ntw, 0);
1308
1309    if (cmds->add_marked)           NT_quick_add(awm, ntw, NT_ADD_MARKED);
1310    if (cmds->add_selected)         NT_quick_add(awm, ntw, NT_ADD_SELECTED);
1311    if (cmds->calc_branch_lengths)  NT_branch_lengths(awm, ntw);
1312    if (cmds->calc_bootstrap)       NT_bootstrap(awm, ntw, 0);
1313    if (cmds->quit)                 pars_exit(awm);
1314
1315    GB_transaction dummy(ntw->gb_main);
1316
1317    GBDATA *gb_arb_presets = GB_search(ntw->gb_main, "arb_presets", GB_CREATE_CONTAINER);
1318    GB_add_callback(gb_arb_presets, GB_CB_CHANGED, (GB_CB)AWT_expose_cb, (int *)ntw);
1319
1320#if defined(DEBUG)
1321    AWT_create_debug_menu(awm);
1322#endif // DEBUG
1323
1324    awm->create_menu("File", "F", AWM_ALL);
1325    {
1326        awm->insert_menu_topic("print_tree", "Print Tree ...",          "P", "tree2prt.hlp", AWM_ALL, AWT_popup_print_window, (AW_CL)ntw, 0);
1327        awm->insert_menu_topic("quit",      "Quit",             "Q", "quit.hlp",    AWM_ALL, (AW_CB)PARS_export_cb, (AW_CL)ntw, 2);
1328    }
1329
1330    awm->create_menu("Species", "S", AWM_ALL);
1331    {
1332        NT_insert_mark_submenus(awm, ntw, 0);
1333
1334    }
1335    awm->create_menu("Tree", "T", AWM_ALL);
1336    {
1337
1338        awm->insert_menu_topic("nds",       "NDS (Node Display Setup) ...",      "N", "props_nds.hlp",   AWM_ALL, AW_POPUP, (AW_CL)AWT_create_nds_window, (AW_CL)ntw->gb_main);
1339
1340        awm->sep______________();
1341        awm->insert_menu_topic("tree_2_xfig", "Export tree to XFIG ...", "E", "tree2file.hlp", AWM_ALL, AWT_popup_tree_export_window, (AW_CL)ntw, 0);
1342        awm->insert_menu_topic("tree_print",  "Print tree ...",          "P", "tree2prt.hlp",  AWM_ALL, AWT_popup_print_window,       (AW_CL)ntw, 0);
1343        awm->sep______________();
1344        awm->insert_sub_menu("Collapse/Expand Tree",         "C");
1345        {
1346            awm->insert_menu_topic("tree_group_all",        "Group All",            "A", "tgroupall.hlp",   AWM_ALL,    (AW_CB)NT_group_tree_cb,    (AW_CL)ntw, 0);
1347            awm->insert_menu_topic("tree_group_not_marked", "Group All Except Marked",  "M", "tgroupnmrkd.hlp", AWM_ALL,    (AW_CB)NT_group_not_marked_cb,  (AW_CL)ntw, 0);
1348            awm->insert_menu_topic("tree_ungroup_all",      "Ungroup All",          "U", "tungroupall.hlp", AWM_ALL,    (AW_CB)NT_ungroup_all_cb,   (AW_CL)ntw, 0);
1349            awm->sep______________();
1350            NT_insert_color_collapse_submenu(awm, ntw);
1351        }
1352        awm->close_sub_menu();
1353        awm->sep______________();
1354        awm->insert_sub_menu("Remove Species from Tree",     "R");
1355        {
1356            awm->insert_menu_topic("tree_remove_deleted", "Remove Zombies", "Z", "trm_del.hlp",    AWM_ALL, (AW_CB)NT_remove_leafs, (AW_CL)ntw, AWT_REMOVE_DELETED|AWT_REMOVE_BUT_DONT_FREE);
1357            awm->insert_menu_topic("tree_remove_marked",  "Remove Marked",  "M", "trm_mrkd.hlp",   AWM_ALL, (AW_CB)NT_remove_leafs, (AW_CL)ntw, AWT_REMOVE_MARKED|AWT_REMOVE_BUT_DONT_FREE);
1358            awm->insert_menu_topic("tree_keep_marked",    "Keep Marked",    "K", "tkeep_mrkd.hlp", AWM_ALL, (AW_CB)NT_remove_leafs, (AW_CL)ntw, AWT_REMOVE_NOT_MARKED|AWT_REMOVE_DELETED|AWT_REMOVE_BUT_DONT_FREE);
1359        }
1360        awm->close_sub_menu();
1361        awm->insert_sub_menu("Add Species to Tree",      "A");
1362        {
1363            awm->insert_menu_topic("add_marked",         "Add Marked Species",                              "M", "pa_quick.hlp",     AWM_ALL, (AW_CB)NT_quick_add,  (AW_CL)ntw, NT_ADD_MARKED);
1364            awm->insert_menu_topic("add_marked_nni",     "Add Marked Species + Local Optimization (NNI)",   "N", "pa_add.hlp",       AWM_ALL, (AW_CB)NT_add,        (AW_CL)ntw, NT_ADD_MARKED);
1365            awm->insert_menu_topic("rm_add_marked",      "Remove & Add Marked Species",                     "R", "pa_add.hlp",       AWM_ALL, (AW_CB)NT_rquick_add, (AW_CL)ntw, NT_ADD_MARKED);
1366            awm->insert_menu_topic("rm_add_marked_nni|", "Remove & Add Marked + Local Optimization (NNI)",  "L", "pa_add.hlp",       AWM_ALL, (AW_CB)NT_radd,       (AW_CL)ntw, NT_ADD_MARKED);
1367            awm->sep______________();
1368            awm->insert_menu_topic("add_marked_partial", "Add Marked Partial Species",                      "P", "pa_partial.hlp",   AWM_ALL, NT_partial_add,       (AW_CL)ntw, (AW_CL)0);
1369            awm->sep______________();
1370            awm->insert_menu_topic("add_selected",       "Add Selected Species",                            "S", "pa_quick_sel.hlp", AWM_ALL, (AW_CB)NT_quick_add,  (AW_CL)ntw, NT_ADD_SELECTED);
1371            awm->insert_menu_topic("add_selected_nni",   "Add Selected Species + Local Optimization (NNI)", "O", "pa_add_sel.hlp",   AWM_ALL, (AW_CB)NT_add,        (AW_CL)ntw, NT_ADD_SELECTED);
1372        }
1373        awm->close_sub_menu();
1374        awm->sep______________();
1375        awm->insert_sub_menu("Tree Optimization",        "O");
1376        {
1377            awm->insert_menu_topic("nni",           "Local Optimization (NNI) of Marked Visible Nodes", "L", "",        AWM_ALL,    (AW_CB)NT_recursiveNNI, (AW_CL)ntw, 0);
1378            awm->insert_menu_topic("kl_optimization",   "Global Optimization of Marked Visible Nodes",      "G", "pa_optimizer.hlp", AWM_ALL,   (AW_CB)NT_optimize, (AW_CL)ntw, 0);
1379        }
1380        awm->close_sub_menu();
1381        awm->insert_menu_topic("reset", "Reset optimal parsimony", "s", "", AWM_ALL, (AW_CB)pars_reset_optimal_parsimony, (AW_CL)ntw, 0);
1382        awm->sep______________();
1383        awm->insert_menu_topic("beautify_tree",       "Beautify Tree",            "B", "resorttree.hlp",       AWM_ALL, (AW_CB)NT_resort_tree_cb, (AW_CL)ntw, 0);
1384        awm->insert_menu_topic("calc_branch_lengths", "Calculate Branch Lengths", "L", "pa_branchlengths.hlp", AWM_ALL, (AW_CB)NT_branch_lengths, (AW_CL)ntw, 0);
1385        awm->sep______________();
1386        awm->insert_menu_topic("calc_upper_bootstrap_indep", "Calculate Upper Bootstrap Limit (dependent NNI)",   "d", "pa_bootstrap.hlp", AWM_ALL, (AW_CB)NT_bootstrap,        (AW_CL)ntw, 0);
1387        awm->insert_menu_topic("calc_upper_bootstrap_dep",   "Calculate Upper Bootstrap Limit (independent NNI)", "i", "pa_bootstrap.hlp", AWM_ALL, (AW_CB)NT_bootstrap,        (AW_CL)ntw, 1);
1388        awm->insert_menu_topic("tree_remove_remark",         "Remove Bootstrap Values",                           "V", "trm_boot.hlp",     AWM_ALL, (AW_CB)NT_remove_bootstrap, (AW_CL)ntw, 0);
1389    }
1390
1391#if defined(TESTMENU)
1392    init_TEST_menu(awm, ntw);
1393#endif // TESTMENU
1394
1395    awm->create_menu("Reset", "R", AWM_ALL);
1396    {
1397        awm->insert_menu_topic("reset_logical_zoom",    "Logical Zoom",   "L", "rst_log_zoom.hlp", AWM_ALL, (AW_CB)NT_reset_lzoom_cb, (AW_CL)ntw, 0);
1398        awm->insert_menu_topic("reset_physical_zoom",   "Physical Zoom",  "P", "rst_phys_zoom.hlp", AWM_ALL, (AW_CB)NT_reset_pzoom_cb, (AW_CL)ntw, 0);
1399    }
1400
1401    awm->create_menu("Properties", "r", AWM_ALL);
1402    {
1403        awm->insert_menu_topic("props_menu",  "Menu: Colors and Fonts ...", "M", "props_frame.hlp",      AWM_ALL, AW_POPUP,(AW_CL)AW_preset_window,        0);
1404        awm->insert_menu_topic("props_tree",  "Tree: Colors and Fonts ...", "C", "pars_props_data.hlp",  AWM_ALL, AW_POPUP,(AW_CL)AW_create_gc_window,     (AW_CL)aw_gc_manager);
1405        awm->insert_menu_topic("props_tree2", "Tree: Settings ...",         "T", "nt_tree_settings.hlp", AWM_ALL, AW_POPUP,(AW_CL)NT_create_tree_setting,  (AW_CL)ntw);
1406        awm->insert_menu_topic("props_kl",    "KERN. LIN ...",              "K", "kernlin.hlp",          AWM_ALL, AW_POPUP,(AW_CL)create_kernighan_window, 0);
1407        awm->sep______________();
1408        AW_insert_common_property_menu_entries(awm);
1409        awm->sep______________();
1410        awm->insert_menu_topic("save_props",  "Save Defaults (pars.arb)",   "D", "savedef.hlp",          AWM_ALL,          (AW_CB)AW_save_properties,      0, 0);
1411    }
1412    awm->button_length(5);
1413
1414    awm->insert_help_topic("How to use Help",    "H", "help.hlp",     AWM_ALL, (AW_CB)AW_POPUP_HELP, (AW_CL)"help.hlp",     0);
1415    awm->insert_help_topic("ARB Help",           "A", "arb.hlp",      AWM_ALL, (AW_CB)AW_POPUP_HELP, (AW_CL)"arb.hlp",      0);
1416    awm->insert_help_topic("ARB PARSIMONY Help", "N", "arb_pars.hlp", AWM_ALL, (AW_CB)AW_POPUP_HELP, (AW_CL)"arb_pars.hlp", 0);
1417
1418    awm->create_mode("select.bitmap", "mode_select.hlp", AWM_ALL, (AW_CB)nt_mode_event, (AW_CL)ntw, (AW_CL)AWT_MODE_SELECT);
1419    awm->create_mode("mark.bitmap",   "mode_mark.hlp",   AWM_ALL, (AW_CB)nt_mode_event, (AW_CL)ntw, (AW_CL)AWT_MODE_MARK);
1420    awm->create_mode("group.bitmap",  "mode_group.hlp",  AWM_ALL, (AW_CB)nt_mode_event, (AW_CL)ntw, (AW_CL)AWT_MODE_GROUP);
1421    awm->create_mode("pzoom.bitmap",  "mode_pzoom.hlp",  AWM_ALL, (AW_CB)nt_mode_event, (AW_CL)ntw, (AW_CL)AWT_MODE_ZOOM);
1422    awm->create_mode("lzoom.bitmap",  "mode_lzoom.hlp",  AWM_ALL, (AW_CB)nt_mode_event, (AW_CL)ntw, (AW_CL)AWT_MODE_LZOOM);
1423    awm->create_mode("swap.bitmap",   "mode_swap.hlp",   AWM_ALL, (AW_CB)nt_mode_event, (AW_CL)ntw, (AW_CL)AWT_MODE_SWAP);
1424    awm->create_mode("move.bitmap",   "mode_move.hlp",   AWM_ALL, (AW_CB)nt_mode_event, (AW_CL)ntw, (AW_CL)AWT_MODE_MOVE);
1425#ifdef NNI_MODES
1426    awm->create_mode("nearestn.bitmap", "mode_nni.hlp",      AWM_ALL, (AW_CB)nt_mode_event, (AW_CL)ntw, (AW_CL)AWT_MODE_NNI);
1427    awm->create_mode("kernlin.bitmap",  "mode_kernlin.hlp",  AWM_ALL, (AW_CB)nt_mode_event, (AW_CL)ntw, (AW_CL)AWT_MODE_KERNINGHAN);
1428    awm->create_mode("optimize.bitmap", "mode_optimize.hlp", AWM_ALL, (AW_CB)nt_mode_event, (AW_CL)ntw, (AW_CL)AWT_MODE_OPTIMIZE);
1429#endif // NNI_MODES
1430    awm->create_mode("setroot.bitmap", "mode_set_root.hlp", AWM_ALL, (AW_CB)nt_mode_event, (AW_CL)ntw, (AW_CL)AWT_MODE_SETROOT);
1431    awm->create_mode("reset.bitmap",   "mode_reset.hlp",    AWM_ALL, (AW_CB)nt_mode_event, (AW_CL)ntw, (AW_CL)AWT_MODE_RESET);
1432
1433    awm->at(5, 2);
1434    awm->auto_space(0, -2);
1435    awm->shadow_width(1);
1436
1437
1438    int db_treex, db_treey;
1439    awm->get_at_position(&db_treex, &db_treey);
1440    awm->callback(AW_POPUP_HELP, (AW_CL)"nt_tree_select.hlp");
1441    awm->button_length(16);
1442    awm->help_text("nt_tree_select.hlp");
1443    awm->create_button(0, AWAR_TREE);
1444
1445
1446    int db_stackx, db_stacky;
1447    awm->label_length(8);
1448    awm->label("Stored");
1449    awm->get_at_position(&db_stackx, &db_stacky);
1450    awm->button_length(6);
1451    awm->callback(AW_POPUP_HELP, (AW_CL)"ap_stack.hlp");
1452    awm->help_text("ap_stack.hlp");
1453    awm->create_button(0, AWAR_STACKPOINTER);
1454
1455    int db_parsx, db_parsy;
1456    awm->label_length(14);
1457    awm->label("Current Pars:");
1458    awm->get_at_position(&db_parsx, &db_parsy);
1459
1460    awm->button_length(10);
1461    awm->create_button(0, AWAR_PARSIMONY);
1462
1463    awm->button_length(0);
1464
1465    awm->callback((AW_CB)NT_jump_cb, (AW_CL)ntw, 1);
1466    awm->help_text("tr_jump.hlp");
1467    awm->create_button("JUMP", "#pjump.bitmap", 0);
1468
1469    awm->callback(AW_POPUP_HELP, (AW_CL)"arb_pars.hlp");
1470    awm->help_text("help.hlp");
1471    awm->create_button("HELP", "HELP", "H");
1472
1473    awm->at_newline();
1474
1475    awm->button_length(8);
1476    awm->at_x(db_stackx);
1477    awm->callback((AW_CB1)AP_user_pop_cb, (AW_CL)ntw);
1478    awm->help_text("ap_stack.hlp");
1479    awm->create_button("POP", "RESTORE", 0);
1480
1481    awm->button_length(6);
1482    awm->callback((AW_CB1)AP_user_push_cb, (AW_CL)ntw);
1483    awm->help_text("ap_stack.hlp");
1484    awm->create_button("PUSH", "STORE", 0);
1485
1486    awm->button_length(7);
1487
1488    awm->at_x(db_treex);
1489    awm->callback((AW_CB)NT_set_tree_style, (AW_CL)ntw, (AW_CL)AP_TREE_RADIAL);
1490    awm->help_text("tr_type_radial.hlp");
1491    awm->create_button("RADIAL_TREE", "#radial.bitmap", 0);
1492
1493    awm->callback((AW_CB)NT_set_tree_style, (AW_CL)ntw, (AW_CL)AP_TREE_NORMAL);
1494    awm->help_text("tr_type_list.hlp");
1495    awm->create_button("LIST_TREE", "#list.bitmap", 0);
1496
1497    awm->at_x(db_parsx);
1498    awm->label_length(14);
1499    awm->label("Optimal Pars:");
1500
1501    awm->button_length(10);
1502    awm->create_button(0, AWAR_BEST_PARSIMONY);
1503
1504    awm->at_newline();
1505
1506    {
1507        AW_at_maxsize maxSize; // store size (so AWAR_FOOTER does not affect min. window size)
1508        maxSize.store(awm->_at);
1509        awm->button_length(AWAR_FOOTER_MAX_LEN);
1510        awm->create_button(0, AWAR_FOOTER);
1511        awm->at_newline();
1512        maxSize.restore(awm->_at);
1513    }
1514
1515    awm->get_at_position(&db_treex, &db_treey);
1516    awm->set_info_area_height(db_treey+6);
1517
1518    awm->set_bottom_area_height(0);
1519    awm->set_focus_callback((AW_CB)PA_focus_cb, (AW_CL)ntw->gb_main, 0);
1520
1521    aw_parent->hide(); // hide parent
1522    awm->show();
1523
1524    AP_user_push_cb(aw_parent, ntw); // push initial tree
1525}
1526
1527static AW_window *create_pars_init_window(AW_root *awr, const PARS_commands *cmds) {
1528    AW_window_simple *aws = new AW_window_simple;
1529    aws->init(awr, "PARS_PROPS", "SET PARSIMONY OPTIONS");
1530    aws->load_xfig("pars/init.fig");
1531
1532    aws->button_length(10);
1533    aws->label_length(10);
1534
1535    aws->callback(pars_exit);
1536    aws->at("close");
1537    aws->create_button("ABORT", "ABORT", "A");
1538
1539    aws->callback(AW_POPUP_HELP, (AW_CL)"arb_pars_init.hlp");
1540    aws->at("help");
1541    aws->create_button("HELP", "HELP", "H");
1542
1543    WeightedFilter *weighted_filter = // do NOT free (bound to callbacks)
1544        new WeightedFilter(GLOBAL_gb_main, aws->get_root(), AWAR_FILTER_NAME, AWAR_COLUMNSTAT_NAME, aws->get_root()->awar_string(AWAR_ALIGNMENT));
1545
1546    aws->at("filter");
1547    aws->callback(AW_POPUP, (AW_CL)awt_create_select_filter_win, (AW_CL)weighted_filter->get_adfiltercbstruct());
1548    aws->create_button("SELECT_FILTER", AWAR_FILTER_NAME);
1549
1550    aws->at("weights");
1551    aws->callback(AW_POPUP, (AW_CL)COLSTAT_create_selection_window, (AW_CL)weighted_filter->get_column_stat());
1552    aws->sens_mask(AWM_EXP);
1553    aws->create_button("SELECT_CSP", AWAR_COLUMNSTAT_NAME);
1554    aws->sens_mask(AWM_ALL);
1555
1556    aws->at("alignment");
1557    awt_create_selection_list_on_alignments(GLOBAL_gb_main, (AW_window *)aws, AWAR_ALIGNMENT, "*=");
1558
1559    aws->at("tree");
1560    awt_create_selection_list_on_trees(GLOBAL_gb_main, (AW_window *)aws, AWAR_TREE);
1561
1562    aws->callback(pars_start_cb, (AW_CL)weighted_filter, (AW_CL)cmds);
1563    aws->at("go");
1564    aws->create_button("GO", "GO", "G");
1565
1566    return aws;
1567}
1568
1569static void create_parsimony_variables(AW_root *aw_root, AW_default def)
1570{
1571    // parsimony
1572#if 0
1573    aw_root->awar_float("genetic/m_rate", 0, def);
1574    aw_root->awar_int("genetic/input_1", 0, def);
1575    aw_root->awar_int("genetic/input_2", 0, def);
1576    aw_root->awar_float("genetic/input_3", 0, def);
1577    aw_root->awar_float("genetic/input_4", 0, def);
1578    aw_root->awar_float("genetic/input_5", 0, def);
1579    aw_root->awar_float("genetic/input_6", 0, def);
1580    aw_root->awar_float("genetic/input_7", 0, def);
1581    aw_root->awar_float("genetic/input_8", 0, def);
1582    aw_root->awar_float("genetic/input_9", 0, def);
1583    aw_root->awar_float("genetic/input_10", 0, def);
1584    aw_root->awar_float("genetic/input_11", 0, def);
1585    aw_root->awar_int("genetic/out_1", 0, def);
1586    aw_root->awar_float("genetic/out_2", 0, def);
1587    aw_root->awar_float("genetic/out_3", 0, def);
1588    aw_root->awar_float("genetic/out_4", 0, def);
1589    aw_root->awar_float("genetic/out_5", 0, def);
1590    aw_root->awar_float("genetic/out_6", 0, def);
1591    aw_root->awar_float("genetic/out_7", 0, def);
1592    aw_root->awar_float("genetic/out_8", 0, def);
1593#endif
1594    // kernighan
1595
1596    aw_root->awar_float("genetic/kh/nodes", 1.7, def);
1597    aw_root->awar_int("genetic/kh/maxdepth", 15, def);
1598    aw_root->awar_int("genetic/kh/incdepth", 5, def);
1599
1600    aw_root->awar_int("genetic/kh/static/enable", 1, def);
1601    aw_root->awar_int("genetic/kh/static/depth0", 2, def);
1602    aw_root->awar_int("genetic/kh/static/depth1", 2, def);
1603    aw_root->awar_int("genetic/kh/static/depth2", 2, def);
1604    aw_root->awar_int("genetic/kh/static/depth3", 2, def);
1605    aw_root->awar_int("genetic/kh/static/depth4", 1, def);
1606
1607    aw_root->awar_int("genetic/kh/dynamic/enable", 1, def);
1608    aw_root->awar_int("genetic/kh/dynamic/start", 100, def);
1609    aw_root->awar_int("genetic/kh/dynamic/maxx", 6, def);
1610    aw_root->awar_int("genetic/kh/dynamic/maxy", 150, def);
1611
1612    aw_root->awar_int("genetic/kh/function_type", AP_QUADRAT_START, def);
1613
1614    awt_create_dtree_awars(aw_root, def);
1615}
1616
1617static void pars_create_all_awars(AW_root *awr, AW_default aw_def)
1618{
1619    awr->awar_string(AWAR_SPECIES_NAME, "",     GLOBAL_gb_main);
1620    awr->awar_string(AWAR_FOOTER,       "",     aw_def);
1621    awr->awar_string(AWAR_FILTER_NAME,  "none", GLOBAL_gb_main);
1622
1623    {
1624        GB_transaction  ta(GLOBAL_gb_main);
1625        char           *dali = GBT_get_default_alignment(GLOBAL_gb_main);
1626
1627        awr->awar_string(AWAR_ALIGNMENT, dali, GLOBAL_gb_main)->write_string(dali);
1628        free(dali);
1629    }
1630
1631    awt_set_awar_to_valid_filter_good_for_tree_methods(GLOBAL_gb_main, awr, AWAR_FILTER_NAME);
1632
1633    awr->awar_string(AWAR_FILTER_FILTER,    "", GLOBAL_gb_main);
1634    awr->awar_string(AWAR_FILTER_ALIGNMENT, "", aw_def);
1635
1636    awr->awar(AWAR_FILTER_ALIGNMENT)->map(AWAR_ALIGNMENT);
1637
1638    awr->awar_int(AWAR_PARS_TYPE, PARS_WAGNER, GLOBAL_gb_main);
1639
1640    {
1641        GB_transaction  ta(GLOBAL_gb_main);
1642        GBDATA *gb_tree_name = GB_search(GLOBAL_gb_main, AWAR_TREE, GB_STRING);
1643        char   *tree_name    = GB_read_string(gb_tree_name);
1644
1645        awr->awar_string(AWAR_TREE, 0, aw_def)->write_string(tree_name);
1646        free(tree_name);
1647    }
1648
1649    awr->awar_int(AWAR_PARSIMONY,      0, aw_def);
1650    awr->awar_int(AWAR_BEST_PARSIMONY, 0, aw_def);
1651    awr->awar_int(AWAR_STACKPOINTER,   0, aw_def);
1652
1653    create_parsimony_variables(awr, GLOBAL_gb_main);
1654    create_nds_vars(awr, aw_def, GLOBAL_gb_main);
1655
1656#if defined(DEBUG)
1657    AWT_create_db_browser_awars(awr, aw_def);
1658#endif // DEBUG
1659
1660    GB_ERROR error = ARB_init_global_awars(awr, aw_def, GLOBAL_gb_main);
1661    if (error) aw_message(error);
1662}
1663
1664static AW_root *AD_map_viewer_aw_root = 0;
1665
1666void PARS_map_viewer(GBDATA *gb_species, AD_MAP_VIEWER_TYPE vtype) {
1667    if (vtype == ADMVT_SELECT && AD_map_viewer_aw_root && gb_species) {
1668        AD_map_viewer_aw_root->awar(AWAR_SPECIES_NAME)->write_string(GBT_read_name(gb_species));
1669    }
1670}
1671
1672int ARB_main(int argc, const char *argv[]) {
1673    aw_initstatus();
1674
1675    GB_shell shell;
1676    AW_root *aw_root      = AWT_create_root("pars.arb", "ARB_PARS");
1677    AD_map_viewer_aw_root = aw_root;
1678
1679    ap_main = new AP_main;
1680
1681    GLOBAL_PARS      = (PARS_global *)calloc(sizeof(PARS_global), 1);
1682    GLOBAL_PARS->awr = aw_root;
1683
1684    const char *db_server = ":";
1685
1686    PARS_commands cmds;
1687
1688    while (argc>=2 && argv[1][0] == '-') {
1689        argc--;
1690        argv++;
1691        if (!strcmp(argv[0], "-quit"))                   cmds.quit = 1;
1692        else if (!strcmp(argv[0], "-add_marked"))        cmds.add_marked = 1;
1693        else if (!strcmp(argv[0], "-add_selected"))      cmds.add_selected = 1;
1694        else if (!strcmp(argv[0], "-calc_branchlengths")) cmds.calc_branch_lengths = 1;
1695        else if (!strcmp(argv[0], "-calc_bootstrap"))    cmds.calc_bootstrap = 1;
1696        else {
1697            fprintf(stderr, "Unknown option '%s'\n", argv[0]);
1698
1699            printf("    Options:                Meaning:\n"
1700                   "\n"
1701                   "    -add_marked             add marked species   (without changing topology)\n"
1702                   "    -add_selected           add selected species (without changing topology)\n"
1703                   "    -calc_branchlengths     calculate branch lengths only\n"
1704                   "    -calc_bootstrap         estimate bootstrap values\n"
1705                   "    -quit                   quit after performing operations\n"
1706                   );
1707
1708            exit(EXIT_FAILURE);
1709        }
1710    }
1711
1712
1713    if (argc==2) {
1714        db_server = argv[1];
1715    }
1716
1717    GLOBAL_gb_main = GBT_open(db_server, "rw");
1718    if (!GLOBAL_gb_main) aw_popup_exit(GB_await_error()); // exits
1719
1720#if defined(DEBUG)
1721    AWT_announce_db_to_browser(GLOBAL_gb_main, GBS_global_string("ARB-database (%s)", db_server));
1722#endif // DEBUG
1723
1724    pars_create_all_awars(aw_root, AW_ROOT_DEFAULT);
1725
1726    AW_window *aww = create_pars_init_window(aw_root, &cmds);
1727    aww->show();
1728
1729    AWT_install_cb_guards();
1730    aw_root->main_loop();
1731    return EXIT_SUCCESS;
1732}
1733
Note: See TracBrowser for help on using the repository browser.