source: branches/properties/PROBE_DESIGN/SaiProbeVisualization.cxx

Last change on this file was 19349, checked in by westram, 2 years ago
  • fix mnemonics:
    • in 'Tree' menu:
      • p: was used for 'Print tree' + 'Compare topology…'
      • o: 'Sync tree scrolling..' → 'Compare topology…'
      • e: 'Beautify tree' → 'Sync tree scrolling..'
      • u: 'Mark duplicates' → 'Beautify tree'
      • k: now used for 'Mark duplicates'
      • removed 'Select tree' (also bound to tree button).
      • T: used for 'Tree admin' now (was 'Select tree')
      • i: used for (genome-only) 'Relink tree to organisms' (was 'Tree admin')
    • in 'Sequence' menu:
      • S: was used for 'Split sequences' + 'Align Sequences'.
      • l: now used for 'Align sequences'.
    • in species transfer of merge tool.
    • in properties menu of 'ARB gene map'.
    • in properties menu of 'PROBE and SAI' (most changed).
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.2 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : SaiProbeVisualization.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 <nds.h>
15#include <items.h>
16#include <awt_sel_boxes.hxx>
17#include <awt_config_manager.hxx>
18#include <aw_awars.hxx>
19#include <aw_root.hxx>
20#include <aw_preset.hxx>
21#include <aw_msg.hxx>
22#include <arbdbt.h>
23
24#include <iostream>
25#include <arb_global_defs.h>
26#include <item_sel_list.h>
27#include <gb_aci.h>
28
29
30using namespace std;
31
32#define PROBE_PREFIX_LENGTH 9
33#define PROBE_SUFFIX_LENGTH 9
34
35static saiProbeData *g_pbdata  = NULp;
36static char         *saiValues = NULp;
37
38static bool in_colorDefChanged_callback = false; // used to avoid colorDef correction
39
40#define BUFSIZE 100
41static const char *getAwarName(int awarNo) {
42    static char buf[BUFSIZE];
43
44    strcpy(buf, AWAR_SPV_SAI_COLOR);
45    (strchr(buf, 0)-1)[0] = '0'+awarNo;
46
47    return buf;
48}
49
50AW_gc_manager *SAI_graphic::init_devices(AW_window *aww, AW_device *device, AWT_canvas *scr) {
51    AW_gc_manager *gc_manager =
52        AW_manage_GC(aww,
53                     scr->get_gc_base_name(),
54                     device,
55                     SAI_GC_MAX,
56                     AW_GCM_DATA_AREA,
57                     makeGcChangedCallback(AWT_GC_changed_cb, scr),
58                     "#005500",
59                     "Selected Probe$#FF0000",
60                     "Foreground$#FFAA00",
61                     "Probe$#FFFF00",
62                     "+-COLOR 0$#FFFFFF", "-COLOR 1$#E0E0E0",
63                     "+-COLOR 2$#C0C0C0", "-COLOR 3$#A0A0A0",
64                     "+-COLOR 4$#909090", "-COLOR 5$#808080",
65                     "+-COLOR 6$#707070", "-COLOR 7$#505050",
66                     "+-COLOR 8$#404040", "-COLOR 9$#303030",
67                     NULp);
68
69    return gc_manager;
70}
71
72SAI_graphic::SAI_graphic(AW_root *aw_rooti, GBDATA *gb_maini) {
73    exports.zoom_mode = AWT_ZOOM_NEVER;
74    exports.fit_mode  = AWT_FIT_NEVER;
75
76    exports.set_standard_default_padding();
77
78    this->aw_root = aw_rooti;
79    this->gb_main = gb_maini;
80}
81
82void SAI_graphic::handle_command(AW_device *, AWT_graphic_event& event) {
83    if (event.type() == AW_Mouse_Press && event.button() != AW_BUTTON_MIDDLE) {
84        const AW_clicked_element *clicked = event.best_click();
85        if (clicked && clicked->is_text()) {
86            int         clicked_idx  = (int)clicked->cd1();
87            const char *species_name = g_pbdata->probeSpecies[clicked_idx].c_str();
88
89            aw_root->awar(AWAR_SPECIES_NAME)->write_string(species_name);
90            aw_root->awar(AWAR_SPV_SELECTED_PROBE)->write_string(species_name);
91        }
92    }
93}
94
95SAI_graphic::~SAI_graphic() {}
96
97void SAI_graphic::show(AW_device *device) {
98    paint(device);
99}
100
101static void colorDefChanged_callback(AW_root *awr, int awarNo) {
102    if (!in_colorDefChanged_callback) {
103        LocallyModify<bool> flag(in_colorDefChanged_callback, true);
104        unsigned char charUsed[256]; memset(charUsed, 255, 256);
105        {
106            for (int i=0; i<10;  i++) {
107                char *awarString_next = awr->awar_string(getAwarName(i))->read_string();
108                for (int c=0; awarString_next[c]; ++c) {
109                    charUsed[(unsigned char)awarString_next[c]] = i;
110                }
111                free(awarString_next);
112            }
113            char *awarString = awr->awar_string(getAwarName(awarNo))->read_string();
114
115            for (int c = 0; awarString[c]; ++c) {
116                charUsed[(unsigned char)awarString[c]] = awarNo;
117            }
118            free(awarString);
119
120            typedef unsigned char mystr[256];
121            mystr s[10];
122            for (int i=0; i<10; i++)  s[i][0]=0; // initializing the strings
123
124            for (int i=0; i<256; i++) {
125                int table = charUsed[i];
126                if (table != 255) {
127                    char *eos = strchr((char *)s[table], 0); // get pointer to end of string
128                    eos[0] = char(i);
129                    eos[1] = 0;
130                }
131            }
132
133            for (int i=0; i<10; i++) {
134                awr->awar_string(getAwarName(i))->write_string((char *)s[i]);
135            }
136        }
137    }
138    awr->awar(AWAR_SPV_DISP_SAI)->touch(); // refreshes the display
139}
140
141static void refreshCanvas(AW_root*, AWT_canvas *scr) {
142    // repaints the canvas
143    AWT_auto_refresh allowed_on(scr);
144    scr->request_refresh();
145}
146
147static void createSaiProbeAwars(AW_root *aw_root) {
148    // creating awars specific for the painting routine
149    aw_root->awar_int(AWAR_SPV_DISP_SAI, 0, AW_ROOT_DEFAULT); // to display SAI values
150
151    for (int i = 0; i < 10; i++) {  // initializing 10 color definition string AWARS
152       AW_awar *def_awar = aw_root->awar_string(getAwarName(i), "", AW_ROOT_DEFAULT);
153       def_awar->add_callback(makeRootCallback(colorDefChanged_callback, i));
154    }
155}
156
157static void addCallBacks(AW_root *awr, AWT_canvas *scr) {
158    // add callbacks to the awars (refresh display on change)
159    RootCallback refresh_cb = makeRootCallback(refreshCanvas, scr);
160
161    awr->awar(AWAR_SPV_DISP_SAI)      ->add_callback(refresh_cb);
162    awr->awar(AWAR_SPV_SAI_2_PROBE)   ->add_callback(refresh_cb);
163    awr->awar(AWAR_SPV_DB_FIELD_NAME) ->add_callback(refresh_cb);
164    awr->awar(AWAR_SPV_DB_FIELD_WIDTH)->add_callback(refresh_cb);
165    awr->awar(AWAR_SPV_SELECTED_PROBE)->add_callback(refresh_cb);
166    awr->awar(AWAR_SPV_ACI_COMMAND)   ->add_callback(refresh_cb);
167}
168
169static const char *translateSAItoColors(AW_root *awr, GBDATA *gb_main, int start, int end, int speciesNo) {
170    // translating SAIs to color strings
171    static int   seqBufferSize = 0;
172    static char *saiColors     = NULp;
173
174    if (start >= end) return NULp;
175
176    int seqSize = (end - start) + 1;
177
178    if (seqSize > seqBufferSize) {
179        free(saiColors);
180        seqBufferSize = seqSize;
181        ARB_alloc(saiColors, seqBufferSize);
182        ARB_alloc(saiValues, seqBufferSize); // @@@ leak?
183    }
184
185    memset(saiColors, '0'-1, seqSize);
186    memset(saiValues, '0'-1, seqSize);
187
188    GB_ERROR error     = GB_push_transaction(gb_main);
189    int      positions = 0;
190
191    if (!error) {
192        char   *saiSelected = awr->awar(AWAR_SPV_SAI_2_PROBE)->read_string();
193        GBDATA *gb_extended = GBT_find_SAI(gb_main, saiSelected);
194
195        if (gb_extended) {
196            char *alignment_name = GBT_get_default_alignment(gb_main);
197            if (!alignment_name) {
198                error = GB_await_error();
199            }
200            else {
201                GBDATA *gb_ali = GB_entry(gb_extended, alignment_name);
202                if (gb_ali) {
203                    const char *saiData      = NULp;
204                    const char *seqData      = NULp;
205                    bool        free_saiData = false;
206
207                    {
208                        GBDATA *saiSequence = GB_entry(gb_ali, "data"); // search "data" entry (normal SAI)
209                        if (saiSequence) {
210                            saiData = GB_read_char_pntr(saiSequence); // not allocated
211                        }
212                        else {
213                            saiSequence = GB_entry(gb_ali, "bits"); // search "bits" entry (binary SAI)
214                            if (saiSequence) {
215                                saiData      = GB_read_as_string(saiSequence); // allocated
216                                free_saiData = true; // free saiData below
217                            }
218                        }
219
220                        const char *species_name = g_pbdata->probeSpecies[speciesNo].c_str();
221                        GBDATA *gb_species       = GBT_find_species(gb_main, species_name);
222                        GBDATA *gb_seq_data      = GBT_find_sequence(gb_species, alignment_name);
223                        if (gb_seq_data) seqData = GB_read_char_pntr(gb_seq_data);
224                    }
225
226                    if (saiData) {
227                        char trans_table[256];
228                        {
229
230                            // @@@ FIXME: build trans_table ONCE for each refresh only (not for each translation)
231
232                            // build the translation table
233                            memset(trans_table, '0'-1, 256);
234                            for (int i = 0; i < SAI_CLR_COUNT; ++i) {
235                                char *def      = awr->awar(getAwarName(i))->read_string();
236                                int   clrRange = i + '0'; // configured values use '0' to '9' (unconfigured use '0'-1)
237
238                                for (const char *d = def; *d; ++d) {
239                                    trans_table[(unsigned char)*d] = clrRange;
240                                }
241                                free(def);
242                            }
243                        }
244
245                        // translate SAI to colors
246                        int i, j;
247                        for (i = start, j = 0;   i <= end; ++i) {
248                            if (!GAP::is_std_gap(seqData[i])) {
249                                saiColors[j] = trans_table[(unsigned char)saiData[i]];
250                                saiValues[j] = saiData[i];
251                                ++j;
252                            }
253                        }
254                        positions = j;
255                    }
256
257                    if (free_saiData) {
258                        free(const_cast<char*>(saiData)); // in this case saiData is allocated (see above)
259                    }
260                }
261                free(alignment_name);
262            }
263        }
264        free(saiSelected);
265    }
266
267    saiColors[positions] = 0;
268    saiValues[positions] = 0;
269
270    error = GB_end_transaction(gb_main, error);
271
272    aw_message_if(error);
273
274    return saiColors;
275}
276
277static int calculateEndPosition(GBDATA *gb_main, int startPos, int speciesNo, int mode, int probeLen, GB_ERROR& error) {
278    // returns -2 in case of error
279    // Note: if mode == 'PROBE_PREFIX' the result is 1 in front of last base (and so may be -1)
280
281    int endPos = -2;
282
283    error = GB_push_transaction(gb_main);
284    if (!error) {
285        char *alignment_name = GBT_get_default_alignment(gb_main);
286        if (!alignment_name) {
287            error = GB_await_error();
288        }
289        else {
290            const char *species_name = g_pbdata->probeSpecies[speciesNo].c_str();
291            GBDATA     *gb_species   = GBT_find_species(gb_main, species_name);
292            if (!gb_species) {
293                error = GBS_global_string("species '%s' not found", species_name);
294            }
295            else {
296                GBDATA *gb_seq_data = GBT_find_sequence(gb_species, alignment_name);
297                if (!gb_seq_data) {
298                    error = GBS_global_string("species '%s' has no data in alignment '%s'", species_name, alignment_name);
299                }
300                else {
301                    const char *seqData = GB_read_char_pntr(gb_seq_data);
302                    if (!seqData) {
303                        error            = GB_incur_error();
304                        if (error) error = GBS_global_string("can't read data (Reason: %s)", error);
305                        else error       = "can't read data";
306                    }
307                    else {
308                        int i        = 0;
309                        int baseCntr = 0;
310
311                        switch (mode) {
312                            case PROBE:
313                                for (i = startPos; baseCntr < probeLen; ++i) {
314                                    if (!GAP::is_std_gap(seqData[i]))
315                                        baseCntr++;
316                                }
317                                break;
318                            case PROBE_PREFIX:
319                                for (i = startPos; baseCntr < PROBE_PREFIX_LENGTH && i >= 0; --i) {
320                                    if (!GAP::is_std_gap(seqData[i]))
321                                        baseCntr++;
322                                }
323                                break;
324                            case PROBE_SUFFIX:
325                                for (i = startPos; baseCntr < PROBE_SUFFIX_LENGTH && seqData[i]; ++i) {
326                                    if (!GAP::is_std_gap(seqData[i]))
327                                        baseCntr++;
328                                }
329                                break;
330                        }
331                        endPos = i;
332                    }
333                }
334            }
335            free(alignment_name);
336        }
337    }
338    error = GB_end_transaction(gb_main, error);
339
340    return endPos;
341}
342
343// --------------------------------------------------------------------------------
344// painting routine
345
346static void paintBackgroundAndSAI (AW_device *device, size_t probeRegionLen, AW_pos pbRgX1, AW_pos pbY, AW_pos pbMaxWidth, AW_pos pbMaxHeight,
347                                   const char *saiCols, int dispSai)
348{
349    // painting background in translated colors from the chosen SAI values
350    // and also printing the values based on the options set by user
351    for (size_t j = 0; j<probeRegionLen; j++) {
352        if (saiCols[j] >= '0') {
353            device->box(saiCols[j]-'0'+SAI_GC_0, AW::FillStyle::SOLID, pbRgX1+j*pbMaxWidth, pbY-pbMaxHeight+1, pbMaxWidth, pbMaxHeight);
354        }
355        if (dispSai && saiValues[j]) {
356            char saiVal[2];
357            saiVal[0] = saiValues[j];
358            saiVal[1] = 0;
359            device->text(SAI_GC_FOREGROUND, saiVal, (pbRgX1+(j*pbMaxWidth)), pbY+pbMaxHeight, 0, AW_SCREEN);
360        }
361    }
362}
363
364// static void paintProbeInfo(AW_device *device, const char *probe_info, AW_pos x, AW_pos y, AW_pos xoff, AW_pos yoff, AW_pos maxDescent, AW_CL clientdata, int textCOLOR) {
365static void paintProbeInfo(AW_device *device, const char *probe_info, AW_pos x, AW_pos y, AW_pos xoff, AW_pos yoff, AW_pos maxDescent, int textCOLOR) {
366    char probeChar[2];
367    probeChar[1] = 0;
368
369    for (size_t j = 0; probe_info[j]; ++j) {
370        if (probe_info[j] == '=') {
371            AW_pos yl = y-maxDescent-(yoff-maxDescent)/3;
372            AW_pos xl = x+xoff*j;
373            device->line(SAI_GC_PROBE, xl, yl, xl+xoff-1, yl);
374        }
375        else {
376            probeChar[0] = probe_info[j];
377            // device->text(textCOLOR, probeChar, x+j*xoff, y-maxDescent, 0, AW_SCREEN|AW_CLICK, clientdata, 0);
378            device->text(textCOLOR, probeChar, x+j*xoff, y-maxDescent, 0, AW_SCREEN|AW_CLICK);
379        }
380    }
381}
382
383static char *GetDisplayInfo(AW_root *root, GBDATA *gb_main, const char *speciesName, size_t displayWidth, const char *default_tree_name) {
384    GB_ERROR        error       = NULp;
385    char           *displayInfo = NULp;
386    GB_transaction  ta(gb_main);
387    GBDATA         *gb_Species  = GBT_expect_species(gb_main, speciesName);
388
389    if (!gb_Species) error = GB_await_error();
390    else {
391        char *field_content = NULp;
392        {
393            const char *dbFieldName = root->awar_string(AWAR_SPV_DB_FIELD_NAME)->read_char_pntr();
394            if (strcmp(dbFieldName, NO_FIELD_SELECTED) == 0) {
395                field_content = ARB_strdup("no field, no content");
396            }
397            else {
398                GBDATA *gb_field = GB_search(gb_Species, dbFieldName, GB_FIND);
399                if (gb_field) {
400                    field_content             = GB_read_as_string(gb_field);
401                    if (!field_content) error = GB_await_error();
402                }
403                else {
404                    if (GB_have_error()) {
405                        error = GBS_global_string("Failed to retrieve field '%s' (Reason: %s)", dbFieldName, GB_await_error());
406                    }
407                    else {
408                        error = GBS_global_string("No entry '%s' in species '%s'", dbFieldName, speciesName);
409                    }
410                }
411            }
412        }
413
414        if (!error) {
415            char *aciCommand = root->awar_string(AWAR_SPV_ACI_COMMAND)->read_string();
416
417            GBL_env      env(gb_main, default_tree_name);
418            GBL_call_env callEnv(gb_Species, env);
419
420            displayInfo             = GB_command_interpreter_in_env(field_content, aciCommand, callEnv);
421            if (!displayInfo) error = GB_await_error();
422            free(aciCommand);
423        }
424
425        if (displayInfo && strlen(displayInfo)>displayWidth) displayInfo[displayWidth] = 0; // shorten result
426        free(field_content);
427    }
428
429    if (error) freedup(displayInfo, error);                // display the error
430
431    sai_assert(displayInfo);
432    return displayInfo;
433}
434
435void SAI_graphic::paint(AW_device *device) {
436    // Painting routine of the canvas based on the probe match results
437
438    double xStep_info   = 0;
439    double xStep_border = 0;
440    double xStep_target = 0;
441    double yStep        = 0;
442    double maxDescent   = 0;
443    // detect x/y step to use
444    {
445        const AW_font_limits& fgFontLim = device->get_font_limits(SAI_GC_FOREGROUND_FONT, 0);
446        const AW_font_limits& pbFontLim = device->get_font_limits(SAI_GC_PROBE_FONT, 0);
447        const AW_font_limits& hlFontLim = device->get_font_limits(SAI_GC_HIGHLIGHT_FONT, 0);
448
449        AW_font_limits target_font_limits(pbFontLim, hlFontLim);
450        AW_font_limits all_font_limits(fgFontLim, target_font_limits);
451
452        xStep_info   = fgFontLim.width;
453        xStep_border = pbFontLim.width;
454        xStep_target = target_font_limits.width;
455
456        yStep      = all_font_limits.get_height();
457        maxDescent = all_font_limits.descent;
458    }
459
460    AW_pos fgY = yStep + 10;
461    AW_pos pbY = yStep + 10;
462
463    char *saiSelected  = aw_root->awar(AWAR_SPV_SAI_2_PROBE)->read_string();
464    int   dispSai      = aw_root->awar(AWAR_SPV_DISP_SAI)->read_int();       // to display SAI below probe targets
465    int   displayWidth = aw_root->awar(AWAR_SPV_DB_FIELD_WIDTH)->read_int(); // display column width of the selected database field
466
467    {
468        char buf[1024];
469        if (strcmp(saiSelected, "")==0) sprintf(buf, "Selected SAI = Not Selected!");
470        else sprintf(buf, "Selected SAI = %s", saiSelected);
471        device->text(SAI_GC_PROBE, buf, 100, -30, 0.0, AW_SCREEN);
472    }
473
474    double yLineStep = dispSai ? yStep*2 : yStep;
475
476    if (g_pbdata) {
477        device->text(SAI_GC_PROBE,  "Species INFO", 0, 8, 0.0, AW_SCREEN);
478        if (!g_pbdata->probeSpecies.empty()) {
479            char *default_tree  = aw_root->awar(AWAR_TREE)->read_string();
480            char *selectedProbe = aw_root->awar(AWAR_SPV_SELECTED_PROBE)->read_string();
481
482            for (size_t j = 0; j < g_pbdata->probeSpecies.size(); ++j) {
483                const char *name        = g_pbdata->probeSpecies[j].c_str();
484                char       *displayInfo = GetDisplayInfo(aw_root, gb_main, name, displayWidth, default_tree);
485
486                AW_pos fgX = 0;
487
488                AW_click_cd cd(device, j);
489                if (strcmp(selectedProbe, name) == 0) {
490                    device->box(SAI_GC_FOREGROUND, AW::FillStyle::SOLID, fgX, (fgY - (yStep * 0.9)), (displayWidth * xStep_info), yStep);
491                    device->text(SAI_GC_HIGHLIGHT, displayInfo, fgX, fgY-1, 0, AW_SCREEN|AW_CLICK);
492                }
493                else {
494                    device->text(SAI_GC_FOREGROUND, displayInfo, fgX, fgY, 0, AW_SCREEN|AW_CLICK);
495                }
496                fgY += yLineStep;
497
498                free(displayInfo);
499            }
500
501            free(selectedProbe);
502            free(default_tree);
503        }
504
505        double spacer   = 4.0;
506        AW_pos lineXpos = 0;
507
508        AW_pos pbRgX1 = ((displayWidth+1) * xStep_info);
509        AW_pos pbX    = pbRgX1 + (9 * xStep_border) + spacer;
510        AW_pos pbRgX2 = pbX + (g_pbdata->getProbeTargetLen() * xStep_target) + spacer;
511
512        int  probeLen = g_pbdata->getProbeTargetLen();
513
514        device->box(SAI_GC_FOREGROUND, AW::FillStyle::SOLID, pbX, 10-yStep, (probeLen * xStep_target), yStep);
515        paintProbeInfo(device, g_pbdata->getProbeTarget(), pbX, 10, xStep_target, yStep, maxDescent, SAI_GC_HIGHLIGHT);
516        device->set_line_attributes(SAI_GC_FOREGROUND, 2, AW_SOLID);
517
518
519        ProbeMatchParser parser(g_pbdata->getProbeTarget(), g_pbdata->getHeadline());
520        if (parser.get_error()) {
521            device->text(SAI_GC_PROBE, GBS_global_string("Error: %s", parser.get_error()), pbRgX2, pbY, 0, AW_SCREEN);
522        }
523        else {
524            for (size_t i = 0;  i < g_pbdata->probeSeq.size(); ++i) { // loop over all matches
525                GB_ERROR         error;
526                ParsedProbeMatch parsed(g_pbdata->probeSeq[i].c_str(), parser);
527                AW_click_cd      cd(device, i);
528
529                if ((error = parsed.get_error())) {
530                    device->text(SAI_GC_PROBE, GBS_global_string("Error: %s", error), pbRgX2, pbY, 0, AW_SCREEN);
531                }
532                else {
533                    const char *probeRegion      = parsed.get_probe_region();
534                    sai_assert(probeRegion);
535                    char       *probeRegion_copy = ARB_strdup(probeRegion);
536
537                    const char *tok_prefix = strtok(probeRegion_copy, "-");
538                    const char *tok_infix  = tok_prefix ? strtok(NULp, "-") : NULp;
539                    const char *tok_suffix = tok_infix  ? strtok(NULp, "-") : NULp;
540
541                    if (!tok_suffix) {
542                        // handle special case where no suffix exists
543                        const char *end = strchr(probeRegion, 0);
544                        if (end>probeRegion && end[-1] == '-') tok_suffix = "";
545                    }
546
547                    const char *err = NULp;
548                    if (tok_suffix) {
549                        // --------------------
550                        // pre-probe region - 9 bases
551                        int startPos = parsed.get_position();
552                        if (parsed.get_error()) {
553                            err = GBS_global_string("Could not parse match position (Reason: %s).", parsed.get_error());
554                        }
555                        else {
556                            GB_ERROR endErr;
557                            int      endPos = calculateEndPosition(gb_main, startPos-1, i, PROBE_PREFIX, probeLen, endErr);
558                            if (endPos == -2) {
559                                err = GBS_global_string("Can't handle '%s' (%s)", g_pbdata->probeSpecies[i].c_str(), endErr);
560                            }
561                            else {
562                                sai_assert(!endErr);
563                                sai_assert(endPos >= -1); // note: -1 gets fixed in the next line
564                                endPos++; // calculateEndPosition returns 'one position in front of start'
565                                const char *saiCols = translateSAItoColors(aw_root, gb_main, endPos, startPos-1, i);
566                                if (saiCols) {
567                                    int positions = strlen(saiCols);
568                                    int skipLeft  = PROBE_PREFIX_LENGTH-positions;
569                                    sai_assert(skipLeft >= 0);
570                                    paintBackgroundAndSAI(device, positions, pbRgX1+skipLeft*xStep_border, pbY, xStep_border, yStep, saiCols, dispSai);
571                                }
572                                paintProbeInfo(device, tok_prefix, pbRgX1, pbY, xStep_border, yStep, maxDescent, SAI_GC_PROBE);
573
574                                // --------------------
575                                // probe region
576                                endPos  = calculateEndPosition(gb_main, startPos, i, PROBE, probeLen, endErr);
577                                sai_assert(endPos >= startPos);
578                                sai_assert(!endErr);
579                                saiCols = translateSAItoColors(aw_root, gb_main, startPos, endPos, i);
580
581                                paintBackgroundAndSAI(device, strlen(tok_infix), pbX, pbY, xStep_target, yStep, saiCols, dispSai);
582                                paintProbeInfo(device, tok_infix, pbX, pbY, xStep_target, yStep, maxDescent, SAI_GC_PROBE);
583
584                                // post-probe region - 9 bases
585                                size_t post_start_pos = endPos;
586
587                                endPos = calculateEndPosition(gb_main, post_start_pos, i, PROBE_SUFFIX, probeLen, endErr);
588                                sai_assert(endPos >= int(post_start_pos));
589                                sai_assert(!endErr);
590
591                                saiCols = translateSAItoColors(aw_root, gb_main, post_start_pos, endPos, i);
592                                if (saiCols) paintBackgroundAndSAI(device, strlen(tok_suffix), pbRgX2, pbY, xStep_border, yStep, saiCols, dispSai);
593                                paintProbeInfo(device, tok_suffix, pbRgX2, pbY, xStep_border, yStep, maxDescent, SAI_GC_PROBE);
594                            }
595                        }
596                    }
597                    else {
598                        err = GBS_global_string("probe-region '%s' has invalid format", probeRegion);
599                    }
600
601                    if (err) device->text(SAI_GC_PROBE, err, pbRgX2, pbY, 0, AW_SCREEN);
602                    free(probeRegion_copy);
603                }
604                pbY += yLineStep;
605            }
606        }
607        lineXpos = pbRgX2 + (9 * xStep_border);
608        device->set_line_attributes(SAI_GC_FOREGROUND, 1, AW_SOLID);
609
610        device->line(SAI_GC_FOREGROUND, 0, -20, lineXpos, -20);
611        device->line(SAI_GC_FOREGROUND, 0, pbY, lineXpos, pbY);
612
613        {
614            double vert_x1 = pbX-spacer/2;
615            double vert_x2 = pbRgX2-spacer/2;
616            device->line(SAI_GC_FOREGROUND, vert_x1, -20, vert_x1, pbY);
617            device->line(SAI_GC_FOREGROUND, vert_x2, -20, vert_x2, pbY);
618        }
619    }
620}
621
622void transferProbeData(saiProbeData *spd) {
623    // store pointer to currently used probe data
624    g_pbdata = spd;
625
626}
627
628// ---------------------------------- Creating WINDOWS ------------------------------------------------
629
630static AWT_predefined_config predefined_saiColorDefinitions[] = {
631    {
632        "*binary",
633        "Use with SAIs containing binary columns\ne.g. \'markerline\'",
634        "0='-.0=';1='';2='';3='';4='';5='';6='';7='';8='';9='1x'"
635    },
636    {
637        "*column_weights_09",
638        "Use with SAIs containing column weights (0-9)\ne.g. MAX_FREQUENCY",
639        "0='0';1='1';2='2';3='3';4='4';5='5';6='6';7='7';8='8';9='9'"
640    },
641    {
642        "*column_weights_0Z_posvar",
643        "Use with SAIs containing column weights (0-9,A-Z)\ne.g. POS_VAR_BY_PARSIMONY",
644        "0='012';1='345';2='678';3='9AB';4='CDE';5='FGH';6='IJK';7='LMN';8='OPQ';9='RST'"
645    },
646    {
647        "*sequence_data",
648        "Use with SAIs containing nucleotide sequence data",
649        "0='-.';1='';2='';3='A';4='';5='C';6='';7='G';8='';9='TU'"
650    },
651    {
652        "*helix",
653        "Use with SAI:HELIX",
654        "0='';1='';2='';3='<[';4='';5='';6='>]';7='';8='';9=''"
655    },
656    { NULp, NULp, NULp }
657};
658
659static void setup_saiColorDefs_config(AWT_config_definition& cdef) {
660    for (int i = 0; i < 10; i++) {
661        const char *awarDef = getAwarName(i);
662        cdef.add(awarDef, "",  i);
663    }
664}
665
666static AW_window *create_colorTranslationTable_window(AW_root *aw_root) { // creates color translation table window
667    // window to define color translations of selected SAI
668    static AW_window_simple *aws = NULp;
669    if (!aws) {
670        aws = new AW_window_simple;
671        aws->init(aw_root, "SAI_CTT", "Color Translation Table");
672        aws->load_xfig("probeSaiColors.fig");
673
674        aws->at("close");
675        aws->callback(AW_POPDOWN);
676        aws->create_button("CLOSE", "CLOSE", "C");
677
678        aws->at("help");
679        aws->callback(makeHelpCallback("saiProbe.hlp"));
680        aws->create_button("HELP", "HELP");
681
682        // create input fields:
683        {
684            char at_name[] = "rangex";
685            char *dig      = strchr(at_name, 0)-1;
686
687            for (int i = 0; i<SAI_CLR_COUNT; ++i) {
688                dig[0] = '0'+i;
689                aws->at(at_name);
690                aws->create_input_field(getAwarName(i), 15);
691            }
692        }
693
694        aws->at("dispSai");
695        aws->create_toggle(AWAR_SPV_DISP_SAI);
696
697        aws->at("config");
698        AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, "saveSaiColorDefs", makeConfigSetupCallback(setup_saiColorDefs_config), NULp, predefined_saiColorDefinitions);
699    }
700    return aws;
701}
702
703static AW_window *createDisplayField_window(AW_root *aw_root, GBDATA *gb_main) {
704    // window to select existing species field (simple NDS setup for PROBE/SAI-viewer)
705    static AW_window_simple *aws = NULp;
706    if (!aws) {
707        aws = new AW_window_simple;
708        aws->init(aw_root, "SELECT_DISPLAY_FIELD", "Select display field");
709        aws->load_xfig("displayField.fig");
710
711        aws->button_length(10);
712
713        aws->at("close");
714        aws->callback(AW_POPDOWN);
715        aws->create_button("CLOSE", "CLOSE", "C");
716
717        aws->at("help");
718        aws->callback(makeHelpCallback("displayField.hlp"));
719        aws->create_button("HELP", "HELP", "H");
720
721        create_itemfield_selection_button(aws, FieldSelDef(AWAR_SPV_DB_FIELD_NAME, gb_main, SPECIES_get_selector(), FIELD_FILTER_NDS, "display-field"), "dbField");
722
723        aws->at("aciSelect");
724        aws->button_length(12);
725        aws->callback(makeWindowCallback(NDS_popup_select_srtaci_window, AWAR_SPV_ACI_COMMAND));
726        aws->create_button("SELECT_ACI", "Select ACI");
727
728        aws->at("aciCmd");
729        aws->create_input_field(AWAR_SPV_ACI_COMMAND, 40);
730
731        aws->at("width");
732        aws->create_input_field(AWAR_SPV_DB_FIELD_WIDTH, 4);
733
734        aws->window_fit();
735    }
736    return aws;
737}
738
739static AW_window *createSaiColorWindow(AW_root *aw_root, AW_gc_manager *gc_manager) {
740    return AW_create_gc_window_named(aw_root, gc_manager, "SAI_COLOR_DEF2", "Probe/SAI Colors and Fonts");
741}
742
743AW_window *createSaiProbeMatchWindow(AW_root *awr, GBDATA *gb_main) {
744    // Main Window - Canvas on which the actual painting is done
745    GB_transaction ta(gb_main);
746
747    createSaiProbeAwars(awr); // creating awars for colors ( 0 to 9)
748
749    AW_window_menu *awm = new AW_window_menu;
750    awm->init(awr, "MATCH_SAI", "PROBE and SAI", 200, 300);
751
752    SAI_graphic *saiProbeGraphic = new SAI_graphic(awr, gb_main);
753    AWT_canvas  *scr             = new AWT_canvas(gb_main, awm, awm->get_window_id(), saiProbeGraphic);
754
755    AWT_auto_refresh allowed_on(scr);
756    scr->request_resize();
757
758    awm->insert_help_topic("How to Visualize SAI`s ?", "V", "saiProbe.hlp", AWM_ALL, makeHelpCallback("saiProbe.hlp"));
759
760    awm->create_menu("File", "F", AWM_ALL);
761    awm->insert_menu_topic("close", "Close", "C", "quit.hlp", AWM_ALL, AW_POPDOWN);
762
763    awm->create_menu("Properties", "P", AWM_ALL);
764    awm->insert_menu_topic("selectDispField", "Select display field",      "f", "displayField.hlp", AWM_ALL, makeCreateWindowCallback(createDisplayField_window, gb_main));
765    awm->insert_menu_topic("selectSAI",       "Select SAI",                "I", "saiProbe.hlp",     AWM_ALL, makeWindowCallback(awt_popup_SAI_selection_list, AWAR_SPV_SAI_2_PROBE, gb_main));
766    awm->insert_menu_topic("clrTransTable",   "Define Color Translations", "T", "saiProbe.hlp",     AWM_ALL, create_colorTranslationTable_window);
767    awm->insert_menu_topic("SetColors",       "Set Colors and Fonts",      "C", "color_props.hlp",  AWM_ALL, makeCreateWindowCallback(createSaiColorWindow, scr->gc_manager));
768
769    addCallBacks(awr, scr);
770
771    return awm;
772}
Note: See TracBrowser for help on using the repository browser.