source: branches/profile/EDIT4/ED4_dots.cxx

Last change on this file was 12803, checked in by westram, 5 years ago
File size: 10.0 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
22using namespace std;
23
24#define AWAR_DOT_BASE      "dotmiss/"
25#define AWAR_DOT_SAI       AWAR_DOT_BASE "sainame" // selected SAI
26#define AWAR_DOT_SAI_CHARS AWAR_DOT_BASE "chars"   // handle columns where SAI contains one of these chars
27#define AWAR_DOT_MARKED    AWAR_DOT_BASE "marked"  // handle marked only?
28
29struct dot_insert_stat {
30    size_t  pos_count;
31    size_t *position;           // contains 'pos_count' positions, where dots get inserted if sequence contains '-'
32
33    bool marked_only;
34
35    // statistics:
36    size_t dots_inserted;
37    size_t already_there;
38    size_t sequences_checked;
39};
40
41static ARB_ERROR dot_sequence_by_consensus(ED4_base *base, AW_CL cl_insert_stat) {
42    ARB_ERROR error = 0;
43
44    if (base->is_sequence_info_terminal()) {
45        ED4_sequence_info_terminal *seq_term = base->to_sequence_info_terminal();
46        if (seq_term) {
47            GBDATA *gb_ali = seq_term->data();
48            if (gb_ali) {
49                GBDATA           *gb_species = GB_get_grandfather(gb_ali);
50                bool              marked     = GB_read_flag(gb_species);
51                dot_insert_stat&  stat       = *reinterpret_cast<dot_insert_stat *>(cl_insert_stat);
52
53                if (marked || !stat.marked_only) {
54                    char *sequence = GB_read_string(gb_ali);
55
56                    if (!sequence) {
57                        GB_ERROR err = GB_await_error();
58                        error        = GBS_global_string("No sequence found for '%s'\n(Reason: %s)",
59                                                         GBT_read_name(gb_species), err);
60                    }
61                    else {
62                        size_t length            = GB_read_string_count(gb_ali);
63                        size_t old_dots_inserted = stat.dots_inserted;
64
65                        for (size_t p = 0; p<stat.pos_count; p++) {
66                            size_t pos = stat.position[p];
67
68                            if (pos<length) {
69                                switch (sequence[pos]) {
70                                    case '-':
71                                        sequence[pos] = '.';
72                                        stat.dots_inserted++;
73                                        break;
74
75                                    case '.':
76                                        stat.already_there++;
77                                        break;
78
79                                    default:
80                                        break;
81                                }
82                            }
83                        }
84
85                        if (stat.dots_inserted > old_dots_inserted) { // did sequence change?
86                            error = GB_write_string(gb_ali, sequence);
87                        }
88
89                        free(sequence);
90                        stat.sequences_checked++;
91                    }
92                }
93            }
94        }
95    }
96
97    return error;
98}
99
100static void dot_missing_bases(AW_window *aww) {
101    ED4_MostRecentWinContext context;
102
103    ED4_cursor *cursor = &current_cursor();
104    ARB_ERROR   error  = 0;
105
106    if (!cursor->in_consensus_terminal()) {
107        error = "No consensus selected";
108    }
109    else {
110        AW_root *aw_root = aww->get_root();
111
112        dot_insert_stat stat;
113        stat.dots_inserted     = 0;
114        stat.already_there     = 0;
115        stat.position          = 0;
116        stat.sequences_checked = 0;
117        stat.marked_only       = aw_root->awar(AWAR_DOT_MARKED)->read_int();
118
119        ED4_group_manager *group_manager = cursor->owner_of_cursor->get_parent(ED4_L_GROUP)->to_group_manager();
120        {
121            // build list of positions where consensus contains upper case characters:
122            char *consensus = group_manager->table().build_consensus_string();
123            for (int pass = 1; pass <= 2; pass++) {
124                stat.pos_count = 0;
125                for (int pos = 0; consensus[pos]; pos++) {
126                    if (isupper(consensus[pos])) {
127                        if (pass == 2) stat.position[stat.pos_count] = pos;
128                        stat.pos_count++;
129                    }
130                }
131
132                if (pass == 1) stat.position = (size_t*)malloc(stat.pos_count * sizeof(*stat.position));
133            }
134            free(consensus);
135        }
136
137        if (!stat.pos_count) {
138            error = "No consensus column contains upper case characters";
139        }
140        else {
141            // if SAI is selected, reduce list of affected positions
142            char   *sai     = 0;
143            size_t  sai_len = -1;
144            {
145                GB_transaction  ta(GLOBAL_gb_main);
146                char           *sai_name = aw_root->awar(AWAR_DOT_SAI)->read_string();
147
148                if (sai_name && sai_name[0]) {
149                    GBDATA *gb_sai     = GBT_expect_SAI(GLOBAL_gb_main, sai_name);
150                    if (!gb_sai) error = GB_await_error();
151                    else {
152                        GBDATA *gb_ali = GBT_find_sequence(gb_sai, ED4_ROOT->alignment_name);
153                        if (!gb_ali) {
154                            error = GBS_global_string("SAI '%s' has no data in '%s'", sai_name, ED4_ROOT->alignment_name);
155                        }
156                        else {
157                            sai     = GB_read_string(gb_ali);
158                            sai_len = GB_read_string_count(gb_ali);
159                        }
160                    }
161                }
162                free(sai_name);
163                error = ta.close(error);
164            }
165
166            if (sai) { // SAI is selected
167                if (!error) {
168                    char *sai_chars = aw_root->awar(AWAR_DOT_SAI_CHARS)->read_string();
169                    if (sai_chars[0] == 0) error = "No SAI characters given -> no column selectable";
170                    else {
171                        size_t k = 0;
172                        size_t p;
173                        for (p = 0; p<stat.pos_count && stat.position[p]<sai_len; p++) {
174                            size_t  pos = stat.position[p];
175                            if (strchr(sai_chars, sai[pos]) != NULL) { // SAI contains one of the 'sai_chars'
176                                stat.position[k++] = pos; // use current position
177                            }
178                        }
179                        stat.pos_count = k;
180
181                        if (!stat.pos_count) error = "SAI selects other columns than consensus. Nothing to do.";
182                    }
183                    free(sai_chars);
184                }
185                free(sai);
186            }
187        }
188
189        if (!error) {
190            e4_assert(stat.pos_count);
191            GB_transaction ta(GLOBAL_gb_main);
192            error = group_manager->route_down_hierarchy(dot_sequence_by_consensus, (AW_CL)&stat);
193
194            if (stat.sequences_checked == 0 && !error) {
195                error = GBS_global_string("Group contains no %ssequences", stat.marked_only ? "marked " : "");
196            }
197
198            if (!error) {
199                const char *present = "";
200                if (stat.already_there) {
201                    present = GBS_global_string("Dots already present: %zu  ", stat.already_there);
202                }
203
204                const char *changed = stat.dots_inserted
205                    ? GBS_global_string("Gaps changed into dots: %zu", stat.dots_inserted)
206                    : "No gaps were changed into dots.";
207
208                aw_message(GBS_global_string("%s%s", present, changed));
209            }
210
211            error = ta.close(error);
212        }
213    }
214
215    aw_message_if(error);
216}
217
218void ED4_create_dot_missing_bases_awars(AW_root *aw_root, AW_default aw_def) {
219    aw_root->awar_int(AWAR_DOT_MARKED, 0, aw_def);
220    aw_root->awar_string(AWAR_DOT_SAI, "", aw_def);
221    aw_root->awar_string(AWAR_DOT_SAI_CHARS, "", aw_def);
222}
223
224void ED4_popup_dot_missing_bases_window(AW_window *editor_window, AW_CL, AW_CL) {
225    AW_root                 *aw_root = editor_window->get_root();
226    static AW_window_simple *aws     = 0;
227
228    ED4_LocalWinContext uses(editor_window);
229
230    if (!aws) {
231        aws = new AW_window_simple;
232
233        aws->init(aw_root, "DOT_MISS_BASES", "Dot potentially missing bases");
234        aws->load_xfig("edit4/missbase.fig");
235
236        aws->button_length(10);
237       
238        aws->at("close");
239        aws->callback(AW_POPDOWN);
240        aws->create_button("CLOSE", "CLOSE", "C");
241
242        aws->at("help");
243        aws->callback(makeHelpCallback("missbase.hlp"));
244        aws->create_button("HELP", "HELP", "H");
245
246        aws->at("marked");
247        aws->label("Marked species only");
248        aws->create_toggle(AWAR_DOT_MARKED);
249
250        aws->at("SAI");
251        aws->button_length(30);
252        awt_create_SAI_selection_button(GLOBAL_gb_main, aws, AWAR_DOT_SAI);
253
254        aws->at("SAI_chars");
255        aws->label("contains one of");
256        aws->create_input_field(AWAR_DOT_SAI_CHARS, 20);
257
258        aws->button_length(10);
259
260        aws->at("cons_def");
261        aws->label("Change definition of");
262        aws->callback(ED4_create_consensus_definition_window);
263        aws->create_button("CONS_DEF", "Consensus", "C");
264
265        aws->at("go");
266        aws->callback(dot_missing_bases);
267        aws->create_button("GO", "GO", "G");
268    }
269
270    e4_assert(aws);
271
272    aws->activate();
273}
274
Note: See TracBrowser for help on using the repository browser.