source: tags/ms_r16q3/EDIT4/ED4_dots.cxx

Last change on this file was 15223, checked in by westram, 8 years ago
  • reintegrates 'flags' into 'trunk'
    • DRYed
      • group generation code
      • ref-terminal access
    • layout done by managers (removed manual coordinate calculation)
    • dynamic size calculated by terminals themselves
    • fix design issues
      • brackets were used where groups should have been used. fixed
      • fix many bad/spammy names
    • fix broken member-code (only worked with a NULL sentinel present)
    • dynamic indentation (according to visible group-nesting)
  • adds: log:branches/flags@15098:15222
File size: 10.2 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : ED4_dots.cxx                                       //
4//   Purpose   : Insert dots where bases may be missing             //
5//                                                                  //
6//   Coded by Ralf Westram (coder@reallysoft.de) in December 2008   //
7//   Institute of Microbiology (Technical University Munich)        //
8//   http://www.arb-home.de/                                        //
9//                                                                  //
10// ================================================================ //
11
12#include "ed4_dots.hxx"
13#include "ed4_class.hxx"
14
15#include <awt_sel_boxes.hxx>
16#include <aw_awar.hxx>
17#include <aw_msg.hxx>
18#include <aw_root.hxx>
19#include <arbdbt.h>
20#include <cctype>
21#include <awt_config_manager.hxx>
22
23using namespace std;
24
25#define AWAR_DOT_BASE      "dotmiss/"
26#define AWAR_DOT_SAI       AWAR_DOT_BASE "sainame" // selected SAI
27#define AWAR_DOT_SAI_CHARS AWAR_DOT_BASE "chars"   // handle columns where SAI contains one of these chars
28#define AWAR_DOT_MARKED    AWAR_DOT_BASE "marked"  // handle marked only?
29
30struct dot_insert_stat {
31    size_t  pos_count;
32    size_t *position;           // contains 'pos_count' positions, where dots get inserted if sequence contains '-'
33
34    bool marked_only;
35
36    // statistics:
37    size_t dots_inserted;
38    size_t already_there;
39    size_t sequences_checked;
40};
41
42static ARB_ERROR dot_sequence_by_consensus(ED4_base *base, dot_insert_stat *statPtr) {
43    ARB_ERROR error = 0;
44
45    if (base->is_sequence_info_terminal()) {
46        ED4_sequence_info_terminal *seq_term = base->to_sequence_info_terminal();
47        if (seq_term) {
48            GBDATA *gb_ali = seq_term->data();
49            if (gb_ali) {
50                GBDATA           *gb_species = GB_get_grandfather(gb_ali);
51                bool              marked     = GB_read_flag(gb_species);
52                dot_insert_stat&  stat       = *statPtr;
53
54                if (marked || !stat.marked_only) {
55                    char *sequence = GB_read_string(gb_ali);
56
57                    if (!sequence) {
58                        GB_ERROR err = GB_await_error();
59                        error        = GBS_global_string("No sequence found for '%s'\n(Reason: %s)",
60                                                         GBT_read_name(gb_species), err);
61                    }
62                    else {
63                        size_t length            = GB_read_string_count(gb_ali);
64                        size_t old_dots_inserted = stat.dots_inserted;
65
66                        for (size_t p = 0; p<stat.pos_count; p++) {
67                            size_t pos = stat.position[p];
68
69                            if (pos<length) {
70                                switch (sequence[pos]) {
71                                    case '-':
72                                        sequence[pos] = '.';
73                                        stat.dots_inserted++;
74                                        break;
75
76                                    case '.':
77                                        stat.already_there++;
78                                        break;
79
80                                    default:
81                                        break;
82                                }
83                            }
84                        }
85
86                        if (stat.dots_inserted > old_dots_inserted) { // did sequence change?
87                            error = GB_write_string(gb_ali, sequence);
88                        }
89
90                        free(sequence);
91                        stat.sequences_checked++;
92                    }
93                }
94            }
95        }
96    }
97
98    return error;
99}
100
101static void dot_missing_bases(AW_window *aww) {
102    ED4_MostRecentWinContext context;
103
104    ED4_cursor *cursor = &current_cursor();
105    ARB_ERROR   error  = 0;
106
107    if (!cursor->in_consensus_terminal()) {
108        error = "No consensus selected";
109    }
110    else {
111        AW_root *aw_root = aww->get_root();
112
113        dot_insert_stat stat;
114        stat.dots_inserted     = 0;
115        stat.already_there     = 0;
116        stat.position          = 0;
117        stat.sequences_checked = 0;
118        stat.marked_only       = aw_root->awar(AWAR_DOT_MARKED)->read_int();
119
120        ED4_group_manager *group_manager = cursor->owner_of_cursor->get_parent(LEV_GROUP)->to_group_manager();
121        {
122            // build list of positions where consensus contains upper case characters:
123            char *consensus = group_manager->build_consensus_string();
124            for (int pass = 1; pass <= 2; pass++) {
125                stat.pos_count = 0;
126                for (int pos = 0; consensus[pos]; pos++) {
127                    if (isupper(consensus[pos])) {
128                        if (pass == 2) stat.position[stat.pos_count] = pos;
129                        stat.pos_count++;
130                    }
131                }
132
133                if (pass == 1) ARB_alloc(stat.position, stat.pos_count);
134            }
135            free(consensus);
136        }
137
138        if (!stat.pos_count) {
139            error = "No consensus column contains upper case characters";
140        }
141        else {
142            // if SAI is selected, reduce list of affected positions
143            char   *sai     = 0;
144            size_t  sai_len = -1;
145            {
146                GB_transaction  ta(GLOBAL_gb_main);
147                char           *sai_name = aw_root->awar(AWAR_DOT_SAI)->read_string();
148
149                if (sai_name && sai_name[0]) {
150                    GBDATA *gb_sai     = GBT_expect_SAI(GLOBAL_gb_main, sai_name);
151                    if (!gb_sai) error = GB_await_error();
152                    else {
153                        GBDATA *gb_ali = GBT_find_sequence(gb_sai, ED4_ROOT->alignment_name);
154                        if (!gb_ali) {
155                            error = GBS_global_string("SAI '%s' has no data in '%s'", sai_name, ED4_ROOT->alignment_name);
156                        }
157                        else {
158                            sai     = GB_read_string(gb_ali);
159                            sai_len = GB_read_string_count(gb_ali);
160                        }
161                    }
162                }
163                free(sai_name);
164                error = ta.close(error);
165            }
166
167            if (sai) { // SAI is selected
168                if (!error) {
169                    char *sai_chars = aw_root->awar(AWAR_DOT_SAI_CHARS)->read_string();
170                    if (sai_chars[0] == 0) error = "No SAI characters given -> no column selectable";
171                    else {
172                        size_t k = 0;
173                        size_t p;
174                        for (p = 0; p<stat.pos_count && stat.position[p]<sai_len; p++) {
175                            size_t  pos = stat.position[p];
176                            if (strchr(sai_chars, sai[pos]) != NULL) { // SAI contains one of the 'sai_chars'
177                                stat.position[k++] = pos; // use current position
178                            }
179                        }
180                        stat.pos_count = k;
181
182                        if (!stat.pos_count) error = "SAI selects other columns than consensus. Nothing to do.";
183                    }
184                    free(sai_chars);
185                }
186                free(sai);
187            }
188        }
189
190        if (!error) {
191            e4_assert(stat.pos_count);
192            GB_transaction ta(GLOBAL_gb_main);
193            error = group_manager->route_down_hierarchy(makeED4_route_cb(dot_sequence_by_consensus, &stat));
194
195            if (stat.sequences_checked == 0 && !error) {
196                error = GBS_global_string("Group contains no %ssequences", stat.marked_only ? "marked " : "");
197            }
198
199            if (!error) {
200                const char *present = "";
201                if (stat.already_there) {
202                    present = GBS_global_string("Dots already present: %zu  ", stat.already_there);
203                }
204
205                const char *changed = stat.dots_inserted
206                    ? GBS_global_string("Gaps changed into dots: %zu", stat.dots_inserted)
207                    : "No gaps were changed into dots.";
208
209                aw_message(GBS_global_string("%s%s", present, changed));
210            }
211
212            error = ta.close(error);
213        }
214    }
215
216    aw_message_if(error);
217}
218
219void ED4_create_dot_missing_bases_awars(AW_root *aw_root, AW_default aw_def) {
220    aw_root->awar_int(AWAR_DOT_MARKED, 0, aw_def);
221    aw_root->awar_string(AWAR_DOT_SAI, "", aw_def);
222    aw_root->awar_string(AWAR_DOT_SAI_CHARS, "", aw_def);
223}
224
225static AWT_config_mapping_def dotbases_config_mapping[] = {
226    { AWAR_DOT_MARKED,    "marked" },
227    { AWAR_DOT_SAI,       "sai" },
228    { AWAR_DOT_SAI_CHARS, "saichars" },
229
230    { 0, 0 }
231};
232
233void ED4_popup_dot_missing_bases_window(AW_window *editor_window) {
234    AW_root                 *aw_root = editor_window->get_root();
235    static AW_window_simple *aws     = 0;
236
237    ED4_LocalWinContext uses(editor_window);
238
239    if (!aws) {
240        aws = new AW_window_simple;
241
242        aws->init(aw_root, "DOT_MISS_BASES", "Dot potentially missing bases");
243        aws->load_xfig("edit4/missbase.fig");
244
245        aws->button_length(10);
246       
247        aws->at("close");
248        aws->callback(AW_POPDOWN);
249        aws->create_button("CLOSE", "CLOSE", "C");
250
251        aws->at("help");
252        aws->callback(makeHelpCallback("missbase.hlp"));
253        aws->create_button("HELP", "HELP", "H");
254
255        aws->at("marked");
256        aws->label("Marked species only");
257        aws->create_toggle(AWAR_DOT_MARKED);
258
259        aws->at("SAI");
260        aws->button_length(30);
261        awt_create_SAI_selection_button(GLOBAL_gb_main, aws, AWAR_DOT_SAI);
262
263        aws->at("SAI_chars");
264        aws->label("contains one of");
265        aws->create_input_field(AWAR_DOT_SAI_CHARS, 20);
266
267        aws->button_length(10);
268
269        aws->at("cons_def");
270        aws->label("Change definition of");
271        aws->callback(ED4_create_consensus_definition_window);
272        aws->create_button("CONS_DEF", "Consensus", "C");
273
274        aws->at("go");
275        aws->callback(dot_missing_bases);
276        aws->create_button("GO", "GO", "G");
277
278        aws->at("config");
279        AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, "dotbases", dotbases_config_mapping);
280    }
281
282    e4_assert(aws);
283
284    aws->activate();
285}
286
Note: See TracBrowser for help on using the repository browser.