source: branches/lib/EDIT4/graph_aligner_gui.cxx

Last change on this file was 19549, checked in by westram, 5 weeks ago
  • reintegrates 'sync' into 'trunk'
    • fixes #869
      • introduces synchronisation of external commands via DB
      • macros now wait for these external commands to finish ⇒ macro can continue with results
  • adds: log:branches/sync@19535:19548
File size: 34.5 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : graph_aligner_gui.cxx                             //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Coded by Elmar Pruesse in October 2008                        //
7//   Institute of Microbiology (Technical University Munich)       //
8//   http://www.arb-home.de/                                       //
9//                                                                 //
10// =============================================================== //
11
12#include "graph_aligner_gui.hxx"
13
14#include "ed4_defs.hxx"
15
16// need to use AlignDataAccess defined here to get selected species
17#include <fast_aligner.hxx>
18
19#include <aw_awars.hxx>
20#include <aw_global_awars.hxx>
21#include <aw_msg.hxx>
22#include <aw_root.hxx>
23#include <awt_sel_boxes.hxx>
24#include <awt_config_manager.hxx>
25#include <xcmd.hxx>
26#include <servercntrl.h>
27#include <PT_com.h>
28#include <client.h>
29#include <arbdbt.h>
30#include <arb_strbuf.h>
31#include <arb_misc.h>
32#include <arb_file.h>
33
34#include <sys/types.h>
35#include <sys/wait.h>
36
37#include <unistd.h>
38
39#include <string>
40#include <sstream>
41#include <iostream>
42#include <vector>
43
44using std::cerr;
45using std::cout;
46using std::endl;
47
48#define ga_assert(cond) arb_assert(cond)
49
50#define GA_AWAR_ROOT "sina/"
51#define GA_AWAR_TEMP "tmp/" GA_AWAR_ROOT
52
53#define GA_AWAR_CMD            GA_AWAR_ROOT "cmd"
54#define GA_AWAR_TGT            GA_AWAR_ROOT "target"
55#define GA_AWAR_SAI            GA_AWAR_ROOT "sai"
56#define GA_AWAR_ALIGNMENT      GA_AWAR_ROOT "alignment"
57#define GA_AWAR_PROTECTION     GA_AWAR_ROOT "protection"
58#define GA_AWAR_TURN_CHECK     GA_AWAR_ROOT "turncheck"
59#define GA_AWAR_REALIGN        GA_AWAR_ROOT "realign"
60#define GA_AWAR_MATCH_SCORE    GA_AWAR_ROOT "match_score"
61#define GA_AWAR_MISMATCH_SCORE GA_AWAR_ROOT "mismatch_score"
62#define GA_AWAR_GAP_PEN        GA_AWAR_ROOT "gap_pen"
63#define GA_AWAR_GAP_EXT        GA_AWAR_ROOT "gap_ext"
64#define GA_AWAR_ADVANCED       GA_AWAR_ROOT "advanced"
65#define GA_AWAR_FS_MIN         GA_AWAR_ROOT "fs_min"
66#define GA_AWAR_FS_MAX         GA_AWAR_ROOT "fs_max"
67#define GA_AWAR_FS_MSC         GA_AWAR_ROOT "fs_msc"
68#define GA_AWAR_MIN_FULL       GA_AWAR_ROOT "min_full"
69#define GA_AWAR_FULL_MINLEN    GA_AWAR_ROOT "full_minlen"
70#define GA_AWAR_OVERHANG       GA_AWAR_ROOT "overhang"
71#define GA_AWAR_THREADS        GA_AWAR_ROOT "threads"
72#define GA_AWAR_QSIZE          GA_AWAR_ROOT "qsize"
73#define GA_AWAR_KMER_LEN       GA_AWAR_ROOT "kmer_len"
74#define GA_AWAR_KMER_MM        GA_AWAR_ROOT "kmer_mm"
75#define GA_AWAR_MIN_LEN        GA_AWAR_ROOT "min_len"
76#define GA_AWAR_WEIGHT         GA_AWAR_ROOT "weight"
77#define GA_AWAR_INSERT         GA_AWAR_ROOT "insert"
78#define GA_AWAR_LOWERCASE      GA_AWAR_ROOT "lowercase"
79#define GA_AWAR_AUTOFILTER     GA_AWAR_ROOT "autofilter"
80#define GA_AWAR_KMER_NOREL     GA_AWAR_ROOT "kmer_norel"
81#define GA_AWAR_KMER_NOFAST    GA_AWAR_ROOT "kmer_nofast"
82#define GA_AWAR_SHOW_DIST      GA_AWAR_ROOT "show_dist"
83#define GA_AWAR_SHOW_DIFF      GA_AWAR_ROOT "show_diff"
84#define GA_AWAR_COLOR          GA_AWAR_ROOT "color"
85#define GA_AWAR_GENE_START     GA_AWAR_ROOT "gene_start"
86#define GA_AWAR_GENE_END       GA_AWAR_ROOT "gene_end"
87#define GA_AWAR_FS_COVER_GENE  GA_AWAR_ROOT "fs_cover_gene"
88#define GA_AWAR_USED_RELS      GA_AWAR_ROOT "write_used_rels"
89#define GA_AWAR_CALC_IDENTITY  GA_AWAR_ROOT "calc_idty"
90#define GA_AWAR_NOWARN_START   GA_AWAR_ROOT "nowarn_start"
91#define GA_AWAR_REFDB_MODE     GA_AWAR_ROOT "refdb_mode"
92#define GA_AWAR_REFDB          GA_AWAR_ROOT "refdb"
93#define GA_AWAR_REFDB_SELECT   GA_AWAR_TEMP "refdb"
94
95enum RefDbMode {
96    REF_EXPLICIT,  // use explicitly specified database
97    REF_LAST_SAVE, // use last saved state of loaded database
98    REF_CURRENT,   // use current state of loaded database
99};
100
101static void refDbModeChanged_cb(AW_root *root) {
102    RefDbMode  mode       = RefDbMode(root->awar(GA_AWAR_REFDB_MODE)->read_int());
103    AW_awar   *awar_refdb = root->awar(GA_AWAR_REFDB);
104
105    switch (mode) {
106        case REF_EXPLICIT: {
107            const char *refdb = awar_refdb->read_char_pntr();
108            if (!GB_is_readablefile(refdb)) {
109                const char *refdb_sel = root->awar(GA_AWAR_REFDB_SELECT)->read_char_pntr();
110                if (GB_is_readablefile(refdb_sel)) {
111                    awar_refdb->write_string(refdb_sel);
112                }
113                else {
114                    aw_message("Please select a reference database");
115                }
116            }
117            break;
118        }
119        case REF_LAST_SAVE: {
120            const char *db_name = root->awar(AWAR_SAVED_DB_PATH)->read_char_pntr();
121            if (db_name[0] == 0) { // happens when editor runs standalone
122                aw_message("Failed to detect name of current database - please select manually");
123            }
124            awar_refdb->write_string(db_name);
125            break;
126        }
127        case REF_CURRENT: {
128            awar_refdb->write_string(":");
129            break;
130        }
131    }
132}
133
134static void newRefDbSelected_cb(AW_root *root) {
135    const char *refdb_sel = root->awar(GA_AWAR_REFDB_SELECT)->read_char_pntr();
136
137    if (GB_is_readablefile(refdb_sel)) {
138        root->awar(GA_AWAR_REFDB_MODE)->write_int(REF_EXPLICIT);
139        root->awar(GA_AWAR_REFDB)->write_string(refdb_sel);
140    }
141    else {
142        root->awar(GA_AWAR_REFDB_MODE)->write_int(REF_CURRENT);
143    }
144}
145
146void create_sina_variables(AW_root *root, AW_default db1) {
147    const char *sinaCmd = "arb_sina.sh";
148    root->awar_string(GA_AWAR_CMD,            sinaCmd,  db1);
149    root->awar_int   (GA_AWAR_TGT,            2,        db1);
150    root->awar_int   (AWAR_PT_SERVER,         0,        db1);
151    root->awar_string(GA_AWAR_SAI,            "",       db1);
152    root->awar_int   (GA_AWAR_PROTECTION,     0,        db1);
153    root->awar_int   (GA_AWAR_TURN_CHECK,     1,        db1);
154    root->awar_int   (GA_AWAR_REALIGN,        1,        db1);
155    root->awar_float (GA_AWAR_GAP_PEN,        5.0,      db1);
156    root->awar_float (GA_AWAR_GAP_EXT,        2.0,      db1);
157    root->awar_float (GA_AWAR_MATCH_SCORE,    2.0,      db1);
158    root->awar_float (GA_AWAR_MISMATCH_SCORE, -1.0,     db1);
159    root->awar_int   (GA_AWAR_ADVANCED,       0,        db1);
160    root->awar_int   (GA_AWAR_FS_MIN,         40,       db1);
161    root->awar_int   (GA_AWAR_FS_MAX,         40,       db1);
162    root->awar_float (GA_AWAR_FS_MSC,         .7,       db1);
163    root->awar_int   (GA_AWAR_MIN_FULL,       1,        db1);
164    root->awar_int   (GA_AWAR_FULL_MINLEN,    1400,     db1);
165    root->awar_string(GA_AWAR_OVERHANG,       "attach", db1);
166    root->awar_int   (GA_AWAR_THREADS,        1,        db1);
167    root->awar_int   (GA_AWAR_QSIZE,          1,        db1);
168    root->awar_int   (GA_AWAR_KMER_LEN,       10,       db1);
169    root->awar_int   (GA_AWAR_KMER_MM,        0,        db1);
170    root->awar_int   (GA_AWAR_MIN_LEN,        150,      db1);
171    root->awar_float (GA_AWAR_WEIGHT,         1,        db1);
172    root->awar_string(GA_AWAR_INSERT,         "shift",  db1);
173    root->awar_string(GA_AWAR_LOWERCASE,      "none",   db1);
174    root->awar_string(GA_AWAR_AUTOFILTER,     "",       db1);
175    root->awar_int   (GA_AWAR_KMER_NOREL,     0,        db1);
176    root->awar_int   (GA_AWAR_KMER_NOFAST,    0,        db1);
177    root->awar_int   (GA_AWAR_SHOW_DIST,      0,        db1);
178    root->awar_int   (GA_AWAR_SHOW_DIFF,      0,        db1);
179    root->awar_int   (GA_AWAR_COLOR,          1,        db1);
180    root->awar_int   (GA_AWAR_GENE_START,     0,        db1);
181    root->awar_int   (GA_AWAR_GENE_END,       0,        db1);
182    root->awar_int   (GA_AWAR_FS_COVER_GENE,  0,        db1);
183    root->awar_int   (GA_AWAR_USED_RELS,      0,        db1);
184    root->awar_int   (GA_AWAR_CALC_IDENTITY,  0,        db1);
185    root->awar_int   (GA_AWAR_NOWARN_START,   0,        db1);
186
187    AW_awar *awar_mode = root->awar_int     (GA_AWAR_REFDB_MODE,   REF_CURRENT, db1);
188    root->awar_string                       (GA_AWAR_REFDB,        ":",         db1);
189    AW_awar *awar_select = root->awar_string(GA_AWAR_REFDB_SELECT, "",          db1);
190
191    awar_mode->add_callback(makeRootCallback(refDbModeChanged_cb));
192    awar_select->add_callback(makeRootCallback(newRefDbSelected_cb));
193}
194
195enum SinaArbInterfaceVersion {
196    ARB_5_99,
197    ARB_7_1,
198};
199const SinaArbInterfaceVersion NO_INTERFACE = SinaArbInterfaceVersion(-1);
200
201struct sina_arb_interface_def {
202    SinaArbInterfaceVersion  version;
203    const char              *id; // as define by SINA
204};
205
206static sina_arb_interface_def supported_sina_versions[] = {
207    // order matters: first supported version will be used.
208
209    { ARB_7_1, "ARB7.1" },   // only defined in patched version delivered with arb
210    { ARB_5_99, "ARB5.99" }, // supported at least by sina 1.3 up to 1.7.2
211
212    { NO_INTERFACE, "<none>" }, // version=sentinel
213};
214
215static const char *get_interface_id(SinaArbInterfaceVersion version) {
216    for (int v = 0; ; ++v) {
217        const sina_arb_interface_def& sina_interface = supported_sina_versions[v];
218        if (sina_interface.version == version) {
219            return sina_interface.id;
220        }
221    }
222    return get_interface_id(NO_INTERFACE);
223}
224
225static SinaArbInterfaceVersion used_sina_interface = NO_INTERFACE;
226
227static GB_ERROR detect_sina_version(AW_root *awr) {
228    const char  *sinaName          = awr->awar(GA_AWAR_CMD)->read_char_pntr();
229    char        *sina              = ARB_executable(sinaName, GB_getenv("PATH"));
230    const char  *fail_reason       = NULp;
231    std::string  tested_interfaces = "";
232
233    used_sina_interface = NO_INTERFACE;
234
235    if (sina) {
236        if (ARB_path_contains_unwanted_chars(sina)) {
237            char *description = GBS_global_string_copy("the sina executable derived from\n"
238                                                       "- gui property '%s' and\n"
239                                                       "- environment variable PATH", sinaName);
240            ARB_warn_about_unwanted_chars(sina, description);
241            free(description);
242        }
243
244        for (int v = 0; ; ++v) {
245            const sina_arb_interface_def& sina_interface = supported_sina_versions[v];
246
247            if (sina_interface.version == NO_INTERFACE) {
248                if (fail_reason) fail_reason = GBS_global_string("%s (this ARB supports these interface versions: %s)", fail_reason, tested_interfaces.c_str());
249                break;
250            }
251
252            int exitstatus = system(GBS_global_string("%s --has-cli-vers %s", sina, sina_interface.id));
253            exitstatus     = WEXITSTATUS(exitstatus);
254
255            if (exitstatus == EXIT_FAILURE) {
256                fail_reason = "Incompatible SINA and ARB versions";
257
258                if (!tested_interfaces.empty()) tested_interfaces += ' ';
259                tested_interfaces                                 += sina_interface.id;
260            }
261            else {
262                if (exitstatus == EXIT_SUCCESS) {
263                    used_sina_interface = sina_interface.version;
264                    fail_reason         = NULp;
265
266                    fprintf(stdout, "Using SINA-ARB interface version '%s'%s\n", sina_interface.id, v>0 ? " (old)" : "");
267                }
268                else {
269                    fail_reason = GBS_global_string("Could not execute SINA binary '%s' (exitstatus was %i)",
270                                                    sinaName, exitstatus);
271                }
272                break; // either found compatible version or failed completely -> stop
273            }
274        }
275
276        free(sina);
277    }
278    else {
279        fail_reason = GBS_global_string("'%s' not found", sinaName);
280    }
281
282    return fail_reason;
283}
284
285AW_active sina_mask(AW_root *awr) {
286    GB_ERROR fail_reason = detect_sina_version(awr);
287
288    if (fail_reason) {
289        fprintf(stderr, "Note: SINA (SILVA Aligner) disabled (Reason: %s)\n", fail_reason);
290    }
291
292    return fail_reason ? AWM_DISABLED : AWM_ALL;
293}
294
295inline const char *stream2static(const std::stringstream& str) {
296    return GBS_static_string(str.str().c_str());
297}
298
299inline const char *empty_as_none(const char *sainame) {
300    // see http://bugs.arb-home.de/ticket/519
301    if (sainame && !sainame[0]) sainame = "none";
302    return sainame;
303}
304
305static void sina_start(AW_window *window, const AlignDataAccess *data_access) {
306    cerr << "Starting SINA..." << endl;
307
308    AW_root  *root     = window->get_root();
309    GB_ERROR  gb_error = NULp;
310
311    // make string from pt server selection
312    const char *pt_server = NULp;
313    {
314        int pt = root->awar(AWAR_PT_SERVER)->read_int();
315        if (pt == -1) { // do NOT use ptserver (aka "use sina internal family search")
316            if (used_sina_interface == ARB_5_99) {
317                gb_error = "internal SINA family search is not available with your SINA version";
318            }
319        }
320        else {
321            std::stringstream ptnam;
322            ptnam << "ARB_PT_SERVER" << pt;
323
324            pt_server = GBS_read_arb_tcp(ptnam.str().c_str());
325            if (!pt_server) {
326                gb_error = GBS_global_string("Unable to find definition for chosen PT-server\n(Reason: %s)", GB_await_error());
327            }
328            else {
329                const char *pt_db = pt_server + strlen(pt_server) + 1;
330                pt_db += strlen(pt_db)+3;
331
332                // start pt server if necessary
333                gb_error = arb_look_and_start_server(AISC_MAGIC_NUMBER, ptnam.str().c_str());
334                if (gb_error) {
335                    std::stringstream tmp;
336                    tmp << "Cannot contact PT server. Aborting" << endl
337                        << " ID: \"" << tmp.str().c_str()
338                        << "\" PORT: \"" << pt_server
339                        << "\" DB: \"" << pt_db  << endl
340                        << "\" GBERROR: \"" << gb_error << "\"" << endl;
341                    gb_error = stream2static(tmp);
342                }
343            }
344        }
345    }
346
347    if (!gb_error) {
348        // create temporary file
349        char* tmpfile;
350        FILE* tmpfile_F;
351        {
352            char* tmpfile_tpl = GB_unique_filename("sina_select", "tmp");
353            tmpfile_F         = GB_fopen_tempfile(tmpfile_tpl, "w", &tmpfile);
354            free(tmpfile_tpl);
355        }
356
357        if (!tmpfile_F) {
358            std::stringstream tmp;
359            tmp << "Error: Unable to create temporary file \"" << tmpfile << "\"!";
360            gb_error = stream2static(tmp);
361        }
362        else {
363            GB_remove_on_exit(tmpfile);
364            GBDATA *gb_main = data_access->gb_main;
365
366            std::vector<std::string> spec_names;
367            switch (root->awar(GA_AWAR_TGT)->read_int()) {
368                case 0: { // current
369                    char *spec_name = root->awar(AWAR_SPECIES_NAME)->read_string();
370                    if (spec_name) {
371                        fwrite(spec_name, strlen(spec_name), 1, tmpfile_F);
372                        fwrite("\n", 1, 1, tmpfile_F);
373                    }
374                    else {
375                        gb_error = "Unable to get name of currently active species";
376                    }
377                    free(spec_name);
378                    break;
379                }
380                case 1: { // selected
381                    GB_begin_transaction(gb_main);
382                    int num_selected = 0;
383                    for (GBDATA *gb_spec = data_access->get_first_selected_species(&num_selected);
384                         gb_spec;
385                         gb_spec = data_access->get_next_selected_species())
386                    {
387                        GBDATA *gbd_name = GB_find(gb_spec, "name", SEARCH_CHILD);
388                        if (gbd_name) {
389                            const char *str = GB_read_char_pntr(gbd_name);
390                            fwrite(str, strlen(str), 1, tmpfile_F);
391                            fwrite("\n", 1, 1, tmpfile_F);
392                        }
393                    }
394                    GB_commit_transaction(gb_main);
395                    break;
396                }
397                case 2: { // marked
398                    GB_begin_transaction(gb_main);
399                    for (GBDATA *gb_spec = GBT_first_marked_species(gb_main);
400                         gb_spec; gb_spec = GBT_next_marked_species(gb_spec)) {
401                        GBDATA *gbd_name = GB_find(gb_spec, "name", SEARCH_CHILD);
402                        if (gbd_name) {
403                            const char *str = GB_read_char_pntr(gbd_name);
404                            fwrite(str, strlen(str), 1, tmpfile_F);
405                            fwrite("\n", 1, 1, tmpfile_F);
406                        }
407                    }
408                    GB_commit_transaction(gb_main);
409                    break;
410                }
411            }
412            fclose(tmpfile_F);
413
414            if (!gb_error) {
415                // build command line
416                GBS_strstruct cl(2000);
417
418                cl.cat(root->awar(GA_AWAR_CMD)->read_char_pntr());
419                cl.cat(" -i :");
420
421                switch (used_sina_interface) {
422                    case ARB_5_99: cl.cat(" --ptdb :"); break;
423                    case ARB_7_1:
424                        cl.cat(" --out :");
425                        cl.cat(" --db "); cl.cat(root->awar(GA_AWAR_REFDB)->read_char_pntr());
426                        if (root->awar(GA_AWAR_NOWARN_START)->read_int()) cl.cat(" --dont-expect-start");
427                        if (root->awar(GA_AWAR_CALC_IDENTITY)->read_int()) cl.cat(" --calc-idty");
428                        cl.cat(" --default-alignment "); cl.cat(data_access->alignment_name.c_str()); // always use alignment used in editor
429                        break;
430                }
431
432                if (pt_server) {
433                    cl.cat(" --ptport ");             cl.cat(pt_server);
434                    if (used_sina_interface == ARB_7_1) {
435                        cl.cat(" --fs-engine ");      cl.cat("pt-server");
436                    }
437                }
438                else { // use sina internal search
439                    ga_assert(used_sina_interface == ARB_7_1);
440                    cl.cat(" --fs-engine ");          cl.cat("internal");
441                }
442
443                cl.cat(" --turn ");               cl.cat(root->awar(GA_AWAR_TURN_CHECK)->read_int() ? "all" : "none");
444                cl.cat(" --overhang ");           cl.cat(root->awar(GA_AWAR_OVERHANG)->read_char_pntr());
445                cl.cat(" --filter ");             cl.cat(empty_as_none(root->awar(GA_AWAR_SAI)->read_char_pntr()));
446                cl.cat(" --fs-min ");             cl.putlong(root->awar(GA_AWAR_FS_MIN)->read_int());
447                cl.cat(" --fs-msc ");             cl.putfloat(root->awar(GA_AWAR_FS_MSC)->read_float());
448                cl.cat(" --fs-max ");             cl.putlong(root->awar(GA_AWAR_FS_MAX)->read_int());
449                cl.cat(" --fs-req 1");            // hardcoded to 1 - uses stricter requirement for full-length sequences
450                cl.cat(" --fs-req-full ");        cl.putlong(root->awar(GA_AWAR_MIN_FULL)->read_int());
451                cl.cat(" --fs-full-len ");        cl.putlong(root->awar(GA_AWAR_FULL_MINLEN)->read_int());
452                cl.cat(" --fs-kmer-len ");        cl.putlong(root->awar(GA_AWAR_KMER_LEN)->read_int());
453                cl.cat(" --fs-kmer-mm ");         cl.putlong(root->awar(GA_AWAR_KMER_MM)->read_int()); // @@@ only with ptserver -> document + add 2 gui
454                cl.cat(" --fs-min-len ");         cl.putlong(root->awar(GA_AWAR_MIN_LEN)->read_int());
455                cl.cat(" --fs-weight ");          cl.putfloat(root->awar(GA_AWAR_WEIGHT)->read_float());
456                cl.cat(" --pen-gap ");            cl.putfloat(root->awar(GA_AWAR_GAP_PEN)->read_float());
457                cl.cat(" --pen-gapext ");         cl.putfloat(root->awar(GA_AWAR_GAP_EXT)->read_float());
458                cl.cat(" --match-score ");        cl.putfloat(root->awar(GA_AWAR_MATCH_SCORE)->read_float());
459                cl.cat(" --mismatch-score ");     cl.putfloat(root->awar(GA_AWAR_MISMATCH_SCORE)->read_float());
460                cl.cat(" --prot-level ");         cl.putlong(root->awar(GA_AWAR_PROTECTION)->read_int());
461                cl.cat(" --select-file ");        cl.cat(tmpfile);
462                cl.cat(" --insertion ");          cl.cat(root->awar(GA_AWAR_INSERT)->read_char_pntr());
463                cl.cat(" --lowercase ");          cl.cat(root->awar(GA_AWAR_LOWERCASE)->read_char_pntr());
464                cl.cat(" --auto-filter-field ");  cl.cat_sQuoted(root->awar(GA_AWAR_AUTOFILTER)->read_char_pntr()); // note: default value passed to sina 1.3 was 'none' (w/o quotes)
465                cl.cat(" --gene-start ");         cl.putlong(root->awar(GA_AWAR_GENE_START)->read_int());
466                cl.cat(" --gene-end ");           cl.putlong(root->awar(GA_AWAR_GENE_END)->read_int());
467                cl.cat(" --fs-cover-gene ");      cl.putlong(root->awar(GA_AWAR_FS_COVER_GENE)->read_int());
468
469
470                if (root->awar(GA_AWAR_KMER_NOREL)->read_int())  cl.cat(" --fs-kmer-norel ");
471                if (root->awar(GA_AWAR_KMER_NOFAST)->read_int()) cl.cat(" --fs-kmer-no-fast ");
472                if (root->awar(GA_AWAR_SHOW_DIST)->read_int())   cl.cat(" --show-dist ");
473                if (root->awar(GA_AWAR_SHOW_DIFF)->read_int())   cl.cat(" --show-diff ");
474                if (root->awar(GA_AWAR_COLOR)->read_int())       cl.cat(" --color");
475                if (root->awar(GA_AWAR_REALIGN)->read_int())     cl.cat(" --realign");
476                if (root->awar(GA_AWAR_USED_RELS)->read_int())   cl.cat(" --write-used-rels");
477
478                gb_error = ARB_system(cl.get_data(), XCmdType(XCMD_SERVSYNC_WAIT_ON_ERROR, gb_main));
479            }
480
481            if (!gb_error) aw_message("SINA finished aligning.");
482        }
483        free(tmpfile);
484    }
485
486    aw_message_if(gb_error);
487}
488
489
490
491static char* filter_posvar_SAI_for_ali(GBDATA *gb_extended, const char *ali_name) {
492    char   *result   = NULp;
493    char   *typePath = GBS_global_string_copy("%s/_TYPE", ali_name);
494    GBDATA *gbd      = GB_search(gb_extended, typePath, GB_FIND);
495    if (gbd) {
496        const char* type = GB_read_char_pntr(gbd);
497        if (type && strncmp("PV", type, 2) == 0) {
498            gbd    = GB_find(gb_extended, "name", SEARCH_CHILD);
499            result = GB_read_string(gbd);
500        }
501    }
502    free(typePath);
503    return result;
504}
505
506static AWT_config_mapping_def sina_config_mapping[] = {
507    // both
508    { GA_AWAR_TGT,         "target" },
509    { GA_AWAR_OVERHANG,    "overhang" },
510    { GA_AWAR_INSERT,      "insertions" },
511    { GA_AWAR_LOWERCASE,   "lowercase" },
512    { GA_AWAR_WEIGHT,      "weight" },
513    { GA_AWAR_FULL_MINLEN, "fullminlen" },
514
515    // advanced only
516    { GA_AWAR_SAI,            "sai" },
517    { GA_AWAR_AUTOFILTER,     "autofilter" },
518    { GA_AWAR_TURN_CHECK,     "turncheck" },
519    { GA_AWAR_REALIGN,        "realign" },
520    { GA_AWAR_GAP_PEN,        "gappen" },
521    { GA_AWAR_GAP_EXT,        "gapext" },
522    { GA_AWAR_MATCH_SCORE,    "matchscore" },
523    { GA_AWAR_MISMATCH_SCORE, "mismatchscore" },
524    { GA_AWAR_FS_MIN,         "fs_min" },
525    { GA_AWAR_FS_MSC,         "fs_minscore" },
526    { GA_AWAR_FS_MAX,         "fs_min" },
527    { GA_AWAR_MIN_FULL,       "minfull" },
528    { GA_AWAR_KMER_LEN,       "kmerlen" },
529    { GA_AWAR_KMER_MM,        "kmermm" },
530    { GA_AWAR_MIN_LEN,        "refminlen" },
531    { GA_AWAR_GENE_START,     "genestart" },
532    { GA_AWAR_GENE_END,       "geneend" },
533    { GA_AWAR_FS_COVER_GENE,  "fs_covergene" },
534    { GA_AWAR_USED_RELS,      "write_used_rels" },
535    { GA_AWAR_CALC_IDENTITY,  "calc_identity" },
536    { GA_AWAR_KMER_NOFAST,    "kmernofast" },
537    { GA_AWAR_KMER_NOREL,     "kmernorel" },
538
539    // both
540    { GA_AWAR_SHOW_DIFF, "showdiff" },
541    { GA_AWAR_COLOR,     "color" },
542    { GA_AWAR_SHOW_DIST, "showdist" },
543
544    { NULp, NULp }
545};
546
547static void accept_selected_ref_db(AW_window *aww, const char * const *awar_filename) {
548    AW_root *root     = aww->get_root();
549    char    *filename = root->awar(*awar_filename)->read_string();
550
551    if (GB_is_readablefile(filename)) {
552        AW_awar *awar_refdb_sel = root->awar(GA_AWAR_REFDB_SELECT);
553        awar_refdb_sel->write_string(filename);
554        aww->hide();
555    }
556
557    free(filename);
558}
559
560static AW_window *create_ref_db_selection_window(AW_root *aw_root) {
561    static char *awar_name = NULp; // do not free, bound to callback
562    return awt_create_load_box(aw_root,
563                               "Select",
564                               "SINA reference database",
565                               ".", "arb", &awar_name,
566                               makeWindowCallback(accept_selected_ref_db,  (const char*const*)&awar_name));
567}
568
569
570static void sina_select_ref_db(AW_window *aww) {
571    static AW_window *aw_ref_db_selection = NULL;
572
573    if (!aw_ref_db_selection) {
574        AW_root *root = aww->get_root();
575        aw_ref_db_selection = create_ref_db_selection_window(root);
576    }
577
578    aw_ref_db_selection->activate();
579}
580
581
582static SinaArbInterfaceVersion gui_sina_interface = NO_INTERFACE; // interface used in GUI
583
584static void sina_cmd_changed_cb(AW_root *awr) {
585    GB_ERROR fail_reason = detect_sina_version(awr);
586
587    if (fail_reason) {
588        aw_message(fail_reason);
589    }
590    else {
591        if (used_sina_interface != gui_sina_interface) {
592            aw_message("The GUI does not match the used sina version!\n"
593                       "Please save properties and restart the editor.");
594        }
595        aw_message(GBS_global_string("Using sina-arb interface '%s'", get_interface_id(used_sina_interface)));
596    }
597}
598
599static AW_window_simple* new_sina_simple(AW_root *root, const AlignDataAccess *alignData, bool adv) {
600    const int         hgap = 10;
601    AW_window_simple *aws  = new AW_window_simple;
602
603    if (gui_sina_interface == NO_INTERFACE) {
604        gui_sina_interface = used_sina_interface;
605        root->awar(GA_AWAR_CMD)->add_callback(sina_cmd_changed_cb);
606    }
607
608    aws->reset_layout("20220422");
609    aws->init(root, adv ? "XSINA" : "SINA", "SINA (SILVA Incremental Aligner)");
610
611    aws->button_length(12);
612    aws->at(10, 10);
613    aws->auto_space(5, 5);
614
615    int closex, closey; aws->get_at_position(&closex, &closey);
616
617    aws->callback(AW_POPDOWN);
618    aws->create_button("CLOSE", "CLOSE", "O");
619
620    int closex2 = aws->get_at_xposition();
621
622    if (gui_sina_interface == NO_INTERFACE) {
623        // happens when no sina detected + menu entry is triggered via macro // @@@ would be nice to globally avoid callbacks for inactive menu entries
624
625        aws->at_newline();
626        aws->label_length(0);
627        aws->label("SINA command\nError: Failed to find or identify sina version!");
628        aws->create_input_field(GA_AWAR_CMD, 20);
629
630        return aws;
631    }
632
633    aws->at_shift(10, 0);
634    aws->label_length(0);
635    aws->label("Show advanced options");
636    aws->create_toggle(GA_AWAR_ADVANCED);
637
638    bool cbInstalled = false;
639    if (!cbInstalled) {
640        root->awar(GA_AWAR_ADVANCED)->add_callback(makeRootCallback(show_sina_window, alignData));
641        cbInstalled = true;
642    }
643
644    aws->at_newline();
645    aws->at_shift(0, hgap);
646    int y_col2 = aws->get_at_yposition();
647    aws->label_length(15);
648    aws->create_toggle_field(GA_AWAR_TGT, "Align what?");
649    aws->insert_toggle("Current Species:", "C", 0);
650    aws->insert_toggle("Selected Species", "S", 1);
651    aws->insert_default_toggle("Marked Species", "M", 2);
652    aws->update_toggle_field();
653
654    aws->at_shift(0, 3);
655    aws->create_input_field(AWAR_SPECIES_NAME, 20);
656
657    aws->at_newline();
658    aws->at_shift(0, hgap);
659    aws->button_length(24);
660    if (used_sina_interface == ARB_5_99) {
661        aws->label("PT Server:");
662    }
663    else {
664        aws->label_length(20);
665        aws->label("PT Server\n"
666                   "undefined => sina kmer");
667    }
668    awt_create_PTSERVER_selection_button(aws, AWAR_PT_SERVER);
669
670    aws->label_length(0);
671
672    if (gui_sina_interface == ARB_7_1) {
673        aws->at_newline();
674        aws->create_toggle_field(GA_AWAR_REFDB_MODE, "Reference database");
675        aws->insert_toggle("Explicit as ", "E", REF_EXPLICIT);
676        aws->insert_toggle("Last saved", "s", REF_LAST_SAVE);
677        aws->insert_default_toggle("Current", "C", REF_CURRENT);
678        aws->update_toggle_field();
679
680        aws->at_shift(0, 3);
681        aws->callback(makeWindowCallback(sina_select_ref_db));
682        aws->create_autosize_button("selected", "selected", "s");
683
684        aws->at_newline();
685        aws->create_input_field(GA_AWAR_REFDB, 40);
686    }
687
688    aws->at_newline();
689    aws->label("Overhang placement");
690    aws->create_option_menu(GA_AWAR_OVERHANG);
691    aws->insert_option("keep attached", NULp, "attach");
692    aws->insert_option("move to edge",  NULp, "edge");
693    aws->insert_option("remove",        NULp, "remove");
694    aws->update_option_menu();
695
696    aws->at_newline();
697    aws->label("Handling of unmappable insertions");
698    aws->create_option_menu(GA_AWAR_INSERT);
699    aws->insert_option("Shift surrounding bases",    NULp, "shift");
700    aws->insert_option("Forbid during DP alignment", NULp, "forbid");
701    aws->insert_option("Delete bases",               NULp, "remove");
702    aws->update_option_menu();
703
704    int x_col2 = aws->get_at_xposition();
705
706    aws->at_newline();
707    aws->label("Character Case");
708    aws->create_option_menu(GA_AWAR_LOWERCASE);
709    aws->insert_option("Do not modify",                      NULp, "original");
710    aws->insert_option("Show unaligned bases as lower case", NULp, "unaligned");
711    aws->insert_option("Uppercase all",                      NULp, "none");
712    aws->update_option_menu();
713
714    aws->at_newline();
715    aws->label("Family conservation weight (0-1)");
716    aws->create_input_field(GA_AWAR_WEIGHT, 3);
717
718    aws->at_newline();
719    aws->label("Size of full-length sequences");
720    aws->create_input_field(GA_AWAR_FULL_MINLEN, 5);
721
722    aws->at_newline();
723    aws->label_length(17);
724    aws->label("Protection Level");
725    aws->create_option_menu(GA_AWAR_PROTECTION);
726    aws->insert_option("0", NULp, 0);
727    aws->insert_option("1", NULp, 1);
728    aws->insert_option("2", NULp, 2);
729    aws->insert_option("3", NULp, 3);
730    aws->insert_option("4", NULp, 4);
731    aws->insert_option("5", NULp, 5);
732    aws->insert_option("6", NULp, 6);
733    aws->update_option_menu();
734
735    aws->at_newline();
736
737    aws->label_length(21);
738    aws->label("Show changed sections");
739    aws->create_toggle(GA_AWAR_SHOW_DIFF);
740    aws->label_length(11);
741    aws->label("color bases");
742    aws->create_toggle(GA_AWAR_COLOR);
743
744    aws->at_newline();
745    aws->label_length(21);
746    aws->label("Show statistics");
747    aws->create_toggle(GA_AWAR_SHOW_DIST);
748
749    aws->at_newline();
750
751    int startx, starty; aws->get_at_position(&startx, &starty);
752
753    aws->button_length(12);
754    aws->at(closex, starty);
755    aws->callback(makeWindowCallback(sina_start, alignData));
756    aws->highlight();
757    aws->create_button("Start", "Start", "S");
758
759    aws->at(closex2+200, starty-10);
760    AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, "sina", sina_config_mapping);
761
762    if (adv) {
763        aws->at(x_col2, y_col2);
764        aws->auto_space(5, 5); // resets position for at_newline
765
766        aws->label_length(0);
767        aws->label("Pos. Var.:");
768        awt_create_SAI_selection_button(alignData->gb_main, aws, GA_AWAR_SAI, makeSaiSelectionlistFilterCallback(filter_posvar_SAI_for_ali, alignData->alignment_name.c_str()));
769
770        aws->at_newline();
771        aws->label("Field used for automatic\nfilter selection");
772        aws->create_input_field(GA_AWAR_AUTOFILTER, 20);
773
774        aws->at_newline();
775        aws->label("Turn check"); aws->create_toggle(GA_AWAR_TURN_CHECK);
776        aws->label("Realign"); aws->create_toggle(GA_AWAR_REALIGN);
777
778        aws->at_newline();
779        aws->at_shift(0, hgap);
780
781        aws->label("Gap insertion/extension penalties");
782        aws->create_input_field(GA_AWAR_GAP_PEN, 5);
783        aws->create_input_field(GA_AWAR_GAP_EXT, 5);
784
785        aws->at_newline();
786        aws->label("Match score");
787        aws->create_input_field(GA_AWAR_MATCH_SCORE, 3);
788        aws->label("Mismatch score");
789        aws->create_input_field(GA_AWAR_MISMATCH_SCORE, 3);
790
791        aws->at_newline();
792        aws->label("Family search min/min_score/max");
793        aws->create_input_field(GA_AWAR_FS_MIN, 3);
794        aws->create_input_field(GA_AWAR_FS_MSC, 3);
795        aws->create_input_field(GA_AWAR_FS_MAX, 3);
796
797        aws->at_newline();
798        aws->label("Minimal number of full length sequences");
799        aws->create_input_field(GA_AWAR_MIN_FULL, 3);
800
801        aws->at_newline();
802        aws->label("Family search oligo length / mismatches");
803        aws->create_input_field(GA_AWAR_KMER_LEN, 3);
804        aws->create_input_field(GA_AWAR_KMER_MM, 3);
805
806        aws->at_newline();
807        aws->label("Minimal reference sequence length");
808        aws->create_input_field(GA_AWAR_MIN_LEN, 5);
809
810        aws->at_newline();
811        aws->label("Alignment bounds: start");
812        aws->create_input_field(GA_AWAR_GENE_START, 6);
813        aws->label("end");
814        aws->create_input_field(GA_AWAR_GENE_END, 6);
815
816        aws->at_newline();
817        aws->label("Number of references required to touch bounds");
818        aws->create_input_field(GA_AWAR_FS_COVER_GENE, 3);
819
820        aws->at_newline();
821        aws->label("Save used references in 'used_rels'");
822        aws->create_toggle(GA_AWAR_USED_RELS);
823
824        aws->at_newline();
825        aws->label("Store highest identity in 'align_ident_slv'");
826        aws->create_toggle(GA_AWAR_CALC_IDENTITY);
827
828        aws->at_newline();
829        aws->label("Disable fast search");
830        aws->create_toggle(GA_AWAR_KMER_NOFAST);
831
832        aws->at_newline();
833        aws->label("Score search results by absolute oligo match count");
834        aws->create_toggle(GA_AWAR_KMER_NOREL);
835
836        if (gui_sina_interface == ARB_7_1) {
837            aws->at_newline();
838            aws->label("Suppress warnings about missing 'start' field");
839            aws->create_toggle(GA_AWAR_NOWARN_START);
840        }
841
842        aws->at_newline();
843        aws->label("SINA command");
844        aws->create_input_field(GA_AWAR_CMD, 20);
845    }
846
847    int winx, winy; aws->get_window_size(winx, winy);
848
849    aws->button_length(12);
850    aws->at(winx-closex2+5, closey);
851    aws->callback(makeHelpCallback("sina_main.hlp"));
852    aws->create_button("HELP", "HELP");
853
854    return aws;
855}
856
857void show_sina_window(UNFIXED, const AlignDataAccess *alignData) {
858    AW_root *root = AW_root::SINGLETON;
859
860    static AW_window_simple *ga_aws     = NULp;
861    static AW_window_simple *ga_aws_adv = NULp;
862
863    if (root->awar(GA_AWAR_ADVANCED)->read_int()) {
864        if (!ga_aws_adv) ga_aws_adv = new_sina_simple(root, alignData, true);
865        ga_aws_adv->show();
866
867        if (ga_aws) ga_aws->hide();
868    }
869    else {
870        if (!ga_aws) ga_aws = new_sina_simple(root, alignData, false);
871        ga_aws->show();
872
873        if (ga_aws_adv) ga_aws_adv->hide();
874    }
875
876    static bool refdb_mode_refreshed = false;
877    if (!refdb_mode_refreshed) {
878        AW_awar *awar_mode         = root->awar(GA_AWAR_REFDB_MODE);
879        if (awar_mode->read_int() != REF_EXPLICIT) awar_mode->touch(); // trigger callback
880        refdb_mode_refreshed       = true;
881    }
882}
883
Note: See TracBrowser for help on using the repository browser.