source: branches/lib/SECEDIT/SEC_db.cxx

Last change on this file was 19407, checked in by westram, 2 years ago
  • reintegrates 'ali' into 'trunk'
    • use bond settings from EDIT4 in SECEDIT
    • fix refresh logic
    • refactor underlying code
  • adds: log:branches/ali@19393:19406
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.1 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 <ed4_extern.hxx>
18#include <AW_helix.hxx>
19
20#include <aw_awars.hxx>
21#include <aw_file.hxx>
22#include <aw_msg.hxx>
23#include <aw_root.hxx>
24
25#include <arbdbt.h>
26#include <ad_cb.h>
27
28#include <arb_defs.h>
29
30using namespace std;
31
32// -----------------------------------
33//      member function callbacks
34
35typedef void (SEC_db_interface::*interface_cb)(const SEC_dbcb *);
36
37struct SEC_dbcb {
38    SEC_db_interface *instance;
39    interface_cb      member_fun;
40
41    SEC_dbcb(SEC_db_interface *db, interface_cb cb) : instance(db), member_fun(cb) {}
42    void call() const { (instance->*member_fun)(this); }
43};
44
45static void sec_dbcb(UNFIXED, const SEC_dbcb *cb) {
46    cb->call();
47}
48
49// ----------------------
50//      SEC_seq_data
51
52SEC_seq_data::SEC_seq_data(GBDATA *gb_item, const char *aliname, const SEC_dbcb *cb) {
53    gb_name   = GB_search(gb_item, "name", GB_FIND);
54    gb_data   = GBT_find_sequence(gb_item, aliname);
55    change_cb = cb;
56    len       = GB_read_string_count(gb_data);
57    Data      = GB_read_string(gb_data);
58
59    if (gb_name) GB_add_callback(gb_name, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(sec_dbcb, change_cb));
60    if (gb_data) GB_add_callback(gb_data, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(sec_dbcb, change_cb));
61}
62
63SEC_seq_data::~SEC_seq_data() {
64    if (gb_name) GB_remove_callback(gb_name, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(sec_dbcb, change_cb));
65    if (gb_data) GB_remove_callback(gb_data, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(sec_dbcb, change_cb));
66    free(Data);
67}
68
69// --------------------------------------
70//      translation of helix symbols
71
72GB_ERROR SEC_bond_def::update_translation(AW_root *aw_root) {
73    const char *edit4_sym = aw_root->awar(AWAR_SECEDIT_BOND_SYMBOLS_EDIT4)->read_char_pntr();
74    const char *trans_sym = aw_root->awar(AWAR_SECEDIT_BOND_SYMBOLS_TRANS)->read_char_pntr();
75
76    return fill_translation_table(edit4_sym, trans_sym);
77}
78
79static void transl_def_changed_cb(AW_root *aw_root, SEC_db_interface *db) {
80    AWT_auto_refresh allowed_on(db->canvas());
81
82    GB_ERROR err = db->bonds()->update_translation(aw_root);
83    if (err) aw_message(err);
84
85    db->canvas()->request_refresh();
86}
87
88static void bind_transldef_awars(SEC_db_interface *db) {
89    AW_root *aw_root = db->awroot();
90
91    aw_root->awar(AWAR_SECEDIT_BOND_SYMBOLS_EDIT4)->add_callback(makeRootCallback(transl_def_changed_cb, db));
92    aw_root->awar(AWAR_SECEDIT_BOND_SYMBOLS_TRANS)->add_callback(makeRootCallback(transl_def_changed_cb, db));
93
94    transl_def_changed_cb(aw_root, db);
95}
96
97// --------------------------------------------------------------------------------
98
99void SEC_displayParams::reread(AW_root *aw_root, const ED4_plugin_host& host) {
100    show_helixNrs            = aw_root->awar(AWAR_SECEDIT_SHOW_HELIX_NRS)->read_int();
101    distance_between_strands = aw_root->awar(AWAR_SECEDIT_DIST_BETW_STRANDS)->read_float();
102    show_bonds               = (ShowBonds)aw_root->awar(AWAR_SECEDIT_SHOW_BONDS)->read_int();
103    show_curpos              = (ShowCursorPos)aw_root->awar(AWAR_SECEDIT_SHOW_CURPOS)->read_int();
104
105    hide_bases     = aw_root->awar(AWAR_SECEDIT_HIDE_BASES)->read_int();
106    show_ecoli_pos = aw_root->awar(AWAR_SECEDIT_SHOW_ECOLI_POS)->read_int();
107    display_search = aw_root->awar(AWAR_SECEDIT_DISPLAY_SEARCH)->read_int();
108    display_sai    = aw_root->awar(AWAR_SECEDIT_DISPLAY_SAI)->read_int() && host.SAIs_visualized();
109
110    show_strSkeleton   = aw_root->awar(AWAR_SECEDIT_SHOW_STR_SKELETON)->read_int();
111    skeleton_thickness = aw_root->awar(AWAR_SECEDIT_SKELETON_THICKNESS)->read_int();
112    bond_thickness     = aw_root->awar(AWAR_SECEDIT_BOND_THICKNESS)->read_int();
113
114    edit_rightward = aw_root->awar(AWAR_EDIT_RIGHTWARD)->read_int();
115
116#if defined(DEBUG)
117    show_debug = aw_root->awar(AWAR_SECEDIT_SHOW_DEBUG)->read_int();
118#endif // DEBUG
119}
120
121// --------------------------
122//      SEC_db_interface
123
124void SEC_db_interface::reload_sequence(const SEC_dbcb *cb) {
125    GB_transaction ta(gb_main);
126    AWT_auto_refresh allowed_on(scr);
127
128    char   *species_name = aw_root->awar(AWAR_SPECIES_NAME)->read_string();
129    bool    had_sequence = sequence;
130    GBDATA *gb_species   = GBT_find_species(gb_main, species_name);
131
132    delete sequence;
133    sequence = gb_species ? new SEC_seq_data(gb_species, aliname, cb) : NULp;
134    Host.announce_current_species(species_name);
135
136    if (bool(sequence) != had_sequence) scr->request_zoom_reset();
137    if (sequence) gfx->request_update(SEC_UPDATE_SHOWN_POSITIONS);
138
139    scr->request_refresh();
140
141    free(species_name);
142}
143
144void SEC_db_interface::reload_ecoli(const SEC_dbcb *cb) {
145    GB_transaction ta(gb_main);
146    AWT_auto_refresh allowed_on(scr);
147
148    delete ecoli_seq;
149    delete Ecoli;
150
151    GBDATA *gb_ecoli = GBT_find_SAI(gb_main, "ECOLI");
152    if (gb_ecoli) {
153        ecoli_seq = new SEC_seq_data(gb_ecoli, aliname, cb);
154        Ecoli = new BI_ecoli_ref;
155
156        Ecoli->init(ecoli_seq->sequence(), ecoli_seq->length());
157    }
158    else {
159        ecoli_seq = NULp;
160        Ecoli     = NULp;
161    }
162
163    gfx->request_update(SEC_UPDATE_SHOWN_POSITIONS);
164    scr->request_refresh();
165}
166
167void SEC_db_interface::reload_helix(const SEC_dbcb *cb) {
168    GB_transaction ta(gb_main);
169    AWT_auto_refresh allowed_on(scr);
170
171    delete helix_nr;    helix_nr  = NULp;
172    delete helix_pos;   helix_pos = NULp;
173    delete Helix;       Helix     = NULp;
174
175    char *helix_pos_name = GBT_get_default_helix(gb_main);
176    GBDATA *gb_helix_pos = GBT_find_SAI(gb_main, helix_pos_name);
177    if (gb_helix_pos) {
178        char   *helix_nr_name = GBT_get_default_helix_nr(gb_main);
179        GBDATA *gb_helix_nr   = GBT_find_SAI(gb_main, helix_nr_name);
180
181        if (gb_helix_nr) {
182            helix_pos = new SEC_seq_data(gb_helix_pos, aliname, cb);
183            helix_nr  = new SEC_seq_data(gb_helix_nr, aliname, cb);
184            Helix     = new BI_helix;
185
186            GB_ERROR error = Helix->initFromData(helix_nr->sequence(), helix_pos->sequence(), helix_pos->length());
187            if (error) {
188                error = ta.close(error);
189                aw_message(error);
190            }
191        }
192
193        free(helix_nr_name);
194    }
195    free(helix_pos_name);
196
197    gfx->request_update(static_cast<SEC_update_request>(SEC_UPDATE_SHOWN_POSITIONS|SEC_UPDATE_RELOAD));
198    scr->request_refresh();
199}
200
201void SEC_db_interface::update_positions(const SEC_dbcb *) {
202    AWT_auto_refresh allowed_on(scr);
203    displayBindingHelixPositions = aw_root->awar(AWAR_SECEDIT_DISPPOS_BINDING)->read_int();
204    displayEcoliPositions        = aw_root->awar(AWAR_SECEDIT_DISPPOS_ECOLI)->read_int();
205
206    gfx->sec_root->nail_cursor();
207    gfx->request_update(SEC_UPDATE_SHOWN_POSITIONS);
208    scr->request_refresh();
209}
210
211void SEC_db_interface::relayout(const SEC_dbcb *) {
212    SEC_root *root = secroot();
213    AWT_auto_refresh allowed_on(scr);
214    root->reread_display_params(awroot(), Host);
215    root->nail_cursor();
216    gfx->request_update(SEC_UPDATE_RECOUNT);
217    scr->request_refresh();
218}
219
220void SEC_db_interface::refresh(const SEC_dbcb *) {
221    SEC_root *root = secroot();
222    AWT_auto_refresh allowed_on(scr);
223    root->reread_display_params(awroot(), Host);
224    scr->request_refresh();
225}
226
227void SEC_root::set_cursor(int abspos) {
228
229    nail_cursor();
230    int nailedPos = nailedAbsPos;
231
232    cursorAbsPos = abspos;
233
234    {
235        AWT_auto_refresh allowed_on(db->canvas()); // @@@ try up-scope!
236        db->canvas()->request_refresh();
237    }
238
239    nailedAbsPos = nailedPos;
240    position_cursor(false, false);
241}
242
243void SEC_db_interface::cursor_changed(const SEC_dbcb *) {
244    SEC_root *root    = secroot();
245    int       seq_pos = bio2info(aw_root->awar_int(AWAR_CURSOR_POSITION)->read_int());
246
247    root->set_cursor(seq_pos);
248}
249
250void SEC_db_interface::alilen_changed(const SEC_dbcb *) {
251    AWT_auto_refresh allowed_on(scr);
252
253    // @@@ reread alilen. test changing ali length!
254
255    gfx->request_update(SEC_UPDATE_RELOAD);
256    scr->request_refresh();
257}
258
259// --------------------------------------------------------------------------------
260
261static const char *update_pos_awars[] = {
262    AWAR_SECEDIT_DISPPOS_BINDING,
263    AWAR_SECEDIT_DISPPOS_ECOLI,
264    NULp
265};
266
267static const char *relayout_awars[] = {
268    AWAR_SECEDIT_DIST_BETW_STRANDS,
269    NULp
270};
271
272static const char *refresh_awars[] = {
273    AWAR_SECEDIT_SHOW_HELIX_NRS,
274    AWAR_SECEDIT_SHOW_BONDS,
275    AWAR_SECEDIT_SHOW_CURPOS,
276    AWAR_SECEDIT_HIDE_BASES,
277    AWAR_SECEDIT_SHOW_ECOLI_POS,
278    AWAR_SECEDIT_DISPLAY_SEARCH,
279    AWAR_SECEDIT_DISPLAY_SAI,
280    AWAR_SECEDIT_SHOW_STR_SKELETON,
281    AWAR_SECEDIT_SKELETON_THICKNESS,
282    AWAR_SECEDIT_BOND_THICKNESS,
283    AWAR_EDIT_RIGHTWARD,
284    ED4_AWAR_SEARCH_RESULT_CHANGED,
285#if defined(DEBUG)
286    AWAR_SECEDIT_SHOW_DEBUG,
287#endif // DEBUG
288    NULp
289};
290
291void SEC_db_interface::bind_awars(const char **awars, SEC_dbcb *cb) {
292    RootCallback awarcb = makeRootCallback(sec_dbcb, cb);
293    for (int i = 0; awars[i]; ++i) {
294        aw_root->awar(awars[i])->add_callback(awarcb);
295    }
296}
297
298// --------------------------------------------------------------------------------
299
300static void create_awars(AW_root *aw_root, AW_default def) {
301    aw_root->awar_int(AWAR_SECEDIT_BASELINEWIDTH, 0, def)->set_minmax(0, 10);
302    aw_root->awar_string(AWAR_FOOTER);
303
304    {
305        char *dir = ARB_strdup(GB_path_in_arbprop("secondary_structure"));
306        AW_create_fileselection_awars(aw_root, AWAR_SECEDIT_SAVEDIR, dir, ".ass", "noname.ass");
307        free(dir);
308    }
309
310    aw_root->awar_float(AWAR_SECEDIT_DIST_BETW_STRANDS,  1, def)->set_minmax(0.01, 40);
311    aw_root->awar_int  (AWAR_SECEDIT_SKELETON_THICKNESS, 1, def)->set_minmax(1,    10);
312    aw_root->awar_int  (AWAR_SECEDIT_BOND_THICKNESS,     1, def)->set_minmax(1,    10);
313
314#if defined(DEBUG)
315    aw_root->awar_int(AWAR_SECEDIT_SHOW_DEBUG,        0,                def);
316#endif // DEBUG
317    aw_root->awar_int(AWAR_SECEDIT_SHOW_HELIX_NRS,    0,                def);
318    aw_root->awar_int(AWAR_SECEDIT_SHOW_ECOLI_POS,    0,                def);
319    aw_root->awar_int(AWAR_SECEDIT_SHOW_STR_SKELETON, 0,                def);
320    aw_root->awar_int(AWAR_SECEDIT_HIDE_BASES,        0,                def);
321    aw_root->awar_int(AWAR_SECEDIT_SHOW_BONDS,        SHOW_HELIX_BONDS, def);
322    aw_root->awar_int(AWAR_SECEDIT_SHOW_CURPOS,       SHOW_ABS_CURPOS,  def);
323    aw_root->awar_int(AWAR_SECEDIT_DISPLAY_SAI,       0,                def);
324    aw_root->awar_int(AWAR_SECEDIT_DISPLAY_SEARCH,    0,                def);
325    aw_root->awar_int(AWAR_SECEDIT_DISPPOS_BINDING,   0,                def);
326    aw_root->awar_int(AWAR_SECEDIT_DISPPOS_ECOLI,     1,                def);
327
328    aw_root->awar_string(AWAR_SECEDIT_BOND_SYMBOLS_EDIT4, "");
329    aw_root->awar_string(AWAR_SECEDIT_BOND_SYMBOLS_TRANS, "");
330}
331
332// --------------------------------------------------------------------------------
333
334SEC_db_interface::SEC_db_interface(SEC_graphic *Gfx, AWT_canvas *Scr, ED4_plugin_host& host_) :
335    sequence(NULp),
336    Host(host_),
337    displayEcoliPositions(false),
338    ecoli_seq(NULp),
339    Ecoli(NULp),
340    displayBindingHelixPositions(true),
341    helix_nr(NULp),
342    helix_pos(NULp),
343    Helix(NULp),
344    gfx(Gfx),
345    scr(Scr),
346    gb_main(gfx->gb_main),
347    aw_root(gfx->aw_root)
348{
349    AWT_auto_refresh allowed_on(Scr);
350    GB_transaction   ta(gb_main);
351
352    create_awars(aw_root, AW_ROOT_DEFAULT);
353
354    aliname = GBT_get_default_alignment(gb_main);
355    sec_assert(aliname); // ok w/o error handling here (EDIT4 has freezed a valid alignment)
356
357    ali_length = GBT_get_alignment_len(gb_main, aliname);
358    sec_assert(ali_length>0);
359
360    const AW_helix *aw_helix = Host.get_helix();
361
362    displayPos = new bool[ali_length];
363    bonddef    = new SEC_bond_def(aw_helix);
364
365    // awar and DB callbacks:
366
367    sequence_cb       = new SEC_dbcb(this, &SEC_db_interface::reload_sequence);
368    ecoli_cb          = new SEC_dbcb(this, &SEC_db_interface::reload_ecoli);
369    helix_cb          = new SEC_dbcb(this, &SEC_db_interface::reload_helix);
370    updatepos_cb      = new SEC_dbcb(this, &SEC_db_interface::update_positions);
371    relayout_cb       = new SEC_dbcb(this, &SEC_db_interface::relayout);
372    refresh_cb        = new SEC_dbcb(this, &SEC_db_interface::refresh);
373    cursorpos_cb      = new SEC_dbcb(this, &SEC_db_interface::cursor_changed);
374    alilen_changed_cb = new SEC_dbcb(this, &SEC_db_interface::alilen_changed);
375
376    aw_root->awar_string(AWAR_SPECIES_NAME,    "", gb_main)->add_callback(makeRootCallback(sec_dbcb, sequence_cb));
377    aw_root->awar_string(AWAR_CURSOR_POSITION, "", gb_main)->add_callback(makeRootCallback(sec_dbcb, cursorpos_cb));
378
379    bind_awars(update_pos_awars, updatepos_cb);
380    bind_awars(relayout_awars, relayout_cb);
381    bind_awars(refresh_awars, refresh_cb);
382
383    bind_transldef_awars(this);
384
385    {
386        GBDATA *gb_alignment = GBT_get_alignment(gb_main, aliname);
387        sec_assert(gb_alignment);
388
389        GBDATA *gb_alignment_len = GB_search(gb_alignment, "alignment_len", GB_FIND);
390        sec_assert(gb_alignment_len);
391
392        GB_add_callback(gb_alignment_len, GB_CB_CHANGED, makeDatabaseCallback(sec_dbcb, alilen_changed_cb));
393    }
394
395    sequence_cb->call();
396    ecoli_cb->call();
397    helix_cb->call();
398    updatepos_cb->call();
399    relayout_cb->call();
400    refresh_cb->call();
401
402    // refresh secedit display whenever helix settings in edit4 are changed:
403    aw_helix->add_callback(makeRootCallback(sec_dbcb, refresh_cb));
404
405    toggler = NULp;
406}
407
408SEC_db_interface::~SEC_db_interface() {
409    free(aliname);
410
411    delete [] displayPos;
412
413    delete sequence;    sequence = NULp;
414
415    delete ecoli_seq;   ecoli_seq = NULp;
416    delete Ecoli;       Ecoli     = NULp;
417
418    delete helix_nr;    helix_nr  = NULp;
419    delete helix_pos;   helix_pos = NULp;
420    delete Helix;       Helix     = NULp;
421
422    delete sequence_cb;         sequence_cb       = NULp;
423    delete ecoli_cb;            ecoli_cb          = NULp;
424    delete helix_cb;            helix_cb          = NULp;
425    delete updatepos_cb;        updatepos_cb      = NULp;
426    delete relayout_cb;         relayout_cb       = NULp;
427    delete refresh_cb;          refresh_cb        = NULp;
428    delete cursorpos_cb;        cursorpos_cb      = NULp;
429    delete alilen_changed_cb;   alilen_changed_cb = NULp;
430
431    delete toggler;     toggler = NULp;
432
433    delete bonddef;     bonddef = NULp;
434}
435
436SEC_root *SEC_db_interface::secroot() const { return gfx->sec_root; }
437
438// --------------------------------------------------------------------------------
439
440void SEC_db_interface::update_shown_positions() {
441    shown = 0;
442
443    sec_assert(sequence && Helix);
444
445    for (size_t pos = 0; pos<ali_length; ++pos) {
446        char base = baseAt(pos);
447
448        if (Helix->is_pairpos(pos)) {
449            if (displayBindingHelixPositions) {
450                displayPos[pos] = true;
451            }
452            else {
453                char oppoBase = baseAt(Helix->opposite_position(pos));
454                displayPos[pos] = !(SEC_is_gap(base) && SEC_is_gap(oppoBase)); // display if one side of helix has base
455            }
456        }
457        else {
458            displayPos[pos] = !SEC_is_gap(base);
459        }
460
461        shown += displayPos[pos];
462    }
463
464    // add hidden ecoli positions
465    if (displayEcoliPositions && ecoli_seq) {
466        for (size_t pos = 0; pos<ali_length; ++pos) {
467            if (!displayPos[pos] && !SEC_is_gap(ecoli_seq->data(pos))) {
468                displayPos[pos] = true;
469                shown++;
470            }
471        }
472    }
473}
474
475void SEC_db_interface::init_toggler() const {
476    if (!toggler) toggler = new SEC_structure_toggler(gb_main, aliname, gfx);
477}
478
479void SEC_root::update_shown_positions() {
480    db->update_shown_positions();
481}
482
483// --------------------------------------------------------------------------------
484
Note: See TracBrowser for help on using the repository browser.