1
// ================================================================ //
3
// File : MP_Window.cxx //
6
// Institute of Microbiology (Technical University Munich) //
7
// http://www.arb-home.de/ //
9
// ================================================================ //
11
#include "MP_externs.hxx"
12
#include "MultiProbe.hxx"
13
#include "mp_proto.hxx"
15
#include <awt_sel_boxes.hxx>
16
#include <awt_modules.hxx>
17
#include <aw_select.hxx>
18
#include <aw_file.hxx>
3
20
#include <aw_root.hxx>
4
#include <aw_window.hxx>
5
#include <aw_awars.hxx>
6
#include <aw_global.hxx>
8
#include <awt_sel_boxes.hxx>
10
#include "MultiProbe.hxx"
11
#include <mp_proto.hxx>
13
struct mp_gl_struct mp_pd_gl;
16
//**************************************************************************
18
AW_selection_list *selected_list; //globale id's fuer
19
AW_selection_list *probelist; //Identifizierung der Listen
21
#include <aw_awar_defs.hxx>
23
#include <arb_strarray.h>
25
#include <arb_strbuf.h>
28
#include <RegExpr.hxx>
30
// **************************************************************************
32
struct mp_gl_struct mp_pd_gl; // global link
34
AW_selection_list *selected_list;
35
AW_selection_list *probelist;
20
36
AW_selection_list *result_probes_list;
23
AW_window_simple *MP_Window::create_result_window(AW_root *aw_root)
25
if (result_window) return result_window;
27
result_window = new AW_window_simple;
28
result_window->init( aw_root, "MULTIPROBE_RESULTS", "MultiProbe combination results");
29
result_window->load_xfig("mp_results.fig");
31
result_window->button_length(8);
32
result_window->at("close");
33
result_window->callback(AW_POPDOWN);
34
result_window->create_button("CLOSE", "CLOSE");
36
result_window->at("DeleteAll");
37
result_window->callback(MP_del_all_result);
38
result_window->create_button("DELETE_ALL", "DELETE");
40
result_window->at("DeleteSel");
41
result_window->callback(MP_del_sel_result);
42
result_window->create_button("DELETE_SEELECTED", "DELETE");
44
result_window->at("box");
45
result_window->callback(MP_result_chosen);
47
result_probes_list = result_window->create_selection_list( MP_AWAR_RESULTPROBES,"ResultProbes","R" );
48
result_probes_list->value_equal_display = true; // plain load/save (no # interpretation)
50
result_window->set_selection_list_suffix(result_probes_list,"mpr");
52
result_window->insert_default_selection(result_probes_list, "","");
55
result_window->at("Load");
56
result_window->callback(AW_POPUP, (AW_CL)create_load_box_for_selection_lists, (AW_CL)result_probes_list );
57
result_window->create_button("LOAD_RPL", "LOAD");
59
result_window->at("Save");
60
result_window->callback( AW_POPUP, (AW_CL)create_save_box_for_selection_lists, (AW_CL)result_probes_list);
61
result_window->create_button("SAVE_RPL", "SAVE");
63
result_window->button_length(7);
64
result_window->at("Help");
65
result_window->callback(AW_POPUP_HELP,(AW_CL)"multiproberesults.hlp");
66
result_window->create_button("HELP","HELP");
70
result_window->button_length(8);
72
result_window->at("Trash");
73
result_window->callback(MP_Comment, (AW_CL) "Bad");
74
result_window->create_button("MARK_AS_BAD", "BAD");
76
result_window->at("Good");
77
result_window->callback(MP_Comment, (AW_CL) "???");
78
result_window->create_button("MARK_AS_GOOD", "???");
80
result_window->at("Best");
81
result_window->callback(MP_Comment, (AW_CL) "Good");
82
result_window->create_button("MARK_AS_BEST", "Good");
84
result_window->at("Comment");
85
result_window->callback(MP_Comment, (AW_CL)0);
86
result_window->create_input_field(MP_AWAR_RESULTPROBESCOMMENT);
88
result_window->at("auto");
89
result_window->create_toggle(MP_AWAR_AUTOADVANCE);
93
result_window->button_length(3);
95
result_window->at("ct_back");
96
result_window->callback(MP_show_probes_in_tree_move, (AW_CL)1, (AW_CL)result_probes_list);
97
result_window->create_button("COLOR_TREE_BACKWARD", "#rightleft_small.bitmap");
99
result_window->at("ct_fwd");
100
result_window->callback(MP_show_probes_in_tree_move, (AW_CL)0, (AW_CL)result_probes_list);
101
result_window->create_button("COLOR_TREE_FORWARD", "#leftright_small.bitmap");
103
result_window->button_length(8);
105
result_window->at("ColorTree");
106
result_window->button_length(4);
107
result_window->callback(MP_show_probes_in_tree);
108
result_window->create_button("COLOR_TREE", "GO");
110
result_window->at("MarkTree");
111
result_window->callback(MP_mark_probes_in_tree);
112
result_window->create_button("MARK_TREE", "GO");
114
result_window->at("GroupAll");
115
result_window->callback(MP_group_all_except_marked);
116
result_window->create_button("GROUP_UNMARKED", "GO");
118
result_window->at("StandardColor");
119
result_window->callback(MP_normal_colors_in_tree);
120
result_window->create_button("RESET_COLORS", "GO");
39
AW_window_simple *MP_Window::create_result_window(AW_root *aw_root) {
41
result_window = new AW_window_simple;
42
result_window->init(aw_root, "MULTIPROBE_RESULTS", "MultiProbe combination results");
43
result_window->load_xfig("mp_results.fig");
45
result_window->auto_space(5, 5);
47
result_window->button_length(7);
48
result_window->at("close");
49
result_window->callback(AW_POPDOWN);
50
result_window->create_button("CLOSE", "CLOSE");
52
result_window->at("Help");
53
result_window->callback(makeHelpCallback("multiproberesults.hlp"));
54
result_window->create_button("HELP", "HELP");
56
result_window->at("Comment");
57
result_window->callback(MP_Comment, (AW_CL)0);
58
result_window->create_input_field(MP_AWAR_RESULTPROBESCOMMENT);
60
result_window->at("box");
61
result_window->callback(MP_result_chosen);
62
result_probes_list = result_window->create_selection_list(MP_AWAR_RESULTPROBES, true);
63
result_probes_list->set_file_suffix("mpr");
64
result_probes_list->insert_default("", "");
66
const StorableSelectionList *storable_probes_list = new StorableSelectionList(TypedSelectionList("mpr", result_probes_list, "multiprobes", "multi_probes"));
68
result_window->at("buttons");
69
result_window->callback(makeCreateWindowCallback(create_load_box_for_selection_lists, storable_probes_list));
70
result_window->create_button("LOAD_RPL", "LOAD");
72
result_window->callback(makeCreateWindowCallback(create_save_box_for_selection_lists, storable_probes_list));
73
result_window->create_button("SAVE_RPL", "SAVE");
75
result_window->callback(makeWindowCallback(awt_clear_selection_list_cb, result_probes_list));
76
result_window->create_button("CLEAR", "CLEAR");
78
result_window->callback(makeWindowCallback(MP_delete_selected, result_probes_list));
79
result_window->create_button("DELETE", "DELETE");
83
result_window->button_length(8);
85
result_window->at("comment");
86
result_window->callback(MP_Comment, (AW_CL) "Bad");
87
result_window->create_button("MARK_AS_BAD", "BAD");
89
result_window->callback(MP_Comment, (AW_CL) "???");
90
result_window->create_button("MARK_AS_GOOD", "???");
92
result_window->callback(MP_Comment, (AW_CL) "Good");
93
result_window->create_button("MARK_AS_BEST", "Good");
95
result_window->at("auto");
96
result_window->create_toggle(MP_AWAR_AUTOADVANCE);
100
result_window->button_length(3);
102
result_window->at("ct_back");
103
result_window->callback(MP_show_probes_in_tree_move, (AW_CL)1, (AW_CL)result_probes_list);
104
result_window->create_button("COLOR_TREE_BACKWARD", "#rightleft_small.xpm");
106
result_window->at("ct_fwd");
107
result_window->callback(MP_show_probes_in_tree_move, (AW_CL)0, (AW_CL)result_probes_list);
108
result_window->create_button("COLOR_TREE_FORWARD", "#leftright_small.xpm");
110
result_window->button_length(8);
112
result_window->at("ColorTree");
113
result_window->button_length(4);
114
result_window->callback(MP_show_probes_in_tree);
115
result_window->create_button("COLOR_TREE", "GO");
117
result_window->at("MarkTree");
118
result_window->callback(MP_mark_probes_in_tree);
119
result_window->create_button("MARK_TREE", "GO");
121
result_window->at("GroupAll");
122
result_window->callback(MP_group_all_except_marked);
123
result_window->create_button("GROUP_UNMARKED", "GO");
125
result_window->at("StandardColor");
126
result_window->callback(MP_normal_colors_in_tree);
127
result_window->create_button("RESET_COLORS", "GO");
122
129
return result_window;
125
static const char *parse_word(const char *& line, int& wordlen) {
128
while (line[0] == ' ') ++line; // eat whitespace
129
if (line[0] == 0) return 0; // at EOL
131
const char *behind_word = strchr(line, ' ');
132
if (!behind_word) behind_word = strchr(line, 0); // get EOL
133
gb_assert(behind_word);
135
wordlen = behind_word-line;
138
static char *word_buffer = 0;
139
freeset(word_buffer, GB_strndup(line, wordlen));
146
static GB_ERROR parse_probe_list_entry(const char *one_line, char*& probe_string, int& ecoli_position) {
147
const char *start = one_line;
148
const char *reason = "more tokens expected";
150
const char *word = parse_word(one_line, wordlen);
154
int target_length = wordlen;
155
word = parse_word(one_line, wordlen);
157
int length = atoi(word);
159
if (length != target_length) {
160
reason = "Length mismatch between 'Target' and 'le'";
163
word = parse_word(one_line, wordlen);
164
if (word && wordlen == 2) { // spaces between 'A=' and number
165
word = parse_word(one_line, wordlen); // parse number
167
if (word) word = parse_word(one_line, wordlen); // parse ecoli
169
ecoli_position = atoi(word);
170
if (word) word = parse_word(one_line, wordlen); // parse 'grps'
171
if (word) word = parse_word(one_line, wordlen); // parse 'G+C'
172
if (word) word = parse_word(one_line, wordlen); // parse '4GC+2AT'
173
if (word) word = parse_word(one_line, wordlen); // parse 'Probe sequence'
175
if (wordlen != target_length) {
176
reason = "Length mismatch between 'Target' and 'Probe sequence'";
179
probe_string = strdup(word);
188
return GBS_global_string("can't parse line '%s' (Reason: %s)", start, reason);
192
void mp_load_list( AW_window *aww, AW_selection_list *selection_list, char *base_name)
194
aww->clear_selection_list(selection_list);
197
const char *awar_file = GBS_global_string("%s/file_name", base_name);
198
char *filename = aww->get_root()->awar(awar_file)->read_string();
199
data = GB_read_file(filename);
203
aw_message(GB_await_error());
208
if (strstr(data,"Probe design Parameters:")) { // designliste nach Sonden filtern
213
for (char *line = data; line; line = next_line) {
215
char *nl = strchr(line, '\n');
226
if (strncmp(line, "Target ", 7) == 0) {
231
char *probe_string = 0;
232
int ecoli_position = -1;
233
error = parse_probe_list_entry(line, probe_string, ecoli_position);
239
const char *real_disp = GBS_global_string("%1d#%1d#%6d#%s", QUALITYDEFAULT, 0, ecoli_position, probe_string);
240
aww->insert_selection(selection_list, real_disp, real_disp);
249
for (char *pl = data; pl && pl[0]; pl = next_word)
251
char *ko = strchr(pl,'\n');
266
if (selection_list == selected_list || selection_list == probelist) //in ausgewaehltenliste laden
268
real_disp = new char[3+strlen(ko)];
269
sprintf(real_disp,"%1d#%s",atoi(pl),ko);
273
real_disp = new char[21+strlen(SEPARATOR)+strlen(ko)+1];
274
sprintf(real_disp,"%20s%s%s",pl,SEPARATOR,ko);
279
if (selection_list == selected_list || selection_list == probelist)
281
real_disp = new char[5+7+strlen(pl)];
282
sprintf(real_disp,"%1d#%1d#%6d#%s",QUALITYDEFAULT,0,0,pl);
286
real_disp = new char[21+strlen(SEPARATOR)+strlen(pl)+1];
287
sprintf(real_disp,"%20s%s%s"," ",SEPARATOR,pl);
291
aww->insert_selection(selection_list,real_disp,real_disp);
298
aww->insert_default_selection(selection_list,"","");
299
// aww->sort_selection_list( selection_list );
300
aww->update_selection_list(selection_list);
303
static AW_window *mp_create_load_box_for_selection_lists(AW_root *aw_root, AW_CL selid)
305
AW_selection_list *selection_list = (AW_selection_list*)selid;
307
char *var_id = GBS_string_2_key(selection_list->variable_name);
308
char *base_name = GBS_global_string_copy("tmp/load_box_sel_%s", var_id); // do not free (attached to cbs)
310
aw_create_selection_box_awars(aw_root, base_name, ".", ".list", "");
312
AW_window_simple *aws = new AW_window_simple;
313
char *window_id = GBS_global_string_copy("LOAD_%s", var_id);
314
aws->init( aw_root, window_id, "Load");
315
aws->load_xfig("sl_l_box.fig");
318
aws->callback((AW_CB0)AW_POPDOWN);
319
aws->create_button("CLOSE","CLOSE","C");
323
aws->callback((AW_CB)mp_load_list,(AW_CL)selid,(AW_CL)base_name); // transfers ownership of base_name
324
aws->create_button("LOAD","LOAD","L");
326
awt_create_selection_box(aws, base_name);
334
void MP_Window::build_pt_server_list()
132
// --------------------------------------------------------------------------------
133
// Format of probe-list for multi-probes:
135
// The saved format is identical to the internal format (of sellist entries; where value always equals displayed!)
136
// "quality#singlemismatch#ecolipos#target"
138
// When loading input probes, several other formats are accepted:
140
// "quality,singlemismatch#ecolipos#probe" (old save format)
141
// "target le pos apos ecol grps GC 4gc2at probe | ..." (save of probe design; old format)
142
// "target le pos apos ecol grps GC 4gc2at probe | ...,target" (save of probe design)
145
// 'target' is the target-string of the 'probe'. Internally MP works with target strings,
146
// so when loading the old save-format, 'probe' gets reverse-complemented into 'target'
149
#define SPACED(expr) "[[:space:]]*" expr "[[:space:]]*"
151
inline char *gen_display(int quality, int singleMis, int ecoliPos, const char *probe) {
152
return GBS_global_string_copy("%i#%i#%5i#%s", quality, singleMis, ecoliPos, probe);
155
static GB_ERROR mp_list2file(const CharPtrArray& display, const CharPtrArray& value, StrArray& line) {
156
GB_ERROR error = NULL;
158
if (value.empty()) error = "nothing to save";
160
for (size_t i = 0; i<display.size() && !error; ++i) {
161
line.put(strdup(display[i]));
167
static char T_or_U_for_load = 0;
169
static GB_ERROR mp_file2list(const CharPtrArray& line, StrArray& display, StrArray& value) {
170
GB_ERROR error = NULL;
172
if (line.empty()) error = "empty file";
176
// 1. try to read probes saved from multiprobes inputlist
177
RegExpr reg_saved("^" SPACED("([0-9]+)") "([,#])" SPACED("([0-9])+") "#" SPACED("([0-9]+)") "#" SPACED("([A-Z]+)") "$", true);
178
bool isSavedFormat = true;
180
for (size_t i = 0; i<line.size() && isSavedFormat; ++i) {
181
const RegMatch *match = reg_saved.match(line[i]);
182
if (!match || reg_saved.subexpr_count() != 5) {
183
isSavedFormat = false;
186
char T_or_U = T_or_U_for_load ? T_or_U_for_load : 'U';
188
std::string sep = reg_saved.subexpr_match(2)->extract(line[i]);
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());
194
std::string probe = reg_saved.subexpr_match(5)->extract(line[i]);
196
if (sep[0] == ',') { // old format (saved probe instead of probe-target)
197
size_t plen = probe.length();
198
char *dprobe = GB_strndup(probe.c_str(), plen);
200
GBT_reverseComplementNucSequence(dprobe, plen, T_or_U);
205
char *entry = gen_display(quality, singlemis, ecoli, probe.c_str());
206
display.put(entry); // transfers ownership - dont free!
207
value.put(strdup(entry));
211
if (!isSavedFormat) {
212
// delete attempt to read saved format:
216
// try to read designed list
217
RegExpr reg_designed("^([A-Z]+)" // subexpr #1 (target)
219
"[[:space:]]+[A-Z][=+-]"
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}"
225
"[[:space:]]+[|]", true);
227
for (size_t i = 0; i<line.size() && !error; ++i) {
229
char *description = NULL;
230
bool new_format = false;
232
const char *comma = strchr(line[i], ',');
234
description = GB_strpartdup(line[i], comma-1);
236
const char *cprobe = comma+1;
237
while (cprobe[0] == ' ') ++cprobe;
238
probe = strdup(cprobe);
243
description = strdup(line[i]);
246
const RegMatch *match = reg_designed.match(description);
247
if (match) { // line from probe design (old + new format)
248
mp_assert(match->didMatch());
250
match = reg_designed.subexpr_match(1);
251
mp_assert(match->didMatch());
252
std::string parsed_probe = match->extract(description);
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]);
261
probe = strdup(parsed_probe.c_str());
267
match = reg_designed.subexpr_match(2);
268
mp_assert(match->didMatch());
269
ecoli = atoi(match->extract(description).c_str());
272
char *entry = gen_display(quality, 0, ecoli, probe);
273
display.put(entry); // transfers ownership - dont free!
274
value.put(strdup(entry));
277
else if (new_format && probe[0]) {
278
error = GBS_global_string("can't parse line '%s'", line[i]);
280
// (when loading old format -> silently ignore non-matching lines)
291
void MP_Window::build_pt_server_list() {
339
#if defined(DEVEL_RALF)
295
#if defined(WARN_TODO)
340
296
#warning why option_menu ? better use selection list ( awt_create_selection_list_on_pt_servers )
343
299
aws->at("PTServer");
344
300
aws->callback(MP_cache_sonden);
345
aws->create_option_menu( MP_AWAR_PTSERVER, NULL, "");
301
aws->create_option_menu(MP_AWAR_PTSERVER, true);
347
303
for (i=0; ; i++) {
348
304
choice = GBS_ptserver_id_to_choice(i, 1);
349
305
if (! choice) break;
351
aws->insert_option( choice, "", i);
307
aws->insert_option(choice, "", i);
355
311
aws->update_option_menu();
358
MP_Window::MP_Window(AW_root *aw_root)
360
int max_seq_col = 35,
314
static void track_ali_change_cb(AW_root*, GBDATA *gb_main) {
315
GB_transaction ta(gb_main);
316
char *aliname = GBT_get_default_alignment(gb_main);
317
GB_alignment_type alitype = GBT_get_alignment_type(gb_main, aliname);
319
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
325
static void MP_collect_probes(AW_window*, awt_collect_mode mode, AW_CL) {
328
if (!probelist->default_is_selected()) {
329
int idx = probelist->get_index_of_selected();
330
AW_selection_list_iterator sel(probelist, idx);
331
selected_list->insert(sel.get_displayed(), sel.get_value());
332
MP_delete_selected(NULL, probelist);
337
if (!selected_list->default_is_selected()) {
338
int idx = selected_list->get_index_of_selected();
339
AW_selection_list_iterator sel(selected_list, idx);
340
probelist->insert(sel.get_displayed(), sel.get_value());
341
MP_delete_selected(NULL, selected_list);
346
probelist->move_content_to(selected_list);
350
selected_list->move_content_to(probelist);
354
selected_list->sort(false, true);
357
selected_list->update();
360
MP_Window::MP_Window(AW_root *aw_root, GBDATA *gb_main) {
361
int max_seq_col = 35;
362
int max_seq_hgt = 15;
365
static bool initialized = false;
366
mp_assert(!initialized); // this function may only be called once!
370
aw_root->awar(AWAR_DEFAULT_ALIGNMENT)->add_callback(makeRootCallback(track_ali_change_cb, gb_main));
371
track_ali_change_cb(aw_root, gb_main);
363
373
result_window = NULL;
365
375
aws = new AW_window_simple;
366
aws->init( aw_root, "MULTI_PROBE", "MULTI_PROBE");
376
aws->init(aw_root, "MULTIPROBE", "MULTI_PROBE");
367
377
aws->load_xfig("multiprobe.fig");
369
379
aws->at("close");
370
aws->callback(MP_cache_sonden);
371
380
aws->callback(MP_close_main);
372
aws->create_button("CLOSE","CLOSE");
381
aws->create_button("CLOSE", "CLOSE");
375
aws->callback(AW_POPUP_HELP,(AW_CL)"multiprobe.hlp");
376
aws->create_button("HELP","HELP");
378
// aws->at("Sequenzeingabe");
379
// aws->callback(MP_take_manual_sequence);
380
// aws->create_input_field(MP_AWAR_SEQUENZEINGABE, max_seq_col);
384
aws->callback(makeHelpCallback("multiprobe.hlp"));
385
aws->create_button("HELP", "HELP");
387
aws->button_length(7);
388
aws->at("Selectedprobes");
389
aws->callback(MP_selected_chosen);
390
selected_list = aws->create_selection_list(MP_AWAR_SELECTEDPROBES, max_seq_col, max_seq_hgt, true);
391
const StorableSelectionList *storable_selected_list = new StorableSelectionList(TypedSelectionList("prb", selected_list, "probes", "selected_probes"), mp_list2file, mp_file2list);
393
selected_list->insert_default("", "");
395
aws->at("Probelist");
396
probelist = aws->create_selection_list(MP_AWAR_PROBELIST, true);
397
const StorableSelectionList *storable_probelist = new StorableSelectionList(TypedSelectionList("prb", probelist, "probes", "all_probes"), mp_list2file, mp_file2list);
398
probelist->insert_default("", "");
401
awt_create_collect_buttons(aws, true, MP_collect_probes, 0);
403
aws->auto_space(5, 5);
404
aws->button_length(7);
406
for (int rightSide = 0; rightSide <= 1; ++rightSide) {
407
const StorableSelectionList *storableList = rightSide ? storable_selected_list : storable_probelist;
408
const char *id_suffix = rightSide ? "SELECTED_PROBES" : "PROBES";
410
AW_selection_list *sellist = storableList->get_typedsellist().get_sellist();
412
aws->at(rightSide ? "RightButtons" : "LeftButtons");
414
aws->callback(makeCreateWindowCallback(create_load_box_for_selection_lists, storableList));
415
aws->create_button(GBS_global_string("LOAD_%s", id_suffix), "LOAD");
417
aws->callback(makeCreateWindowCallback(create_save_box_for_selection_lists, storableList));
418
aws->create_button(GBS_global_string("SAVE_%s", id_suffix), "SAVE");
420
aws->callback(makeWindowCallback(awt_clear_selection_list_cb, sellist));
421
aws->create_button(GBS_global_string("CLEAR_%s", id_suffix), "CLEAR");
423
aws->callback(makeWindowCallback(MP_delete_selected, sellist));
424
aws->create_button(GBS_global_string("DELETE_%s", id_suffix), "DELETE");
383
428
aws->callback(MP_cache_sonden);
384
aws->create_input_field(MP_AWAR_QUALITYBORDER1, 4);
386
// aws->at("EcoliPos");
387
// aws->create_input_field(MP_AWAR_ECOLIPOS, 6);
389
aws->button_length(5);
429
aws->create_option_menu(MP_AWAR_QUALITY, true);
430
aws->insert_option("High Priority", "", 5);
431
aws->insert_option(" 4", "", 4);
432
aws->insert_option("Normal 3", "", 3);
433
aws->insert_option(" 2", "", 2);
434
aws->insert_option("Low Prio. 1", "", 1);
435
aws->update_option_menu();
391
438
aws->callback(MP_new_sequence);
392
aws->create_button("CREATE_NEW_SEQUENCE", "ADD");
439
aws->create_autosize_button("ADD_PROBE", "ADD");
441
aws->create_input_field(MP_AWAR_SEQIN, 25);
443
// --------------------------------
444
// multi probe parameters
447
awt_create_selection_list_on_pt_servers(aws, MP_AWAR_PTSERVER, true);
448
aw_root->awar(MP_AWAR_PTSERVER)->add_callback(MP_cache_sonden2); // remove cached probes when changing pt-server
450
aws->at("NoOfProbes");
451
aws->create_option_menu(MP_AWAR_NOOFPROBES, true);
452
aws->callback(MP_cache_sonden);
453
aws->insert_option("Compute 1 probe ", "", 1);
455
for (int i=2; i<=MAXPROBECOMBIS; i++) {
456
sprintf(str, "%2d-probe-combinations", i);
457
aws->insert_option(str, "", i);
459
aws->update_option_menu();
394
461
aws->button_length(10);
395
462
aws->at("Compute");
396
aws->callback(MP_compute);
463
aws->callback(MP_compute, (AW_CL)gb_main);
397
464
aws->highlight();
398
465
aws->help_text("Compute possible Solutions");
399
aws->create_button("GO","GO");
466
aws->create_button("GO", "GO");
401
468
aws->button_length(20);
402
469
aws->at("Results");
403
470
aws->callback(MP_popup_result_window);
404
471
aws->create_button("OPEN_RESULT_WIN", "Open result window");
406
aws->button_length(5);
407
aws->at("RightLeft");
408
aws->callback(MP_rightleft);
409
aws->create_button("MOVE_RIGHT", "#rightleft.bitmap"); //rightleft.bitmap
411
aws->at("LeftRight");
412
aws->callback(MP_leftright);
413
aws->create_button("MOVE_LEFT", "#leftright.bitmap"); //leftright.bitmap
416
aws->callback(MP_all_right);
417
aws->create_button("MOVE_ALL_RIGHT", "#allright.bitmap");
473
aws->at("Komplement");
420
474
aws->callback(MP_cache_sonden);
421
aws->create_option_menu( MP_AWAR_QUALITY, NULL, "");
422
aws->insert_option( "High Priority", "", 5 );
423
aws->insert_option( " 4", "", 4 );
424
aws->insert_option( "Normal 3", "", 3 );
425
aws->insert_option( " 2", "", 2 );
426
aws->insert_option( "Low Prio. 1", "", 1 );
427
aws->update_option_menu();
430
aws->at("OutsideMismatches");
431
aws->callback(MP_cache_sonden);
432
aws->create_option_menu( MP_AWAR_OUTSIDEMISMATCHES, NULL, "");
433
aws->insert_option( "3.0", "", (float)3.0 );
434
aws->insert_option( "2.5", "", (float)2.5 );
435
aws->insert_option( "2.0", "", (float)2.0 );
436
aws->insert_option( "1.5", "", (float)1.5 );
437
aws->insert_option( "1.0", "", (float)1.0 );
439
aws->insert_option( "0", "", (float)1.0 );
442
aws->update_option_menu();
446
aws->button_length(7);
447
aws->at("Selectedprobes");
448
aws->callback(MP_selected_chosen);
449
selected_list = aws->create_selection_list( MP_AWAR_SELECTEDPROBES,
454
aws->set_selection_list_suffix(selected_list,"prb");
456
aws->insert_default_selection(selected_list, "","");
458
aws->at("Probelist");
459
probelist = aws->create_selection_list( MP_AWAR_PROBELIST,
462
aws->set_selection_list_suffix(probelist,"prb");
463
aws->insert_default_selection(probelist, "","");
465
aws->at("LoadProbes");
466
aws->callback(AW_POPUP, (AW_CL)mp_create_load_box_for_selection_lists, (AW_CL)probelist);
467
aws->create_button("LOAD_PROBES","LOAD");
469
aws->at("SaveProbes");
470
aws->callback( AW_POPUP, (AW_CL)create_save_box_for_selection_lists, (AW_CL)probelist);
471
aws->create_button("SAVE_PROBES", "SAVE");
473
aws->at("LoadSelProbes");
474
aws->callback(AW_POPUP, (AW_CL)mp_create_load_box_for_selection_lists, (AW_CL)selected_list);
475
aws->create_button("LOAD_SELECTED_PROBES", "LOAD");
477
aws->at("SaveSelProbes");
478
aws->callback( AW_POPUP, (AW_CL)create_save_box_for_selection_lists, (AW_CL)selected_list );
479
aws->create_button("SAVE_SELECTED_PROBES", "SAVE");
481
aws->at("DeleteAllPr");
482
aws->callback(MP_del_all_probes);
483
aws->create_button("DELETE_ALL_PROBES", "DELETE");
485
aws->at("DeleteAllSelPr");
486
aws->callback(MP_del_all_sel_probes);
487
aws->create_button("DELETE_ALL_SELECTED_PROBES", "DELETE");
489
aws->at("DeleteSel");
490
aws->callback(MP_del_sel_probes);
491
aws->create_button("DELETE_SELECTED_PROBE", "DELETE");
494
aws->callback(MP_del_probes);
495
aws->create_button("DELETE_PROBES", "DELETE");
475
aws->create_toggle(MP_AWAR_COMPLEMENT);
497
477
aws->at("WeightedMismatches");
498
478
aws->callback(MP_cache_sonden);
499
479
aws->create_toggle(MP_AWAR_WEIGHTEDMISMATCHES);
502
// aws->create_toggle_field(MP_AWAR_WEIGHTEDMISMATCHES,1);
503
// aws->insert_toggle("#weighted1.bitmap","0",0);
504
// aws->insert_toggle("#weighted3.bitmap","1",1);
505
// aws->insert_toggle("#weighted2.bitmap","2",2);
506
// aws->update_toggle_field();
509
aws->at("Komplement");
510
aws->callback(MP_cache_sonden);
511
aws->create_toggle(MP_AWAR_COMPLEMENT);
514
// aws->at("Mismatches");
515
// aws->create_option_menu( MP_AWAR_MISMATCHES, NULL, "");
516
// aws->callback(MP_cache_sonden);
517
// aws->insert_option( "0 mismatches", "", 0 );
518
// aws->insert_option( "1 mismatches", "", 1 );
519
// aws->insert_option( "2 mismatches", "", 2 );
520
// aws->insert_option( "3 mismatches", "", 3 );
521
// aws->insert_option( "4 mismatches", "", 4 );
522
// aws->insert_option( "5 mismatches", "", 5 );
523
// aws->update_option_menu();
526
// aws->at("SingleMismatches");
527
// aws->create_option_menu( MP_AWAR_SINGLEMISMATCHES, NULL, "");
528
// aws->insert_option( "0 mismatches", "", 0 );
529
// aws->insert_option( "1 mismatches", "", 1 );
530
// aws->insert_option( "2 mismatches", "", 2 );
531
// aws->insert_option( "3 mismatches", "", 3 );
532
// aws->insert_option( "4 mismatches", "", 4 );
533
// aws->insert_option( "5 mismatches", "", 5 );
534
// aws->update_option_menu();
481
// max non group hits
483
aws->callback(MP_cache_sonden);
484
aws->create_input_field(MP_AWAR_QUALITYBORDER1, 6);
486
aws->at("OutsideMismatches");
487
aws->callback(MP_cache_sonden);
488
aws->create_option_menu(MP_AWAR_OUTSIDEMISMATCHES, true);
489
aws->insert_option("3.0", "", (float)3.0);
490
aws->insert_option("2.5", "", (float)2.5);
491
aws->insert_option("2.0", "", (float)2.0);
492
aws->insert_option("1.5", "", (float)1.5);
493
aws->insert_option("1.0", "", (float)1.0);
494
aws->update_option_menu();
496
// max mismatches for group
537
497
aws->at("Greyzone");
538
498
aws->callback(MP_cache_sonden);
539
aws->create_option_menu( MP_AWAR_GREYZONE, NULL, "");
541
aws->insert_default_option( "0.0", "", (float)0.0 );
542
for (float lauf=0.1; lauf<(float)1.0; lauf+=0.1){
499
aws->create_option_menu(MP_AWAR_GREYZONE, true);
500
aws->insert_default_option("0.0", "", (float)0.0);
501
for (float lauf=0.1; lauf<(float)1.0; lauf+=0.1) {
544
sprintf(strs,"%.1f",lauf);
545
aws->insert_option( strs, "", lauf );
547
aws->update_option_menu();
550
aws->at("NoOfProbes");
551
aws->create_option_menu( MP_AWAR_NOOFPROBES, NULL, "");
552
aws->callback(MP_cache_sonden);
554
aws->insert_option( "Compute 1 probe ", "", 1 );
556
for (int i=2; i<=MAXPROBECOMBIS; i++){
557
sprintf(str,"%2d-probe-combinations",i);
558
aws->insert_option( str, "", i );
561
aws->update_option_menu();
564
awt_create_selection_list_on_pt_servers(aws, MP_AWAR_PTSERVER, true);
566
aw_root->awar(MP_AWAR_PTSERVER)->add_callback(MP_cache_sonden2); // remove cached probes when changing pt-server
568
// build_pt_server_list();
503
sprintf(strs, "%.1f", lauf);
504
aws->insert_option(strs, "", lauf);
506
aws->update_option_menu();
577
516
delete result_window;
520
// --------------------------------------------------------------------------------
524
#include <test_unit.h>
526
#include <command_output.h>
528
inline void array2cpa(const char **content, int count, ConstStrArray& array) {
530
for (int i = 0; i<count; ++i) {
531
array.put(content[i]);
535
inline char *array2string(const CharPtrArray& array) {
536
GBS_strstruct out(1000);
538
for (size_t i = 0; i<array.size(); ++i) {
543
return out.release();
546
static arb_test::match_expectation inputConvertsInto(const char *input, const char *expected_result) {
548
GBT_split_string(lines, input, "\n", true);
550
using namespace arb_test;
551
expectation_group expected;
553
StrArray display, value;
554
expected.add(doesnt_report_error(mp_file2list(lines, display, value)));
556
char *displ_as_string = array2string(display);
557
char *value_as_string = array2string(value);
559
expected.add(that(displ_as_string).is_equal_to(expected_result));
560
expected.add(that(value_as_string).is_equal_to(expected_result));
562
free(value_as_string);
563
free(displ_as_string);
565
return all().ofgroup(expected);
568
#define TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS(input,expected) TEST_EXPECTATION(inputConvertsInto(input, expected))
569
#define TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS__BROKEN(input,expected) TEST_EXPECTATION__BROKEN(inputConvertsInto(input, expected))
571
void TEST_load_probe_design_results() {
573
const char *expected =
574
"3#0# 521#GCAGCCGCGGUAAUACGG\n"
575
"3#0# 510#ACUCCGUGCCAGCAGCCG\n"
576
"3#0# 511#CUCCGUGCCAGCAGCCGC\n"
577
"3#0# 512#UCCGUGCCAGCAGCCGCG\n"
578
"3#0# 513#CCGUGCCAGCAGCCGCGG\n"
579
"3#0# 509#AACUCCGUGCCAGCAGCC\n";
581
const char *old_probeDesignSave =
582
"Probe design Parameters:\n"
583
"Length of probe 18\n"
584
"Temperature [30.0 -100.0]\n"
585
"GC-Content [50.0 -100.0]\n"
586
"E.Coli Position [any]\n"
587
"Max Non Group Hits 0\n"
588
"Min Group Hits 50%\n"
589
"Target le apos ecol grps G+C 4GC+2AT Probe sequence | Decrease T by n*.3C -> probe matches n non group species\n"
590
"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"
591
"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"
592
"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"
593
"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"
594
"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"
595
"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";
597
TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS(old_probeDesignSave, expected);
600
const char *old_multiprobeInputSave = // old multi-probe saved probe (i.e. not target) sequences -> load shall correct that
601
"3,0# 521#CCGUAUUACCGCGGCUGC\n"
602
"3,0# 510#CGGCUGCUGGCACGGAGU\n"
603
"3,0# 511#GCGGCUGCUGGCACGGAG\n"
604
"3,0# 512#CGCGGCUGCUGGCACGGA\n"
605
"3,0# 513#CCGCGGCUGCUGGCACGG\n"
606
"3,0# 509#GGCUGCUGGCACGGAGUU\n";
609
LocallyModify<char> TorU(T_or_U_for_load, 'U');
610
TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS(old_multiprobeInputSave, expected);
613
const char *new_probeDesignSave_v1 =
614
"Probe design Parameters:,\n"
615
"Length of probe 18,\n"
616
"Temperature [30.0 -100.0],\n"
617
"GC-Content [50.0 -100.0],\n"
618
"E.Coli Position [any],\n"
619
"Max Non Group Hits 0,\n"
620
"Min Group Hits 50%,\n"
621
"Target le apos ecol grps G+C 4GC+2AT Probe sequence | Decrease T by n*.3C -> probe matches n non group species,\n"
622
"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"
623
"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"
624
"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"
625
"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"
626
"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"
627
"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";
629
TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS(new_probeDesignSave_v1, expected);
632
const char *new_multiprobeInputSave =
633
"3#0# 521#GCAGCCGCGGUAAUACGG\n"
634
"3#0# 510#ACUCCGUGCCAGCAGCCG\n"
635
"3#0# 511#CUCCGUGCCAGCAGCCGC\n"
636
"3#0# 512#UCCGUGCCAGCAGCCGCG\n"
637
"3#0# 513#CCGUGCCAGCAGCCGCGG\n"
638
"3#0# 509#AACUCCGUGCCAGCAGCC\n";
640
TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS(new_multiprobeInputSave, expected);
644
static const char *recent_expected =
645
"3#0# 82#CGAAAGGAAGAUUA\n"
646
"3#0# 82#CGAAAGGAAGAUUAA\n"
647
"3#0# 86#AGGAAGAUUAAUACC\n"
648
"3#0# 87#GGAAGAUUAAUACC\n"
649
"3#0# 21#GUCGAGCGAUGAAG\n"
650
"3#0# 20#AGUCGAGCGAUGAAG\n"
651
"3#0# 20#AGUCGAGCGAUGAA\n"
652
"3#0# 19#AAGUCGAGCGAUGAA\n"
653
"3#0# 18#CAAGUCGAGCGAUGA\n"
654
"3#0# 19#AAGUCGAGCGAUGA\n"
655
"3#0# 17#UCAAGUCGAGCGAUG\n"
656
"3#0# 18#CAAGUCGAGCGAUG\n"
657
"3#0# 16#AUCAAGUCGAGCGAU\n"
658
"3#0# 17#UCAAGUCGAGCGAU\n"
659
"3#0# 16#AUCAAGUCGAGCGA\n";
661
static const char *recent_probeDesignSave =
662
"Probe design parameters:,\n"
663
"Length of probe 14-15,\n"
664
"Temperature [ 0.0 -400.0],\n"
665
"GC-content [30.0 - 80.0],\n"
666
"E.Coli position [any],\n"
667
"Max. nongroup hits 0,\n"
668
"Min. group hits 100% (max. rejected coverage: 75%),\n"
669
"Target le apos ecol qual grps G+C temp Probe sequence | Decrease T by n*.3C -> probe matches n non group species,\n"
670
"CGAAAGGAAGAUUA 14 A=94 82 77 4 35.7 38.0 UAAUCUUCCUUUCG | - - - - - - - - - - - - - - - - - - - -,CGAAAGGAAGAUUA\n"
671
"CGAAAGGAAGAUUAA 15 A+ 0 82 77 4 33.3 40.0 UUAAUCUUCCUUUCG | - - - - - - - - - - - - - - - - - - - -,CGAAAGGAAGAUUAA\n"
672
"AGGAAGAUUAAUACC 15 A+ 4 86 77 4 33.3 40.0 GGUAUUAAUCUUCCU | - - - - - - - - - - - - - - - - - - - -,AGGAAGAUUAAUACC\n"
673
"GGAAGAUUAAUACC 14 A+ 5 87 77 4 35.7 38.0 GGUAUUAAUCUUCC | - - - - - - - - - - - - - - - - - - - -,GGAAGAUUAAUACC\n"
674
"GUCGAGCGAUGAAG 14 B=22 21 77 4 57.1 44.0 CUUCAUCGCUCGAC | - - - - - - - - - - - - - - - - - - - 2,GUCGAGCGAUGAAG\n"
675
"AGUCGAGCGAUGAAG 15 B- 1 20 73 4 53.3 46.0 CUUCAUCGCUCGACU | - - - - - - - - - - - - - - - - - - 2 2,AGUCGAGCGAUGAAG\n"
676
"AGUCGAGCGAUGAA 14 B- 1 20 57 4 50.0 42.0 UUCAUCGCUCGACU | - - - - - - - - - - - - - - 2 2 2 2 2 2,AGUCGAGCGAUGAA\n"
677
"AAGUCGAGCGAUGAA 15 B- 2 19 53 4 46.7 44.0 UUCAUCGCUCGACUU | - - - - - - - - - - - - - 2 2 2 2 2 2 2,AAGUCGAGCGAUGAA\n"
678
"CAAGUCGAGCGAUGA 15 B- 3 18 41 4 53.3 46.0 UCAUCGCUCGACUUG | - - - - - - - - - - 2 2 2 2 2 2 2 2 2 2,CAAGUCGAGCGAUGA\n"
679
"AAGUCGAGCGAUGA 14 B- 2 19 41 4 50.0 42.0 UCAUCGCUCGACUU | - - - - - - - - - - 2 2 2 2 2 2 2 2 2 2,AAGUCGAGCGAUGA\n"
680
"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"
681
"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"
682
"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"
683
"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"
684
"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";
686
void TEST_AFTER_SLOW_recent_probe_design_result() {
687
// --------------------------------------------------------------------------------
688
// whenever probe design output changes, copy current 'recent_probeDesignSave' and
689
// 'recent_expected' into TEST_load_probe_design_results, to ensure ARB can load
690
// any saved probe design ever created with ARB.
692
TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS(recent_probeDesignSave, recent_expected);
695
void TEST_SLOW_design_probes_and_load_result() {
696
TEST_SETUP_GLOBAL_ENVIRONMENT("ptserver");
698
CommandOutput designed_probes("arb_probe serverid=-666 designprobelength=14 designmaxprobelength=15 designnames=ClnCorin#CltBotul#CPPParap#ClfPerfr designmintargets=100", true);
699
TEST_EXPECT_NO_ERROR(designed_probes.get_error());
701
// Simulate result of designing probes in ARB_NT and saving the result to a file:
702
char *saved_design_result = NULL; // content of that file
705
GBT_split_string(lines, designed_probes.get_stdoutput(), "\n", true);
707
StrArray saved_lines;
709
for (size_t i = 0; i<lines.size(); ++i) {
710
char *probe; // same as awar-value of probe-design-resultlist in ARB_NT
712
size_t plen = strspn(lines[i], "acgtuACGTU");
713
if (plen<10) { // no probe at start // @@@ 10 is min. probelen, use a global definition here!
717
probe = GB_strndup(lines[i], plen);
721
char *conv4save = GBS_string_eval(lines[i], ":,=;", NULL); // saving selection list converts comma to semicolon
722
arb_assert(conv4save);
724
saved_lines.put(GBS_global_string_copy("%s,%s", conv4save, probe));
730
saved_design_result = GBT_join_names(saved_lines, '\n');
731
TEST_EXPECT_EQUAL(saved_design_result, recent_probeDesignSave); // see comment in TEST_LATE_recent_probe_design_result
734
TEST_EXPECT_LOADS_INTO_MULTIPROBE_AS(saved_design_result, recent_expected);
735
free(saved_design_result);
741
// --------------------------------------------------------------------------------