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 | |
---|
37 | enum SaiContains { DOESNT_CONTAIN, CONTAINS }; |
---|
38 | enum InsdelMode { INSERT, DELETE }; |
---|
39 | |
---|
40 | class StaticData { |
---|
41 | char *ali; |
---|
42 | RangeList ranges; |
---|
43 | |
---|
44 | public: |
---|
45 | StaticData() : ali(NULp) {} |
---|
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 ? NULp : "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 | |
---|
61 | static StaticData SELECTED; |
---|
62 | |
---|
63 | static void cleanup_when_closing(AW_window*) { |
---|
64 | SELECTED = StaticData(); |
---|
65 | } |
---|
66 | |
---|
67 | static 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 | |
---|
75 | static 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 | |
---|
85 | static void range_changed_cb(AW_root *root) { |
---|
86 | UseRange use = UseRange(root->awar(AWAR_INSDEL_RANGE)->read_int()); |
---|
87 | const char *what = NULp; |
---|
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 | |
---|
96 | static 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 = NULp; |
---|
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 = NULp; // do not show "Could not find extended with name ''" |
---|
125 | } |
---|
126 | range_count_update_cb(root); |
---|
127 | |
---|
128 | return error; |
---|
129 | } |
---|
130 | |
---|
131 | static void update_RangeList_cb(AW_root *root) { |
---|
132 | aw_message_if(update_RangeList(root, GLOBAL.gb_main)); |
---|
133 | } |
---|
134 | |
---|
135 | void 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 | |
---|
153 | static 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, NULp); |
---|
167 | |
---|
168 | GB_end_transaction_show_error(gb_main, error, aw_message); |
---|
169 | } |
---|
170 | |
---|
171 | static 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, NULp); |
---|
197 | |
---|
198 | GB_end_transaction_show_error(gb_main, error, aw_message); |
---|
199 | } |
---|
200 | |
---|
201 | AW_window *create_insertDeleteColumn_window(AW_root *root) { |
---|
202 | static AW_window_simple *aws = NULp; |
---|
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 | |
---|
242 | static 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 | { NULp, NULp }, |
---|
252 | }; |
---|
253 | |
---|
254 | static 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 | { NULp, NULp, NULp }, |
---|
266 | }; |
---|
267 | |
---|
268 | AW_window *create_insertDeleteBySAI_window(AW_root *root, GBDATA *gb_main) { |
---|
269 | static AW_window_simple *aws = NULp; |
---|
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, NULp, 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(NULp, AWAR_INSDEL_AFFECTED, NULp, "+"); |
---|
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(NULp, AWAR_INSDEL_WHAT); |
---|
339 | aws->at("what1"); aws->create_button(NULp, AWAR_INSDEL_WHAT); |
---|
340 | aws->at("what2"); aws->create_button(NULp, AWAR_INSDEL_WHAT); |
---|
341 | |
---|
342 | aws->on_hide(cleanup_when_closing); |
---|
343 | } |
---|
344 | return aws; |
---|
345 | } |
---|