source: tags/ms_r16q2/NTREE/NT_ins_col.cxx

Last change on this file was 14453, checked in by westram, 8 years ago
  • do not cast AW_POPDOWN
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.1 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : NT_ins_col.cxx                                    //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "NT_local.h"
12
13#include <RangeList.h>
14#include <arbdbt.h>
15#include <insdel.h>
16#include <aw_window.hxx>
17#include <aw_root.hxx>
18#include <aw_awars.hxx>
19#include <aw_msg.hxx>
20#include <awt_sel_boxes.hxx>
21#include <arb_defs.h>
22#include <awt_config_manager.hxx>
23
24#define AWAR_INSDEL     "insdel/"
25#define TMP_AWAR_INSDEL "tmp/" AWAR_INSDEL
26
27#define AWAR_INSDEL_AMOUNT    AWAR_INSDEL "nchar"
28#define AWAR_INSDEL_DELETABLE AWAR_INSDEL "characters"
29#define AWAR_INSDEL_RANGE     AWAR_INSDEL "range"
30#define AWAR_INSDEL_SAI       AWAR_INSDEL "sainame"
31#define AWAR_INSDEL_CONTAINS  AWAR_INSDEL "contain"
32#define AWAR_INSDEL_SAI_CHARS AWAR_INSDEL "saichars"
33#define AWAR_INSDEL_AFFECTED  TMP_AWAR_INSDEL "affected"
34#define AWAR_INSDEL_WHAT      TMP_AWAR_INSDEL "what"
35#define AWAR_INSDEL_DIRECTION AWAR_INSDEL "direction"
36
37enum SaiContains { DOESNT_CONTAIN, CONTAINS };
38enum InsdelMode { INSERT, DELETE };
39
40class StaticData {
41    char      *ali;
42    RangeList  ranges;
43
44public:
45    StaticData() : ali(NULL) {}
46    StaticData(const StaticData& other) : ali(nulldup(other.ali)), ranges(other.ranges) {}
47    DECLARE_ASSIGNMENT_OPERATOR(StaticData);
48    ~StaticData() { free(ali); }
49
50    GB_ERROR track_ali(GBDATA *gb_main) {
51        freeset(ali, GBT_get_default_alignment(gb_main));
52        return ali ? NULL : "no alignment found";
53    }
54
55    const char *get_ali() const { return ali; }
56
57    const RangeList& get_ranges() const { return ranges; }
58    void set_ranges(const RangeList& new_ranges) { ranges = new_ranges; }
59};
60
61static StaticData SELECTED;
62
63static void cleanup_when_closing(AW_window*) {
64    SELECTED = StaticData();
65}
66
67static int columns_of(const RangeList& ranges) {
68    int count = 0;
69    for (RangeList::iterator r = ranges.begin(); r != ranges.end(); ++r) {
70        count += r->size();
71    }
72    return count;
73}
74
75static void range_count_update_cb(AW_root *root) {
76    UseRange use   = UseRange(root->awar(AWAR_INSDEL_RANGE)->read_int());
77    int      count = 0;
78    switch (use) {
79        case RANGES:         count = SELECTED.get_ranges().size(); break;
80        case SINGLE_COLUMNS: count = columns_of(SELECTED.get_ranges()); break;
81    }
82    root->awar(AWAR_INSDEL_AFFECTED)->write_int(count);
83}
84
85static void range_changed_cb(AW_root *root) {
86    UseRange    use  = UseRange(root->awar(AWAR_INSDEL_RANGE)->read_int());
87    const char *what = NULL;
88    switch (use) {
89        case RANGES:         what = "selected ranges";  break;
90        case SINGLE_COLUMNS: what = "selected columns"; break;
91    }
92    root->awar(AWAR_INSDEL_WHAT)->write_string(what);
93    range_count_update_cb(root);
94}
95
96static GB_ERROR update_RangeList(AW_root *root, GBDATA *gb_main) {
97    const char     *saiName = root->awar(AWAR_INSDEL_SAI)->read_char_pntr();
98    GB_transaction  ta(gb_main);
99    GBDATA         *gb_sai  = GBT_expect_SAI(gb_main, saiName);
100    GB_ERROR        error   = NULL;
101
102    if (!gb_sai) error = GB_await_error();
103    if (!error) error  = SELECTED.track_ali(gb_main);
104
105    if (!error) {
106        GBDATA *gb_data = GBT_find_sequence(gb_sai, SELECTED.get_ali());
107        if (!gb_data) {
108            if (GB_have_error()) error = GB_await_error();
109            else error                 = GBS_global_string("SAI '%s' has no data in alignment '%s'", saiName, SELECTED.get_ali());
110        }
111        else {
112            const char *data = GB_read_char_pntr(gb_data);
113            if (!data) error = GB_await_error();
114            else {
115                const char  *chars    = root->awar(AWAR_INSDEL_SAI_CHARS)->read_char_pntr();
116                SaiContains  contains = SaiContains(root->awar(AWAR_INSDEL_CONTAINS)->read_int());
117
118                SELECTED.set_ranges(build_RangeList_from_string(data, chars, contains == DOESNT_CONTAIN));
119            }
120        }
121    }
122    if (error) {
123        SELECTED.set_ranges(RangeList());
124        if (!saiName[0]) error = NULL; // do not show "Could not find extended with name ''"
125    }
126    range_count_update_cb(root);
127
128    return error;
129}
130
131static void update_RangeList_cb(AW_root *root) {
132    aw_message_if(update_RangeList(root, GLOBAL.gb_main));
133}
134
135void create_insertDeleteColumn_variables(AW_root *root, AW_default props) {
136    root->awar_int   (AWAR_CURSOR_POSITION,  info2bio(0), GLOBAL.gb_main);
137    root->awar_int   (AWAR_INSDEL_AMOUNT,    0,           props)->set_minmax(0, 9999999);
138    root->awar_string(AWAR_INSDEL_DELETABLE, "-.",        props);
139    root->awar_int   (AWAR_INSDEL_RANGE,     RANGES,      props)->add_callback(range_changed_cb);
140
141    root->awar_string(AWAR_INSDEL_SAI,       "",             props)->add_callback(update_RangeList_cb);
142    root->awar_int   (AWAR_INSDEL_CONTAINS,  DOESNT_CONTAIN, props)->add_callback(update_RangeList_cb);
143    root->awar_string(AWAR_INSDEL_SAI_CHARS, "-.",           props)->add_callback(update_RangeList_cb);
144
145    root->awar_int   (AWAR_INSDEL_AFFECTED,  0,      props);
146    root->awar_string(AWAR_INSDEL_WHAT,      "???",  props);
147    root->awar_int   (AWAR_INSDEL_DIRECTION, BEHIND, props);
148
149    range_changed_cb(root);
150    update_RangeList(root, GLOBAL.gb_main);
151}
152
153static void insdel_event(AW_window *aws, InsdelMode mode) {
154    GBDATA  *gb_main = GLOBAL.gb_main;
155    AW_root *root    = aws->get_root();
156
157    long  pos       = bio2info(root->awar(AWAR_CURSOR_POSITION)->read_int());
158    long  nchar     = root->awar(AWAR_INSDEL_AMOUNT)->read_int();
159    const char *deletable = root->awar(AWAR_INSDEL_DELETABLE)->read_char_pntr();
160
161    if (mode == DELETE) nchar = -nchar;
162
163    GB_ERROR error    = GB_begin_transaction(gb_main);
164    if (!error) error = SELECTED.track_ali(gb_main);
165    if (!error) error = ARB_insdel_columns(gb_main, SELECTED.get_ali(), pos, nchar, deletable);
166    if (!error) error = GBT_check_data(gb_main, 0);
167
168    GB_end_transaction_show_error(gb_main, error, aw_message);
169}
170
171static void insdel_sai_event(AW_window *aws, InsdelMode mode) {
172    GBDATA   *gb_main = GLOBAL.gb_main;
173    GB_ERROR  error   = GB_begin_transaction(GLOBAL.gb_main);
174    if (!error) error = SELECTED.track_ali(gb_main);
175
176    if (!error) {
177        AW_root *root = aws->get_root();
178
179        switch (mode) {
180            case INSERT: {
181                UseRange    units  = UseRange(root->awar(AWAR_INSDEL_RANGE)->read_int());
182                InsertWhere where  = InsertWhere(root->awar(AWAR_INSDEL_DIRECTION)->read_int());
183                size_t      amount = root->awar(AWAR_INSDEL_AMOUNT)->read_int();
184
185                error = ARB_insert_columns_using_SAI(gb_main, SELECTED.get_ali(), SELECTED.get_ranges(), units, where, amount);
186                break;
187            }
188            case DELETE: {
189                const char *deletable = root->awar(AWAR_INSDEL_DELETABLE)->read_char_pntr();
190
191                error = ARB_delete_columns_using_SAI(gb_main, SELECTED.get_ali(), SELECTED.get_ranges(), deletable);
192                break;
193            }
194        }
195    }
196    if (!error) error = GBT_check_data(gb_main, 0);
197
198    GB_end_transaction_show_error(gb_main, error, aw_message);
199}
200
201AW_window *create_insertDeleteColumn_window(AW_root *root) {
202    static AW_window_simple *aws = 0;
203    if (!aws) {
204        aws = new AW_window_simple;
205
206        aws->init(root, "INSDEL_COLUMNS", "Insert/delete columns");
207
208        aws->load_xfig("insdel.fig");
209        aws->button_length(8);
210
211        aws->at("close");
212        aws->callback(AW_POPDOWN);
213        aws->create_button("CLOSE", "CLOSE", "C");
214
215        aws->callback(makeHelpCallback("insdel.hlp"));
216        aws->at("help");
217        aws->create_button("HELP", "HELP", "H");
218
219        aws->label_length(27);
220
221        aws->at("pos");
222        aws->label("Sequence Position");
223        aws->create_input_field(AWAR_CURSOR_POSITION, 7);
224
225        aws->at("len");
226        aws->label("How many Characters");
227        aws->create_input_field(AWAR_INSDEL_AMOUNT, 7);
228
229        aws->at("characters");
230        aws->label("Delete Only (% = all)");
231        aws->create_input_field(AWAR_INSDEL_DELETABLE, 7);
232
233        aws->auto_space(10, 0);
234
235        aws->at("actions");
236        aws->callback(makeWindowCallback(insdel_event, INSERT)); aws->create_button("INSERT", "INSERT", "I");
237        aws->callback(makeWindowCallback(insdel_event, DELETE)); aws->create_button("DELETE", "DELETE", "D");
238    }
239    return aws;
240}
241
242static AWT_config_mapping_def insdel_by_SAI_config_def[] = {
243    { AWAR_INSDEL_RANGE,     "range" },
244    { AWAR_INSDEL_SAI,       "sai" },
245    { AWAR_INSDEL_CONTAINS,  "contain" },
246    { AWAR_INSDEL_SAI_CHARS, "chars" },
247    { AWAR_INSDEL_DELETABLE, "deletable" },
248    { AWAR_INSDEL_AMOUNT,    "amount" },
249    { AWAR_INSDEL_DIRECTION, "direction" },
250
251    { 0, 0 },
252};
253
254static AWT_predefined_config insdel_by_SAI_predef_config[] = {
255    {
256        "*gaps_by_variability",
257        "Use to insert 2 gaps next to all\ncolumns with high variability",
258        "amount='2';chars='123';contain='1';direction='1';range='1';sai='POS_VAR_BY_PARSIMONY'",
259    },
260    {
261        "*erase_columns_without_data",
262        "selects all columns where \nMAX_FREQUENCY contains '='",
263        "chars='=';contain='1';deletable='-.';range='1';sai='MAX_FREQUENCY'",
264    },
265    { 0, 0, 0 },
266};
267
268AW_window *create_insertDeleteBySAI_window(AW_root *root, GBDATA *gb_main) {
269    static AW_window_simple *aws = 0;
270    if (!aws) {
271        aws = new AW_window_simple;
272
273        aws->init(root, "INSDEL_BY_SAI", "Insert/delete using SAI");
274
275        aws->load_xfig("insdel_sai.fig");
276        aws->button_length(8);
277
278        aws->at("close");
279        aws->callback(AW_POPDOWN);
280        aws->create_button("CLOSE", "CLOSE", "C");
281
282        aws->callback(makeHelpCallback("insdel_sai.hlp"));
283        aws->at("help");
284        aws->create_button("HELP", "HELP", "H");
285
286        aws->at("config");
287        AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, "insdel_by_sai", insdel_by_SAI_config_def, NULL, insdel_by_SAI_predef_config);
288
289        aws->at("select");
290        aws->create_option_menu(AWAR_INSDEL_RANGE, true);
291        aws->insert_option("ranges",  "r", RANGES);
292        aws->insert_option("columns", "c", SINGLE_COLUMNS);
293        aws->update_option_menu();
294
295        aws->button_length(25);
296
297        aws->at("sai");
298        awt_create_SAI_selection_button(gb_main, aws, AWAR_INSDEL_SAI);
299
300        aws->at("contains");
301        aws->create_option_menu(AWAR_INSDEL_CONTAINS, true);
302        aws->insert_option("contains",        "c", CONTAINS);
303        aws->insert_option("doesn't contain", "d", DOESNT_CONTAIN);
304        aws->update_option_menu();
305
306        aws->at("characters");
307        aws->create_input_field(AWAR_INSDEL_SAI_CHARS, 18);
308
309        aws->button_length(18);
310
311        aws->at("affected");
312        aws->create_button(0, AWAR_INSDEL_AFFECTED, 0, "+");
313
314        aws->button_length(7);
315
316        aws->at("delete");
317        aws->callback(makeWindowCallback(insdel_sai_event, DELETE));
318        aws->create_button("DELETE", "DELETE", "D");
319
320        aws->at("deletable");
321        aws->create_input_field(AWAR_INSDEL_DELETABLE, 7);
322
323        aws->at("insert");
324        aws->callback(makeWindowCallback(insdel_sai_event, INSERT));
325        aws->create_button("INSERT", "INSERT", "I");
326
327        aws->at("amount");
328        aws->create_input_field(AWAR_INSDEL_AMOUNT, 7);
329
330        aws->at("direction");
331        aws->create_option_menu(AWAR_INSDEL_DIRECTION, true);
332        aws->insert_option("in front of", "f", INFRONTOF);
333        aws->insert_option("behind",      "b", BEHIND);
334        aws->update_option_menu();
335
336        // add window text which depends on AWAR_INSDEL_RANGE
337        aws->button_length(15);
338        aws->at("what0"); aws->create_button(0, AWAR_INSDEL_WHAT);
339        aws->at("what1"); aws->create_button(0, AWAR_INSDEL_WHAT);
340        aws->at("what2"); aws->create_button(0, AWAR_INSDEL_WHAT);
341
342        aws->on_hide(cleanup_when_closing);
343    }
344    return aws;
345}
Note: See TracBrowser for help on using the repository browser.