source: branches/profile/PROBE_DESIGN/probe_design.cxx

Last change on this file was 12884, checked in by westram, 10 years ago
  • implements #22 ("expand zombies")
    • DRYed NT- and PARSIMONY-'collapse/expand'-submenu
      • provides 'collapse terminal' to PARSIMONY (missing there)
    • merged all helpfiles concerning collapse/expand into one
      • fixes missing help for 'collapse terminal'
    • added 'expand any color group'
    • expand/collapse-callbacks
      • renamed
      • hide externally unused inside TREEDISP
  • other help updates
    • zombies → glossary
    • group mode
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 78.8 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : probe_design.cxx                                  //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "SaiProbeVisualization.hxx"
12#include "probe_match_parser.hxx"
13
14#include <PT_com.h>
15#include <PT_server.h> // needed for DOMAIN_MIN_LENGTH
16#include <client.h>
17#include <servercntrl.h>
18#include <probe_design.hxx>
19
20#include <GEN.hxx>
21#include <TreeCallbacks.hxx>
22
23#include <iupac.h>
24#include <awt_config_manager.hxx>
25#include <awt_sel_boxes.hxx>
26
27#include <aw_awars.hxx>
28#include <aw_preset.hxx>
29#include <aw_select.hxx>
30#include <aw_msg.hxx>
31#include <arb_progress.h>
32#include <aw_root.hxx>
33#include <aw_question.hxx>
34#include <adGene.h>
35#include <arb_strbuf.h>
36#include <arb_strarray.h>
37#include <arb_file.h>
38#include <aw_edit.hxx>
39
40// general awars
41
42#define AWAR_PROBE_CREATE_GENE_SERVER "tmp/probe_admin/gene_server" // whether to create a gene pt server
43
44// probe match awars
45
46// #define AWAR_PD_MATCH_ITEM     AWAR_SPECIES_NAME
47#define AWAR_PD_SELECTED_MATCH "tmp/probe_design/match"
48#define AWAR_PD_MATCH_RESOLVE  "tmp/probe_design/match_resolve" // for IUPAC resolution
49
50#define AWAR_PD_MATCH_SORTBY     "probe_match/sort_by" // weighted mismatches
51#define AWAR_PD_MATCH_COMPLEMENT "probe_match/complement" // check reverse complement too
52#define AWAR_PD_MATCH_MARKHITS   "probe_match/mark_hits" // mark hitten species in database
53#define AWAR_PD_MATCH_WRITE2TMP  "probe_match/write_2_tmp" // write result to field tmp
54#define AWAR_PD_MATCH_AUTOMATCH  "probe_match/auto_match" // auto match probes when target string changes
55
56#define AWAR_PD_MATCH_NHITS    "tmp/probe_match/nhits" // display the 'number of hits'
57
58// probe design awars
59
60#define AWAR_PD_DESIGN_CLIPRESULT "probe_design/CLIPRESULT" // 'length of output' (how many probes will get designed)
61#define AWAR_PD_DESIGN_MISHIT     "probe_design/MISHIT"     // 'non group hits'
62#define AWAR_PD_DESIGN_MAXBOND    "probe_design/MAXBOND"    // max hairpinbonds ?
63#define AWAR_PD_DESIGN_MINTARGETS "probe_design/MINTARGETS" // 'min. group hits (%)'
64
65#define AWAR_PD_DESIGN_MIN_LENGTH "probe_design/PROBELENGTH"      // min. length of probe
66#define AWAR_PD_DESIGN_MAX_LENGTH "probe_design/PROBEMAXLENGTH"   // max. length of probe (or empty)
67
68#define AWAR_PD_DESIGN_MIN_TEMP     "probe_design/MINTEMP"     // temperature (min)
69#define AWAR_PD_DESIGN_MAX_TEMP     "probe_design/MAXTEMP"     // temperature (max)
70#define AWAR_PD_DESIGN_MIN_GC       "probe_design/MINGC"       // GC content (min)
71#define AWAR_PD_DESIGN_MAX_GC       "probe_design/MAXGC"       // GC content (max)
72#define AWAR_PD_DESIGN_MIN_ECOLIPOS "probe_design/MINECOLI"    // ecolipos (min)
73#define AWAR_PD_DESIGN_MAX_ECOLIPOS "probe_design/MAXECOLI"    // ecolipos (max)
74
75#define AWAR_PD_DESIGN_GENE "probe_design/gene" // generate probes for genes ?
76
77// probe design/match (expert window)
78#define AWAR_PD_COMMON_EXP_BONDS "probe_design/bonds/pos"  // prefix for bonds
79#define AWAR_PD_COMMON_EXP_SPLIT "probe_design/SPLIT"
80
81#define AWAR_PD_DESIGN_EXP_DTEDGE "probe_design/DTEDGE"
82#define AWAR_PD_DESIGN_EXP_DT     "probe_design/DT"
83
84#define AWAR_PD_MATCH_NMATCHES   "probe_match/nmatches"
85#define AWAR_PD_MATCH_LIM_NMATCH "probe_match/lim_nmatch"
86#define AWAR_PD_MATCH_MAX_RES    "probe_match/maxres"
87
88// ----------------------------------------
89
90static saiProbeData *g_spd = 0;
91
92static struct {
93    aisc_com          *link;
94    T_PT_LOCS          locs;
95    T_PT_MAIN          com;
96    AW_window_simple  *win;
97    AW_selection_list *resultList; // @@@ replace by TypedSelectionList?
98} PD;
99
100struct ProbeMatchEventParam {
101    GBDATA            *gb_main;
102    AW_selection_list *selection_id;                // may be NULL
103    int               *counter;                     // may be NULL
104
105    ProbeMatchEventParam(GBDATA *gb_main_, int *counter_)         : gb_main(gb_main_), selection_id(NULL), counter(counter_) {}
106    ProbeMatchEventParam(GBDATA *gb_main_, AW_selection_list *id) : gb_main(gb_main_), selection_id(id),   counter(NULL)     {}
107};
108
109struct AutoMatchSettings {
110    AW_window            *aww;
111    ProbeMatchEventParam *event_param; // not owned!
112    bool                  disable;
113
114    AutoMatchSettings(AW_window *aww_, ProbeMatchEventParam *event_param_, bool disable_)
115        : aww(aww_) , event_param(event_param_) , disable(disable_)
116    {}
117    AutoMatchSettings()
118        : aww(NULL), event_param(NULL) , disable(true)
119    {}
120
121    bool initialized() const { return aww != NULL; }
122};
123
124static AutoMatchSettings auto_match_cb_settings;
125
126static void probe_match_event(AW_window *aww, ProbeMatchEventParam *event_param); // prototype
127
128static void auto_match_cb(AW_root *root) {
129    if (!auto_match_cb_settings.disable) {
130        char *ts = root->awar(AWAR_TARGET_STRING)->read_string();
131        if (strlen(ts) > 0) {
132            probe_match_event(auto_match_cb_settings.aww, auto_match_cb_settings.event_param);
133        }
134        free(ts);
135    }
136}
137
138static const char *auto_match_sensitive_awars[] = {
139    AWAR_TARGET_STRING,
140    AWAR_PT_SERVER,
141    AWAR_PD_MATCH_COMPLEMENT,
142    AWAR_MAX_MISMATCHES,
143    AWAR_PD_MATCH_SORTBY,
144    0
145};
146
147static void auto_match_changed(AW_root *root) {
148    static bool callback_active = false;
149    int         autoMatch       = root->awar(AWAR_PD_MATCH_AUTOMATCH)->read_int();
150
151    if (autoMatch) {
152        if (!callback_active) {
153            for (int i = 0; auto_match_sensitive_awars[i]; ++i) {
154                root->awar(auto_match_sensitive_awars[i])->add_callback(auto_match_cb);
155            }
156        }
157    }
158    else {
159        if (callback_active) {
160            for (int i = 0; auto_match_sensitive_awars[i]; ++i) {
161                root->awar(auto_match_sensitive_awars[i])->remove_callback(auto_match_cb);
162            }
163        }
164    }
165    callback_active = bool(autoMatch);
166}
167
168static void enable_auto_match_cb(AW_root *root, AW_window *aww, ProbeMatchEventParam *event_param) {
169    if (event_param == NULL && auto_match_cb_settings.initialized()) {
170        // "partially" enable (w/o ProbeMatchEventParam) is only done
171        // if not already "fully enabled"
172        return;
173    }
174
175    auto_match_cb_settings = AutoMatchSettings(aww, event_param, false);
176    auto_match_changed(root);
177}
178
179static void popup_match_window_cb(AW_window *aww, GBDATA *gb_main) { // @@@ shall be called by auto_match_cb (if never opened b4)
180    AW_root   *root         = aww->get_root();
181    AW_window *match_window = create_probe_match_window(root, gb_main);
182    match_window->activate();
183    root->awar(AWAR_TARGET_STRING)->touch(); // force re-match
184}
185
186// --------------------------------------------------------------------------------
187
188static void popup_probe_design_result_window(AW_window *aww, GBDATA *gb_main) {
189    if (!PD.win) {
190        AW_root *root = aww->get_root();
191
192        PD.win = new AW_window_simple;
193        PD.win->init(root, "PD_RESULT", "PD RESULT");
194        PD.win->load_xfig("pd_reslt.fig");
195
196        PD.win->button_length(6);
197        PD.win->auto_space(10, 10);
198
199        PD.win->at("help");
200        PD.win->callback(makeHelpCallback("probedesignresult.hlp"));
201        PD.win->create_button("HELP", "HELP", "H");
202
203        PD.win->at("result");
204        PD.resultList = PD.win->create_selection_list(AWAR_TARGET_STRING, 40, 5, false);
205        const StorableSelectionList *storable_result_list = new StorableSelectionList(TypedSelectionList("prb", PD.resultList, "designed probes", "designed")); // @@@ make member of PD ?
206
207        PD.resultList->clear();
208        PD.resultList->insert_default("No probes designed yet", "");
209
210        PD.win->at("buttons");
211       
212        PD.win->callback((AW_CB0)AW_POPDOWN);
213        PD.win->create_button("CLOSE", "CLOSE", "C");
214
215        PD.win->callback(makeWindowCallback(awt_clear_selection_list_cb, PD.resultList));
216        PD.win->create_button("CLEAR", "CLEAR", "R");
217       
218        PD.win->callback(makeCreateWindowCallback(create_load_box_for_selection_lists, storable_result_list));
219        PD.win->create_button("LOAD", "LOAD", "L");
220
221        PD.win->callback(makeCreateWindowCallback(create_save_box_for_selection_lists, storable_result_list));
222        PD.win->create_button("SAVE", "SAVE", "S");
223
224        PD.win->callback(makeWindowCallback(create_print_box_for_selection_lists, &storable_result_list->get_typedsellist()));
225        PD.win->create_button("PRINT", "PRINT", "P");
226
227        PD.win->callback(makeWindowCallback(popup_match_window_cb, gb_main));
228        PD.win->create_button("MATCH", "MATCH", "M");
229
230        PD.win->label("Auto match");
231        PD.win->create_toggle(AWAR_PD_MATCH_AUTOMATCH);
232
233        enable_auto_match_cb(root, PD.win, 0);
234    }
235    PD.win->activate();
236}
237
238static int init_local_com_struct()
239{
240    const char *user = GB_getenvUSER();
241
242    if (aisc_create(PD.link, PT_MAIN, PD.com,
243                    MAIN_LOCS, PT_LOCS, PD.locs,
244                    LOCS_USER, user,
245                    NULL)) {
246        return 1;
247    }
248    return 0;
249}
250
251static const char *PD_probe_pt_look_for_server(AW_root *root, GB_ERROR& error) {
252    // return PT server info string (see GBS_read_arb_tcp for details)
253    // or NULL (in this case 'error' is set)
254
255    // DRY vs  ../TOOLS/arb_probe.cxx@AP_probe_pt_look_for_server
256    // DRY vs  ../MULTI_PROBE/MP_noclass.cxx@MP_probe_pt_look_for_server
257
258    const char *result     = 0;
259    const char *server_tag = GBS_ptserver_tag(root->awar(AWAR_PT_SERVER)->read_int());
260
261    error = arb_look_and_start_server(AISC_MAGIC_NUMBER, server_tag);
262    if (!error) {
263        result             = GBS_read_arb_tcp(server_tag);
264        if (!result) error = GB_await_error();
265    }
266    pd_assert(contradicted(result, error));
267    return result;
268}
269
270static GB_ERROR species_requires(GBDATA *gb_species, const char *whats_required) {
271    return GBS_global_string("Species '%s' needs %s", GBT_read_name(gb_species), whats_required);
272}
273
274static GB_ERROR gene_requires(GBDATA *gb_gene, const char *whats_required) {
275    GBDATA *gb_species = GB_get_grandfather(gb_gene);
276    pd_assert(gb_species);
277    return GBS_global_string("Gene '%s' of organism '%s' needs %s", GBT_read_name(gb_gene), GBT_read_name(gb_species), whats_required);
278}
279
280static GB_ERROR pd_get_the_names(GBDATA *gb_main, bytestring &bs, bytestring &checksum) {
281    GBS_strstruct *names     = GBS_stropen(1024);
282    GBS_strstruct *checksums = GBS_stropen(1024);
283    GB_ERROR       error     = 0;
284
285    GB_begin_transaction(gb_main);
286
287    char *use = GBT_get_default_alignment(gb_main);
288
289    for (GBDATA *gb_species = GBT_first_marked_species(gb_main); gb_species; gb_species = GBT_next_marked_species(gb_species)) {
290        GBDATA *gb_name = GB_entry(gb_species, "name");
291        if (!gb_name) { error = species_requires(gb_species, "name"); break; }
292
293        GBDATA *gb_data = GBT_find_sequence(gb_species, use);
294        if (!gb_data) { error = species_requires(gb_species, GBS_global_string("data in '%s'", use)); break; }
295
296        GBS_intcat(checksums, GBS_checksum(GB_read_char_pntr(gb_data), 1, ".-"));
297        GBS_strcat(names, GB_read_char_pntr(gb_name));
298        GBS_chrcat(checksums, '#');
299        GBS_chrcat(names, '#');
300    }
301
302    GBS_str_cut_tail(names, 1); // remove trailing '#'
303    GBS_str_cut_tail(checksums, 1); // remove trailing '#'
304
305    free(use);
306
307    bs.data = GBS_strclose(names);
308    bs.size = strlen(bs.data)+1;
309
310    checksum.data = GBS_strclose(checksums);
311    checksum.size = strlen(checksum.data)+1;
312
313    GB_commit_transaction(gb_main);
314
315    return error;
316}
317
318static GB_ERROR pd_get_the_gene_names(GBDATA *gb_main, bytestring &bs, bytestring &checksum) {
319    GBS_strstruct *names     = GBS_stropen(1024);
320    GBS_strstruct *checksums = GBS_stropen(1024);
321    GB_ERROR       error     = 0;
322
323    GB_begin_transaction(gb_main);
324    const char *use = GENOM_ALIGNMENT; // gene pt server is always build on 'ali_genom'
325
326    for (GBDATA *gb_species = GEN_first_organism(gb_main); gb_species && !error; gb_species = GEN_next_organism(gb_species)) {
327        const char *species_name = 0;
328        {
329            GBDATA *gb_data = GBT_find_sequence(gb_species, use);
330            if (!gb_data) { error = species_requires(gb_species, GBS_global_string("data in '%s'", use)); break; }
331
332            GBDATA *gb_name = GB_search(gb_species, "name", GB_FIND);
333            if (!gb_name) { error = species_requires(gb_species, "name"); break; }
334            species_name = GB_read_char_pntr(gb_name);
335        }
336
337        for (GBDATA *gb_gene = GEN_first_marked_gene(gb_species); gb_gene && !error; gb_gene = GEN_next_marked_gene(gb_gene)) {
338            const char *gene_name = 0;
339            {
340                GBDATA *gb_gene_name = GB_entry(gb_gene, "name");
341                if (!gb_gene_name) { error = gene_requires(gb_gene, "name"); break; }
342                gene_name = GB_read_char_pntr(gb_gene_name);
343            }
344
345            {
346                char *gene_seq       = GBT_read_gene_sequence(gb_gene, false, 0);
347                if (!gene_seq) error = GB_await_error();
348                else {
349                    long        CheckSum = GBS_checksum(gene_seq, 1, ".-");
350                    const char *id       = GBS_global_string("%s/%s", species_name, gene_name);
351
352                    GBS_intcat(checksums, CheckSum);
353                    GBS_strcat(names, id);
354                    GBS_chrcat(checksums, '#');
355                    GBS_chrcat(names, '#');
356
357                    free(gene_seq);
358                }
359            }
360        }
361    }
362
363    GBS_str_cut_tail(names, 1); // remove trailing '#'
364    GBS_str_cut_tail(checksums, 1); // remove trailing '#'
365
366    if (error) {
367        GBS_strforget(names);
368        GBS_strforget(checksums);
369    }
370    else {
371        bs.size = GBS_memoffset(names)+1;
372        bs.data = GBS_strclose(names);
373
374        checksum.size = GBS_memoffset(checksums)+1;
375        checksum.data = GBS_strclose(checksums);
376    }
377    error = GB_end_transaction(gb_main, error);
378    return error;
379}
380
381static int probe_common_send_data(AW_root *root) {
382    // send data common to probe-design AND -match
383    if (aisc_put(PD.link, PT_LOCS, PD.locs,
384                 LOCS_SPLIT,   (double)root->awar(AWAR_PD_COMMON_EXP_SPLIT)->read_float(),
385                 NULL))
386        return 1;
387
388    for (int i=0; i<16; i++) {
389        char buffer[256];
390        sprintf(buffer, AWAR_PD_COMMON_EXP_BONDS "%i", i);
391        if (aisc_put(PD.link, PT_LOCS, PD.locs,
392                     PT_INDEX,  i,
393                     LOCS_BONDVAL, (double)root->awar(buffer)->read_float(),
394                     NULL))
395            return 1;
396    }
397    return 0;
398}
399static int probe_design_send_data(AW_root *root, const T_PT_PDC& pdc) {
400    if (aisc_put(PD.link, PT_PDC, pdc,
401                 PDC_DTEDGE,     (double)root->awar(AWAR_PD_DESIGN_EXP_DTEDGE)->read_float()*100.0,
402                 PDC_DT,         (double)root->awar(AWAR_PD_DESIGN_EXP_DT)->read_float()*100.0,
403                 PDC_CLIPRESULT, root->awar(AWAR_PD_DESIGN_CLIPRESULT)->read_int(),
404                 NULL))
405        return 1;
406
407    return probe_common_send_data(root);
408}
409static int probe_match_send_data(AW_root *root) {
410    if (aisc_put(PD.link, PT_LOCS, PD.locs,
411                 LOCS_MATCH_N_ACCEPT, root->awar(AWAR_PD_MATCH_NMATCHES)->read_int(), 
412                 LOCS_MATCH_N_LIMIT,  root->awar(AWAR_PD_MATCH_LIM_NMATCH)->read_int(),
413                 LOCS_MATCH_MAX_HITS, root->awar(AWAR_PD_MATCH_MAX_RES)->read_int(),
414                 NULL))
415        return 1;
416
417    return probe_common_send_data(root);
418}
419
420static int ecolipos2int(const char *awar_val) {
421    int i = atoi(awar_val);
422    return i>0 ? i : -1;
423}
424
425static char *readableUnknownNames(const ConstStrArray& unames) {
426    GBS_strstruct readable(100);
427
428    int ulast = unames.size()-1;
429    int umax  = ulast <= 10 ? ulast : 10;
430    for (int u = 0; u <= umax; ++u) {
431        if (u) readable.cat(u == ulast ? " and " : ", ");
432        readable.cat(unames[u]);
433    }
434
435    if (umax<ulast) readable.nprintf(30, " (and %i other)", ulast-umax);
436
437    return readable.release();
438}
439
440static void probe_design_event(AW_window *aww, GBDATA *gb_main) {
441    AW_root     *root  = aww->get_root();
442    T_PT_PDC     pdc;
443    T_PT_TPROBE  tprobe;
444    bytestring   bs;
445    bytestring   check;
446    GB_ERROR     error = 0;
447
448    arb_progress progress("Probe design");
449    progress.subtitle("Connecting PT-server");
450
451    {
452        const char *servername = PD_probe_pt_look_for_server(root, error);
453        if (servername) {
454            PD.link = aisc_open(servername, PD.com, AISC_MAGIC_NUMBER, &error);
455            if (!PD.link) error = "can't contact PT server";
456            PD.locs.clear();
457        }
458    }
459
460    if (!error && init_local_com_struct()) {
461        error = "Cannot contact to probe server: Connection Refused";
462    }
463
464    bool design_gene_probes = root->awar(AWAR_PD_DESIGN_GENE)->read_int();
465    if (design_gene_probes) {
466        GB_transaction ta(gb_main);
467        if (!GEN_is_genome_db(gb_main, -1)) design_gene_probes = false;
468    }
469
470    if (!error) {
471        if (design_gene_probes) { // design probes for genes
472            error = pd_get_the_gene_names(gb_main, bs, check);
473        }
474        else {
475            error = pd_get_the_names(gb_main, bs, check);
476        }
477    }
478
479    if (error) {
480        aw_message(error);
481        return;
482    }
483
484    progress.subtitle("probe design running");
485
486    if (aisc_create(PD.link, PT_LOCS, PD.locs,
487                    LOCS_PROBE_DESIGN_CONFIG, PT_PDC, pdc,
488                    PDC_MIN_PROBELEN, root->awar(AWAR_PD_DESIGN_MIN_LENGTH)->read_int(),
489                    PDC_MAX_PROBELEN, root->awar(AWAR_PD_DESIGN_MAX_LENGTH)->read_int(),
490                    PDC_MINTEMP,      (double)root->awar(AWAR_PD_DESIGN_MIN_TEMP)->read_float(),
491                    PDC_MAXTEMP,      (double)root->awar(AWAR_PD_DESIGN_MAX_TEMP)->read_float(),
492                    PDC_MINGC,        (double)root->awar(AWAR_PD_DESIGN_MIN_GC)->read_float()/100.0,
493                    PDC_MAXGC,        (double)root->awar(AWAR_PD_DESIGN_MAX_GC)->read_float()/100.0,
494                    PDC_MAXBOND,      (double)root->awar(AWAR_PD_DESIGN_MAXBOND)->read_int(),
495                    PDC_MIN_ECOLIPOS, (long)ecolipos2int(root->awar(AWAR_PD_DESIGN_MIN_ECOLIPOS)->read_char_pntr()),
496                    PDC_MAX_ECOLIPOS, (long)ecolipos2int(root->awar(AWAR_PD_DESIGN_MAX_ECOLIPOS)->read_char_pntr()),
497                    PDC_MISHIT,       root->awar(AWAR_PD_DESIGN_MISHIT)->read_int(),
498                    PDC_MINTARGETS,   (double)root->awar(AWAR_PD_DESIGN_MINTARGETS)->read_float()/100.0,
499                    NULL))
500    {
501        aw_message ("Connection to PT_SERVER lost (1)");
502        return;
503    }
504   
505    if (probe_design_send_data(root, pdc)) {
506        aw_message ("Connection to PT_SERVER lost (1)");
507        return;
508    }
509
510    aisc_put(PD.link, PT_PDC, pdc,
511             PDC_NAMES, &bs,
512             PDC_CHECKSUMS, &check,
513             NULL);
514
515
516    // Get the unknown names
517    bytestring unknown_names;
518    if (aisc_get(PD.link, PT_PDC, pdc,
519                 PDC_UNKNOWN_NAMES, &unknown_names,
520                 NULL)) {
521        aw_message ("Connection to PT_SERVER lost (1)");
522        return;
523    }
524
525    bool abort = false;
526
527    if (unknown_names.size>1) {
528        ConstStrArray unames_array;
529        GBT_split_string(unames_array, unknown_names.data, "#", true);
530
531        char *readable_unames = readableUnknownNames(unames_array);
532
533        if (design_gene_probes) { // updating sequences of missing genes is not possible with gene PT server
534            aw_message(GBS_global_string("Your PT server is not up to date or wrongly chosen!\n"
535                                         "It knows nothing about the following genes:\n"
536                                         "\n"
537                                         "  %s\n"
538                                         "\n"
539                                         "You have to rebuild the PT server.",
540                                         readable_unames));
541            abort = true;
542        }
543        else if (aw_question("ptserver_add_unknown",
544                             GBS_global_string("Your PT server is not up to date or wrongly chosen!\n"
545                                               "It knows nothing about the following species:\n"
546                                               "\n"
547                                               "  %s\n"
548                                               "\n"
549                                               "You may now temporarily add these sequences for probe design.\n",
550                                               readable_unames),
551                             "Add and continue,Abort"))
552        {
553            abort = true;
554        }
555        else {
556            GB_transaction ta(gb_main);
557
558            char *ali_name = GBT_get_default_alignment(gb_main);
559
560            for (size_t u = 0; !abort && u<unames_array.size(); ++u) {
561                const char *uname      = unames_array[u];
562                GBDATA     *gb_species = GBT_find_species(gb_main, uname);
563                if (!gb_species) {
564                    aw_message(GBS_global_string("Species '%s' not found", uname));
565                    abort = true;
566                }
567                else {
568                    GBDATA *data = GBT_find_sequence(gb_species, ali_name);
569                    if (!data) {
570                        aw_message(GB_export_errorf("Species '%s' has no sequence belonging to alignment '%s'", uname, ali_name));
571                        abort = true;
572                    }
573                    else {
574                        T_PT_SEQUENCE pts;
575
576                        bytestring bs_seq;
577                        bs_seq.data = (char*)GB_read_char_pntr(data);
578                        bs_seq.size = GB_read_string_count(data)+1;
579
580                        aisc_create(PD.link, PT_PDC, pdc,
581                                    PDC_SEQUENCE, PT_SEQUENCE, pts,
582                                    SEQUENCE_SEQUENCE, &bs_seq,
583                                    NULL);
584                    }
585                }
586            }
587            free(ali_name);
588        }
589        free(readable_unames);
590        free(unknown_names.data);
591    }
592
593    if (!abort) {
594        aisc_put(PD.link, PT_PDC, pdc,
595                 PDC_GO, 0,
596                 NULL);
597
598        progress.subtitle("Reading results from server");
599        {
600            char *locs_error = 0;
601            if (aisc_get(PD.link, PT_LOCS, PD.locs,
602                         LOCS_ERROR, &locs_error,
603                         NULL))
604            {
605                aw_message ("Connection to PT_SERVER lost (1)");
606                abort = true;
607            }
608            else if (*locs_error) {
609                aw_message(locs_error);
610                abort = true;
611            }
612            else {
613                free(locs_error);
614            }
615        }
616    }
617
618    if (!abort) {
619        aisc_get(PD.link, PT_PDC, pdc,
620                 PDC_TPROBE, tprobe.as_result_param(),
621                 NULL);
622
623        popup_probe_design_result_window(aww, gb_main);
624        PD.resultList->clear();
625
626        {
627            char *match_info = 0;
628            aisc_get(PD.link, PT_PDC, pdc,
629                     PDC_INFO_HEADER, &match_info,
630                     NULL);
631
632            char *s = strtok(match_info, "\n");
633            while (s) {
634                PD.resultList->insert(s, "");
635                s = strtok(0, "\n");
636            }
637            free(match_info);
638        }
639
640        while (tprobe.exists()) {
641            T_PT_TPROBE  tprobe_next;
642            char        *match_info = 0;
643
644            if (aisc_get(PD.link, PT_TPROBE, tprobe,
645                         TPROBE_NEXT, tprobe_next.as_result_param(),
646                         TPROBE_INFO, &match_info,
647                         NULL)) break;
648
649            tprobe.assign(tprobe_next);
650
651            char *probe, *space;
652            probe = strpbrk(match_info, "acgtuACGTU");
653            if (probe) space = strchr(probe, ' ');
654            if (probe && space) {
655                *space = 0; probe = strdup(probe); *space=' ';
656            }
657            else {
658                probe = strdup("");
659            }
660            PD.resultList->insert(match_info, probe);
661            free(probe);
662            free(match_info);
663        }
664        PD.resultList->insert_default("", "");
665        PD.resultList->update();
666    }
667
668    aisc_close(PD.link, PD.com); PD.link = 0;
669    return;
670}
671
672static bool allow_probe_match_event = true;
673
674static void probe_match_event(AW_window *aww, ProbeMatchEventParam *event_param) {
675    if (allow_probe_match_event) {
676        AW_selection_list *selection_id = event_param ? event_param->selection_id : NULL;
677        int               *counter      = event_param ? event_param->counter : NULL;
678        GBDATA            *gb_main      = event_param ? event_param->gb_main : NULL;
679        AW_root           *root         = aww->get_root();
680        int                show_status  = 0;
681        int                extras       = 1;        // mark species and write to temp fields
682        GB_ERROR           error        = 0;
683
684        if (!gb_main) { error = "Please open probe match window once to enable auto-match"; }
685
686        SmartPtr<arb_progress> progress;
687       
688        if (!error) {
689            const char *servername = PD_probe_pt_look_for_server(root, error);
690
691            if (!error) {
692                if (selection_id) {
693                    selection_id->clear();
694                    pd_assert(!counter);
695                    show_status = 1;
696                }
697                else if (counter) {
698                    extras = 0;
699                }
700
701                if (show_status) {
702                    progress = new arb_progress("Probe match");
703                    progress->subtitle("Connecting PT-server");
704                }
705
706                PD.link = aisc_open(servername, PD.com, AISC_MAGIC_NUMBER, &error);
707                if (!error && !PD.link) error = "Cannot contact PT-server";
708                PD.locs.clear();
709            }
710        }
711
712        if (!error && init_local_com_struct())     error = "Cannot contact PT-server (2)";
713        if (!error && probe_match_send_data(root)) error = "Connection to PT_SERVER lost (2)";
714
715        char *probe = root->awar(AWAR_TARGET_STRING)->read_string();
716
717        if (!error) {
718            if (show_status) progress->subtitle("Probe match running");
719
720            if (aisc_nput(PD.link, PT_LOCS, PD.locs,
721                          LOCS_MATCH_REVERSED,       root->awar(AWAR_PD_MATCH_COMPLEMENT)->read_int(),
722                          LOCS_MATCH_SORT_BY,        root->awar(AWAR_PD_MATCH_SORTBY)->read_int(),
723                          LOCS_MATCH_COMPLEMENT,     0,
724                          LOCS_MATCH_MAX_MISMATCHES, root->awar(AWAR_MAX_MISMATCHES)->read_int(),
725                          LOCS_SEARCHMATCH,          probe,
726                          NULL))
727            {
728                error = "Connection to PT_SERVER lost (2)";
729            }
730            else {
731                delete(g_spd);              // delete previous probe data
732                g_spd = new saiProbeData;
733                transferProbeData(g_spd);
734
735                if (selection_id) {
736                    g_spd->setProbeTarget(probe);
737                }
738            }
739        }
740
741        bytestring bs;
742        bs.data = 0;
743
744        long matches_truncated = 0;
745        if (!error) {
746            if (show_status) progress->subtitle("Reading results");
747
748            T_PT_MATCHLIST  match_list;
749            long            match_list_cnt    = 0;
750            char           *locs_error        = 0;
751
752            if (aisc_get(PD.link, PT_LOCS, PD.locs,
753                         LOCS_MATCH_LIST,        match_list.as_result_param(),
754                         LOCS_MATCH_LIST_CNT,    &match_list_cnt,
755                         LOCS_MATCH_STRING,      &bs,
756                         LOCS_MATCHES_TRUNCATED, &matches_truncated,
757                         LOCS_ERROR,             &locs_error,
758                         NULL))
759            {
760                error = "Connection to PT_SERVER lost (3)";
761            }
762            else {
763                if (locs_error) {
764                    if (*locs_error) error = GBS_static_string(locs_error);
765                    free(locs_error);
766                }
767                else {
768                    error = "Missing status from server (connection aborted?)";
769                }
770            }
771
772            root->awar(AWAR_PD_MATCH_NHITS)->write_string(GBS_global_string(matches_truncated ? "[more than %li]" : "%li", match_list_cnt));
773            if (matches_truncated) {
774                aw_message("Too many matches, displaying a random digest.\n"
775                           "Increase the limit in the expert window.");
776            }
777        }
778
779        long mcount                = 0;
780        long unknown_species_count = 0;
781        long unknown_gene_count    = 0;
782
783        if (!error) {
784            char        toksep[2]  = { 1, 0 };
785            char       *strtok_ptr = 0; // stores strtok position
786            const char *hinfo      = strtok_r(bs.data, toksep, &strtok_ptr);
787
788            bool              gene_flag = false;
789            ProbeMatchParser *parser    = 0;
790            char             *result    = (char*)malloc(1024);
791
792
793            if (hinfo) {
794                g_spd->setHeadline(hinfo);
795                parser = new ProbeMatchParser(probe, hinfo);
796                error  = parser->get_error();
797                if (!error) gene_flag = parser->is_gene_result();
798            }
799
800            if (selection_id) {
801                int width         = 0;
802                if (parser && !error) width = parser->get_probe_region_offset()+2+10; // 2 cause headline is shorter and 10 for match prefix region
803
804                const char *searched = GBS_global_string("%-*s%s", width, "Searched for ", probe);
805                selection_id->insert(searched, probe);
806                if (hinfo) selection_id->insert(hinfo, "");
807            }
808
809
810            // clear all marks and delete all 'tmp' entries
811
812            int mark        = extras && (int)root->awar(AWAR_PD_MATCH_MARKHITS)->read_int();
813            int write_2_tmp = extras && (int)root->awar(AWAR_PD_MATCH_WRITE2TMP)->read_int();
814
815            GB_push_transaction(gb_main);
816
817            GBDATA *gb_species_data = GBT_get_species_data(gb_main);
818            if (mark && !error) {
819                if (show_status) progress->subtitle(gene_flag ? "Unmarking all species and genes" : "Unmarking all species");
820                for (GBDATA *gb_species = GBT_first_marked_species_rel_species_data(gb_species_data);
821                     gb_species;
822                     gb_species = GBT_next_marked_species(gb_species))
823                {
824                    GB_write_flag(gb_species, 0);
825                }
826
827                if (gene_flag) {
828                    // unmark genes of ALL species
829                    for (GBDATA *gb_species = GBT_first_species_rel_species_data(gb_species_data);
830                         gb_species;
831                         gb_species = GBT_next_species(gb_species))
832                    {
833                        GBDATA *genData = GEN_find_gene_data(gb_species);
834                        if (genData) {
835                            for (GBDATA *gb_gene = GEN_first_marked_gene(gb_species);
836                                 gb_gene;
837                                 gb_gene = GEN_next_marked_gene(gb_gene))
838                            {
839                                GB_write_flag(gb_gene, 0);
840                            }
841                        }
842                    }
843                }
844            }
845            if (write_2_tmp && !error) {
846                if (show_status) progress->subtitle("Deleting old 'tmp' fields");
847                for (GBDATA *gb_species = GBT_first_species_rel_species_data(gb_species_data);
848                     gb_species;
849                     gb_species = GBT_next_species(gb_species))
850                {
851                    GBDATA *gb_tmp = GB_entry(gb_species, "tmp");
852                    if (gb_tmp) GB_delete(gb_tmp);
853                    if (gene_flag) {
854                        for (GBDATA *gb_gene = GEN_first_gene(gb_species);
855                             gb_gene;
856                             gb_gene = GEN_next_gene(gb_species))
857                        {
858                            gb_tmp = GB_entry(gb_gene, "tmp");
859                            if (gb_tmp) GB_delete(gb_tmp);
860                        }
861                    }
862                }
863            }
864
865            // read results from pt-server :
866
867            if (!error) {
868                if (show_status) progress->subtitle("Parsing results");
869
870                g_spd->probeSpecies.clear();
871                g_spd->probeSeq.clear();
872
873                if (gene_flag) {
874                    if (!GEN_is_genome_db(gb_main, -1)) {
875                        error = "Wrong PT-Server chosen (selected one is built for genes)";
876                    }
877                }
878            }
879
880            const char *match_name = 0;
881            while (hinfo && !error && (match_name = strtok_r(0, toksep, &strtok_ptr))) {
882                const char *match_info = strtok_r(0, toksep, &strtok_ptr);
883                if (!match_info) break;
884
885                pd_assert(parser);
886                ParsedProbeMatch  ppm(match_info, *parser);
887                char             *gene_str = 0;
888
889                if (gene_flag) {
890                    gene_str = ppm.get_column_content("genename", true);
891                }
892
893                if (!error) {
894                    char flags[]       = "xx";
895                    GBDATA *gb_species = GBT_find_species_rel_species_data(gb_species_data, match_name);
896
897                    if (gb_species) {
898                        GBDATA *gb_gene = 0;
899                        if (gene_flag && strncmp(gene_str, "intergene_", 10) != 0) { // real gene
900                            gb_gene = GEN_find_gene(gb_species, gene_str);
901                            if (!gb_gene) {
902                                aw_message(GBS_global_string("Gene '%s' not found in organism '%s'", gene_str, match_name));
903                            }
904                        }
905
906                        if (mark) {
907                            GB_write_flag(gb_species, 1);
908                            flags[0] = '*';
909                            if (gb_gene) {
910                                GB_write_flag(gb_gene, 1);
911                                flags[1] = '*';
912                            }
913                            else {
914                                flags[1] = '?'; // no gene
915                            }
916                        }
917                        else {
918                            flags[0] = " *"[GB_read_flag(gb_species)];
919                            flags[1] = " *?"[gb_gene ? GB_read_flag(gb_gene) : 2];
920                        }
921
922                        if (write_2_tmp) {
923                            // write or append to field 'tmp'
924                       
925                            GBDATA   *gb_tmp = 0;
926                            GB_ERROR  error2 = 0;
927                            bool      append = true;
928                            {
929                                GBDATA *gb_parent = gene_flag ? gb_gene : gb_species;
930                                gb_tmp            = GB_search(gb_parent, "tmp", GB_FIND);
931                                if (!gb_tmp) {
932                                    append              = false;
933                                    gb_tmp              = GB_search(gb_parent, "tmp", GB_STRING);
934                                    if (!gb_tmp) error2 = GB_await_error();
935                                }
936                            }
937
938                            if (!error2) {
939                                pd_assert(gb_tmp);
940                                if (append) {
941                                    char *prevContent = GB_read_string(gb_tmp);
942                                    if (!prevContent) {
943                                        error2 = GB_await_error();
944                                    }
945                                    else {
946                                        char *concatenatedContent = (char *)malloc(strlen(prevContent)+1+strlen(match_info)+1);
947                                        sprintf(concatenatedContent, "%s\n%s", prevContent, match_info);
948                                        error2 = GB_write_string(gb_tmp, concatenatedContent);
949                                        free(concatenatedContent);
950                                        free(prevContent);
951                                    }
952                                }
953                                else {
954                                    error2 = GB_write_string(gb_tmp, match_info);
955                                }
956                            }
957
958                            if (error2) aw_message(error2);
959                        }
960                    }
961                    else {
962                        flags[0] = flags[1] = '?'; // species does not exist
963                        unknown_species_count++;
964                    }
965
966
967                    if (gene_flag) {
968                        sprintf(result, "%s %s", flags, match_info+1); // both flags (skip 1 space from match info to keep alignment)
969                        char *gene_match_name = new char[strlen(match_name) + strlen(gene_str)+2];
970                        sprintf(gene_match_name, "%s/%s", match_name, gene_str);
971                        if (selection_id) selection_id->insert(result, gene_match_name);   // @@@ wert fuer awar eintragen
972                    }
973                    else {
974                        sprintf(result, "%c %s", flags[0], match_info); // only first flag ( = species related)
975                        if (selection_id) selection_id->insert(result, match_name);   // @@@ wert fuer awar eintragen
976
977                        if (selection_id) {  // storing probe data into linked lists
978                            g_spd->probeSeq.push_back(strdup(match_info));
979                            g_spd->probeSpecies.push_back(strdup(match_name));
980                        }
981                    }
982                    mcount++;
983                }
984
985                free(gene_str);
986            }
987
988            if (error) error = GBS_static_string(error); // make static copy (error may be freed by delete parser)
989            delete parser;
990            free(result);
991
992            GB_pop_transaction(gb_main);
993        }
994
995        if (error) {
996            root->awar(AWAR_PD_MATCH_NHITS)->write_string("[none]"); // clear hits
997            aw_message(error);
998        }
999        else {
1000            if (unknown_species_count>0) {
1001                aw_message(GBS_global_string("%li matches hit unknown species -- PT-server is out-of-date or build upon a different database", unknown_species_count));
1002            }
1003            if (unknown_gene_count>0) {
1004                aw_message(GBS_global_string("%li matches hit unknown genes -- PT-server is out-of-date or build upon a different database", unknown_gene_count));
1005            }
1006
1007            if (selection_id) {     // if !selection_id then probe match window is not opened
1008                pd_assert(g_spd);
1009                root->awar(AWAR_SPV_DB_FIELD_NAME)->touch(); // force refresh of SAI/Probe window
1010            }
1011        }
1012
1013        if (counter) *counter = mcount;
1014
1015        aisc_close(PD.link, PD.com);
1016        PD.link = 0;
1017
1018        if (selection_id) {
1019            const char *last_line                 = 0;
1020            if (error) last_line                  = GBS_global_string("****** Error: %s *******", error);
1021            else if (matches_truncated) last_line = "****** List is truncated *******";
1022            else        last_line                 = "****** End of List *******";
1023
1024            selection_id->insert_default(last_line, "");
1025            selection_id->update();
1026        }
1027
1028        free(bs.data);
1029        free(probe);
1030
1031        LocallyModify<bool> flag(allow_probe_match_event, false);
1032        root->awar(AWAR_TREE_REFRESH)->touch();
1033    }
1034
1035    return;
1036}
1037
1038static void probe_match_all_event(AW_window *aww, AW_selection_list *iselection_id, GBDATA *gb_main) {
1039    auto_match_cb_settings.disable = true;
1040
1041    AW_root *root          = aww->get_root();
1042    char    *target_string = root->awar(AWAR_TARGET_STRING)->read_string();
1043
1044    AW_selection_list_iterator selentry(iselection_id);
1045
1046    arb_progress progress("Matching all resolved strings", iselection_id->size());
1047
1048    bool got_result = false;
1049    while (selentry) {
1050        const char *entry = selentry.get_value();
1051        root->awar(AWAR_TARGET_STRING)->write_string(entry); // probe match
1052        int counter = -1;
1053        ProbeMatchEventParam match_event(gb_main, &counter);
1054        probe_match_event(aww, &match_event);
1055        if (counter==-1) break;
1056
1057        {
1058            char *buffer = new char[strlen(entry)+10]; // write # of matched to list entries
1059            sprintf(buffer, "%5i %s", counter, entry);
1060            selentry.set_displayed(buffer);
1061            got_result   = true;
1062            delete [] buffer;
1063        }
1064
1065        ++selentry;
1066        progress.inc();
1067       
1068    }
1069
1070    if (got_result) {
1071        iselection_id->sort(true, true);
1072        iselection_id->update();
1073        root->awar(AWAR_TARGET_STRING)->write_string(target_string);
1074    }
1075
1076    auto_match_cb_settings.disable = false;
1077}
1078
1079static void resolved_probe_chosen(AW_root *root) {
1080    char *string = root->awar(AWAR_PD_MATCH_RESOLVE)->read_string();
1081    root->awar(AWAR_TARGET_STRING)->write_string(string);
1082}
1083
1084static void selected_match_changed_cb(AW_root *root) {
1085    // this gets called when ever the selected probe match changes
1086    char *temp;
1087    char *selected_match = root->awar(AWAR_PD_SELECTED_MATCH)->read_string();
1088
1089    if (strchr(selected_match, '/')) { // "organism/gene"
1090        temp = strtok(selected_match, "/");
1091        root->awar(AWAR_SPECIES_NAME)->write_string(temp);
1092        temp = strtok(NULL, " /\n");
1093        root->awar(AWAR_GENE_NAME)->write_string(temp);
1094    }
1095    else {
1096        root->awar(AWAR_SPECIES_NAME)->write_string(selected_match);
1097    }
1098
1099    {
1100        LocallyModify<bool> flag(allow_probe_match_event, false); // avoid recursion
1101        root->awar(AWAR_TARGET_STRING)->touch(); // forces editor to jump to probe match in gene
1102    }
1103
1104    free(selected_match);
1105}
1106
1107static void probelength_changed_cb(AW_root *root, bool min_changed) {
1108    AW_awar *awar_minl = root->awar(AWAR_PD_DESIGN_MIN_LENGTH);
1109    AW_awar *awar_maxl = root->awar(AWAR_PD_DESIGN_MAX_LENGTH);
1110
1111    int minl = awar_minl->read_int();
1112    int maxl = awar_maxl->read_int();
1113
1114    if (minl>maxl) {
1115        if (min_changed) awar_maxl->write_int(minl);
1116        else             awar_minl->write_int(maxl);
1117    }
1118}
1119
1120void create_probe_design_variables(AW_root *root, AW_default props, AW_default db)
1121{
1122    char buffer[256]; memset(buffer, 0, 256);
1123    int  i;
1124    PD.win = 0;        // design result window not created
1125    root->awar_string(AWAR_SPECIES_NAME,         "", props);
1126    root->awar_string(AWAR_PD_SELECTED_MATCH,    "", props)->add_callback(selected_match_changed_cb);
1127    root->awar_float (AWAR_PD_DESIGN_EXP_DTEDGE, .5, props);
1128    root->awar_float (AWAR_PD_DESIGN_EXP_DT,     .5, props);
1129
1130
1131    double default_bonds[16] = {
1132        0.0, 0.0, 0.5, 1.1,
1133        0.0, 0.0, 1.5, 0.0,
1134        0.5, 1.5, 0.4, 0.9,
1135        1.1, 0.0, 0.9, 0.0
1136    };
1137
1138    for (i=0; i<16; i++) {
1139        sprintf(buffer, AWAR_PD_COMMON_EXP_BONDS "%i", i);
1140        root->awar_float(buffer, default_bonds[i], props);
1141        root->awar(buffer)->set_minmax(0, 3.0);
1142    }
1143    root->awar_float(AWAR_PD_COMMON_EXP_SPLIT,  .5, props);
1144    root->awar_float(AWAR_PD_DESIGN_EXP_DTEDGE, .5, props);
1145    root->awar_float(AWAR_PD_DESIGN_EXP_DT,     .5, props);
1146
1147    root->awar_int  (AWAR_PD_DESIGN_CLIPRESULT, 50,   props)->set_minmax(0, 1000);
1148    root->awar_int  (AWAR_PD_DESIGN_MISHIT,     0,    props)->set_minmax(0, 100000);
1149    root->awar_int  (AWAR_PD_DESIGN_MAXBOND,    4,    props)->set_minmax(0, 20);
1150    root->awar_float(AWAR_PD_DESIGN_MINTARGETS, 50.0, props)->set_minmax(0, 100);
1151
1152    AW_awar *awar_min_len = root->awar_int(AWAR_PD_DESIGN_MIN_LENGTH, 18, props);
1153    awar_min_len->set_minmax(DOMAIN_MIN_LENGTH, 100)->add_callback(makeRootCallback(probelength_changed_cb, true));
1154    root->awar_int(AWAR_PD_DESIGN_MAX_LENGTH, awar_min_len->read_int(), props)->set_minmax(DOMAIN_MIN_LENGTH, 100)->add_callback(makeRootCallback(probelength_changed_cb, false));
1155
1156    root->awar_float(AWAR_PD_DESIGN_MIN_TEMP,     30.0,   props)->set_minmax(0, 1000);
1157    root->awar_float(AWAR_PD_DESIGN_MAX_TEMP,     100.0,  props)->set_minmax(0, 1000);
1158    root->awar_float(AWAR_PD_DESIGN_MIN_GC,       50.0,   props)->set_minmax(0, 100);
1159    root->awar_float(AWAR_PD_DESIGN_MAX_GC,       100.0,  props)->set_minmax(0, 100);
1160
1161    root->awar_string(AWAR_PD_DESIGN_MIN_ECOLIPOS, "", props);
1162    root->awar_string(AWAR_PD_DESIGN_MAX_ECOLIPOS, "", props);
1163
1164    root->awar_int(AWAR_PT_SERVER,      0, props);
1165    root->awar_int(AWAR_PD_DESIGN_GENE, 0, props);
1166
1167    root->awar_int   (AWAR_PD_MATCH_MARKHITS,   1,       props);
1168    root->awar_int   (AWAR_PD_MATCH_SORTBY,     0,       props);
1169    root->awar_int   (AWAR_PD_MATCH_WRITE2TMP,  0,       props);
1170    root->awar_int   (AWAR_PD_MATCH_COMPLEMENT, 0,       props);
1171
1172    root->awar_int   (AWAR_MAX_MISMATCHES,      0,       db)->set_min(0);
1173    root->awar_string(AWAR_TARGET_STRING,       0,       db);
1174
1175    root->awar_string(AWAR_PD_MATCH_NHITS,      "[none]",props);
1176    root->awar_int   (AWAR_PD_MATCH_NMATCHES,   1,       props);
1177    root->awar_int   (AWAR_PD_MATCH_LIM_NMATCH, 4,       props);
1178    root->awar_int   (AWAR_PD_MATCH_MAX_RES,    1000000, props);
1179
1180    root->awar_int   (AWAR_PD_MATCH_AUTOMATCH,  0,    props)->add_callback(auto_match_changed);
1181
1182    root->awar_string(AWAR_PD_MATCH_RESOLVE, "", props)->add_callback(resolved_probe_chosen);
1183    root->awar_string(AWAR_ITARGET_STRING, "", db);
1184
1185    root->awar_int   (AWAR_PROBE_ADMIN_PT_SERVER,    0,  db);
1186    root->awar_int   (AWAR_PROBE_CREATE_GENE_SERVER, 0,  db);
1187
1188    root->awar_string(AWAR_SPV_SAI_2_PROBE,    "",     db); // name of SAI selected in list
1189    root->awar_string(AWAR_SPV_DB_FIELD_NAME,  "name", db); // name of displayed species field
1190    root->awar_int   (AWAR_SPV_DB_FIELD_WIDTH, 10,     db); // width of displayed species field
1191    root->awar_string(AWAR_SPV_ACI_COMMAND,    "",     db); // User defined or pre-defined ACI command to display
1192    root->awar_string(AWAR_SPV_SELECTED_PROBE, "",     db); // For highlighting the selected PROBE
1193}
1194
1195static AW_window *create_probe_expert_window(AW_root *root, bool for_design) {
1196    AW_window_simple *aws = new AW_window_simple;
1197    if (for_design) {
1198        aws->init(root, "PD_exp", "Probe Design (Expert)");
1199        aws->load_xfig("pd_spec.fig");
1200    }
1201    else {
1202        aws->init(root, "PM_exp", "Probe Match (Expert)");
1203        aws->load_xfig("pm_spec.fig");
1204    }
1205   
1206    aws->label_length(30);
1207    aws->button_length(10);
1208
1209    aws->callback((AW_CB0)AW_POPDOWN);
1210    aws->at("close");
1211    aws->create_button("CLOSE", "CLOSE", "C");
1212
1213    aws->callback(makeHelpCallback(for_design ? "pd_spec_param.hlp" : "pm_spec_param.hlp")); // uses_hlp_res("pm_spec_param.hlp", "pd_spec_param.hlp"); see ../SOURCE_TOOLS/check_ressources.pl@uses_hlp_res
1214    aws->at("help");
1215    aws->create_button("HELP", "HELP", "C");
1216
1217    for (int i=0; i<16; i++) { // bond matrix
1218        char buffer[256];
1219        sprintf(buffer, "%i", i);
1220        aws->at(buffer);
1221        sprintf(buffer, AWAR_PD_COMMON_EXP_BONDS "%i", i);
1222        aws->create_input_field(buffer, 4);
1223    }
1224
1225    aws->sens_mask(AWM_EXP);
1226    aws->at("split"); aws->create_input_field(AWAR_PD_COMMON_EXP_SPLIT,  6);
1227
1228    if (for_design) {
1229        aws->at("dt_edge"); aws->create_input_field(AWAR_PD_DESIGN_EXP_DTEDGE, 6);
1230        aws->at("dt");      aws->create_input_field(AWAR_PD_DESIGN_EXP_DT,     6);
1231        aws->sens_mask(AWM_ALL);
1232    }
1233    else {
1234        aws->at("nmatches");   aws->create_input_field(AWAR_PD_MATCH_NMATCHES,   3);
1235        aws->at("lim_nmatch"); aws->create_input_field(AWAR_PD_MATCH_LIM_NMATCH, 3);
1236        aws->sens_mask(AWM_ALL);
1237        aws->at("max_res");    aws->create_input_field(AWAR_PD_MATCH_MAX_RES,    14);
1238    }
1239   
1240    return aws;
1241}
1242
1243static AWT_config_mapping_def probe_design_mapping_def[] = {
1244    { AWAR_PD_DESIGN_CLIPRESULT,   "clip" },
1245    { AWAR_PD_DESIGN_MISHIT,       "mishit" },
1246    { AWAR_PD_DESIGN_MAXBOND,      "maxbond" },
1247    { AWAR_PD_DESIGN_MINTARGETS,   "mintarget" },
1248    { AWAR_PD_DESIGN_MIN_LENGTH,   "probelen" },
1249    { AWAR_PD_DESIGN_MAX_LENGTH,   "probemaxlen" },
1250    { AWAR_PD_DESIGN_MIN_TEMP,     "mintemp" },
1251    { AWAR_PD_DESIGN_MAX_TEMP,     "maxtemp" },
1252    { AWAR_PD_DESIGN_MIN_GC,       "mingc" },
1253    { AWAR_PD_DESIGN_MAX_GC,       "maxgc" },
1254    { AWAR_PD_DESIGN_MIN_ECOLIPOS, "minecoli" },
1255    { AWAR_PD_DESIGN_MAX_ECOLIPOS, "maxecoli" },
1256    { AWAR_PD_DESIGN_GENE,         "gene" },
1257    { AWAR_PD_COMMON_EXP_SPLIT,    "split" }, 
1258    { AWAR_PD_DESIGN_EXP_DTEDGE,   "dtedge" },
1259    { AWAR_PD_DESIGN_EXP_DT,       "dt" },
1260    { 0, 0 }
1261};
1262
1263static void probe_design_init_config(AWT_config_definition& cdef) {
1264    cdef.add(probe_design_mapping_def);
1265    for (int i = 0; i<16; ++i) {
1266        cdef.add(GBS_global_string(AWAR_PD_COMMON_EXP_BONDS "%i", i), "bond", i);
1267    }
1268}
1269
1270static char *probe_design_store_config(AW_CL, AW_CL) {
1271    AWT_config_definition cdef;
1272    probe_design_init_config(cdef);
1273    return cdef.read();
1274}
1275static void probe_design_restore_config(const char *stored_string, AW_CL, AW_CL) {
1276    AWT_config_definition cdef;
1277    probe_design_init_config(cdef);
1278    cdef.write(stored_string);
1279}
1280
1281AW_window *create_probe_design_window(AW_root *root, GBDATA *gb_main) {
1282    bool is_genom_db;
1283    {
1284        GB_transaction ta(gb_main);
1285        is_genom_db = GEN_is_genome_db(gb_main, -1);
1286    }
1287
1288    AW_window_simple *aws = new AW_window_simple;
1289    aws->init(root, "PROBE_DESIGN", "PROBE DESIGN");
1290
1291    aws->load_xfig("pd_main.fig");
1292
1293    aws->callback((AW_CB0)AW_POPDOWN);
1294    aws->at("close");
1295    aws->create_button("CLOSE", "CLOSE", "C");
1296
1297    aws->at("help");
1298    aws->callback(makeHelpCallback("probedesign.hlp"));
1299    aws->create_button("HELP", "HELP", "H");
1300
1301    aws->callback(makeWindowCallback(probe_design_event, gb_main));
1302    aws->at("design");
1303    aws->highlight();
1304    aws->create_button("GO", "GO", "G");
1305
1306    aws->callback(makeWindowCallback(popup_probe_design_result_window, gb_main));
1307    aws->at("result");
1308    aws->create_button("RESULT", "RESULT", "S");
1309
1310    aws->callback(makeCreateWindowCallback(create_probe_expert_window, true));
1311    aws->at("expert");
1312    aws->create_button("EXPERT", "EXPERT", "S");
1313
1314    aws->at("pt_server");
1315    aws->label("PT-Server:");
1316    awt_create_PTSERVER_selection_button(aws, AWAR_PT_SERVER);
1317
1318    aws->at("lenout");   aws->create_input_field(AWAR_PD_DESIGN_CLIPRESULT, 6);
1319    aws->at("mishit");   aws->create_input_field(AWAR_PD_DESIGN_MISHIT,     6);
1320    aws->sens_mask(AWM_EXP);
1321    aws->at("maxbonds"); aws->create_input_field(AWAR_PD_DESIGN_MAXBOND,    6);
1322    aws->sens_mask(AWM_ALL);
1323    aws->at("minhits");  aws->create_input_field(AWAR_PD_DESIGN_MINTARGETS, 6);
1324
1325    aws->at("minlen"); aws->create_input_field(AWAR_PD_DESIGN_MIN_LENGTH,   5);
1326    aws->at("maxlen"); aws->create_input_field(AWAR_PD_DESIGN_MAX_LENGTH,   5);
1327    aws->at("mint");   aws->create_input_field(AWAR_PD_DESIGN_MIN_TEMP,     5);
1328    aws->at("maxt");   aws->create_input_field(AWAR_PD_DESIGN_MAX_TEMP,     5);
1329    aws->at("mingc");  aws->create_input_field(AWAR_PD_DESIGN_MIN_GC,       5);
1330    aws->at("maxgc");  aws->create_input_field(AWAR_PD_DESIGN_MAX_GC,       5);
1331    aws->at("minpos"); aws->create_input_field(AWAR_PD_DESIGN_MIN_ECOLIPOS, 5);
1332    aws->at("maxpos"); aws->create_input_field(AWAR_PD_DESIGN_MAX_ECOLIPOS, 5);
1333
1334    if (is_genom_db) {
1335        aws->at("gene");
1336        aws->label("Gene probes?");
1337        aws->create_toggle(AWAR_PD_DESIGN_GENE);
1338    }
1339
1340    aws->at("save");
1341    AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, "probe_design", probe_design_store_config, probe_design_restore_config, 0, 0);
1342
1343    return aws;
1344}
1345
1346// -------------------------------------------------------------------
1347
1348inline void my_strupr(char *s) {
1349    pd_assert(s);
1350    for (int i=0; s[i]; i++) {
1351        s[i] = toupper(s[i]);
1352    }
1353}
1354
1355static void resolve_IUPAC_target_string(AW_root *root, AW_selection_list *selection_id, GBDATA *gb_main) {
1356    selection_id->clear();
1357
1358    GB_alignment_type ali_type = GBT_get_alignment_type(gb_main, GBT_get_default_alignment(gb_main));
1359
1360    GB_ERROR err = 0;
1361    if (ali_type != GB_AT_RNA && ali_type!=GB_AT_DNA) {
1362        err = "Wrong alignment type";
1363        GB_clear_error();
1364    }
1365    else {
1366        int   index   = ali_type==GB_AT_RNA ? 1 : 0;
1367        char *istring = root->awar(AWAR_ITARGET_STRING)->read_string();
1368
1369        if (istring && istring[0]) { // contains sth?
1370            my_strupr(istring);
1371
1372            int bases_to_resolve = 0;
1373            char *istr = istring;
1374            int istring_length = strlen(istring);
1375
1376            for (;;) {
1377                char i = *istr++;
1378                if (!i) break;
1379                if (i=='?') continue; // ignore '?'
1380
1381                int idx = i-'A';
1382                if (idx<0 || idx>=26 || iupac::nuc_group[idx][index].members==0) {
1383                    err = GBS_global_string("Illegal character '%c' in IUPAC-String", i);
1384                    break;
1385                }
1386
1387                if (iupac::nuc_group[idx][index].count>1) {
1388                    bases_to_resolve++;
1389                }
1390            }
1391
1392            if (!err) {
1393                int *offsets_to_resolve = new int[bases_to_resolve];
1394                int resolutions = 1;
1395                {
1396                    istr = istring;
1397                    int offset = 0;
1398                    int offset_count = 0;
1399                    for (;;) {
1400                        char i = *istr++;
1401                        if (!i) break;
1402
1403                        if (i!='?') {
1404                            int idx = iupac::to_index(i);
1405                            pd_assert(iupac::nuc_group[idx][index].members);
1406
1407                            if (iupac::nuc_group[idx][index].count>1) {
1408                                offsets_to_resolve[offset_count++] = offset; // store string offsets of non-unique base-codes
1409                                resolutions *= iupac::nuc_group[idx][index].count; // calc # of resolutions
1410                            }
1411                        }
1412                        offset++;
1413                    }
1414                }
1415
1416                {
1417                    int *resolution_idx = new int[bases_to_resolve];
1418                    int *resolution_max_idx = new int[bases_to_resolve];
1419                    {
1420                        int i;
1421                        for (i=0; i<bases_to_resolve; i++) {
1422                            resolution_idx[i] = 0;
1423                            int idx = iupac::to_index(istring[offsets_to_resolve[i]]);
1424                            resolution_max_idx[i] = iupac::nuc_group[idx][index].count-1;
1425                        }
1426                    }
1427
1428                    char *buffer = new char[istring_length+1];
1429                    int not_last = resolutions-1;
1430
1431                    for (;;) {
1432                        // create string according to resolution_idx[]:
1433                        int i;
1434
1435                        memcpy(buffer, istring, istring_length+1);
1436                        for (i=0; i<bases_to_resolve; i++) {
1437                            int off = offsets_to_resolve[i];
1438                            int idx = iupac::to_index(istring[off]);
1439
1440                            pd_assert(iupac::nuc_group[idx][index].members);
1441                            buffer[off] = iupac::nuc_group[idx][index].members[resolution_idx[i]];
1442                        }
1443
1444                        selection_id->insert(buffer, buffer);
1445                        not_last--;
1446
1447                        // permute indices:
1448                        int nidx = bases_to_resolve-1;
1449                        int done = 0;
1450                        while (!done && nidx>=0) {
1451                            if (resolution_idx[nidx]<resolution_max_idx[nidx]) {
1452                                resolution_idx[nidx]++;
1453                                done = 1;
1454                                break;
1455                            }
1456                            nidx--;
1457                        }
1458                        if (!done) break; // we did all permutations!
1459
1460                        nidx++; // do not touch latest incremented index
1461                        while (nidx<bases_to_resolve) resolution_idx[nidx++] = 0; // zero all other indices
1462                    }
1463
1464                    delete [] buffer;
1465                    delete [] resolution_max_idx;
1466                    delete [] resolution_idx;
1467
1468                    pd_assert(!err);
1469                    selection_id->insert_default("", "");
1470                }
1471
1472                delete [] offsets_to_resolve;
1473            }
1474        }
1475        else { // empty input
1476            selection_id->insert_default("", "");
1477        }
1478    }
1479    if (err) selection_id->insert_default(err, "");
1480    selection_id->update();
1481}
1482
1483enum ModMode { TS_MOD_CLEAR, TS_MOD_REV_COMPL, TS_MOD_COMPL };
1484
1485static void modify_target_string(AW_window *aww, GBDATA *gb_main, ModMode mod_mode) {
1486    AW_root  *root          = aww->get_root();
1487    char     *target_string = root->awar(AWAR_TARGET_STRING)->read_string();
1488    GB_ERROR  error         = 0;
1489
1490    if (mod_mode == TS_MOD_CLEAR) target_string[0] = 0;
1491    else {
1492        GB_transaction    ta(gb_main);
1493        GB_alignment_type ali_type = GBT_get_alignment_type(gb_main, GBT_get_default_alignment(gb_main));
1494        if (ali_type == GB_AT_UNKNOWN) {
1495            error = GB_await_error();
1496        }
1497        else if (mod_mode == TS_MOD_REV_COMPL) {
1498            char T_or_U;
1499            error = GBT_determine_T_or_U(ali_type, &T_or_U, "reverse-complement");
1500            if (!error) GBT_reverseComplementNucSequence(target_string, strlen(target_string), T_or_U);
1501        }
1502        else if (mod_mode == TS_MOD_COMPL) {
1503            char T_or_U;
1504            error = GBT_determine_T_or_U(ali_type, &T_or_U, "complement");
1505            if (!error) freeset(target_string, GBT_complementNucSequence(target_string, strlen(target_string), T_or_U));
1506        }
1507    }
1508
1509    if (error) aw_message(error);
1510    else root->awar(AWAR_TARGET_STRING)->write_string(target_string);
1511    free(target_string);
1512}
1513
1514static AW_window *create_IUPAC_resolve_window(AW_root *root, GBDATA *gb_main) {
1515    AW_window_simple *aws = new AW_window_simple;
1516
1517    aws->init(root, "PROBE_MATCH_RESOLVE_IUPAC", "Resolve IUPAC for Probe Match");
1518    aws->load_xfig("pd_match_iupac.fig");
1519
1520    aws->callback((AW_CB0)AW_POPDOWN);
1521    aws->at("close");
1522    aws->create_button("CLOSE", "CLOSE", "C");
1523
1524    aws->callback(makeHelpCallback("pd_match_iupac.hlp"));
1525    aws->at("help");
1526    aws->create_button("HELP", "HELP", "C");
1527
1528    AW_selection_list *iselection_id;
1529    aws->at("iresult");
1530    iselection_id = aws->create_selection_list(AWAR_PD_MATCH_RESOLVE, 32, 15, true);
1531    iselection_id->insert_default("---empty---", "");
1532
1533    aws->at("istring");
1534    aws->create_input_field(AWAR_ITARGET_STRING, 32);
1535
1536    // add callback for automatic decomposition of AWAR_ITARGET_STRING:
1537    RootCallback upd_cb = makeRootCallback(resolve_IUPAC_target_string, iselection_id, gb_main);
1538    root->awar(AWAR_ITARGET_STRING)->add_callback(upd_cb);
1539    root->awar(AWAR_DEFAULT_ALIGNMENT)->add_callback(upd_cb);
1540
1541    aws->callback(makeWindowCallback(probe_match_all_event, iselection_id, gb_main));
1542    aws->at("match_all");
1543    aws->create_button("MATCH_ALL", "MATCH ALL", "A");
1544
1545    return aws;
1546}
1547
1548static void popupSaiProbeMatchWindow(AW_window *aw, GBDATA *gb_main) {
1549    static AW_window *aw_saiProbeMatch = 0;
1550
1551    if (!aw_saiProbeMatch) aw_saiProbeMatch = createSaiProbeMatchWindow(aw->get_root(), gb_main);
1552    if (g_spd) transferProbeData(g_spd); // transferring probe data to saiProbeMatch function
1553
1554    aw_saiProbeMatch->activate();
1555}
1556
1557AW_window *create_probe_match_window(AW_root *root, GBDATA *gb_main) {
1558    static AW_window_simple *aws = 0; // the one and only probe match window
1559    if (!aws) {
1560        aws = new AW_window_simple;
1561
1562        aws->init(root, "PROBE_MATCH", "PROBE MATCH");
1563
1564        aws->load_xfig("pd_match.fig");
1565
1566        aws->callback((AW_CB0)AW_POPDOWN);
1567        aws->at("close");
1568        aws->create_button("CLOSE", "CLOSE", "C");
1569
1570        aws->callback(makeHelpCallback("probematch.hlp"));
1571        aws->at("help");
1572        aws->create_button("HELP", "HELP", "H");
1573
1574        aws->at("string");
1575        aws->create_input_field(AWAR_TARGET_STRING, 32);
1576
1577        AW_selection_list *selection_id;
1578        aws->at("result");
1579        selection_id = aws->create_selection_list(AWAR_PD_SELECTED_MATCH, 110, 15, true);
1580        selection_id->insert_default("****** No results yet *******", "");  // if list is empty -> crashed if new species was selected in ARB_EDIT4
1581
1582        TypedSelectionList *typed_selection = new TypedSelectionList("match", selection_id, "probe match", "probe_match");
1583        aws->at("print");
1584        aws->callback(makeWindowCallback(create_print_box_for_selection_lists, typed_selection));
1585        aws->create_button("PRINT", "PRINT", "P");
1586
1587        aws->at("matchSai");
1588        aws->callback(makeWindowCallback(popupSaiProbeMatchWindow, gb_main));
1589        aws->create_button("MATCH_SAI", "Match SAI", "S");
1590
1591        aws->callback(makeCreateWindowCallback(create_probe_expert_window, false));
1592        aws->at("expert");
1593        aws->create_button("EXPERT", "EXPERT", "X");
1594
1595        aws->at("pt_server");
1596        awt_create_PTSERVER_selection_button(aws, AWAR_PT_SERVER);
1597
1598        aws->at("complement");
1599        aws->create_toggle(AWAR_PD_MATCH_COMPLEMENT);
1600
1601        aws->at("mark");
1602        aws->create_toggle(AWAR_PD_MATCH_MARKHITS);
1603
1604        aws->at("weighted");
1605        aws->create_toggle(AWAR_PD_MATCH_SORTBY);
1606
1607        aws->at("mismatches");
1608        aws->create_input_field(AWAR_MAX_MISMATCHES);
1609
1610        aws->at("tmp");
1611        aws->create_toggle(AWAR_PD_MATCH_WRITE2TMP);
1612
1613        aws->at("nhits");
1614        aws->create_button(0, AWAR_PD_MATCH_NHITS);
1615
1616        aws->button_length(9);
1617
1618        ProbeMatchEventParam *event_param = new ProbeMatchEventParam(gb_main, selection_id);
1619        aws->callback(makeWindowCallback(probe_match_event, event_param));
1620        aws->at("match");
1621        aws->create_button("MATCH", "MATCH", "D");
1622
1623        aws->at("auto");
1624        aws->label("Auto");
1625        aws->create_toggle(AWAR_PD_MATCH_AUTOMATCH);
1626        enable_auto_match_cb(root, aws, event_param);
1627
1628        aws->callback(makeWindowCallback(modify_target_string, gb_main, TS_MOD_CLEAR));
1629        aws->at("clear");
1630        aws->create_button("CLEAR", "Clear", "0");
1631
1632        aws->callback(makeWindowCallback(modify_target_string, gb_main, TS_MOD_REV_COMPL));
1633        aws->at("revcompl");
1634        aws->create_button("REVCOMPL", "RevCompl", "R");
1635
1636        aws->callback(makeWindowCallback(modify_target_string, gb_main, TS_MOD_COMPL));
1637        aws->at("compl");
1638        aws->create_button("COMPL", "Compl", "C");
1639
1640        aws->callback(makeCreateWindowCallback(create_IUPAC_resolve_window, gb_main));
1641        aws->at("iupac");
1642        aws->create_button("IUPAC", "IUPAC", "I");
1643    }
1644    return aws;
1645}
1646
1647static void pd_start_pt_server(AW_window *aww) {
1648    const char *server_tag = GBS_ptserver_tag(aww->get_root()->awar(AWAR_PROBE_ADMIN_PT_SERVER)->read_int());
1649    arb_progress progress("Connecting PT-server");
1650    GB_ERROR error = arb_look_and_start_server(AISC_MAGIC_NUMBER, server_tag);
1651    if (error) aw_message(error);
1652}
1653
1654static void pd_kill_pt_server(AW_window *aww, bool kill_all)
1655{
1656    if (aw_ask_sure("kill_ptserver",
1657                    GBS_global_string("Are you sure to stop %s", kill_all ? "all servers" : "that server"))) {
1658        long min = 0;
1659        long max = 0;
1660
1661        if (kill_all) {
1662            const char * const *pt_servers = GBS_get_arb_tcp_entries("ARB_PT_SERVER*");
1663            while (pt_servers[max]) max++;
1664        }
1665        else {
1666            min = max = aww->get_root()->awar(AWAR_PROBE_ADMIN_PT_SERVER)->read_int(); // selected server
1667        }
1668
1669        arb_progress progress("Stopping PT-servers..", max-min+1);
1670        GB_ERROR     error = NULL;
1671
1672        for (int i = min; i <= max && !error;  i++) {
1673            char *choice = GBS_ptserver_id_to_choice(i, 0);
1674            if (!choice) {
1675                error = GB_await_error();
1676            }
1677            else {
1678                progress.subtitle(GBS_global_string("Trying to stop '%s'", choice));
1679
1680                const char *server_tag = GBS_ptserver_tag(i);
1681                GB_ERROR    kill_error = arb_look_and_kill_server(AISC_MAGIC_NUMBER, server_tag);
1682
1683                if (kill_error) aw_message(GBS_global_string("Could not stop '%s' (Reason: %s)", choice, kill_error));
1684                else aw_message(GBS_global_string("Stopped '%s'", choice));
1685
1686                free(choice);
1687            }
1688            progress.inc_and_check_user_abort(error);
1689        }
1690        progress.done();
1691        aw_message_if(error);
1692    }
1693}
1694
1695static void pd_query_pt_server(AW_window *aww) {
1696    const char *server_tag = GBS_ptserver_tag(aww->get_root()->awar(AWAR_PROBE_ADMIN_PT_SERVER)->read_int());
1697
1698    GBS_strstruct *strstruct = GBS_stropen(1024);
1699    GBS_strcat(strstruct,   "echo Contents of directory ARBHOME/lib/pts:;echo;"
1700               "(cd $ARBHOME/lib/pts; ls -l);"
1701               "echo; echo Disk space for PT_server files:; echo;"
1702               "df $ARBHOME/lib/pts;");
1703    GBS_strcat(strstruct, "echo;echo 'Running ARB programs:';");
1704
1705    GB_ERROR error = NULL;
1706    {
1707        const char *server = GBS_read_arb_tcp(server_tag);
1708        if (!server) {
1709            error = GB_await_error();
1710        }
1711        else {
1712            char *arb_who = prefixSSH(server, "$ARBHOME/bin/arb_who", 0);
1713            GBS_strcat(strstruct, arb_who);
1714            free(arb_who);
1715        }
1716    }
1717
1718    char *sys         = GBS_strclose(strstruct);
1719    if (!error) error = GB_xcmd(sys, true, false);
1720    free(sys);
1721
1722    aw_message_if(error);
1723}
1724
1725static void pd_export_pt_server(AW_window *aww, GBDATA *gb_main) {
1726    AW_root  *awr   = aww->get_root();
1727    GB_ERROR  error = 0;
1728
1729    bool create_gene_server = awr->awar(AWAR_PROBE_CREATE_GENE_SERVER)->read_int();
1730    {
1731        GB_transaction ta(gb_main);
1732        if (create_gene_server && !GEN_is_genome_db(gb_main, -1)) create_gene_server = false;
1733
1734        // check alignment first
1735        if (create_gene_server) {
1736            GBDATA *gb_ali     = GBT_get_alignment(gb_main, GENOM_ALIGNMENT);
1737            if (!gb_ali) error = GB_await_error();
1738        }
1739        else { // normal pt server
1740            char              *use     = GBT_get_default_alignment(gb_main);
1741            GB_alignment_type  alitype = GBT_get_alignment_type(gb_main, use);
1742            if (alitype == GB_AT_AA) error = "The PT-server does only support RNA/DNA sequence data";
1743            free(use);
1744        }
1745    }
1746
1747    long        server_num = awr->awar(AWAR_PROBE_ADMIN_PT_SERVER)->read_int();
1748    const char *server_tag  = GBS_ptserver_tag(server_num);
1749
1750    if (!error &&
1751        aw_question("update_ptserver",
1752                    "This function will send your loaded database to the pt_server,\n"
1753                    "which will need a long time (up to several hours) to analyse the data.\n"
1754                    "Until the new server has analyzed all data, no server functions are available.\n\n"
1755                    "Note 1: You must have the write permissions to do that ($ARBHOME/lib/pts/xxx))\n"
1756                    "Note 2: The server will do the job in background,\n"
1757                    "        quitting this program won't affect the server",
1758                    "Cancel,Do it"))
1759    {
1760        arb_progress progress("Updating PT-server");
1761        progress.subtitle("Stopping PT-server");
1762        arb_look_and_kill_server(AISC_MAGIC_NUMBER, server_tag);
1763
1764        const char *ipPort = GBS_read_arb_tcp(server_tag);
1765        const char *file   = NULL;
1766        if (!ipPort) error = GB_await_error();
1767        else {
1768            file = GBS_scan_arb_tcp_param(ipPort, "-d");
1769            GBS_add_ptserver_logentry(GBS_global_string("Started build of '%s'", file));
1770
1771            char *db_name = awr->awar(AWAR_DB_PATH)->read_string();
1772            GBS_add_ptserver_logentry(GBS_global_string("Exporting DB '%s'", db_name));
1773            free(db_name);
1774        }
1775
1776        if (!error) {
1777            progress.subtitle("Exporting the database");
1778            {
1779                const char *mode = GB_supports_mapfile() ? "mbf" : "bf"; // save PT-server database with Fastload file (if supported)
1780                if (create_gene_server) {
1781                    char *temp_server_name = GBS_string_eval(file, "*.arb=*_temp.arb", 0);
1782                    error = GB_save_as(gb_main, temp_server_name, mode);
1783
1784                    if (!error) {
1785                        // convert database (genes -> species)
1786                        progress.subtitle("Preparing DB for gene PT server");
1787                        GBS_add_ptserver_logentry("Preparing DB for gene PT server");
1788                        char *command = GBS_global_string_copy("$ARBHOME/bin/arb_gene_probe %s %s", temp_server_name, file);
1789                        printf("Executing '%s'\n", command);
1790                        int result = system(command);
1791                        if (result != 0) {
1792                            error = GBS_global_string("Couldn't convert database for gene pt server (arb_gene_probe failed, see console for reason)");
1793                        }
1794                        free(command);
1795                    }
1796                    free(temp_server_name);
1797                }
1798                else { // normal pt_server
1799                    error = GB_save_as(gb_main, file, mode);
1800                }
1801            }
1802        }
1803
1804        if (!error) { // set pt-server database file to same permissions as pts directory
1805            char *dir = const_cast<char*>(strrchr(file, '/'));
1806            if (dir) {
1807                *dir = 0;
1808                long modi = GB_mode_of_file(file);
1809                *dir = '/';
1810                modi &= 0666;
1811                error = GB_set_mode_of_file(file, modi);
1812            }
1813        }
1814
1815        if (!error) {
1816            progress.subtitle("Start PT-server (builds in background)");
1817            error = arb_start_server(server_tag, 1);
1818        }
1819    }
1820    if (error) aw_message(error);
1821}
1822
1823static void pd_view_pt_log(AW_window *) {
1824    AW_edit(GBS_ptserver_logname());
1825}
1826
1827AW_window *create_probe_admin_window(AW_root *root, GBDATA *gb_main) {
1828    bool is_genom_db;
1829    {
1830        GB_transaction ta(gb_main);
1831        is_genom_db = GEN_is_genome_db(gb_main, -1);
1832    }
1833
1834    AW_window_simple *aws = new AW_window_simple;
1835    aws->init(root, "PT_SERVER_ADMIN", "PT_SERVER ADMIN");
1836
1837    aws->load_xfig("pd_admin.fig");
1838
1839
1840    aws->callback(makeHelpCallback("probeadmin.hlp"));
1841    aws->at("help");
1842    aws->create_button("HELP", "HELP", "H");
1843
1844    aws->callback((AW_CB0)AW_POPDOWN);
1845    aws->at("close");
1846    aws->create_button("CLOSE", "CLOSE", "C");
1847
1848    aws->button_length(18);
1849
1850    aws->at("pt_server");
1851    awt_create_PTSERVER_selection_list(aws, AWAR_PROBE_ADMIN_PT_SERVER);
1852
1853    aws->at("start");
1854    aws->callback(pd_start_pt_server);
1855    aws->create_button("START_SERVER", "Start server");
1856
1857    aws->at("kill");
1858    aws->callback(makeWindowCallback(pd_kill_pt_server, false));
1859    aws->create_button("KILL_SERVER", "Stop server");
1860
1861    aws->at("query");
1862    aws->callback(pd_query_pt_server);
1863    aws->create_button("CHECK_SERVER", "Check server");
1864
1865    aws->at("kill_all");
1866    aws->callback(makeWindowCallback(pd_kill_pt_server, true));
1867    aws->create_button("KILL_ALL_SERVERS", "Stop all servers");
1868
1869    aws->at("edit");
1870    aws->callback(makeWindowCallback(awt_edit_arbtcpdat_cb, gb_main));
1871    aws->create_button("CREATE_TEMPLATE", "Configure");
1872
1873    aws->at("log");
1874    aws->callback(pd_view_pt_log);
1875    aws->create_button("EDIT_LOG", "View logfile");
1876
1877    aws->at("export");
1878    aws->callback(makeWindowCallback(pd_export_pt_server, gb_main));
1879    aws->create_button("UPDATE_SERVER", "Build server");
1880
1881    if (is_genom_db) {
1882        aws->at("gene_server");
1883        aws->label("Gene server?");
1884        aws->create_toggle(AWAR_PROBE_CREATE_GENE_SERVER);
1885    }
1886
1887    return aws;
1888}
1889
1890// --------------------------------------------------------------------------------
1891// Probe group result visualization
1892
1893#define AWAR_PG_SELECTED_RESULT "tmp/pg_result/selected"
1894
1895static struct pg_global_struct {
1896    char              *awar_pg_result_filename;     // awar containing result filename
1897    AW_window_simple  *pg_groups_window;            // window showing groups
1898    AW_selection_list *selList;                     // list containing groups
1899    AW_root           *aw_root;
1900    AWT_canvas        *ntw;                         // canvas of main window
1901
1902    char   *pg_filename;                            // database containing results (from one result file)
1903    GBDATA *pg_main;                                // root-handle of probe-group-database
1904} pg_global;
1905
1906
1907static void pg_result_selected(AW_window*, GBDATA *gb_main) {
1908    AW_root *aw_root = pg_global.aw_root;
1909    long position = aw_root->awar(AWAR_PG_SELECTED_RESULT)->read_int();
1910
1911    if (position) { // ignore headline
1912        long i = 1;
1913
1914        GB_transaction ta1(pg_global.pg_main);
1915        GB_transaction ta2(gb_main);
1916
1917        GBT_mark_all(gb_main, 0); // unmark all species
1918
1919        GBDATA *gb_species_data = GBT_get_species_data(gb_main);
1920        GBDATA *pg_group = GB_search(pg_global.pg_main, "probe_groups/group", GB_FIND);
1921        long count = 0;
1922        long marked = 0;
1923        for (; pg_group; pg_group=GB_nextChild(pg_group), ++i) {
1924            if (i==position) {
1925                GBDATA *pg_species = GB_search(pg_group, "species/name", GB_FIND);
1926                for (; pg_species; pg_species=GB_nextChild(pg_species), count++) {
1927                    const char *name           = GB_read_char_pntr(pg_species);
1928                    GBDATA     *gb_speciesname = GB_find_string(gb_species_data, "name", name, GB_IGNORE_CASE, SEARCH_GRANDCHILD);
1929                    if (gb_speciesname) {
1930                        GBDATA *gb_species = GB_get_father(gb_speciesname);
1931                        pd_assert(gb_species);
1932                        GB_write_flag(gb_species, 1); // mark species
1933                        if (!marked) { // select first species
1934                            aw_root->awar(AWAR_SPECIES_NAME)->write_string(name);
1935                        }
1936                        marked++;
1937                    }
1938                    else {
1939                        aw_message(GBS_global_string("No species '%s' in current DB", name));
1940                    }
1941                }
1942                break;
1943            }
1944        }
1945
1946        if (marked!=count) {
1947            aw_message(GBS_global_string("%li species were in group - %li species marked in database", count, marked));
1948        }
1949
1950        NT_expand_marked_cb(NULL, pg_global.ntw);
1951    }
1952}
1953
1954static void create_probe_group_result_awars(AW_root *aw_root) {
1955    aw_root->awar_int(AWAR_PG_SELECTED_RESULT, 0);
1956}
1957
1958static void create_probe_group_result_sel_box(AW_root *aw_root, AW_window *aws, GBDATA *gb_main) {
1959    char *file_name = aw_root->awar(pg_global.awar_pg_result_filename)->read_string();
1960
1961    AW_selection_list *selList = pg_global.selList;
1962
1963    static bool awars_created;
1964    if (!awars_created) {
1965        create_probe_group_result_awars(aw_root);
1966        awars_created = 1;
1967    }
1968    aw_root->awar(AWAR_PG_SELECTED_RESULT)->write_int(0); // reset to element #0
1969
1970    if (selList==0) {
1971        aws->at("box");
1972        aws->callback(makeWindowCallback(pg_result_selected, gb_main)); // @@@ used as SELLIST_CLICK_CB (see #559)
1973        selList = pg_global.selList = aws->create_selection_list(AWAR_PG_SELECTED_RESULT, 2, 2, true);
1974    }
1975    else {
1976        selList->clear();
1977    }
1978
1979    GB_ERROR error = 0;
1980
1981    if (pg_global.pg_main) {
1982        GB_close(pg_global.pg_main);
1983        pg_global.pg_main = 0;
1984        freenull(pg_global.pg_filename);
1985    }
1986
1987    pg_global.aw_root = aw_root;
1988    pg_global.pg_filename = strdup(file_name);
1989    pg_global.pg_main = GB_open(file_name, "r");
1990
1991    if (pg_global.pg_main) {
1992        const char *reason = 0;
1993        int32_t i = 0;
1994        selList->insert("members | probes | fitness | quality | mintarget | mishit | probelen | birth", i++);
1995
1996        GB_transaction ta(pg_global.pg_main);
1997        GBDATA *pg_group = GB_search(pg_global.pg_main, "probe_groups/group", GB_FIND);
1998        if (pg_group) {
1999            for (; pg_group; pg_group=GB_nextChild(pg_group), ++i) {
2000
2001                double fitness=-1, quality=-1, min_targets=-1;
2002                int mishit=-1, probelength=-1, birth=-1;
2003                int member_count = 0;
2004                int probe_count = 0;
2005
2006                GBDATA *field;
2007
2008                field = GB_entry(pg_group, "fitness");        if (field) fitness     = GB_read_float(field);
2009                field = GB_entry(pg_group, "quality");        if (field) quality     = GB_read_float(field);
2010                field = GB_entry(pg_group, "min_targets");    if (field) min_targets = GB_read_float(field);
2011                field = GB_entry(pg_group, "mishit");         if (field) mishit      = GB_read_int(field);
2012                field = GB_entry(pg_group, "probelength");    if (field) probelength = GB_read_int(field);
2013                field = GB_entry(pg_group, "birth");          if (field) birth       = GB_read_int(field);
2014
2015                GBDATA *species = GB_search(pg_group, "species/name", GB_FIND);
2016                for (; species; species=GB_nextChild(species)) member_count++;
2017
2018                GBDATA *probe = GB_search(pg_group, "probes/data", GB_FIND);
2019                for (; probe; probe=GB_nextChild(probe)) probe_count++;
2020
2021                char entry[200];
2022
2023                sprintf(entry, "%7i | %6i | %7.5f | %7.1f | %9.2f | %6i | %8i | %5i",
2024                        member_count,
2025                        probe_count,
2026                        fitness,
2027                        quality,
2028                        min_targets,
2029                        mishit,
2030                        probelength,
2031                        birth);
2032
2033                selList->insert(entry, i);
2034            }
2035        }
2036        else {
2037            reason = "probe_group/group - no such entry";
2038        }
2039
2040        if (reason) {
2041            error = GB_export_errorf("Error in database format (reason: %s)", reason);
2042            selList->insert(error, (int32_t)0);
2043        }
2044
2045        selList->update();
2046    }
2047    else {
2048        error = GB_export_errorf("Can't open database '%s'", file_name);
2049        freenull(pg_global.pg_filename);
2050    }
2051
2052    free(file_name);
2053
2054    if (error) {
2055        aw_message(error);
2056    }
2057}
2058
2059static void create_probe_group_groups_window(AW_window *aww) {
2060    AW_root *aw_root = aww->get_root();
2061    GBDATA  *gb_main = pg_global.ntw->gb_main;
2062
2063    if (pg_global.pg_groups_window==0) { // window was not created yet
2064        AW_window_simple *aws = new AW_window_simple;
2065
2066        aws->init(aw_root, "PG_RESULT_SELECTION", "Probe group results");
2067        aws->load_xfig("pg_select.fig");
2068
2069        aws->at("close");
2070        aws->callback((AW_CB0)AW_POPDOWN);
2071        aws->create_button("CLOSE", "CLOSE", "C");
2072
2073        aws->at("help");
2074        aws->callback(makeHelpCallback(""));
2075        aws->create_button("HELP", "HELP");
2076
2077        create_probe_group_result_sel_box(aw_root, aws, gb_main);
2078
2079        pg_global.pg_groups_window = aws;
2080    }
2081    else { // window already created -> refresh selection box
2082        create_probe_group_result_sel_box(aw_root, pg_global.pg_groups_window, gb_main);
2083    }
2084
2085    pg_global.pg_groups_window->show();
2086}
2087
2088AW_window *create_probe_group_result_window(AW_root *awr, AWT_canvas *ntw) {
2089    freenull(pg_global.awar_pg_result_filename);
2090    pg_global.ntw = ntw;
2091
2092    return awt_create_load_box(awr, "Load", "arb_probe_group result", ".", "arb",
2093                               &pg_global.awar_pg_result_filename,
2094                               makeWindowCallback(create_probe_group_groups_window));
2095}
2096
Note: See TracBrowser for help on using the repository browser.