1 | // ================================================================ // |
---|
2 | // // |
---|
3 | // File : MP_Window.cxx // |
---|
4 | // Purpose : // |
---|
5 | // // |
---|
6 | // Institute of Microbiology (Technical University Munich) // |
---|
7 | // http://www.arb-home.de/ // |
---|
8 | // // |
---|
9 | // ================================================================ // |
---|
10 | |
---|
11 | #include "MP_externs.hxx" |
---|
12 | #include "MultiProbe.hxx" |
---|
13 | #include "mp_proto.hxx" |
---|
14 | |
---|
15 | #include <awt_sel_boxes.hxx> |
---|
16 | #include <awt_modules.hxx> |
---|
17 | #include <aw_select.hxx> |
---|
18 | #include <aw_file.hxx> |
---|
19 | #include <aw_msg.hxx> |
---|
20 | #include <aw_root.hxx> |
---|
21 | #include <aw_awar_defs.hxx> |
---|
22 | |
---|
23 | #include <arb_strarray.h> |
---|
24 | #include <arb_defs.h> |
---|
25 | #include <arb_strbuf.h> |
---|
26 | #include <arbdbt.h> |
---|
27 | #include <ad_cb.h> |
---|
28 | #include <RegExpr.hxx> |
---|
29 | |
---|
30 | // ************************************************************************** |
---|
31 | |
---|
32 | AW_selection_list *selected_list; |
---|
33 | AW_selection_list *result_probes_list; |
---|
34 | |
---|
35 | static AW_selection_list *probelist; |
---|
36 | |
---|
37 | |
---|
38 | AW_window_simple *MP_Window::create_result_window(AW_root *aw_root) { |
---|
39 | if (!result_window) { |
---|
40 | result_window = new AW_window_simple; |
---|
41 | result_window->init(aw_root, "MULTIPROBE_RESULTS", "MultiProbe combination results"); |
---|
42 | result_window->load_xfig("mp_results.fig"); |
---|
43 | |
---|
44 | result_window->auto_space(5, 5); |
---|
45 | |
---|
46 | result_window->button_length(7); |
---|
47 | result_window->at("close"); |
---|
48 | result_window->callback(AW_POPDOWN); |
---|
49 | result_window->create_button("CLOSE", "CLOSE"); |
---|
50 | |
---|
51 | result_window->at("Help"); |
---|
52 | result_window->callback(makeHelpCallback("multiproberesults.hlp")); |
---|
53 | result_window->create_button("HELP", "HELP"); |
---|
54 | |
---|
55 | result_window->at("Comment"); |
---|
56 | result_window->callback(makeWindowCallback(MP_Comment, (const char *)NULp)); |
---|
57 | result_window->create_input_field(MP_AWAR_RESULTPROBESCOMMENT); |
---|
58 | |
---|
59 | result_window->at("box"); |
---|
60 | aw_root->awar(MP_AWAR_RESULTPROBES)->add_callback(MP_result_combination_chosen); |
---|
61 | result_probes_list = result_window->create_selection_list(MP_AWAR_RESULTPROBES); |
---|
62 | result_probes_list->set_file_suffix("mpr"); |
---|
63 | result_probes_list->insert_default("", ""); |
---|
64 | |
---|
65 | const StorableSelectionList *storable_probes_list = new StorableSelectionList(TypedSelectionList("mpr", result_probes_list, "multiprobes", "multi_probes")); |
---|
66 | |
---|
67 | result_window->at("buttons"); |
---|
68 | result_window->callback(makeCreateWindowCallback(create_load_box_for_selection_lists, storable_probes_list)); |
---|
69 | result_window->create_button("LOAD_RPL", "LOAD"); |
---|
70 | |
---|
71 | result_window->callback(makeCreateWindowCallback(create_save_box_for_selection_lists, storable_probes_list)); |
---|
72 | result_window->create_button("SAVE_RPL", "SAVE"); |
---|
73 | |
---|
74 | result_window->callback(makeWindowCallback(awt_clear_selection_list_cb, result_probes_list)); |
---|
75 | result_window->create_button("CLEAR", "CLEAR"); |
---|
76 | |
---|
77 | result_window->callback(makeWindowCallback(MP_delete_selected, result_probes_list)); |
---|
78 | result_window->create_button("DELETE", "DELETE"); |
---|
79 | |
---|
80 | // change comment : |
---|
81 | |
---|
82 | result_window->button_length(8); |
---|
83 | |
---|
84 | result_window->at("comment"); |
---|
85 | result_window->callback(makeWindowCallback(MP_Comment, "Bad")); |
---|
86 | result_window->create_button("MARK_AS_BAD", "BAD"); |
---|
87 | |
---|
88 | result_window->callback(makeWindowCallback(MP_Comment, "???")); |
---|
89 | result_window->create_button("MARK_AS_GOOD", "???"); |
---|
90 | |
---|
91 | result_window->callback(makeWindowCallback(MP_Comment, "Good")); |
---|
92 | result_window->create_button("MARK_AS_BEST", "Good"); |
---|
93 | |
---|
94 | result_window->at("auto"); |
---|
95 | result_window->create_toggle(MP_AWAR_AUTOADVANCE); |
---|
96 | |
---|
97 | // tree actions : |
---|
98 | |
---|
99 | result_window->button_length(3); |
---|
100 | |
---|
101 | result_window->at("ct_back"); |
---|
102 | result_window->callback(makeWindowCallback(MP_show_probes_in_tree_move, true, result_probes_list)); |
---|
103 | result_window->create_button("COLOR_TREE_BACKWARD", "#rightleft_small.xpm"); |
---|
104 | |
---|
105 | result_window->at("ct_fwd"); |
---|
106 | result_window->callback(makeWindowCallback(MP_show_probes_in_tree_move, false, result_probes_list)); |
---|
107 | result_window->create_button("COLOR_TREE_FORWARD", "#leftright_small.xpm"); |
---|
108 | |
---|
109 | result_window->button_length(8); |
---|
110 | |
---|
111 | result_window->at("ColorTree"); |
---|
112 | result_window->button_length(4); |
---|
113 | result_window->callback(MP_show_probes_in_tree); |
---|
114 | result_window->create_button("COLOR_TREE", "GO"); |
---|
115 | |
---|
116 | result_window->at("MarkTree"); |
---|
117 | result_window->callback(MP_mark_probes_in_tree); |
---|
118 | result_window->create_button("MARK_TREE", "GO"); |
---|
119 | |
---|
120 | result_window->at("GroupAll"); |
---|
121 | result_window->callback(MP_group_all_except_marked); |
---|
122 | result_window->create_button("GROUP_UNMARKED", "GO"); |
---|
123 | |
---|
124 | result_window->at("StandardColor"); |
---|
125 | result_window->callback(MP_normal_colors_in_tree); |
---|
126 | result_window->create_button("RESET_COLORS", "GO"); |
---|
127 | } |
---|
128 | return result_window; |
---|
129 | } |
---|
130 | |
---|
131 | // -------------------------------------------------------------------------------- |
---|
132 | // Format of probe-list for multi-probes: |
---|
133 | // |
---|
134 | // The saved format is identical to the internal format (of sellist entries; where value always equals displayed!) |
---|
135 | // "quality#singlemismatch#ecolipos#target" |
---|
136 | // |
---|
137 | // When loading input probes, several other formats are accepted: |
---|
138 | // |
---|
139 | // "quality,singlemismatch#ecolipos#probe" (old save format) |
---|
140 | // "target le pos apos ecol grps GC 4gc2at probe | ..." (save of probe design; old format) |
---|
141 | // "target le pos apos ecol grps GC 4gc2at probe | ...,target" (save of probe design) |
---|
142 | // |
---|
143 | // above |
---|
144 | // 'target' is the target-string of the 'probe'. Internally MP works with target strings, |
---|
145 | // so when loading the old save-format, 'probe' gets reverse-complemented into 'target' |
---|
146 | |
---|
147 | |
---|
148 | #define SPACED(expr) "[[:space:]]*" expr "[[:space:]]*" |
---|
149 | |
---|
150 | inline char *gen_display(int quality, int singleMis, int ecoliPos, const char *probe) { |
---|
151 | return GBS_global_string_copy("%i#%i#%5i#%s", quality, singleMis, ecoliPos, probe); |
---|
152 | } |
---|
153 | |
---|
154 | static GB_ERROR mp_list2file(const CharPtrArray& display, const CharPtrArray& value, StrArray& line) { |
---|
155 | GB_ERROR error = NULp; |
---|
156 | |
---|
157 | if (value.empty()) error = "nothing to save"; |
---|
158 | |
---|
159 | for (size_t i = 0; i<display.size() && !error; ++i) { |
---|
160 | line.put(ARB_strdup(display[i])); |
---|
161 | } |
---|
162 | |
---|
163 | return error; |
---|
164 | } |
---|
165 | |
---|
166 | static char T_or_U_for_load = 0; |
---|
167 | |
---|
168 | static GB_ERROR mp_file2list(const CharPtrArray& line, StrArray& display, StrArray& value) { |
---|
169 | GB_ERROR error = NULp; |
---|
170 | |
---|
171 | if (line.empty()) error = "empty file"; |
---|
172 | |
---|
173 | // detect format |
---|
174 | if (!error) { |
---|
175 | // 1. try to read probes saved from multiprobes inputlist |
---|
176 | RegExpr reg_saved("^" SPACED("([0-9]+)") "([,#])" SPACED("([0-9])+") "#" SPACED("([0-9]+)") "#" SPACED("([A-Z]+)") "$", true); |
---|
177 | bool isSavedFormat = true; |
---|
178 | |
---|
179 | for (size_t i = 0; i<line.size() && isSavedFormat; ++i) { |
---|
180 | const RegMatch *match = reg_saved.match(line[i]); |
---|
181 | if (!match || reg_saved.subexpr_count() != 5) { |
---|
182 | isSavedFormat = false; |
---|
183 | if (reg_saved.has_failed()) aw_message(reg_saved.get_error()); |
---|
184 | } |
---|
185 | else { |
---|
186 | char T_or_U = T_or_U_for_load ? T_or_U_for_load : 'U'; |
---|
187 | |
---|
188 | std::string sep = reg_saved.subexpr_match(2)->extract(line[i]); |
---|
189 | |
---|
190 | int quality = atoi(reg_saved.subexpr_match(1)->extract(line[i]).c_str()); |
---|
191 | int singlemis = atoi(reg_saved.subexpr_match(3)->extract(line[i]).c_str()); |
---|
192 | int ecoli = atoi(reg_saved.subexpr_match(4)->extract(line[i]).c_str()); |
---|
193 | |
---|
194 | std::string probe = reg_saved.subexpr_match(5)->extract(line[i]); |
---|
195 | |
---|
196 | if (sep[0] == ',') { // old format (saved probe instead of probe-target) |
---|
197 | size_t plen = probe.length(); |
---|
198 | char *dprobe = ARB_strndup(probe.c_str(), plen); |
---|
199 | |
---|
200 | GBT_reverseComplementNucSequence(dprobe, plen, T_or_U); |
---|
201 | probe = dprobe; |
---|
202 | free(dprobe); |
---|
203 | } |
---|
204 | |
---|
205 | char *entry = gen_display(quality, singlemis, ecoli, probe.c_str()); |
---|
206 | display.put(entry); // transfers ownership - dont free! |
---|
207 | value.put(ARB_strdup(entry)); |
---|
208 | } |
---|
209 | } |
---|
210 | |
---|
211 | if (!isSavedFormat) { |
---|
212 | // delete attempt to read saved format: |
---|
213 | display.clear(); |
---|
214 | value.clear(); |
---|
215 | |
---|
216 | // try to read designed list |
---|
217 | RegExpr reg_designed("^([A-Z]+)" // subexpr #1 (target) |
---|
218 | "[[:space:]]+[0-9]+" |
---|
219 | "[[:space:]]+[A-Z][=+-]" |
---|
220 | "[[:space:]]*[0-9]+" |
---|
221 | "[[:space:]]+([0-9]+)" // subexpr #2 (ecoli pos) |
---|
222 | "([[:space:]]+[0-9]+){1,2}" // accept with and without quality entry |
---|
223 | "([[:space:]]+[0-9.]+){2}" |
---|
224 | "[[:space:]]+[A-Z]+" |
---|
225 | "[[:space:]]+[|]", true); |
---|
226 | |
---|
227 | for (size_t i = 0; i<line.size() && !error; ++i) { |
---|
228 | char *probe = NULp; |
---|
229 | char *description = NULp; |
---|
230 | bool new_format = false; |
---|
231 | |
---|
232 | const char *comma = strchr(line[i], ','); |
---|
233 | if (comma) { |
---|
234 | description = ARB_strpartdup(line[i], comma-1); |
---|
235 | |
---|
236 | const char *cprobe = comma+1; |
---|
237 | while (cprobe[0] == ' ') ++cprobe; |
---|
238 | probe = ARB_strdup(cprobe); |
---|
239 | |
---|
240 | new_format = true; |
---|
241 | } |
---|
242 | else { |
---|
243 | description = ARB_strdup(line[i]); |
---|
244 | } |
---|
245 | |
---|
246 | const RegMatch *match = reg_designed.match(description); |
---|
247 | if (match) { // line from probe design (old + new format) |
---|
248 | mp_assert(match->didMatch()); |
---|
249 | |
---|
250 | match = reg_designed.subexpr_match(1); |
---|
251 | mp_assert(match->didMatch()); |
---|
252 | std::string parsed_probe = match->extract(description); |
---|
253 | |
---|
254 | if (new_format) { // already got probe value -> compare |
---|
255 | if (strcmp(probe, parsed_probe.c_str()) != 0) { |
---|
256 | error = GBS_global_string("probe string mismatch (probe='%s', parsed_probe='%s', parsed from='%s')", |
---|
257 | probe, parsed_probe.c_str(), line[i]); |
---|
258 | } |
---|
259 | } |
---|
260 | else { |
---|
261 | probe = ARB_strdup(parsed_probe.c_str()); |
---|
262 | } |
---|
263 | |
---|
264 | if (!error) { |
---|
265 | int quality, ecoli; |
---|
266 | |
---|
267 | match = reg_designed.subexpr_match(2); |
---|
268 | mp_assert(match->didMatch()); |
---|
269 | ecoli = atoi(match->extract(description).c_str()); |
---|
270 | quality = 3; |
---|
271 | |
---|
272 | char *entry = gen_display(quality, 0, ecoli, probe); |
---|
273 | display.put(entry); // transfers ownership - dont free! |
---|
274 | value.put(ARB_strdup(entry)); |
---|
275 | } |
---|
276 | } |
---|
277 | else { |
---|
278 | if (reg_designed.has_failed()) aw_message(reg_designed.get_error()); |
---|
279 | if (new_format && probe[0]) { |
---|
280 | error = GBS_global_string("can't parse line '%s'", line[i]); |
---|
281 | } |
---|
282 | // (when loading old format -> silently ignore non-matching lines) |
---|
283 | } |
---|
284 | |
---|
285 | free(probe); |
---|
286 | free(description); |
---|
287 | } |
---|
288 | } |
---|
289 | } |
---|
290 | |
---|
291 | return error; |
---|
292 | } |
---|
293 | |
---|
294 | static void track_ali_change_cb(AW_root*, GBDATA *gb_main) { |
---|
295 | GB_transaction ta(gb_main); |
---|
296 | |
---|
297 | char *aliname = GBT_get_default_alignment(gb_main); |
---|
298 | if (!aliname) { |
---|
299 | aw_message(GB_await_error()); |
---|
300 | } |
---|
301 | else { |
---|
302 | GB_alignment_type alitype = GBT_get_alignment_type(gb_main, aliname); |
---|
303 | mp_assert(alitype != GB_AT_UNKNOWN); |
---|
304 | GBT_determine_T_or_U(alitype, &T_or_U_for_load, "reverse-complement"); // T_or_U_for_load is set to 0 in error-case |
---|
305 | free(aliname); |
---|
306 | } |
---|
307 | } |
---|
308 | |
---|
309 | static void MP_collect_probes(AW_window*, awt_collect_mode mode) { |
---|
310 | switch (mode) { |
---|
311 | case ACM_ADD: |
---|
312 | if (!probelist->default_is_selected()) { |
---|
313 | int idx = probelist->get_index_of_selected(); |
---|
314 | AW_selection_list_iterator sel(probelist, idx); |
---|
315 | selected_list->insert(sel.get_displayed(), *sel.get_value()); |
---|
316 | MP_delete_selected(NULp, probelist); |
---|
317 | } |
---|
318 | break; |
---|
319 | |
---|
320 | case ACM_REMOVE: |
---|
321 | if (!selected_list->default_is_selected()) { |
---|
322 | int idx = selected_list->get_index_of_selected(); |
---|
323 | AW_selection_list_iterator sel(selected_list, idx); |
---|
324 | probelist->insert(sel.get_displayed(), *sel.get_value()); |
---|
325 | MP_delete_selected(NULp, selected_list); |
---|
326 | } |
---|
327 | break; |
---|
328 | |
---|
329 | case ACM_FILL: |
---|
330 | probelist->move_content_to(selected_list); |
---|
331 | break; |
---|
332 | |
---|
333 | case ACM_EMPTY: |
---|
334 | selected_list->move_content_to(probelist); |
---|
335 | break; |
---|
336 | } |
---|
337 | |
---|
338 | selected_list->sort(false, true); |
---|
339 | |
---|
340 | probelist->update(); |
---|
341 | selected_list->update(); |
---|
342 | } |
---|
343 | |
---|
344 | MP_Window::MP_Window(AW_root *aw_root, GBDATA *gb_main) { |
---|
345 | int max_seq_col = 35; |
---|
346 | int max_seq_hgt = 15; |
---|
347 | |
---|
348 | #if defined(DEBUG) |
---|
349 | static bool initialized = false; |
---|
350 | mp_assert(!initialized); // this function may only be called once! |
---|
351 | initialized = true; |
---|
352 | #endif |
---|
353 | |
---|
354 | aw_root->awar(AWAR_DEFAULT_ALIGNMENT)->add_callback(makeRootCallback(track_ali_change_cb, gb_main)); |
---|
355 | track_ali_change_cb(aw_root, gb_main); |
---|
356 | |
---|
357 | result_window = NULp; |
---|
358 | |
---|
359 | aws = new AW_window_simple; |
---|
360 | aws->init(aw_root, "MULTIPROBE", "MULTI_PROBE"); |
---|
361 | aws->load_xfig("multiprobe.fig"); |
---|
362 | |
---|
363 | aws->at("close"); |
---|
364 | aws->callback(MP_close_main); |
---|
365 | aws->create_button("CLOSE", "CLOSE"); |
---|
366 | |
---|
367 | aws->at("help"); |
---|
368 | aws->callback(makeHelpCallback("multiprobe.hlp")); |
---|
369 | aws->create_button("HELP", "HELP"); |
---|
370 | |
---|
371 | aws->button_length(7); |
---|
372 | aws->at("Selectedprobes"); |
---|
373 | aw_root->awar(MP_AWAR_SELECTEDPROBES)->add_callback(MP_selected_chosen); |
---|
374 | selected_list = aws->create_selection_list(MP_AWAR_SELECTEDPROBES, max_seq_col, max_seq_hgt); |
---|
375 | |
---|
376 | const StorableSelectionList *storable_selected_list = new StorableSelectionList(TypedSelectionList("prb", selected_list, "probes", "selected_probes"), mp_list2file, mp_file2list); |
---|
377 | |
---|
378 | selected_list->insert_default("", ""); |
---|
379 | |
---|
380 | aws->at("Probelist"); |
---|
381 | probelist = aws->create_selection_list(MP_AWAR_PROBELIST); |
---|
382 | const StorableSelectionList *storable_probelist = new StorableSelectionList(TypedSelectionList("prb", probelist, "probes", "all_probes"), mp_list2file, mp_file2list); |
---|
383 | probelist->insert_default("", ""); |
---|
384 | |
---|
385 | aws->at("collect"); |
---|
386 | awt_create_collect_buttons(aws, true, MP_collect_probes); |
---|
387 | |
---|
388 | aws->auto_space(5, 5); |
---|
389 | aws->button_length(7); |
---|
390 | |
---|
391 | for (int rightSide = 0; rightSide <= 1; ++rightSide) { |
---|
392 | const StorableSelectionList *storableList = rightSide ? storable_selected_list : storable_probelist; |
---|
393 | const char *id_suffix = rightSide ? "SELECTED_PROBES" : "PROBES"; |
---|
394 | |
---|
395 | AW_selection_list *sellist = storableList->get_typedsellist().get_sellist(); |
---|
396 | |
---|
397 | aws->at(rightSide ? "RightButtons" : "LeftButtons"); |
---|
398 | |
---|
399 | aws->callback(makeCreateWindowCallback(create_load_box_for_selection_lists, storableList)); |
---|
400 | aws->create_button(GBS_global_string("LOAD_%s", id_suffix), "LOAD"); |
---|
401 | |
---|
402 | aws->callback(makeCreateWindowCallback(create_save_box_for_selection_lists, storableList)); |
---|
403 | aws->create_button(GBS_global_string("SAVE_%s", id_suffix), "SAVE"); |
---|
404 | |
---|
405 | aws->callback(makeWindowCallback(awt_clear_selection_list_cb, sellist)); |
---|
406 | aws->create_button(GBS_global_string("CLEAR_%s", id_suffix), "CLEAR"); |
---|
407 | |
---|
408 | aws->callback(makeWindowCallback(MP_delete_selected, sellist)); |
---|
409 | aws->create_button(GBS_global_string("DELETE_%s", id_suffix), "DELETE"); |
---|
410 | } |
---|
411 | |
---|
412 | aws->at("Quality"); |
---|
413 | aws->callback(MP_cache_sonden); // @@@ used as OPTIONMENU_SELECT_CB (see #559) |
---|
414 | aws->create_option_menu(MP_AWAR_QUALITY); |
---|
415 | aws->insert_option("High Priority", "", 5); |
---|
416 | aws->insert_option(" 4", "", 4); |
---|
417 | aws->insert_option("Normal 3", "", 3); |
---|
418 | aws->insert_option(" 2", "", 2); |
---|
419 | aws->insert_option("Low Prio. 1", "", 1); |
---|
420 | aws->update_option_menu(); |
---|
421 | |
---|
422 | aws->at("add"); |
---|
423 | aws->callback(MP_new_sequence); |
---|
424 | aws->create_autosize_button("ADD_PROBE", "ADD"); |
---|
425 | aws->at("seqin"); |
---|
426 | aws->create_input_field(MP_AWAR_SEQIN, 25); |
---|
427 | |
---|
428 | // -------------------------------- |
---|
429 | // multi probe parameters |
---|
430 | |
---|
431 | aws->at("PTServer"); |
---|
432 | awt_create_PTSERVER_selection_button(aws, MP_AWAR_PTSERVER); |
---|
433 | aw_root->awar(MP_AWAR_PTSERVER)->add_callback(MP_cache_sonden2); // remove cached probes when changing pt-server |
---|
434 | |
---|
435 | aws->at("NoOfProbes"); |
---|
436 | aws->create_option_menu(MP_AWAR_NOOFPROBES); |
---|
437 | aws->callback(MP_cache_sonden); // @@@ used as OPTIONMENU_SELECT_CB (see #559) |
---|
438 | aws->insert_option("Compute 1 probe ", "", 1); |
---|
439 | char str[50]; |
---|
440 | for (int i=2; i<=MAXPROBECOMBIS; i++) { |
---|
441 | sprintf(str, "%2d-probe-combinations", i); |
---|
442 | aws->insert_option(str, "", i); |
---|
443 | } |
---|
444 | aws->update_option_menu(); |
---|
445 | |
---|
446 | aws->button_length(10); |
---|
447 | aws->at("Compute"); |
---|
448 | aws->callback(makeWindowCallback(MP_compute, gb_main)); |
---|
449 | aws->highlight(); |
---|
450 | aws->help_text("Compute possible Solutions"); |
---|
451 | aws->create_button("GO", "GO"); |
---|
452 | |
---|
453 | aws->button_length(20); |
---|
454 | aws->at("Results"); |
---|
455 | aws->callback(MP_popup_result_window); |
---|
456 | aws->create_button("OPEN_RESULT_WIN", "Open result window"); |
---|
457 | |
---|
458 | aws->at("Komplement"); |
---|
459 | aws->callback(MP_cache_sonden); // @@@ used as TOGGLE_CLICK_CB (see #559) |
---|
460 | aws->create_toggle(MP_AWAR_COMPLEMENT); |
---|
461 | |
---|
462 | aws->at("WeightedMismatches"); |
---|
463 | aws->callback(MP_cache_sonden); // @@@ used as TOGGLE_CLICK_CB (see #559) |
---|
464 | aws->create_toggle(MP_AWAR_WEIGHTEDMISMATCHES); |
---|
465 | |
---|
466 | // max non group hits |
---|
467 | aws->at("Border1"); |
---|
468 | aws->callback(MP_cache_sonden); // @@@ used as INPUTFIELD_CB (see #559) |
---|
469 | aws->create_input_field(MP_AWAR_QUALITYBORDER1, 6); |
---|
470 | |
---|
471 | aws->at("OutsideMismatches"); |
---|
472 | aws->callback(MP_cache_sonden); // @@@ used as OPTIONMENU_SELECT_CB (see #559) |
---|
473 | aws->create_option_menu(MP_AWAR_OUTSIDEMISMATCHES); |
---|
474 | aws->insert_option("3.0", "", (float)3.0); |
---|
475 | aws->insert_option("2.5", "", (float)2.5); |
---|
476 | aws->insert_option("2.0", "", (float)2.0); |
---|
477 | aws->insert_option("1.5", "", (float)1.5); |
---|
478 | aws->insert_option("1.0", "", (float)1.0); |
---|
479 | aws->update_option_menu(); |
---|
480 | |
---|
481 | // max mismatches for group |
---|
482 | aws->at("Greyzone"); |
---|
483 | aws->callback(MP_cache_sonden); // @@@ used as OPTIONMENU_SELECT_CB (see #559) |
---|
484 | aws->create_option_menu(MP_AWAR_GREYZONE); |
---|
485 | aws->insert_default_option("0.0", "", (float)0.0); |
---|
486 | for (float lauf=0.1; lauf<(float)1.0; lauf+=0.1) { |
---|
487 | char strs[20]; |
---|
488 | sprintf(strs, "%.1f", lauf); |
---|
489 | aws->insert_option(strs, "", lauf); |
---|
490 | } |
---|
491 | aws->update_option_menu(); |
---|
492 | |
---|
493 | } |
---|
494 | |
---|
495 | |
---|
496 | MP_Window::~MP_Window() { |
---|
497 | if (result_window) result_window->hide(); |
---|
498 | if (aws) aws->hide(); |
---|
499 | |
---|
500 | delete result_window; |
---|
501 | delete aws; |
---|
502 | } |
---|
503 | |
---|
504 | // -------------------------------------------------------------------------------- |
---|
505 | |
---|
506 | #ifdef UNIT_TESTS |
---|
507 | #ifndef TEST_UNIT_H |
---|
508 | #include <test_unit.h> |
---|
509 | #endif |
---|
510 | #include <command_output.h> |
---|
511 | |
---|
512 | inline void array2cpa(const char **content, int count, ConstStrArray& array) { |
---|
513 | array.erase(); |
---|
514 | for (int i = 0; i<count; ++i) { |
---|
515 | array.put(content[i]); |
---|
516 | } |
---|
517 | } |
---|
518 | |
---|
519 | inline char *array2string(const CharPtrArray& array) { |
---|
520 | GBS_strstruct out(1000); |
---|
521 | |
---|
522 | for (size_t i = 0; i<array.size(); ++i) { |
---|
523 | out.cat(array[i]); |
---|
524 | out.put('\n'); |
---|
525 | } |
---|
526 | |
---|
527 | return out.release(); |
---|
528 | } |
---|
529 | |
---|
530 | static arb_test::match_expectation inputConvertsInto(const char *input, const char *expected_result) { |
---|
531 | ConstStrArray lines; |
---|
532 | GBT_split_string(lines, input, "\n", SPLIT_DROPEMPTY); |
---|
533 | |
---|
534 | using namespace arb_test; |
---|
535 | expectation_group expected; |
---|
536 | |
---|
537 | StrArray display, value; |
---|
538 | expected.add(doesnt_report_error(mp_file2list(lines, display, value))); |
---|
539 | |
---|
540 | char *displ_as_string = array2string(display); |
---|
541 | char *value_as_string = array2string(value); |
---|
542 | |
---|
543 | expected.add(that(displ_as_string).is_equal_to(expected_result)); |
---|
544 | expected.add(that(value_as_string).is_equal_to(expected_result)); |
---|
545 | |
---|
546 | free(value_as_string); |
---|
547 | free(displ_as_string); |
---|
548 | |
---|
549 | return all().ofgroup(expected); |
---|
550 | } |
---|
551 | |
---|
552 | #define TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS(input,expected) TEST_EXPECTATION(inputConvertsInto(input, expected)) |
---|
553 | #define TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS__BROKEN(input,expected) TEST_EXPECTATION__BROKEN(inputConvertsInto(input, expected)) |
---|
554 | |
---|
555 | void TEST_load_probe_design_results() { |
---|
556 | { |
---|
557 | const char *expected = |
---|
558 | "3#0# 521#GCAGCCGCGGUAAUACGG\n" |
---|
559 | "3#0# 510#ACUCCGUGCCAGCAGCCG\n" |
---|
560 | "3#0# 511#CUCCGUGCCAGCAGCCGC\n" |
---|
561 | "3#0# 512#UCCGUGCCAGCAGCCGCG\n" |
---|
562 | "3#0# 513#CCGUGCCAGCAGCCGCGG\n" |
---|
563 | "3#0# 509#AACUCCGUGCCAGCAGCC\n"; |
---|
564 | |
---|
565 | const char *old_probeDesignSave = |
---|
566 | "Probe design Parameters:\n" |
---|
567 | "Length of probe 18\n" |
---|
568 | "Temperature [30.0 -100.0]\n" |
---|
569 | "GC-Content [50.0 -100.0]\n" |
---|
570 | "E.Coli Position [any]\n" |
---|
571 | "Max Non Group Hits 0\n" |
---|
572 | "Min Group Hits 50%\n" |
---|
573 | "Target le apos ecol grps G+C 4GC+2AT Probe sequence | Decrease T by n*.3C -> probe matches n non group species\n" |
---|
574 | "GCAGCCGCGGUAAUACGG 18 A= 4398 521 23 66.7 60.0 CCGUAUUACCGCGGCUGC | 0; 0; 0; 0; 0; 0; 0; 0; 35; 35; 35; 38; 74; 74; 74; 77;113;113;113;148;\n" |
---|
575 | "ACUCCGUGCCAGCAGCCG 18 B= 3852 510 23 72.2 62.0 CGGCUGCUGGCACGGAGU | 0; 0; 0; 0; 0; 40; 40; 40; 80; 80; 80; 80;120;120;120;200;200;200;200;201;\n" |
---|
576 | "CUCCGUGCCAGCAGCCGC 18 B+ 4 511 23 77.8 64.0 GCGGCUGCUGGCACGGAG | 0; 0; 0; 0; 0; 40; 40; 40; 40; 80; 80; 80;160;160;160;160;201;201;201;201;\n" |
---|
577 | "UCCGUGCCAGCAGCCGCG 18 B+ 7 512 23 77.8 64.0 CGCGGCUGCUGGCACGGA | 0; 0; 0; 0; 0; 40; 40; 40;120;120;120;120;160;160;161;201;201;201;202;202;\n" |
---|
578 | "CCGUGCCAGCAGCCGCGG 18 B+ 9 513 23 83.3 66.0 CCGCGGCUGCUGGCACGG | 0; 0; 0; 0; 0; 80; 80; 80; 80;120;120;121;161;161;161;162;203;203;204;204;\n" |
---|
579 | "AACUCCGUGCCAGCAGCC 18 B- 1 509 22 66.7 60.0 GGCUGCUGGCACGGAGUU | 0; 0; 0; 0; 0; 40; 40; 40; 80; 80; 80;120;120;120;120;160;160;160;240;240;\n"; |
---|
580 | |
---|
581 | TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS(old_probeDesignSave, expected); |
---|
582 | |
---|
583 | |
---|
584 | const char *old_multiprobeInputSave = // old multi-probe saved probe (i.e. not target) sequences -> load shall correct that |
---|
585 | "3,0# 521#CCGUAUUACCGCGGCUGC\n" |
---|
586 | "3,0# 510#CGGCUGCUGGCACGGAGU\n" |
---|
587 | "3,0# 511#GCGGCUGCUGGCACGGAG\n" |
---|
588 | "3,0# 512#CGCGGCUGCUGGCACGGA\n" |
---|
589 | "3,0# 513#CCGCGGCUGCUGGCACGG\n" |
---|
590 | "3,0# 509#GGCUGCUGGCACGGAGUU\n"; |
---|
591 | |
---|
592 | { |
---|
593 | LocallyModify<char> TorU(T_or_U_for_load, 'U'); |
---|
594 | TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS(old_multiprobeInputSave, expected); |
---|
595 | } |
---|
596 | |
---|
597 | const char *new_probeDesignSave_v1 = |
---|
598 | "Probe design Parameters:,\n" |
---|
599 | "Length of probe 18,\n" |
---|
600 | "Temperature [30.0 -100.0],\n" |
---|
601 | "GC-Content [50.0 -100.0],\n" |
---|
602 | "E.Coli Position [any],\n" |
---|
603 | "Max Non Group Hits 0,\n" |
---|
604 | "Min Group Hits 50%,\n" |
---|
605 | "Target le apos ecol grps G+C 4GC+2AT Probe sequence | Decrease T by n*.3C -> probe matches n non group species,\n" |
---|
606 | "GCAGCCGCGGUAAUACGG 18 A= 4398 521 23 66.7 60.0 CCGUAUUACCGCGGCUGC | 0; 0; 0; 0; 0; 0; 0; 0; 35; 35; 35; 38; 74; 74; 74; 77;113;113;113;148;,GCAGCCGCGGUAAUACGG\n" |
---|
607 | "ACUCCGUGCCAGCAGCCG 18 B= 3852 510 23 72.2 62.0 CGGCUGCUGGCACGGAGU | 0; 0; 0; 0; 0; 40; 40; 40; 80; 80; 80; 80;120;120;120;200;200;200;200;201;,ACUCCGUGCCAGCAGCCG\n" |
---|
608 | "CUCCGUGCCAGCAGCCGC 18 B+ 4 511 23 77.8 64.0 GCGGCUGCUGGCACGGAG | 0; 0; 0; 0; 0; 40; 40; 40; 40; 80; 80; 80;160;160;160;160;201;201;201;201;,CUCCGUGCCAGCAGCCGC\n" |
---|
609 | "UCCGUGCCAGCAGCCGCG 18 B+ 7 512 23 77.8 64.0 CGCGGCUGCUGGCACGGA | 0; 0; 0; 0; 0; 40; 40; 40;120;120;120;120;160;160;161;201;201;201;202;202;,UCCGUGCCAGCAGCCGCG\n" |
---|
610 | "CCGUGCCAGCAGCCGCGG 18 B+ 9 513 23 83.3 66.0 CCGCGGCUGCUGGCACGG | 0; 0; 0; 0; 0; 80; 80; 80; 80;120;120;121;161;161;161;162;203;203;204;204;,CCGUGCCAGCAGCCGCGG\n" |
---|
611 | "AACUCCGUGCCAGCAGCC 18 B- 1 509 22 66.7 60.0 GGCUGCUGGCACGGAGUU | 0; 0; 0; 0; 0; 40; 40; 40; 80; 80; 80;120;120;120;120;160;160;160;240;240;,AACUCCGUGCCAGCAGCC\n"; |
---|
612 | |
---|
613 | TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS(new_probeDesignSave_v1, expected); |
---|
614 | |
---|
615 | |
---|
616 | const char *new_multiprobeInputSave = |
---|
617 | "3#0# 521#GCAGCCGCGGUAAUACGG\n" |
---|
618 | "3#0# 510#ACUCCGUGCCAGCAGCCG\n" |
---|
619 | "3#0# 511#CUCCGUGCCAGCAGCCGC\n" |
---|
620 | "3#0# 512#UCCGUGCCAGCAGCCGCG\n" |
---|
621 | "3#0# 513#CCGUGCCAGCAGCCGCGG\n" |
---|
622 | "3#0# 509#AACUCCGUGCCAGCAGCC\n"; |
---|
623 | |
---|
624 | TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS(new_multiprobeInputSave, expected); |
---|
625 | } |
---|
626 | } |
---|
627 | |
---|
628 | static const char *recent_expected = |
---|
629 | "3#0# 82#CGAAAGGAAGAUUA\n" |
---|
630 | "3#0# 82#CGAAAGGAAGAUUAA\n" |
---|
631 | "3#0# 86#AGGAAGAUUAAUACC\n" |
---|
632 | "3#0# 87#GGAAGAUUAAUACC\n" |
---|
633 | "3#0# 21#GUCGAGCGAUGAAG\n" |
---|
634 | "3#0# 20#AGUCGAGCGAUGAAG\n" |
---|
635 | "3#0# 20#AGUCGAGCGAUGAA\n" |
---|
636 | "3#0# 19#AAGUCGAGCGAUGAA\n" |
---|
637 | "3#0# 18#CAAGUCGAGCGAUGA\n" |
---|
638 | "3#0# 19#AAGUCGAGCGAUGA\n" |
---|
639 | "3#0# 17#UCAAGUCGAGCGAUG\n" |
---|
640 | "3#0# 18#CAAGUCGAGCGAUG\n" |
---|
641 | "3#0# 16#AUCAAGUCGAGCGAU\n" |
---|
642 | "3#0# 17#UCAAGUCGAGCGAU\n" |
---|
643 | "3#0# 16#AUCAAGUCGAGCGA\n"; |
---|
644 | |
---|
645 | static const char *recent_probeDesignSave = |
---|
646 | "Probe design parameters:,\n" |
---|
647 | "Length of probe 14-15,\n" |
---|
648 | "Temperature [ 0.0 -400.0],\n" |
---|
649 | "GC-content [30.0 - 80.0],\n" |
---|
650 | "E.Coli position [any],\n" |
---|
651 | "Max. nongroup hits 0,\n" |
---|
652 | "Min. group hits 100% (max. rejected coverage: 75%),\n" |
---|
653 | "Target le apos ecol qual grps G+C temp Probe sequence | Decrease T by n*.3C -> probe matches n non group species,\n" |
---|
654 | "CGAAAGGAAGAUUA 14 A=94 82 77 4 35.7 38.0 UAAUCUUCCUUUCG | - - - - - - - - - - - - - - - - - - - -,CGAAAGGAAGAUUA\n" |
---|
655 | "CGAAAGGAAGAUUAA 15 A+ 0 82 77 4 33.3 40.0 UUAAUCUUCCUUUCG | - - - - - - - - - - - - - - - - - - - -,CGAAAGGAAGAUUAA\n" |
---|
656 | "AGGAAGAUUAAUACC 15 A+ 4 86 77 4 33.3 40.0 GGUAUUAAUCUUCCU | - - - - - - - - - - - - - - - - - - - -,AGGAAGAUUAAUACC\n" |
---|
657 | "GGAAGAUUAAUACC 14 A+ 5 87 77 4 35.7 38.0 GGUAUUAAUCUUCC | - - - - - - - - - - - - - - - - - - - -,GGAAGAUUAAUACC\n" |
---|
658 | "GUCGAGCGAUGAAG 14 B=22 21 77 4 57.1 44.0 CUUCAUCGCUCGAC | - - - - - - - - - - - - - - - - - - - 2,GUCGAGCGAUGAAG\n" |
---|
659 | "AGUCGAGCGAUGAAG 15 B- 1 20 73 4 53.3 46.0 CUUCAUCGCUCGACU | - - - - - - - - - - - - - - - - - - 2 2,AGUCGAGCGAUGAAG\n" |
---|
660 | "AGUCGAGCGAUGAA 14 B- 1 20 57 4 50.0 42.0 UUCAUCGCUCGACU | - - - - - - - - - - - - - - 2 2 2 2 2 2,AGUCGAGCGAUGAA\n" |
---|
661 | "AAGUCGAGCGAUGAA 15 B- 2 19 53 4 46.7 44.0 UUCAUCGCUCGACUU | - - - - - - - - - - - - - 2 2 2 2 2 2 2,AAGUCGAGCGAUGAA\n" |
---|
662 | "CAAGUCGAGCGAUGA 15 B- 3 18 41 4 53.3 46.0 UCAUCGCUCGACUUG | - - - - - - - - - - 2 2 2 2 2 2 2 2 2 2,CAAGUCGAGCGAUGA\n" |
---|
663 | "AAGUCGAGCGAUGA 14 B- 2 19 41 4 50.0 42.0 UCAUCGCUCGACUU | - - - - - - - - - - 2 2 2 2 2 2 2 2 2 2,AAGUCGAGCGAUGA\n" |
---|
664 | "UCAAGUCGAGCGAUG 15 B- 4 17 25 4 53.3 46.0 CAUCGCUCGACUUGA | - - - - - - 2 2 2 2 2 2 2 2 2 2 2 2 9 9,UCAAGUCGAGCGAUG\n" |
---|
665 | "CAAGUCGAGCGAUG 14 B- 3 18 25 4 57.1 44.0 CAUCGCUCGACUUG | - - - - - - 2 2 2 2 2 2 2 2 2 2 2 2 2 2,CAAGUCGAGCGAUG\n" |
---|
666 | "AUCAAGUCGAGCGAU 15 B- 5 16 5 4 46.7 44.0 AUCGCUCGACUUGAU | - 2 2 2 2 2 2 2 9 9 9 9 9 9 9 9 9 9 9 9,AUCAAGUCGAGCGAU\n" |
---|
667 | "UCAAGUCGAGCGAU 14 B- 4 17 5 4 50.0 42.0 AUCGCUCGACUUGA | - 2 2 2 2 2 2 2 2 9 9 9 9 9 9 9 9 9 9 9,UCAAGUCGAGCGAU\n" |
---|
668 | "AUCAAGUCGAGCGA 14 B- 5 16 5 4 50.0 42.0 UCGCUCGACUUGAU | - 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9,AUCAAGUCGAGCGA"; |
---|
669 | |
---|
670 | void TEST_AFTER_SLOW_recent_probe_design_result() { |
---|
671 | // -------------------------------------------------------------------------------- |
---|
672 | // whenever probe design output changes, copy current 'recent_probeDesignSave' and |
---|
673 | // 'recent_expected' into TEST_load_probe_design_results, to ensure ARB can load |
---|
674 | // any saved probe design ever created with ARB. |
---|
675 | |
---|
676 | TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS(recent_probeDesignSave, recent_expected); |
---|
677 | } |
---|
678 | |
---|
679 | void TEST_SLOW_design_probes_and_load_result() { |
---|
680 | TEST_SETUP_GLOBAL_ENVIRONMENT("ptserver"); |
---|
681 | |
---|
682 | CommandOutput designed_probes("arb_probe serverid=-666 designprobelength=14 designmaxprobelength=15 designnames=ClnCorin#CltBotul#CPPParap#ClfPerfr designmintargets=100", true); |
---|
683 | TEST_EXPECT_NO_ERROR(designed_probes.get_error()); |
---|
684 | |
---|
685 | // Simulate result of designing probes in ARB_NT and saving the result to a file: |
---|
686 | char *saved_design_result = NULp; // content of that file |
---|
687 | { |
---|
688 | ConstStrArray lines; |
---|
689 | GBT_split_string(lines, designed_probes.get_stdoutput(), "\n", SPLIT_DROPEMPTY); |
---|
690 | |
---|
691 | StrArray saved_lines; |
---|
692 | |
---|
693 | for (size_t i = 0; i<lines.size(); ++i) { |
---|
694 | char *probe; // same as awar-value of probe-design-resultlist in ARB_NT |
---|
695 | { |
---|
696 | size_t plen = strspn(lines[i], "acgtuACGTU"); |
---|
697 | if (plen<10) { // no probe at start // @@@ 10 is min. probelen, use a global definition here! |
---|
698 | probe = ARB_strdup(""); |
---|
699 | } |
---|
700 | else { |
---|
701 | probe = ARB_strndup(lines[i], plen); |
---|
702 | } |
---|
703 | } |
---|
704 | |
---|
705 | char *conv4save = GBS_string_eval(lines[i], ":,=;"); // saving selection list converts comma to semicolon |
---|
706 | arb_assert(conv4save); |
---|
707 | |
---|
708 | saved_lines.put(GBS_global_string_copy("%s,%s", conv4save, probe)); |
---|
709 | |
---|
710 | free(conv4save); |
---|
711 | free(probe); |
---|
712 | } |
---|
713 | |
---|
714 | saved_design_result = GBT_join_strings(saved_lines, '\n'); |
---|
715 | TEST_EXPECT_EQUAL(saved_design_result, recent_probeDesignSave); // see comment in TEST_AFTER_SLOW_recent_probe_design_result |
---|
716 | } |
---|
717 | |
---|
718 | TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS(saved_design_result, recent_expected); |
---|
719 | free(saved_design_result); |
---|
720 | } |
---|
721 | |
---|
722 | |
---|
723 | #endif // UNIT_TESTS |
---|
724 | |
---|
725 | // -------------------------------------------------------------------------------- |
---|