ARB
AW_helix.cxx
Go to the documentation of this file.
1 // ==================================================================== //
2 // //
3 // File : AW_helix.cxx //
4 // Purpose : Wrapper for BI_helix + AW-specific functions //
5 // //
6 // //
7 // Coded by Ralf Westram (coder@reallysoft.de) in December 2004 //
8 // Copyright Department of Microbiology (Technical University Munich) //
9 // //
10 // Visit our web site at: http://www.arb-home.de/ //
11 // //
12 // ==================================================================== //
13 
14 #include "AW_helix.hxx"
15 
16 #include <awt_config_manager.hxx>
17 
18 #include <aw_root.hxx>
19 #include <aw_window.hxx>
20 #include <aw_awar.hxx>
21 #include <aw_device.hxx>
22 
23 #include <arbdbt.h>
24 #include <arb_strbuf.h>
25 
26 #include <cctype>
27 
28 #define AWAR_HELIX_REFRESH "tmp/Helix/refresh" // used to trigger client refreshes
29 #define AWAR_HELIX_ENABLE "Helix/enable"
30 #define HELIX_AWAR_SYMBOL_TEMPLATE "Helix/symbols/%s"
31 #define HELIX_AWAR_PAIR_TEMPLATE "Helix/pairs/%s"
32 
34  const char *awar;
36 };
37 
39  { "Strong_Pair", HELIX_STRONG_PAIR },
40  { "Normal_Pair", HELIX_NORMAL_PAIR },
41  { "Weak_Pair", HELIX_WEAK_PAIR },
42  { "No_Pair", HELIX_NO_PAIR },
43  { "User_Pair", HELIX_USER0 },
44  { "User_Pair2", HELIX_USER1 },
45  { "User_Pair3", HELIX_USER2 },
46  { "User_Pair4", HELIX_USER3 },
47  { "User_Pair5", HELIX_USER4 },
48  { "User_Pair6", HELIX_USER5 },
49  { "Default", HELIX_DEFAULT },
50  { NULp, BI_PAIR_TYPE(-1) },
51 };
52 
53 inline const char *helix_symbol_awar(int idx) { return GBS_global_string(HELIX_AWAR_SYMBOL_TEMPLATE, helix_awars[idx].awar); }
54 inline const char *helix_pair_awar (int idx) { return GBS_global_string(HELIX_AWAR_PAIR_TEMPLATE, helix_awars[idx].awar); }
55 
56 char *AW_helix::seq_2_helix(char *sequence, char undefsymbol) const {
57  size_t size2 = strlen(sequence);
58  arb_assert(size2<=size()); // if this fails there is a sequence longer than the alignment
59  char *helix = ARB_calloc<char>(size()+1);
60  for (size_t i=0; i<size2; i++) {
61  if (is_pairpos(i)) {
62  size_t j = opposite_position(i);
63  char sym = get_symbol(sequence[i], sequence[j]);
64  helix[i] = sym == ' ' ? undefsymbol : sym;
65  }
66  else {
67  helix[i] = undefsymbol;
68  }
69  }
70  return helix;
71 }
72 
73 void AW_helix::add_callback(const RootCallback& cb) const {
74  // add client callback. triggered when helix or pair definition has changed.
75  awar_refresh->add_callback(cb);
76 }
77 
78 void AW_helix::remove_callback(const RootCallback& cb) const {
79  awar_refresh->remove_callback(cb);
80 }
81 
82 static void helix_setup_changed_cb(AW_root *aw_root, AW_helix *helix) { helix->setup_changed_cb(aw_root); }
84  enabled = aw_root->awar(AWAR_HELIX_ENABLE)->read_int();
85 
86  for (int j=0; helix_awars[j].awar; j++) {
87  int i = helix_awars[j].pair_type;
88 
91  }
92 
93  aw_root->awar(AWAR_HELIX_REFRESH)->touch(); // trigger client refreshes (EDIT4, SECEDIT, ...)
94 }
95 
96 static void helix_pairs_changed_cb(AW_root *aw_root, int changed_idx) {
97  static bool recursion = false;
98 
99  if (!recursion) {
100  AW_awar *awar_pair = aw_root->awar(helix_pair_awar(changed_idx));
101  const char *pairdef_in = awar_pair->read_char_pntr();
102  GBS_strstruct pairdef_out(strlen(pairdef_in)+2);
103 
104  {
105  LocallyModify<bool> flag(recursion, true);
106  for (int i = 0;;) {
107  while (pairdef_in[i] == ' ') ++i; // skip spaces
108  char left = toupper(pairdef_in[i++]); if (!left) break;
109 
110  if (!pairdef_out.empty()) {
111  pairdef_out.put(' ');
112  }
113  pairdef_out.put(left);
114 
115  while (pairdef_in[i] == ' ') ++i; // skip spaces
116  char right = toupper(pairdef_in[i++]); if (!right) break; // Note: in case of break this accepts single base @ tail
117 
118  pairdef_out.put(right);
119 
120  // remove (first) of duplicated pair definitions:
121  {
122  char pair[] = "xx";
123  pair[0] = left;
124  pair[1] = right;
125 
126  for (int pass = 1; pass<=2; ++pass) {
127  const char *data = pairdef_out.get_data();
128 
129  while (1) {
130  const char *found = strstr(data, pair);
131  if (!found) break; // not found -> done
132 
133  size_t pos = pairdef_out.get_position();
134  if (found == data+pos-2) break; // reached current pair -> done
135 
136  // cut unwanted pair:
137  size_t found_pos = found-data;
138  pairdef_out.cut(found_pos, 3);
139  }
140 
141  std::swap(pair[0], pair[1]);
142  }
143  }
144 
145  for (int j = 0; helix_awars[j].awar; j++) {
146  if (j != changed_idx) {
147  AW_awar *awar_pair2 = aw_root->awar(helix_pair_awar(j));
148  char *pd2 = awar_pair2->read_string();
149  int dst = 0;
150  bool modified = false;
151 
152  for (int k = 0; ; k += 3) {
153  char l = toupper(pd2[k]); if (!l) break;
154  pd2[dst] = l;
155 
156  char r = toupper(pd2[k+1]);
157  if (!r) {
158  // do NOT silently remove trailing single base @ tail
159  dst += 2; // only has effect if modified
160  break;
161  }
162  pd2[dst+1] = r;
163 
164  if ((left == l && right == r) || (left == r && right == l)) {
165  // remove duplicated pair
166  modified = true;
167  }
168  else {
169  dst += 3;
170  }
171  if (!pd2[k+2]) break;
172  }
173 
174  if (modified) {
175  int endS = dst>0 ? dst-1 : dst;
176 
177  arb_assert(endS>=0);
178  pd2[endS] = 0;
179  awar_pair2->write_string(pd2);
180  }
181 
182  free(pd2);
183  }
184  }
185  }
186  awar_pair->write_string(pairdef_out.get_data()); // write back uppercase version
187  }
188  aw_root->awar(AWAR_HELIX_ENABLE)->touch(); // trigger reload of config + refresh
189  }
190 }
191 
193  : enabled(0)
194 {
195  // Note: effectively AW_helix is/hasToBe a SINGLETON
196  // (awar generation will fail on 2nd instance)
197 
198  RootCallback rcb = makeRootCallback(helix_setup_changed_cb, this);
199 
200  for (int j=0; helix_awars[j].awar; j++) {
201  int i = helix_awars[j].pair_type;
202 
203  aw_root->awar_string(helix_pair_awar(j), get_pairs_def(i))->add_callback(makeRootCallback(helix_pairs_changed_cb, i));
205  }
206  aw_root->awar_int(AWAR_HELIX_ENABLE, 1)->add_callback(rcb);
207 
208  awar_refresh = aw_root->awar_int(AWAR_HELIX_REFRESH, 1);
209 
210  setup_changed_cb(aw_root); // init from AWARs
211 }
212 
214  cdef.add(AWAR_HELIX_ENABLE, "enable");
215 
216  for (int j=0; helix_awars[j].awar; j++) {
217  int i = helix_awars[j].pair_type;
218 
219  const char *name = helix_awars[j].awar;
220  if (i != HELIX_DEFAULT) {
221  cdef.add(helix_pair_awar(j), name);
222  }
223  cdef.add(helix_symbol_awar(j), GBS_global_string("%s_symbol", name));
224  }
225 }
226 
228  { "*traditional",
229  "Traditional helix settings used up to arb 7.0\n(GG is defined as \"No pair\" here)\n",
230  "Default_symbol='';No_Pair='AA AC CC CT CU GG TU';No_Pair_symbol='#';Normal_Pair='GT GU';Normal_Pair_symbol='-';Strong_Pair='CG AT AU';Strong_Pair_symbol='~';"
231  "User_Pair='.A .C .G .T .U';User_Pair2='-A -C -G -T -U';User_Pair2_symbol='#';User_Pair3='UU TT';User_Pair3_symbol='+';"
232  "User_Pair4='';User_Pair4_symbol='';User_Pair5='';User_Pair5_symbol='';User_Pair6='';User_Pair6_symbol='';User_Pair_symbol='*';Weak_Pair='GA';Weak_Pair_symbol='=';enable='1'" },
233  { "*IUPAC_ambiguity_best",
234  "Base pairings using ambiguity codes.\nUses best case, i.e. strongest of possible bonds.\nNote: most combinations form a strong bond \nfollowing that approach. They are NOT explicitely \nlisted, instead they use the default symbol.",
235  "Default_symbol='~';No_Pair='AA AC CC CT CU TT UU';No_Pair_symbol='#';Normal_Pair='GT GU';Normal_Pair_symbol='-';Strong_Pair='CG AT AU';Strong_Pair_symbol='~';"
236  "User_Pair='.A .C .G .T .U .M .R .W .S .Y .K .V .H .D .B .N';User_Pair2='-A -C -G -T -U -M -R -W -S -Y -K -V -H -D -B -N';User_Pair2_symbol='#';User_Pair3='-- .. -.';User_Pair3_symbol='';"
237  "User_Pair4='AM CH CM CW CY MM TY UY YY';User_Pair4_symbol='#';User_Pair5='AR AS AV GR RR';User_Pair5_symbol='=';User_Pair6='BT BU DG GK GW KK KT KU ST SU SW';User_Pair6_symbol='-';User_Pair_symbol='*';Weak_Pair='GA GG';Weak_Pair_symbol='=';enable='1'" },
238  { "*IUPAC_ambiguity_mean",
239  "Base pairings using ambiguity codes.\nUses mean of possible bonds.\nNote: most combinations form a normal bond \nfollowing that approach. They are NOT explicitely \nlisted, instead they use the default symbol.",
240  "Default_symbol='=';No_Pair='AA AC CC CT CU TT UU';No_Pair_symbol='#';Normal_Pair='GT GU';Normal_Pair_symbol='-';Strong_Pair='CG AT AU';Strong_Pair_symbol='~';"
241  "User_Pair='.A .C .G .T .U .M .R .W .S .Y .K .V .H .D .B .N';User_Pair2='-A -C -G -T -U -M -R -W -S -Y -K -V -H -D -B -N';User_Pair2_symbol='#';User_Pair3='-- .. -.';User_Pair3_symbol='';"
242  "User_Pair4='AM AV CH CM CW CY HM HY MM TY UY YY';User_Pair4_symbol='#';User_Pair5='AK BG BR BS CK CR CS GH GM GN GS GV KM KR KV RT RU RY SS';User_Pair5_symbol='-';User_Pair6='GY';User_Pair6_symbol='~';User_Pair_symbol='*';Weak_Pair='GA GG';Weak_Pair_symbol='=';enable='1'" },
243  { NULp, NULp, NULp }
244 };
245 
247  AW_window_simple *aws = new AW_window_simple;
248 
249  aws->reset_layout("20230607");
250  aws->init(awr, "HELIX_PROPS", "HELIX_PROPERTIES");
251 
252  aws->at(10, 10);
253  aws->auto_space(3, 3);
254 
255  aws->callback(AW_POPDOWN);
256  aws->create_button("CLOSE", "CLOSE", "C");
257 
258  aws->callback(makeHelpCallback("helixsym.hlp"));
259  aws->create_button("HELP", "HELP", "H");
260 
261  AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, "helix", makeConfigSetupCallback(setup_helix_config), NULp, predefined_helix_configs);
262 
263  aws->at_newline();
264 
265  const size_t max_awar_len = 11;
266  aws->label_length(max_awar_len);
267 
268  aws->label("Show helix?");
269  aws->create_toggle(AWAR_HELIX_ENABLE);
270 
271  aws->at_newline();
272 
273  {
274  int x, y;
275  aws->get_at_position(&x, &y);
276  aws->at(100, 30); // set minimum window size
277  aws->at(x, y);
278  }
279 
280  const int IF_YSIZE = 32; // lineheight of attached input field
281  for (int j = 0; helix_awars[j].awar; j++) {
282  int i = helix_awars[j].pair_type;
283 
284  arb_assert(strlen(helix_awars[j].awar) <= max_awar_len);
285  aws->label(helix_awars[j].awar);
286 
287  aws->create_input_field(helix_symbol_awar(j), 3);
288 
289  if (i != HELIX_DEFAULT) {
290  aws->at_attach_to(true, false, -10, IF_YSIZE);
291  aws->create_input_field(helix_pair_awar(j), 30);
292  }
293 
294  aws->at_newline();
295  }
296  aws->window_fit();
297 
298  return aws;
299 }
300 
301 
bool is_pairpos(size_t pos) const
Definition: BI_helix.hxx:117
#define arb_assert(cond)
Definition: arb_assert.h:245
static AWT_predefined_config predefined_helix_configs[]
Definition: AW_helix.cxx:227
#define HELIX_AWAR_SYMBOL_TEMPLATE
Definition: AW_helix.cxx:30
const char * awar
Definition: AW_helix.cxx:34
void add(const char *awar_name, const char *config_name)
void cut(const size_t at, const size_t byte_count)
Definition: arb_strbuf.h:150
static char * y[maxsp+1]
#define AWAR_HELIX_REFRESH
Definition: AW_helix.cxx:28
void set_pairs_def(int i, const char *new_pairs_def)
Definition: BI_helix.hxx:62
BI_PAIR_TYPE
Definition: BI_helix.hxx:19
void AWT_insert_config_manager(AW_window *aww, AW_default default_file_, const char *id, const StoreConfigCallback &store_cb, const RestoreConfigCallback &load_or_reset_cb, const char *macro_id, const AWT_predefined_config *predef)
long read_int() const
Definition: AW_awar.cxx:184
void add_callback(const RootCallback &cb) const
Definition: AW_helix.cxx:73
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
size_t opposite_position(size_t pos) const
Definition: BI_helix.hxx:113
void AW_POPDOWN(AW_window *window)
Definition: AW_window.cxx:52
void reset_layout(const char *YYYYMMDD)
Definition: AW_window.cxx:3272
const char * get_pairs_def(int i) const
Definition: BI_helix.hxx:53
void set_char_bind(int i, const char *new_char_bind)
Definition: BI_helix.hxx:66
#define cb(action)
AW_awar * add_callback(const RootCallback &cb)
Definition: AW_awar.cxx:231
const char * read_char_pntr() const
Definition: AW_awar.cxx:168
WindowCallback makeHelpCallback(const char *helpfile)
Definition: aw_window.hxx:106
const char * helix_symbol_awar(int idx)
Definition: AW_helix.cxx:53
void touch()
Definition: AW_awar.cxx:207
static void helix_pairs_changed_cb(AW_root *aw_root, int changed_idx)
Definition: AW_helix.cxx:96
CONSTEXPR_INLINE_Cxx14 void swap(unsigned char &c1, unsigned char &c2)
Definition: ad_io_inline.h:19
size_t size() const
Definition: BI_helix.hxx:105
#define HELIX_AWAR_PAIR_TEMPLATE
Definition: AW_helix.cxx:31
static helix_pair_def helix_awars[]
Definition: AW_helix.cxx:38
char * read_string() const
Definition: AW_awar.cxx:198
AW_awar * awar(const char *awar)
Definition: AW_root.cxx:554
AW_awar * remove_callback(const RootCallback &cb)
Definition: AW_awar.cxx:525
AW_helix(AW_root *aw_root)
Definition: AW_helix.cxx:192
char get_symbol(char left, char right) const
Definition: BI_helix.cxx:79
long int flag
Definition: f2c.h:39
AW_awar * awar_int(const char *var_name, long default_value=0, AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:580
BI_PAIR_TYPE pair_type
Definition: AW_helix.cxx:35
static void setup_helix_config(AWT_config_definition &cdef)
Definition: AW_helix.cxx:213
#define AWAR_HELIX_ENABLE
Definition: AW_helix.cxx:29
bool empty() const
Definition: arb_strbuf.h:118
AW_window * create_helix_props_window(AW_root *awr)
Definition: AW_helix.cxx:246
void remove_callback(const RootCallback &cb) const
Definition: AW_helix.cxx:78
#define NULp
Definition: cxxforward.h:116
GB_ERROR write_string(const char *aw_string)
static void helix_setup_changed_cb(AW_root *aw_root, AW_helix *helix)
Definition: AW_helix.cxx:82
const char * get_data() const
Definition: arb_strbuf.h:120
char * seq_2_helix(char *sequence, char undefsymbol= ' ') const
Definition: AW_helix.cxx:56
const char * get_char_bind(int i) const
Definition: BI_helix.hxx:57
AW_awar * awar_string(const char *var_name, const char *default_value="", AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:570
void setup_changed_cb(AW_root *aw_root)
Definition: AW_helix.cxx:83
const char * helix_pair_awar(int idx)
Definition: AW_helix.cxx:54
#define AW_ROOT_DEFAULT
Definition: aw_base.hxx:106
size_t get_position() const
Definition: arb_strbuf.h:112
void put(char c)
Definition: arb_strbuf.h:174