source: branches/profile/SECEDIT/SEC_db.cxx

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