source: tags/ms_r18q1/SECEDIT/SEC_db.cxx

Last change on this file was 16766, checked in by westram, 6 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.0 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : SEC_db.cxx                                        //
4//   Purpose   : db interface                                      //
5//                                                                 //
6//   Coded by Ralf Westram (coder@reallysoft.de) in August 2007    //
7//   Institute of Microbiology (Technical University Munich)       //
8//   http://www.arb-home.de/                                       //
9//                                                                 //
10// =============================================================== //
11
12#include "SEC_graphic.hxx"
13#include "SEC_root.hxx"
14#include "SEC_bonddef.hxx"
15#include "SEC_toggle.hxx"
16
17#include <aw_awars.hxx>
18#include <aw_file.hxx>
19#include <aw_msg.hxx>
20#include <aw_root.hxx>
21#include <ed4_extern.hxx>
22#include <arbdbt.h>
23#include <ad_cb.h>
24
25#include <arb_defs.h>
26
27using namespace std;
28
29// -----------------------------------
30//      member function callbacks
31
32typedef void (SEC_db_interface::*interface_cb)(const SEC_dbcb *);
33
34struct SEC_dbcb {
35    SEC_db_interface *instance;
36    interface_cb      member_fun;
37
38    SEC_dbcb(SEC_db_interface *db, interface_cb cb) : instance(db), member_fun(cb) {}
39    void call() const { (instance->*member_fun)(this); }
40};
41
42static void sec_dbcb(UNFIXED, const SEC_dbcb *cb) {
43    cb->call();
44}
45
46// ----------------------
47//      SEC_seq_data
48
49SEC_seq_data::SEC_seq_data(GBDATA *gb_item, const char *aliname, const SEC_dbcb *cb) {
50    gb_name   = GB_search(gb_item, "name", GB_FIND);
51    gb_data   = GBT_find_sequence(gb_item, aliname);
52    change_cb = cb;
53    len       = GB_read_string_count(gb_data);
54    Data      = GB_read_string(gb_data);
55
56    if (gb_name) GB_add_callback(gb_name, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(sec_dbcb, change_cb));
57    if (gb_data) GB_add_callback(gb_data, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(sec_dbcb, change_cb));
58}
59
60SEC_seq_data::~SEC_seq_data() {
61    if (gb_name) GB_remove_callback(gb_name, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(sec_dbcb, change_cb));
62    if (gb_data) GB_remove_callback(gb_data, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(sec_dbcb, change_cb));
63    free(Data);
64}
65
66// -------------------
67//      pair defs
68
69#define AWAR_PAIRS(type) AWAR_SECEDIT_##type##_PAIRS
70#define AWAR_PCHAR(type) AWAR_SECEDIT_##type##_PAIR_CHAR
71
72struct PairDefinition {
73    const char *awar_pairs;
74    const char *awar_pairchar;
75    const char *default_pairs;
76    const char *default_pairchar;
77};
78
79#define PAIR_TYPES 5
80static PairDefinition pairdef[PAIR_TYPES] = {
81    { AWAR_PAIRS(STRONG), AWAR_PCHAR(STRONG), "GC AU AT",                   "-" },
82    { AWAR_PAIRS(NORMAL), AWAR_PCHAR(NORMAL), "GU GT",                      "." },
83    { AWAR_PAIRS(WEAK),   AWAR_PCHAR(WEAK),   "GA",                         "o" },
84    { AWAR_PAIRS(NO),     AWAR_PCHAR(NO),     "AA AC CC CU CT GG UU TT TU", ""  },
85    { AWAR_PAIRS(USER),   AWAR_PCHAR(USER),   "",                           ""  },
86};
87
88GB_ERROR SEC_bond_def::update(AW_root *aw_root, const char *changed_awar_name) {
89    GB_ERROR error = NULp;
90
91    if (changed_awar_name) {
92        int changed_pair_idx = -1;
93        for (int i = 0; i<PAIR_TYPES; ++i) {
94            if (strcmp(changed_awar_name, pairdef[i].awar_pairs) == 0) {
95                changed_pair_idx = i;
96                break;
97            }
98        }
99
100        sec_assert(changed_pair_idx != -1);
101
102        if (changed_pair_idx != -1) {
103            char *content = aw_root->awar(changed_awar_name)->read_string();
104
105            for (int i = 0; i<PAIR_TYPES; ++i) {
106                if (i != changed_pair_idx) { // correct other pair strings
107                    clear();
108                    AW_awar *awar = aw_root->awar(pairdef[i].awar_pairs);
109
110                    char *oldP = awar->read_string();
111
112                    insert(oldP, '#');
113                    insert(content, ' ');
114
115                    char *newP = get_pair_string('#');
116
117                    if (strcmp(oldP, newP) != 0) awar->write_string(newP);
118
119                    free(newP);
120                    free(oldP);
121                }
122            }
123            free(content);
124        }
125    }
126
127    clear();
128    for (int i = 0; !error && i<PAIR_TYPES; ++i) {
129        char *pairs    = aw_root->awar(pairdef[i].awar_pairs)->read_string();
130        char *pairchar = aw_root->awar(pairdef[i].awar_pairchar)->read_string();
131
132        error = insert(pairs, pairchar[0]);
133
134        free(pairchar);
135        free(pairs);
136    }
137
138    return error;
139}
140
141static void pair_def_changed_cb(AW_root *aw_root, SEC_db_interface *db, const char *awar_name) {
142    AWT_auto_refresh allowed_on(db->canvas());
143    GB_ERROR err = db->bonds()->update(aw_root, awar_name);
144    if (err) aw_message(err);
145    db->canvas()->request_refresh();
146}
147
148static void bind_bonddef_awars(SEC_db_interface *db) {
149    AW_root *aw_root = db->awroot();
150
151    for (int i = 0; i<PAIR_TYPES; ++i) {
152        PairDefinition& pd = pairdef[i];
153        aw_root->awar(pd.awar_pairs)   ->add_callback(makeRootCallback(pair_def_changed_cb, db, pd.awar_pairs));
154        aw_root->awar(pd.awar_pairchar)->add_callback(makeRootCallback(pair_def_changed_cb, db, (const char *)NULp));
155    }
156
157    pair_def_changed_cb(aw_root, db, NULp);
158}
159
160// --------------------------------------------------------------------------------
161
162void SEC_displayParams::reread(AW_root *aw_root, const ED4_plugin_host& host) {
163    show_helixNrs            = aw_root->awar(AWAR_SECEDIT_SHOW_HELIX_NRS)->read_int();
164    distance_between_strands = aw_root->awar(AWAR_SECEDIT_DIST_BETW_STRANDS)->read_float();
165    show_bonds               = (ShowBonds)aw_root->awar(AWAR_SECEDIT_SHOW_BONDS)->read_int();
166    show_curpos              = (ShowCursorPos)aw_root->awar(AWAR_SECEDIT_SHOW_CURPOS)->read_int();
167
168    hide_bases     = aw_root->awar(AWAR_SECEDIT_HIDE_BASES)->read_int();
169    show_ecoli_pos = aw_root->awar(AWAR_SECEDIT_SHOW_ECOLI_POS)->read_int();
170    display_search = aw_root->awar(AWAR_SECEDIT_DISPLAY_SEARCH)->read_int();
171    display_sai    = aw_root->awar(AWAR_SECEDIT_DISPLAY_SAI)->read_int() && host.SAIs_visualized();
172
173    show_strSkeleton   = aw_root->awar(AWAR_SECEDIT_SHOW_STR_SKELETON)->read_int();
174    skeleton_thickness = aw_root->awar(AWAR_SECEDIT_SKELETON_THICKNESS)->read_int();
175    bond_thickness     = aw_root->awar(AWAR_SECEDIT_BOND_THICKNESS)->read_int();
176
177    edit_rightward = aw_root->awar(AWAR_EDIT_RIGHTWARD)->read_int();
178
179#if defined(DEBUG)
180    show_debug = aw_root->awar(AWAR_SECEDIT_SHOW_DEBUG)->read_int();
181#endif // DEBUG
182}
183
184// --------------------------
185//      SEC_db_interface
186
187void SEC_db_interface::reload_sequence(const SEC_dbcb *cb) {
188    GB_transaction ta(gb_main);
189    AWT_auto_refresh allowed_on(scr);
190
191    char   *species_name = aw_root->awar(AWAR_SPECIES_NAME)->read_string();
192    bool    had_sequence = sequence;
193    GBDATA *gb_species   = GBT_find_species(gb_main, species_name);
194
195    delete sequence;
196    sequence = gb_species ? new SEC_seq_data(gb_species, aliname, cb) : NULp;
197    Host.announce_current_species(species_name);
198
199    if (bool(sequence) != had_sequence) scr->request_zoom_reset();
200    if (sequence) gfx->request_update(SEC_UPDATE_SHOWN_POSITIONS);
201
202    scr->request_refresh();
203
204    free(species_name);
205}
206
207void SEC_db_interface::reload_ecoli(const SEC_dbcb *cb) {
208    GB_transaction ta(gb_main);
209    AWT_auto_refresh allowed_on(scr);
210
211    delete ecoli_seq;
212    delete Ecoli;
213
214    GBDATA *gb_ecoli = GBT_find_SAI(gb_main, "ECOLI");
215    if (gb_ecoli) {
216        ecoli_seq = new SEC_seq_data(gb_ecoli, aliname, cb);
217        Ecoli = new BI_ecoli_ref;
218
219        Ecoli->init(ecoli_seq->sequence(), ecoli_seq->length());
220    }
221    else {
222        ecoli_seq = NULp;
223        Ecoli     = NULp;
224    }
225
226    gfx->request_update(SEC_UPDATE_SHOWN_POSITIONS);
227    scr->request_refresh();
228}
229
230void SEC_db_interface::reload_helix(const SEC_dbcb *cb) {
231    GB_transaction ta(gb_main);
232    AWT_auto_refresh allowed_on(scr);
233
234    delete helix_nr;    helix_nr  = NULp;
235    delete helix_pos;   helix_pos = NULp;
236    delete Helix;       Helix     = NULp;
237
238    char *helix_pos_name = GBT_get_default_helix(gb_main);
239    GBDATA *gb_helix_pos = GBT_find_SAI(gb_main, helix_pos_name);
240    if (gb_helix_pos) {
241        char   *helix_nr_name = GBT_get_default_helix_nr(gb_main);
242        GBDATA *gb_helix_nr   = GBT_find_SAI(gb_main, helix_nr_name);
243
244        if (gb_helix_nr) {
245            helix_pos = new SEC_seq_data(gb_helix_pos, aliname, cb);
246            helix_nr  = new SEC_seq_data(gb_helix_nr, aliname, cb);
247            Helix     = new BI_helix;
248
249            GB_ERROR error = Helix->initFromData(helix_nr->sequence(), helix_pos->sequence(), helix_pos->length());
250            if (error) {
251                error = ta.close(error);
252                aw_message(error);
253            }
254        }
255
256        free(helix_nr_name);
257    }
258    free(helix_pos_name);
259
260    gfx->request_update(static_cast<SEC_update_request>(SEC_UPDATE_SHOWN_POSITIONS|SEC_UPDATE_RELOAD));
261    scr->request_refresh();
262}
263
264void SEC_db_interface::update_positions(const SEC_dbcb *) {
265    AWT_auto_refresh allowed_on(scr);
266    displayBindingHelixPositions = aw_root->awar(AWAR_SECEDIT_DISPPOS_BINDING)->read_int();
267    displayEcoliPositions        = aw_root->awar(AWAR_SECEDIT_DISPPOS_ECOLI)->read_int();
268
269    gfx->sec_root->nail_cursor();
270    gfx->request_update(SEC_UPDATE_SHOWN_POSITIONS);
271    scr->request_refresh();
272}
273
274void SEC_db_interface::relayout(const SEC_dbcb *) {
275    SEC_root *root = secroot();
276    AWT_auto_refresh allowed_on(scr);
277    root->reread_display_params(awroot(), Host);
278    root->nail_cursor();
279    gfx->request_update(SEC_UPDATE_RECOUNT);
280    scr->request_refresh();
281}
282
283void SEC_db_interface::refresh(const SEC_dbcb *) {
284    SEC_root *root = secroot();
285    AWT_auto_refresh allowed_on(scr);
286    root->reread_display_params(awroot(), Host);
287    scr->request_refresh();
288}
289
290void SEC_root::set_cursor(int abspos) {
291
292    nail_cursor();
293    int nailedPos = nailedAbsPos;
294
295    cursorAbsPos = abspos;
296
297    {
298        AWT_auto_refresh allowed_on(db->canvas()); // @@@ try up-scope!
299        db->canvas()->request_refresh();
300    }
301
302    nailedAbsPos = nailedPos;
303    position_cursor(false, false);
304}
305
306void SEC_db_interface::cursor_changed(const SEC_dbcb *) {
307    SEC_root *root    = secroot();
308    int       seq_pos = bio2info(aw_root->awar_int(AWAR_CURSOR_POSITION)->read_int());
309
310    root->set_cursor(seq_pos);
311}
312
313void SEC_db_interface::alilen_changed(const SEC_dbcb *) {
314    AWT_auto_refresh allowed_on(scr);
315#if defined(WARN_TODO)
316#warning @@@reread alilen
317#warning test changing ali length!
318#endif
319    gfx->request_update(SEC_UPDATE_RELOAD);
320    scr->request_refresh();
321}
322
323// --------------------------------------------------------------------------------
324
325static const char *update_pos_awars[] = {
326    AWAR_SECEDIT_DISPPOS_BINDING,
327    AWAR_SECEDIT_DISPPOS_ECOLI,
328    NULp
329};
330
331static const char *relayout_awars[] = {
332    AWAR_SECEDIT_DIST_BETW_STRANDS,
333    NULp
334};
335
336static const char *refresh_awars[] = {
337    AWAR_SECEDIT_SHOW_HELIX_NRS,
338    AWAR_SECEDIT_SHOW_BONDS,
339    AWAR_SECEDIT_SHOW_CURPOS,
340    AWAR_SECEDIT_HIDE_BASES,
341    AWAR_SECEDIT_SHOW_ECOLI_POS,
342    AWAR_SECEDIT_DISPLAY_SEARCH,
343    AWAR_SECEDIT_DISPLAY_SAI,
344    AWAR_SECEDIT_SHOW_STR_SKELETON,
345    AWAR_SECEDIT_SKELETON_THICKNESS,
346    AWAR_SECEDIT_BOND_THICKNESS,
347    AWAR_EDIT_RIGHTWARD,
348    ED4_AWAR_SEARCH_RESULT_CHANGED,
349#if defined(DEBUG)
350    AWAR_SECEDIT_SHOW_DEBUG,
351#endif // DEBUG
352    NULp
353};
354
355void SEC_db_interface::bind_awars(const char **awars, SEC_dbcb *cb) {
356    RootCallback awarcb = makeRootCallback(sec_dbcb, cb);
357    for (int i = 0; awars[i]; ++i) {
358        aw_root->awar(awars[i])->add_callback(awarcb);
359    }
360}
361
362// --------------------------------------------------------------------------------
363
364static void create_awars(AW_root *aw_root, AW_default def) {
365    aw_root->awar_int(AWAR_SECEDIT_BASELINEWIDTH, 0, def)->set_minmax(0, 10);
366    aw_root->awar_string(AWAR_FOOTER);
367
368    {
369        char *dir = ARB_strdup(GB_path_in_arbprop("secondary_structure"));
370        AW_create_fileselection_awars(aw_root, AWAR_SECEDIT_SAVEDIR, dir, ".ass", "noname.ass");
371        free(dir);
372    }
373
374    aw_root->awar_float(AWAR_SECEDIT_DIST_BETW_STRANDS,  1, def)->set_minmax(0.01, 40);
375    aw_root->awar_int  (AWAR_SECEDIT_SKELETON_THICKNESS, 1, def)->set_minmax(1,    10);
376    aw_root->awar_int  (AWAR_SECEDIT_BOND_THICKNESS,     1, def)->set_minmax(1,    10);
377
378#if defined(DEBUG)
379    aw_root->awar_int(AWAR_SECEDIT_SHOW_DEBUG,        0,                def);
380#endif // DEBUG
381    aw_root->awar_int(AWAR_SECEDIT_SHOW_HELIX_NRS,    0,                def);
382    aw_root->awar_int(AWAR_SECEDIT_SHOW_ECOLI_POS,    0,                def);
383    aw_root->awar_int(AWAR_SECEDIT_SHOW_STR_SKELETON, 0,                def);
384    aw_root->awar_int(AWAR_SECEDIT_HIDE_BASES,        0,                def);
385    aw_root->awar_int(AWAR_SECEDIT_SHOW_BONDS,        SHOW_HELIX_BONDS, def);
386    aw_root->awar_int(AWAR_SECEDIT_SHOW_CURPOS,       SHOW_ABS_CURPOS,  def);
387    aw_root->awar_int(AWAR_SECEDIT_DISPLAY_SAI,       0,                def);
388    aw_root->awar_int(AWAR_SECEDIT_DISPLAY_SEARCH,    0,                def);
389    aw_root->awar_int(AWAR_SECEDIT_DISPPOS_BINDING,   0,                def);
390    aw_root->awar_int(AWAR_SECEDIT_DISPPOS_ECOLI,     1,                def);
391
392    for (int i = 0; i<PAIR_TYPES; ++i) {
393        PairDefinition& pd = pairdef[i];
394        aw_root->awar_string(pd.awar_pairs,    pd.default_pairs);
395        aw_root->awar_string(pd.awar_pairchar, pd.default_pairchar);
396    }
397}
398
399// --------------------------------------------------------------------------------
400
401SEC_db_interface::SEC_db_interface(SEC_graphic *Gfx, AWT_canvas *Scr, ED4_plugin_host& host_) :
402    sequence(NULp),
403    Host(host_),
404    displayEcoliPositions(false),
405    ecoli_seq(NULp),
406    Ecoli(NULp),
407    displayBindingHelixPositions(true),
408    helix_nr(NULp),
409    helix_pos(NULp),
410    Helix(NULp),
411    gfx(Gfx),
412    scr(Scr),
413    gb_main(gfx->gb_main),
414    aw_root(gfx->aw_root)
415{
416    AWT_auto_refresh allowed_on(Scr);
417    GB_transaction   ta(gb_main);
418
419    create_awars(aw_root, AW_ROOT_DEFAULT);
420
421    aliname    = GBT_get_default_alignment(gb_main);
422    sec_assert(aliname);
423    ali_length = GBT_get_alignment_len(gb_main, aliname);
424    displayPos = new bool[ali_length];
425    bonddef    = new SEC_bond_def(GBT_get_alignment_type(gb_main, aliname));
426
427    // awar and DB callbacks:
428
429    sequence_cb       = new SEC_dbcb(this, &SEC_db_interface::reload_sequence);
430    ecoli_cb          = new SEC_dbcb(this, &SEC_db_interface::reload_ecoli);
431    helix_cb          = new SEC_dbcb(this, &SEC_db_interface::reload_helix);
432    updatepos_cb      = new SEC_dbcb(this, &SEC_db_interface::update_positions);
433    relayout_cb       = new SEC_dbcb(this, &SEC_db_interface::relayout);
434    refresh_cb        = new SEC_dbcb(this, &SEC_db_interface::refresh);
435    cursorpos_cb      = new SEC_dbcb(this, &SEC_db_interface::cursor_changed);
436    alilen_changed_cb = new SEC_dbcb(this, &SEC_db_interface::alilen_changed);
437
438    aw_root->awar_string(AWAR_SPECIES_NAME,    "", gb_main)->add_callback(makeRootCallback(sec_dbcb, sequence_cb));
439    aw_root->awar_string(AWAR_CURSOR_POSITION, "", gb_main)->add_callback(makeRootCallback(sec_dbcb, cursorpos_cb));
440
441    bind_awars(update_pos_awars, updatepos_cb);
442    bind_awars(relayout_awars, relayout_cb);
443    bind_awars(refresh_awars, refresh_cb);
444
445    bind_bonddef_awars(this);
446
447    {
448        GBDATA *gb_alignment     = GBT_get_alignment(gb_main, aliname);
449        GBDATA *gb_alignment_len = GB_search(gb_alignment, "alignment_len", GB_FIND);
450        sec_assert(gb_alignment_len);
451        GB_add_callback(gb_alignment_len, GB_CB_CHANGED, makeDatabaseCallback(sec_dbcb, alilen_changed_cb));
452    }
453
454    sequence_cb->call();
455    ecoli_cb->call();
456    helix_cb->call();
457    updatepos_cb->call();
458    relayout_cb->call();
459    refresh_cb->call();
460
461    toggler = NULp;
462}
463
464SEC_db_interface::~SEC_db_interface() {
465    free(aliname);
466
467    delete [] displayPos;
468
469    delete sequence;    sequence = NULp;
470
471    delete ecoli_seq;   ecoli_seq = NULp;
472    delete Ecoli;       Ecoli     = NULp;
473
474    delete helix_nr;    helix_nr  = NULp;
475    delete helix_pos;   helix_pos = NULp;
476    delete Helix;       Helix     = NULp;
477
478    delete sequence_cb;         sequence_cb       = NULp;
479    delete ecoli_cb;            ecoli_cb          = NULp;
480    delete helix_cb;            helix_cb          = NULp;
481    delete updatepos_cb;        updatepos_cb      = NULp;
482    delete relayout_cb;         relayout_cb       = NULp;
483    delete refresh_cb;          refresh_cb        = NULp;
484    delete cursorpos_cb;        cursorpos_cb      = NULp;
485    delete alilen_changed_cb;   alilen_changed_cb = NULp;
486
487    delete toggler;     toggler = NULp;
488
489    delete bonddef;     bonddef = NULp;
490}
491
492SEC_root *SEC_db_interface::secroot() const { return gfx->sec_root; }
493
494// --------------------------------------------------------------------------------
495
496inline bool gap(char c) { return c == '-' || c == '.'; }
497
498void SEC_db_interface::update_shown_positions() {
499    shown = 0;
500
501    sec_assert(sequence && Helix);
502
503    for (size_t pos = 0; pos<ali_length; ++pos) {
504        bool isPaired = Helix->pairtype(pos) != HELIX_NONE;
505        char base     = baseAt(pos);
506
507        if (isPaired) {
508            if (displayBindingHelixPositions) {
509                displayPos[pos] = true;
510            }
511            else {
512                char oppoBase = baseAt(Helix->opposite_position(pos));
513
514                displayPos[pos] = !(gap(base) && gap(oppoBase)); // display if one side of helix has base
515            }
516        }
517        else {
518            displayPos[pos] = !gap(base);
519        }
520
521        shown += displayPos[pos];
522    }
523
524    // add hidden ecoli positions
525    if (displayEcoliPositions && ecoli_seq) {
526        for (size_t pos = 0; pos<ali_length; ++pos) {
527            if (!displayPos[pos] && !gap(ecoli_seq->data(pos))) {
528                displayPos[pos] = true;
529                shown++;
530            }
531        }
532    }
533}
534
535void SEC_db_interface::init_toggler() const {
536    if (!toggler) toggler = new SEC_structure_toggler(gb_main, aliname, gfx);
537}
538
539void SEC_root::update_shown_positions() {
540    db->update_shown_positions();
541}
542
543// --------------------------------------------------------------------------------
544
Note: See TracBrowser for help on using the repository browser.