ARB
DI_matr.cxx
Go to the documentation of this file.
1 // =============================================================== //
2 // //
3 // File : DI_matr.cxx //
4 // Purpose : //
5 // //
6 // Institute of Microbiology (Technical University Munich) //
7 // http://www.arb-home.de/ //
8 // //
9 // =============================================================== //
10 
11 #include "di_protdist.hxx"
12 #include "di_clusters.hxx"
13 #include "di_view_matrix.hxx"
14 #include "di_awars.hxx"
15 
16 #include <neighbourjoin.hxx>
17 #include <AP_filter.hxx>
18 #include <CT_ctree.hxx>
19 #include <ColumnStat.hxx>
20 
21 #include <awt.hxx>
22 #include <awt_sel_boxes.hxx>
23 #include <awt_filter.hxx>
24 
25 #include <aw_preset.hxx>
26 #include <aw_awars.hxx>
27 #include <aw_file.hxx>
28 #include <aw_msg.hxx>
29 #include <aw_root.hxx>
30 
31 #include <gui_aliview.hxx>
32 
33 #include <climits>
34 #include <ctime>
35 #include <cmath>
36 #include <arb_sort.h>
37 #include <arb_global_defs.h>
38 #include <macros.hxx>
39 #include <ad_cb.h>
40 #include <awt_TreeAwars.hxx>
41 #include <arb_defs.h>
42 
43 using std::string;
44 
45 // --------------------------------------------------------------------------------
46 
47 #define AWAR_DIST_BOOTSTRAP_COUNT AWAR_DIST_PREFIX "bootstrap/count"
48 #define AWAR_DIST_CANCEL_CHARS AWAR_DIST_PREFIX "cancel/chars"
49 #define AWAR_DIST_MATRIX_AUTO_RECALC AWAR_DIST_PREFIX "recalc"
50 
51 #define AWAR_DIST_COLUMN_STAT_NAME AWAR_DIST_COLUMN_STAT_PREFIX "name"
52 
53 #define AWAR_DIST_TREE_SORT_NAME "tmp/" AWAR_DIST_TREE_PREFIX "sort_tree_name"
54 #define AWAR_DIST_TREE_COMP_NAME "tmp/" AWAR_DIST_TREE_PREFIX "compr_tree_name"
55 #define AWAR_DIST_TREE_STD_NAME AWAR_DIST_TREE_PREFIX "tree_name"
56 #define AWAR_DIST_MATRIX_AUTO_CALC_TREE AWAR_DIST_TREE_PREFIX "autocalc"
57 
58 #define AWAR_DIST_SAVE_MATRIX_TYPE AWAR_DIST_SAVE_MATRIX_BASE "/type"
59 #define AWAR_DIST_SAVE_MATRIX_FILENAME AWAR_DIST_SAVE_MATRIX_BASE "/file_name"
60 
61 // --------------------------------------------------------------------------------
62 
64 
67 
71  return NULp;
72  }
75  return &userdef_DNA_matrix;
76 }
77 
79  AW_window *aww;
80  WindowCallback cb;
81 public:
82  BoundWindowCallback(AW_window *aww_, const WindowCallback& cb_)
83  : aww(aww_),
84  cb(cb_)
85  {}
86  void operator()() { cb(aww); }
87 };
88 
91 
93 
94 static void matrix_changed_cb() {
95  if (matrixDisplay) {
96  matrixDisplay->mark(MatrixDisplay::NEED_SETUP);
97  matrixDisplay->update_display();
98  }
99 }
100 
101 struct RecalcNeeded {
102  bool matrix;
103  bool tree;
104 
105  RecalcNeeded() : matrix(false), tree(false) { }
106 };
107 
109 
110 CONSTEXPR unsigned UPDATE_DELAY = 200;
111 
112 static unsigned update_cb(AW_root *aw_root);
113 inline void add_update_cb() {
115 }
116 
117 inline void matrix_needs_recalc_cb() {
118  need_recalc.matrix = true;
119  add_update_cb();
120 }
121 inline void tree_needs_recalc_cb() {
122  need_recalc.tree = true;
123  add_update_cb();
124 }
125 
127  if (GLOBAL_MATRIX.has_type(DI_MATRIX_COMPRESSED)) {
129  }
130 }
131 
132 static unsigned update_cb(AW_root *aw_root) {
133  if (need_recalc.matrix) {
134  GLOBAL_MATRIX.forget();
135  need_recalc.matrix = false; // because it's forgotten
136 
137  int matrix_autocalc = aw_root->awar(AWAR_DIST_MATRIX_AUTO_RECALC)->read_int();
138  if (matrix_autocalc) {
139  bool recalc_now = true;
140  int tree_autocalc = aw_root->awar(AWAR_DIST_MATRIX_AUTO_CALC_TREE)->read_int();
141  if (!tree_autocalc) recalc_now = matrixDisplay ? matrixDisplay->willShow() : false;
142 
143  if (recalc_now) {
144  di_assert(recalculate_matrix_cb.isSet());
145  (*recalculate_matrix_cb)();
146  di_assert(need_recalc.tree == true);
147  }
148  }
149  di_assert(need_recalc.matrix == false);
150  }
151 
152  if (need_recalc.tree) {
153  int tree_autocalc = aw_root->awar(AWAR_DIST_MATRIX_AUTO_CALC_TREE)->read_int();
154  if (tree_autocalc) {
155  di_assert(recalculate_tree_cb.isSet());
156  (*recalculate_tree_cb)();
157  need_recalc.matrix = false; // otherwise endless loop, e.g. if output-tree is used for sorting
158  }
159  }
160 
161  return 0; // do not call again
162 }
163 
164 static void auto_calc_changed_cb(AW_root *aw_root) {
165  int matrix_autocalc = aw_root->awar(AWAR_DIST_MATRIX_AUTO_RECALC)->read_int();
166  int tree_autocalc = aw_root->awar(AWAR_DIST_MATRIX_AUTO_CALC_TREE)->read_int();
167 
168  if (matrix_autocalc && !GLOBAL_MATRIX.exists()) matrix_needs_recalc_cb();
169  if (tree_autocalc && (matrix_autocalc || GLOBAL_MATRIX.exists())) tree_needs_recalc_cb();
170 }
171 
173  AW_window_simple *aws = new AW_window_simple;
174  aws->init(aw_root, "SET_DNA_MATRIX", "SET MATRIX");
175  aws->auto_increment(50, 50);
176  aws->button_length(10);
177  aws->callback(AW_POPDOWN);
178  aws->create_button("CLOSE", "CLOSE");
179 
180  aws->callback(makeHelpCallback("user_matrix.hlp"));
181  aws->create_button("HELP", "HELP");
182 
183  aws->at_newline();
184 
186  aws->window_fit();
187  return aws;
188 }
189 
193  }
194 }
195 
197  GB_transaction ta(db);
198 
204 
206 
207  RootCallback matrix_needs_recalc_callback = makeRootCallback(matrix_needs_recalc_cb);
208  aw_root->awar_int(AWAR_DIST_MATRIX_DNA_ENABLED, 0)->add_callback(matrix_needs_recalc_callback); // user matrix disabled by default
209  {
211  GB_add_callback(gbd, GB_CB_CHANGED, makeDatabaseCallback(matrix_needs_recalc_cb));
212  }
213 
214  aw_root->awar_string(AWAR_DIST_WHICH_SPECIES, "marked", def)->add_callback(matrix_needs_recalc_callback);
215  {
216  char *default_ali = GBT_get_default_alignment(db);
217  if (!default_ali) return GB_await_error();
218 
219  aw_root->awar_string(AWAR_DIST_ALIGNMENT, "", def)->add_callback(matrix_needs_recalc_callback)->write_string(default_ali);
220  free(default_ali);
221  }
222  aw_root->awar_string(AWAR_DIST_FILTER_ALIGNMENT, "none", def);
223  aw_root->awar_string(AWAR_DIST_FILTER_NAME, "none", def);
224  aw_root->awar_string(AWAR_DIST_FILTER_FILTER, "", def)->add_callback(matrix_needs_recalc_callback);
225  aw_root->awar_int (AWAR_DIST_FILTER_SIMPLIFY, 0, def)->add_callback(matrix_needs_recalc_callback);
226 
227  aw_root->awar_string(AWAR_DIST_CANCEL_CHARS, ".", def)->add_callback(matrix_needs_recalc_callback);
228  aw_root->awar_int(AWAR_DIST_CORR_TRANS, (int)DI_TRANSFORMATION_SIMILARITY, def)->add_callback(matrix_needs_recalc_callback)->set_minmax(0, DI_TRANSFORMATION_COUNT-1);
229 
231 
232  AW_create_fileselection_awars(aw_root, AWAR_DIST_SAVE_MATRIX_BASE, ".", "", "infile");
233  aw_root->awar_int(AWAR_DIST_SAVE_MATRIX_TYPE, 0, def);
234 
235  enum treetype { CURR, SORT, COMPRESS, TREEAWARCOUNT };
236  AW_awar *tree_awar[TREEAWARCOUNT] = { NULp, NULp, NULp };
237 
238  aw_root->awar_string(AWAR_DIST_TREE_STD_NAME, "tree_nj", def);
239  {
240  char *currentTree = aw_root->awar_string(AWAR_TREE, "", db)->read_string();
241  tree_awar[CURR] = aw_root->awar_string(AWAR_DIST_TREE_CURR_NAME, currentTree, def);
242  tree_awar[SORT] = aw_root->awar_string(AWAR_DIST_TREE_SORT_NAME, currentTree, def);
243  free(currentTree);
244  }
245  tree_awar[COMPRESS] = aw_root->awar_string(AWAR_DIST_TREE_COMP_NAME, NO_TREE_SELECTED, def);
246 
247  aw_root->awar_int(AWAR_DIST_BOOTSTRAP_COUNT, 1000, def);
250 
251  aw_root->awar_float(AWAR_DIST_MIN_DIST, 0.0)->set_minmax(0.0, 4.0);
252  aw_root->awar_float(AWAR_DIST_MAX_DIST, 0.0)->set_minmax(0.0, 4.0);
253 
254  aw_root->awar_string(AWAR_SPECIES_NAME, "", db);
255 
256  DI_create_cluster_awars(aw_root, def, db);
257 
258 #if defined(DEBUG)
259  AWT_create_db_browser_awars(aw_root, def);
260 #endif // DEBUG
261 
262  {
264 
266  GB_add_callback(gb_species_data, GB_CB_CHANGED, makeDatabaseCallback(matrix_needs_recalc_cb));
267 
268  GB_pop_transaction(db);
269  }
270 
271  AWT_registerTreeAwarCallback(tree_awar[CURR], makeTreeAwarCallback(selected_tree_changed_cb), true);
272  AWT_registerTreeAwarCallback(tree_awar[SORT], makeTreeAwarCallback(matrix_needs_recalc_cb), true);
273  AWT_registerTreeAwarCallback(tree_awar[COMPRESS], makeTreeAwarCallback(compressed_matrix_needs_recalc_cb), true);
274 
275  auto_calc_changed_cb(aw_root);
276 
277  return NULp;
278 }
279 
281  : phmatrix(phmatrix_),
282  full_name(NULp),
283  sequence(NULp),
284  name(NULp),
285  group_nr(0)
286 {
287  GBDATA *gb_ali = GB_entry(gbd, phmatrix->get_aliname());
288  if (gb_ali) {
289  GBDATA *gb_data = GB_entry(gb_ali, "data");
290  if (gb_data) {
291  if (phmatrix->is_AA) {
293  }
294  else {
295  sequence = new AP_sequence_parsimony(phmatrix->get_aliview());
296  }
298  sequence->lazy_load_sequence(); // load sequence
299 
300  name = GBT_read_string(gbd, "name");
301  full_name = GBT_read_string(gbd, "full_name");
302  }
303  }
304 }
305 
306 DI_ENTRY::DI_ENTRY(const char *name_, DI_MATRIX *phmatrix_)
307  : phmatrix(phmatrix_),
308  full_name(NULp),
309  sequence(NULp),
310  name(ARB_strdup(name_)),
311  group_nr(0)
312 {}
313 
315  delete sequence;
316  free(name);
317  free(full_name);
318 }
319 
322  seq_len(0),
323  allocated_entries(0),
324  aliview(new AliView(aliview_)),
325  is_AA(false),
326  entries(NULp),
327  nentries(0),
328  matrix(NULp),
329  matrix_type(DI_MATRIX_FULL)
330 {
331  memset(cancel_columns, 0, sizeof(cancel_columns));
332 }
333 
335  for (size_t i=0; i<nentries; i++) {
336  delete entries[i];
337  }
338  freenull(entries);
339  nentries = 0;
340  return NULp;
341 }
342 
344  unload();
345  delete matrix;
346  delete aliview;
347 }
348 
352 
353  TreeOrderedSpecies(const MatrixOrder& order, GBDATA *gb_spec)
354  : gbd(gb_spec),
355  order_index(order.get_index(GBT_get_name_or_description(gbd)))
356  {}
357 };
358 
360  : name2pos(NULp),
361  leafs(0)
362 {
363  if (sort_tree_name) {
364  int size;
365  TreeNode *sort_tree = GBT_read_tree_and_size(gb_main, sort_tree_name, new SimpleRoot, &size);
366 
367  if (sort_tree) {
368  leafs = size+1;
369  name2pos = GBS_create_hash(leafs, GB_IGNORE_CASE);
370 
371  IF_ASSERTION_USED(int leafsLoaded = leafs);
372  leafs = 0;
373  insert_in_hash(sort_tree);
374 
375  arb_assert(leafsLoaded == leafs);
376  destroy(sort_tree);
377  }
378  else {
379  GB_clear_error();
380  }
381  }
382 }
383 static int TreeOrderedSpecies_cmp(const void *p1, const void *p2, void *) {
386 
387  return s2->order_index - s1->order_index;
388 }
389 
390 void MatrixOrder::applyTo(TreeOrderedSpecies **species_array, size_t array_size) const {
391  GB_sort((void**)species_array, 0, array_size, TreeOrderedSpecies_cmp, NULp);
392 }
393 
394 static size_t get_load_count(LoadWhat what, GBDATA *gb_main, GBDATA **species_list) {
395  size_t no_of_species = -1U;
396 
397  switch (what) {
398  case DI_LOAD_ALL:
399  no_of_species = GBT_get_species_count(gb_main);
400  break;
401  case DI_LOAD_MARKED:
402  no_of_species = GBT_count_marked_species(gb_main);
403  break;
404  case DI_LOAD_LIST:
405  di_assert(species_list);
406  for (no_of_species = 0; species_list[no_of_species]; ++no_of_species) ;
407  break;
408  }
409 
410  di_assert(no_of_species != -1U);
411 
412  return no_of_species;
413 }
414 
415 GB_ERROR DI_MATRIX::load(LoadWhat what, const MatrixOrder& order, bool show_warnings, GBDATA **species_list) {
416  GBDATA *gb_main = get_gb_main();
417  const char *use = get_aliname();
418 
419  GB_transaction ta(gb_main);
420 
421  seq_len = GBT_get_alignment_len(gb_main, use); arb_assert(seq_len>0);
422  is_AA = GBT_is_alignment_protein(gb_main, use);
423  gb_species_data = GBT_get_species_data(gb_main);
424 
425  allocated_entries = 1000;
426  ARB_calloc(entries, allocated_entries);
427 
428  nentries = 0;
429 
430  size_t no_of_species = get_load_count(what, gb_main, species_list);
431  if (no_of_species<2) {
432  return GBS_global_string("Not enough input species (%zu)", no_of_species);
433  }
434 
435  TreeOrderedSpecies *species_to_load[no_of_species];
436 
437  {
438  size_t i = 0;
439  switch (what) {
440  case DI_LOAD_ALL: {
441  for (GBDATA *gb_species = GBT_first_species_rel_species_data(gb_species_data); gb_species; gb_species = GBT_next_species(gb_species), ++i) {
442  species_to_load[i] = new TreeOrderedSpecies(order, gb_species);
443  }
444  break;
445  }
446  case DI_LOAD_MARKED: {
447  for (GBDATA *gb_species = GBT_first_marked_species_rel_species_data(gb_species_data); gb_species; gb_species = GBT_next_marked_species(gb_species), ++i) {
448  species_to_load[i] = new TreeOrderedSpecies(order, gb_species);
449  }
450  break;
451  }
452  case DI_LOAD_LIST: {
453  for (i = 0; species_list[i]; ++i) {
454  species_to_load[i] = new TreeOrderedSpecies(order, species_list[i]);
455  }
456  break;
457  }
458  }
459  arb_assert(i == no_of_species);
460  }
461 
462  if (order.defined()) {
463  order.applyTo(species_to_load, no_of_species);
464  if (show_warnings) {
465  int species_not_in_sort_tree = 0;
466  for (size_t i = 0; i<no_of_species; ++i) {
467  if (!species_to_load[i]->order_index) {
468  species_not_in_sort_tree++;
469  }
470  }
471  if (species_not_in_sort_tree) {
472  GBT_message(gb_main, GBS_global_string("Warning: %i of the affected species are not in sort-tree", species_not_in_sort_tree));
473  }
474  }
475  }
476  else {
477  if (show_warnings) {
478  static bool shown = false;
479  if (!shown) { // showing once is enough
480  GBT_message(gb_main, "Warning: No valid tree given to sort matrix (using default database order)");
481  shown = true;
482  }
483  }
484  }
485 
486  if (no_of_species>allocated_entries) {
487  allocated_entries = no_of_species;
488  ARB_realloc(entries, allocated_entries);
489  }
490 
491  GB_ERROR error = NULp;
492  arb_progress progress("Preparing sequence data", no_of_species);
493  for (size_t i = 0; i<no_of_species && !error; ++i) {
494  DI_ENTRY *phentry = new DI_ENTRY(species_to_load[i]->gbd, this);
495  if (phentry->sequence) { // a species found
496  arb_assert(nentries<allocated_entries);
497  entries[nentries++] = phentry;
498  }
499  else {
500  delete phentry;
501  }
502  delete species_to_load[i];
503  species_to_load[i] = NULp;
504 
505  progress.inc_and_check_user_abort(error);
506  }
507 
508  return error;
509 }
510 
511 char *DI_MATRIX::calculate_overall_freqs(double rel_frequencies[AP_MAX], char *cancel) {
512  di_assert(is_AA == false);
513 
514  long hits2[AP_MAX];
515  long sum = 0;
516  int i;
517  int pos;
518  int b;
519  long s_len = aliview->get_length();
520 
521  memset((char *) &hits2[0], 0, sizeof(hits2));
522  for (size_t row = 0; row < nentries; row++) {
523  const char *seq1 = entries[row]->get_nucl_seq()->get_sequence();
524  for (pos = 0; pos < s_len; pos++) {
525  b = *(seq1++);
526  if (cancel[b]) continue;
527  hits2[b]++;
528  }
529  }
530  for (i = 0; i < AP_MAX; i++) { // LOOP_VECTORIZED
531  sum += hits2[i];
532  }
533  for (i = 0; i < AP_MAX; i++) {
534  rel_frequencies[i] = hits2[i] / (double) sum;
535  }
536  return NULp;
537 }
538 
539 double DI_MATRIX::corr(double dist, double b, double & sigma) {
540  const double eps = 0.01;
541  double ar = 1.0 - dist/b;
542  sigma = 1000.0;
543  if (ar< eps) return 3.0;
544  sigma = b/ar;
545  return - b * log(1-dist/b);
546 }
547 
548 GB_ERROR DI_MATRIX::calculate(const char *cancel, DI_TRANSFORMATION transformation, bool *aborted_flag, AP_matrix *userdef_matrix) {
549  di_assert(is_AA == false);
550 
551  if (userdef_matrix) {
552  switch (transformation) {
556  break;
557  default:
558  aw_message("Sorry: this kind of distance correction does not support a user defined matrix - it will be ignored");
559  userdef_matrix = NULp;
560  break;
561  }
562  }
563 
564  matrix = new AP_smatrix(nentries);
565 
566  long s_len = aliview->get_length();
567  long hits[AP_MAX][AP_MAX];
568  size_t i;
569 
570  if (nentries<=1) {
571  return "Not enough species selected to calculate matrix";
572  }
573  memset(&cancel_columns[0], 0, 256);
574 
575  for (i=0; cancel[i]; i++) {
576  cancel_columns[safeCharIndex(AP_sequence_parsimony::table[safeCharIndex(cancel[i])])] = 1;
577  UNCOVERED(); // @@@ cover
578  }
579 
580  long columns;
581  double b;
582  long frequencies[AP_MAX];
583  double rel_frequencies[AP_MAX];
584  double S_square = 0;
585 
586  switch (transformation) {
588  this->calculate_overall_freqs(rel_frequencies, cancel_columns);
589  S_square = 0.0;
590  for (i=0; i<AP_MAX; i++) { // LOOP_VECTORIZED[!<8.1]
591  S_square += rel_frequencies[i]*rel_frequencies[i];
592  }
593  break;
594  default: break;
595  };
596 
597  arb_progress progress("Calculating distance matrix", matrix_halfsize(nentries, true));
598  GB_ERROR error = NULp;
599  for (size_t row = 0; row<nentries && !error; row++) {
600  for (size_t col=0; col<=row && !error; col++) {
601  columns = 0;
602 
603  const unsigned char *seq1 = entries[row]->get_nucl_seq()->get_usequence();
604  const unsigned char *seq2 = entries[col]->get_nucl_seq()->get_usequence();
605 
606  b = 0.0;
607  switch (transformation) {
609  di_assert(0);
610  break;
612  b = 0.75;
613  // fall-through
616  double dist = 0.0;
617  if (userdef_matrix) {
618  memset((char *)hits, 0, sizeof(long) * AP_MAX * AP_MAX);
619  int pos;
620  for (pos = s_len; pos >= 0; pos--) {
621  hits[*(seq1++)][*(seq2++)]++;
622  }
623  int x, y;
624  double diffsum = 0.0;
625  double all_sum = 0.001;
626  for (x = AP_A; x < AP_MAX; x*=2) {
627  for (y = AP_A; y < AP_MAX; y*=2) {
628  if (x==y) {
629  all_sum += hits[x][y];
630  }
631  else {
632  UNCOVERED(); // @@@ cover
633  diffsum += hits[x][y] * userdef_matrix->get(x, y);
634  all_sum += hits[x][y] * userdef_matrix->get(x, y);
635  }
636  }
637  }
638  dist = diffsum / all_sum;
639  }
640  else {
641  for (int pos = s_len; pos >= 0; pos--) {
642  int b1 = *(seq1++);
643  int b2 = *(seq2++);
644  if (cancel_columns[b1]) continue;
645  if (cancel_columns[b2]) continue;
646  columns++;
647  if (b1&b2) continue;
648  dist+=1.0;
649  }
650  if (columns == 0) columns = 1;
651  dist /= columns;
652  }
653  if (transformation==DI_TRANSFORMATION_SIMILARITY) {
654  dist = (1.0-dist);
655  }
656  else if (b) {
657  double sigma;
658  dist = this->corr(dist, b, sigma);
659  }
660  matrix->set(row, col, dist);
661  break;
662  }
666  int pos;
667  double dist = 0.0;
668  long N, P, Q, M;
669  double p, q;
670 
671  memset((char *)hits, 0, sizeof(long) * AP_MAX * AP_MAX);
672  for (pos = s_len; pos >= 0; pos--) {
673  hits[*(seq1++)][*(seq2++)]++;
674  }
675  switch (transformation) {
677  P = hits[AP_A][AP_G] +
678  hits[AP_G][AP_A] +
679  hits[AP_C][AP_T] +
680  hits[AP_T][AP_C];
681  Q = hits[AP_A][AP_C] +
682  hits[AP_A][AP_T] +
683  hits[AP_C][AP_A] +
684  hits[AP_T][AP_A] +
685  hits[AP_G][AP_C] +
686  hits[AP_G][AP_T] +
687  hits[AP_C][AP_G] +
688  hits[AP_T][AP_G];
689  M = hits[AP_A][AP_A] +
690  hits[AP_C][AP_C] +
691  hits[AP_G][AP_G] +
692  hits[AP_T][AP_T];
693  N = P+Q+M;
694  if (N==0) N=1;
695  p = (double)P/(double)N;
696  q = (double)Q/(double)N;
697  dist = - .5 * log(
698  (1.0-2.0*p-q)*sqrt(1.0-2.0*q)
699  );
700  break;
701 
704 
705  memset((char *)frequencies, 0,
706  sizeof(long) * AP_MAX);
707 
708  N = 0;
709  M = 0;
710 
711  for (i=0; i<AP_MAX; i++) {
712  if (cancel_columns[i]) continue;
713  unsigned int j;
714  for (j=0; j<i; j++) {
715  if (cancel_columns[j]) continue;
716  frequencies[i] +=
717  hits[i][j]+
718  hits[j][i];
719  }
720  frequencies[i] += hits[i][i];
721  N += frequencies[i];
722  M += hits[i][i];
723  }
724  if (N==0) N=1;
725  if (transformation == DI_TRANSFORMATION_OLSEN) { // Calc sum square freq individually for each line
726  S_square = 0.0;
727  for (i=0; i<AP_MAX; i++) S_square += frequencies[i]*frequencies[i];
728  b = 1.0 - S_square/((double)N*(double)N);
729  }
730  else {
731  b = 1.0 - S_square;
732  }
733 
734  dist = ((double)(N-M)) / (double) N;
735  double sigma;
736  dist = this->corr(dist, b, sigma);
737  break;
738 
739  default: return "Sorry: Transformation not implemented";
740  }
741  matrix->set(row, col, dist);
742  break;
743  }
744  default:;
745  } // switch
746  progress.inc_and_check_user_abort(error);
747  }
748  }
749  if (aborted_flag && progress.aborted()) *aborted_flag = true;
750  return error;
751 }
752 
753 GB_ERROR DI_MATRIX::calculate_pro(DI_TRANSFORMATION transformation, bool *aborted_flag) {
754  di_assert(is_AA == true);
755 
756  di_cattype catType;
757  switch (transformation) {
758  case DI_TRANSFORMATION_NONE: catType = NONE; break;
759  case DI_TRANSFORMATION_SIMILARITY: catType = SIMILARITY; break;
760  case DI_TRANSFORMATION_KIMURA: catType = KIMURA; break;
761  case DI_TRANSFORMATION_PAM: catType = PAM; break;
762  case DI_TRANSFORMATION_CATEGORIES_HALL: catType = HALL; break;
763  case DI_TRANSFORMATION_CATEGORIES_BARKER: catType = GEORGE; break;
764  case DI_TRANSFORMATION_CATEGORIES_CHEMICAL: catType = CHEMICAL; break;
765  default:
766  return "This correction is not available for protein data";
767  }
768  matrix = new AP_smatrix(nentries);
769 
770  di_protdist prodist(UNIVERSAL, catType, nentries, entries, aliview->get_length(), matrix);
771  return prodist.makedists(aborted_flag);
772 }
773 
774 typedef std::map<const char*, TreeNode*, charpLess> NamedNodes;
775 
776 GB_ERROR link_to_tree(NamedNodes& named, TreeNode *node) {
777  GB_ERROR error = NULp;
778  if (node->is_leaf()) {
779  NamedNodes::iterator found = named.find(node->name);
780  if (found != named.end()) {
781  if (found->second) {
782  error = GBS_global_string("Invalid tree (two nodes named '%s')", node->name);
783  }
784  else {
785  found->second = node;
786  }
787  }
788  // otherwise, we do not care about the node (e.g. because it is not marked)
789  }
790  else {
791  error = link_to_tree(named, node->get_leftson());
792  if (!error) error = link_to_tree(named, node->get_rightson());
793  }
794  return error;
795 }
796 
797 #if defined(ASSERTION_USED)
798 static TreeNode *findNode(TreeNode *node, const char *name) {
799  if (node->is_leaf()) {
800  return strcmp(node->name, name) == 0 ? node : NULp;
801  }
802 
803  TreeNode *found = findNode(node->get_leftson(), name);
804  if (!found) found = findNode(node->get_rightson(), name);
805  return found;
806 }
807 #endif
808 
809 static GB_ERROR init(NamedNodes& node, TreeNode *tree, const DI_ENTRY*const*const entries, size_t nentries) {
810  GB_ERROR error = NULp;
811  for (size_t n = 0; n<nentries; ++n) {
812  node[entries[n]->name] = NULp;
813  }
814  error = link_to_tree(node, tree);
815  if (!error) { // check for missing species (needed but not in tree)
816  size_t missing = 0;
817  const char *exampleName = NULp;
818 
819  for (size_t n = 0; n<nentries; ++n) {
820  NamedNodes::iterator found = node.find(entries[n]->name);
821  if (found == node.end()) {
822  ++missing;
823  exampleName = entries[n]->name;
824  }
825  else {
826  di_assert(node[entries[n]->name] == findNode(tree, entries[n]->name));
827  if (!node[entries[n]->name]) {
828  ++missing;
829  exampleName = entries[n]->name;
830  }
831  }
832  }
833 
834  if (missing) {
835  error = GBS_global_string("Tree is missing %zu required species (e.g. '%s')", missing, exampleName);
836  }
837  }
838  return error;
839 }
840 
841 GB_ERROR DI_MATRIX::extract_from_tree(const char *treename, bool *aborted_flag) {
842  GB_ERROR error = NULp;
843  if (nentries<=1) error = "Not enough species selected to calculate matrix";
844  else {
845  TreeNode *tree;
846  {
847  GB_transaction ta(get_gb_main());
848  tree = GBT_read_tree(get_gb_main(), treename, new SimpleRoot);
849  }
850  if (!tree) error = GB_await_error();
851  else {
852  arb_progress progress("Extracting distances from tree", matrix_halfsize(nentries, true));
853  NamedNodes node;
854 
855  error = init(node, tree, entries, nentries);
856  matrix = new AP_smatrix(nentries);
857 
858  for (size_t row = 0; row<nentries && !error; row++) {
859  TreeNode *rnode = node[entries[row]->name];
860  for (size_t col=0; col<=row && !error; col++) {
861  double dist;
862  if (col != row) {
863  TreeNode *cnode = node[entries[col]->name];
864  dist = rnode->intree_distance_to(cnode);
865  }
866  else {
867  dist = 0.0;
868  }
869  matrix->set(row, col, dist);
870  progress.inc_and_check_user_abort(error);
871  }
872  }
873  UNCOVERED();
874  destroy(tree);
875  if (aborted_flag && progress.aborted()) *aborted_flag = true;
876  if (error) progress.done();
877  }
878  }
879  return error;
880 }
881 
883  const char *load_what = AW_root::SINGLETON->awar(AWAR_DIST_WHICH_SPECIES)->read_char_pntr();
884  return (strcmp(load_what, "all") == 0) ? DI_LOAD_ALL : DI_LOAD_MARKED;
885 }
886 
887 __ATTR__USERESULT static GB_ERROR di_calculate_matrix(AW_root *aw_root, const WeightedFilter *weighted_filter, bool bootstrap_flag, bool show_warnings, bool *aborted_flag) {
888  // sets 'aborted_flag' to true, if it is non-NULp and the calculation has been aborted
889  GB_ERROR error = NULp;
890 
891  if (GLOBAL_MATRIX.exists()) {
892  di_assert(!need_recalc.matrix);
893  }
894  else {
895  GBDATA *gb_main = weighted_filter->get_gb_main();
896  GB_transaction ta(gb_main);
897 
898  char *use = aw_root->awar(AWAR_DIST_ALIGNMENT)->read_string();
899  long ali_len = GBT_get_alignment_len(gb_main, use);
900 
901  if (ali_len<=0) {
902  error = "Please select a valid alignment";
903  GB_clear_error();
904  }
905  else {
906  const LoadWhat what = whatToLoad();
907  size_t species_count = get_load_count(what, gb_main, NULp);
908  double phase1_fraction;
909  {
910  // keep sync with .@MatrixSteps
911  double O_loadData = 10*species_count;
912  double O_calcMatrix = triangular_number(species_count);
913  phase1_fraction = O_loadData / (O_loadData+O_calcMatrix);
914  }
915 
916  arb_progress progress(WEIGHTED, "Calculating matrix", phase1_fraction); // two steps: 1x load data + 1x calc matrix
917 
918  char *cancel = aw_root->awar(AWAR_DIST_CANCEL_CHARS)->read_string();
919  AliView *aliview = weighted_filter->create_aliview(use, error);
920 
921  if (!error) {
922  if (bootstrap_flag) aliview->get_filter()->enable_bootstrap();
923 
924  const char *sort_tree_name = aw_root->awar(AWAR_DIST_TREE_SORT_NAME)->read_char_pntr();
925  {
926  DI_MATRIX *phm = new DI_MATRIX(*aliview);
928 
929  static SmartCharPtr last_sort_tree_name;
930  static SmartPtr<MatrixOrder> last_order;
931 
932  if (last_sort_tree_name.isNull() || !sort_tree_name || strcmp(&*last_sort_tree_name, sort_tree_name) != 0) {
933  last_sort_tree_name = nulldup(sort_tree_name);
934  last_order = new MatrixOrder(gb_main, sort_tree_name);
935  }
936  di_assert(last_order.isSet());
937  error = phm->load(what, *last_order, show_warnings, NULp); // step1 of progress
938  progress.inc_and_check_user_abort(error);
939  bool aborted = error ? progress.aborted() : false;
940  error = ta.close(error);
941 
942  if (!error) {
944 
945  if (trans == DI_TRANSFORMATION_FROM_TREE) {
946  const char *treename = aw_root->awar(AWAR_DIST_TREE_CURR_NAME)->read_char_pntr();
947  error = phm->extract_from_tree(treename, &aborted);
948  }
949  else {
950  if (phm->is_AA) error = phm->calculate_pro(trans, &aborted);
951  else error = phm->calculate(cancel, trans, &aborted, get_user_matrix());
952  }
953  }
954 
955  if (aborted) {
956  di_assert(error);
957  if (aborted_flag) *aborted_flag = true;
958  }
959  if (error) {
960  delete phm;
961  GLOBAL_MATRIX.forget();
962  }
963  else {
964  GLOBAL_MATRIX.replaceBy(phm);
966  need_recalc.matrix = false;
967  }
968  }
969  }
970 
971  free(cancel);
972  delete aliview;
973  }
974  free(use);
975 
976  di_assert(contradicted(error, GLOBAL_MATRIX.exists()));
977  }
978  return error;
979 }
980 
981 static void di_mark_by_distance(AW_window *aww, WeightedFilter *weighted_filter) {
982  AW_root *aw_root = aww->get_root();
983  float lowerBound = aw_root->awar(AWAR_DIST_MIN_DIST)->read_float();
984  float upperBound = aw_root->awar(AWAR_DIST_MAX_DIST)->read_float();
985 
986  GB_ERROR error = NULp;
987  if (lowerBound >= upperBound) {
988  error = GBS_global_string("Lower bound (%f) has to be smaller than upper bound (%f)", lowerBound, upperBound);
989  }
990  else if (lowerBound<0.0 || lowerBound > 1.0) {
991  error = GBS_global_string("Lower bound (%f) is not in allowed range [0.0 .. 1.0]", lowerBound);
992  }
993  else if (upperBound<0.0 || upperBound > 1.0) {
994  error = GBS_global_string("Upper bound (%f) is not in allowed range [0.0 .. 1.0]", upperBound);
995  }
996  else {
997  GBDATA *gb_main = weighted_filter->get_gb_main();
998  GB_transaction ta(gb_main);
999 
1000  char *selected = aw_root->awar(AWAR_SPECIES_NAME)->read_string();
1001  if (!selected[0]) {
1002  error = "Please select a species";
1003  }
1004  else {
1005  GBDATA *gb_selected = GBT_find_species(gb_main, selected);
1006  if (!gb_selected) {
1007  error = GBS_global_string("Couldn't find species '%s'", selected);
1008  }
1009  else {
1010  char *use = aw_root->awar(AWAR_DIST_ALIGNMENT)->read_string();
1011  char *cancel = aw_root->awar(AWAR_DIST_CANCEL_CHARS)->read_string();
1013  AliView *aliview = weighted_filter->create_aliview(use, error);
1014 
1015  if (!error) {
1016  DI_MATRIX *prev_global = GLOBAL_MATRIX.swap(NULp);
1017 
1018  size_t speciesCount = GBT_get_species_count(gb_main);
1019  bool markedSelected = false;
1020 
1021  arb_progress progress("Mark species by distance", speciesCount);
1022  MatrixOrder order(gb_main, NULp);
1023 
1024  for (GBDATA *gb_species = GBT_first_species(gb_main);
1025  gb_species && !error;
1026  gb_species = GBT_next_species(gb_species))
1027  {
1028  DI_MATRIX *phm = new DI_MATRIX(*aliview);
1029  phm->matrix_type = DI_MATRIX_FULL;
1030  GBDATA *species_pair[] = { gb_selected, gb_species, NULp };
1031 
1032  error = phm->load(DI_LOAD_LIST, order, false, species_pair);
1033 
1034  if (phm->nentries == 2) { // if species has no alignment -> nentries<2
1035  if (!error) {
1036  if (phm->is_AA) error = phm->calculate_pro(trans, NULp);
1037  else error = phm->calculate(cancel, trans, NULp, get_user_matrix());
1038  }
1039 
1040  if (!error) {
1041  double dist_value = phm->matrix->get(0, 1); // distance or conformance
1042  bool mark = (lowerBound <= dist_value && dist_value <= upperBound);
1043  GB_write_flag(gb_species, mark);
1044 
1045  if (!markedSelected) {
1046  dist_value = phm->matrix->get(0, 0); // distance or conformance to self
1047  mark = (lowerBound <= dist_value && dist_value <= upperBound);
1048  GB_write_flag(gb_selected, mark);
1049 
1050  markedSelected = true;
1051  }
1052  }
1053  }
1054 
1055  delete phm;
1056  if (!error) progress.inc_and_check_user_abort(error);
1057  }
1058 
1059  di_assert(!GLOBAL_MATRIX.exists());
1060  ASSERT_RESULT(DI_MATRIX*, NULp, GLOBAL_MATRIX.swap(prev_global));
1061 
1062  if (error) progress.done();
1063  }
1064 
1065  delete aliview;
1066  free(cancel);
1067  free(use);
1068  }
1069  }
1070 
1071  free(selected);
1072  error = ta.close(error);
1073  }
1074 
1075  if (error) {
1076  aw_message(error);
1077  }
1078 }
1079 
1081  // recalculate matrix
1083  if (need_recalc.matrix && GLOBAL_MATRIX.exists()) {
1084  GLOBAL_MATRIX.forget();
1085  }
1086  di_assert(recalculate_matrix_cb.isSet());
1087  (*recalculate_matrix_cb)();
1089 }
1090 
1091 static void di_view_matrix_cb(AW_window *aww, save_matrix_params *sparam) {
1093  if (!error) {
1094  if (!matrixDisplay) matrixDisplay = new MatrixDisplay(sparam->weighted_filter->get_gb_main());
1095 
1096  static AW_window *viewer = NULp;
1097  if (!viewer) viewer = DI_create_view_matrix_window(aww->get_root(), matrixDisplay, sparam);
1098 
1099  matrixDisplay->mark(MatrixDisplay::NEED_SETUP);
1100  matrixDisplay->update_display();
1101 
1102  GLOBAL_MATRIX.set_changed_cb(matrix_changed_cb);
1103 
1104  viewer->activate();
1105  }
1106 }
1107 
1108 static void di_save_matrix_cb(AW_window *aww) {
1109  // save the matrix
1111  if (!error) {
1112  char *filename = aww->get_root()->awar(AWAR_DIST_SAVE_MATRIX_FILENAME)->read_string();
1114 
1115  GLOBAL_MATRIX.get()->save(filename, type);
1116  free(filename);
1117  }
1119  aww->hide_or_notify(error);
1120 }
1121 
1123  static AW_window_simple *aws = NULp;
1124  if (!aws) {
1125  aws = new AW_window_simple;
1126  aws->init(aw_root, "SAVE_MATRIX", "Save Matrix");
1127  aws->load_xfig("sel_box_user.fig");
1128 
1129  aws->at("close");
1130  aws->callback(AW_POPDOWN);
1131  aws->create_button("CLOSE", "CANCEL", "C");
1132 
1133 
1134  aws->at("help"); aws->callback(makeHelpCallback("save_matrix.hlp"));
1135  aws->create_button("HELP", "HELP", "H");
1136 
1137  aws->at("user");
1138  aws->create_option_menu(AWAR_DIST_SAVE_MATRIX_TYPE);
1139  aws->insert_default_option("Phylip Format (Lower Triangular Matrix)", "P", DI_SAVE_PHYLIP_COMP);
1140  aws->insert_option("Readable (using NDS)", "R", DI_SAVE_READABLE);
1141  aws->insert_option("Tabbed (using NDS)", "R", DI_SAVE_TABBED);
1142  aws->update_option_menu();
1143 
1144  AW_create_standard_fileselection(aws, save_params->awar_base);
1145 
1146  aws->at("save2");
1147  aws->callback(makeWindowCallback(di_save_matrix_cb));
1148  aws->create_button("SAVE", "SAVE", "S");
1149 
1150  aws->at("cancel2");
1151  aws->callback(AW_POPDOWN);
1152  aws->create_button("CLOSE", "CANCEL", "C");
1153  }
1154  return aws;
1155 }
1156 
1158  AW_window_simple *aws = new AW_window_simple;
1159  aws->init(aw_root, "SELECT_CHARS_TO_CANCEL_COLUMN", "CANCEL SELECT");
1160  aws->load_xfig("di_cancel.fig");
1161 
1162  aws->at("close");
1163  aws->callback(AW_POPDOWN);
1164  aws->create_button("CLOSE", "CLOSE", "C");
1165 
1166  aws->at("cancel");
1167  aws->create_input_field(AWAR_DIST_CANCEL_CHARS, 12);
1168 
1169  return aws;
1170 }
1171 
1172 static const char *enum_trans_to_string[] = {
1173  "none",
1174  "similarity",
1175  "jukes_cantor",
1176  "felsenstein",
1177 
1178  "pam",
1179  "hall",
1180  "barker",
1181  "chemical",
1182 
1183  "kimura",
1184  "olsen",
1185  "felsenstein voigt",
1186  "olsen voigt",
1187  "max ml",
1188 
1189  NULp, // treedist
1190 };
1191 
1192 STATIC_ASSERT(ARRAY_ELEMS(enum_trans_to_string) == DI_TRANSFORMATION_COUNT);
1193 
1194 static void di_calculate_tree_cb(AW_window *aww, WeightedFilter *weighted_filter, bool bootstrap_flag) {
1195  recalculate_tree_cb = new BoundWindowCallback(aww, makeWindowCallback(di_calculate_tree_cb, weighted_filter, bootstrap_flag));
1196 
1197  AW_root *aw_root = aww->get_root();
1198  GB_ERROR error = NULp;
1199  StrArray *all_names = NULp;
1200 
1201  long loop_count = 0;
1202  long bootstrap_count = aw_root->awar(AWAR_DIST_BOOTSTRAP_COUNT)->read_int();
1203 
1204  {
1205  char *tree_name = aw_root->awar(AWAR_DIST_TREE_STD_NAME)->read_string();
1206  error = GBT_check_tree_name(tree_name);
1207  free(tree_name);
1208  }
1209 
1210  SmartPtr<arb_progress> progress, tree_progress;
1212 
1213  GBDATA *gb_main = weighted_filter->get_gb_main();
1214 
1215  double phase1_fraction;
1216  {
1217  const size_t species_count = get_load_count(whatToLoad(), gb_main, NULp);
1218 
1219  double O_calcMatrix = 60 * (triangular_number(species_count) + 10*species_count); // keep sync with .@MatrixSteps
1220  double O_joinTree = 1 * sum_of_triangular_numbers(species_count); // keep sync with ../SL/NEIGHBOURJOIN/NJ.cxx@NJsteps
1221 
1222  phase1_fraction = O_calcMatrix / (O_calcMatrix+O_joinTree);
1223  }
1224 
1225  if (!error) {
1226  if (bootstrap_flag) {
1227  if (bootstrap_count) {
1228  progress = new arb_progress("Calculating bootstrap trees", bootstrap_count+1); // 1 for each bootstrap-tree + 1 for final consensus tree
1229  }
1230  else {
1231  progress = new arb_progress("Calculating bootstrap trees (KILL to stop)", long(INT_MAX));
1232  }
1233  progress->auto_subtitles("tree");
1234  }
1235  else {
1236  progress = new arb_progress("Calculating tree");
1237  }
1238 
1239  // @@@ handle case where matrix is already up-to-date?
1240  // @@@ if need_recalc.matrix -> use simple wrapping progress (using 1 step); do the same below at 2nd construction point
1241  tree_progress = new arb_progress(WEIGHTED, NULp, phase1_fraction); // each tree calculation consists of 2 steps (matrix+neighbourjoining)
1242 
1243  if (bootstrap_flag) {
1244  GLOBAL_MATRIX.forget();
1245  GLOBAL_MATRIX.set_changed_cb(NULp); // otherwise matrix window will repeatedly pop up/down
1246 
1247  error = di_calculate_matrix(aw_root, weighted_filter, bootstrap_flag, true, NULp);
1248  if (!error) {
1249  DI_MATRIX *matr = GLOBAL_MATRIX.get();
1250  if (!matr) {
1251  error = "unexpected error in di_calculate_matrix_cb (data missing)";
1252  }
1253  else {
1254  all_names = new StrArray;
1255  all_names->reserve(matr->nentries+2);
1256 
1257  for (size_t i=0; i<matr->nentries; i++) {
1258  all_names->put(ARB_strdup(matr->entries[i]->name));
1259  }
1260  ctree = new ConsensusTree(*all_names);
1261  }
1262  }
1263  }
1264  }
1265 
1266  TreeNode *tree = NULp;
1267  bool aborted = false;
1268 
1269  do {
1270  if (error) break;
1271 
1272  aborted = false;
1273 
1274  if (bootstrap_flag) {
1275  if (loop_count>0) { // in first loop we already have a valid matrix -> no need to recalculate
1276  GLOBAL_MATRIX.forget();
1277  }
1278  }
1279  else if (need_recalc.matrix) {
1280  GLOBAL_MATRIX.forget();
1281  }
1282 
1283  if (tree_progress.isNull()) tree_progress = new arb_progress(WEIGHTED, NULp, phase1_fraction); // each tree calculation consists of 2 steps (matrix+neighbourjoining)
1284 
1285  error = di_calculate_matrix(aw_root, weighted_filter, bootstrap_flag, !bootstrap_flag, &aborted); // [implicit progress increment only if matrix is recalculated]
1286  if (error && aborted) {
1287  error = NULp; // clear error (otherwise no tree will be read below)
1288  break; // end of bootstrap
1289  }
1290  tree_progress->inc();
1291 
1292  if (!GLOBAL_MATRIX.exists()) {
1293  error = "unexpected error in di_calculate_matrix_cb (data missing)";
1294  break;
1295  }
1296 
1297  DI_MATRIX *matr = GLOBAL_MATRIX.get();
1298  char **names = ARB_calloc<char*>(matr->nentries+2);
1299 
1300  for (size_t i=0; i<matr->nentries; i++) {
1301  names[i] = matr->entries[i]->name;
1302  }
1303  di_assert(matr->nentries == matr->matrix->size());
1304  tree = neighbourjoining(names, *matr->matrix, new SimpleRoot, &aborted); // [implicit progress increment]
1305  tree_progress->inc();
1306 
1307  if (bootstrap_flag && !aborted) {
1308  error = ctree->insert_tree_weighted(tree, matr->nentries, 1, false);
1309  UNCOVERED();
1310  destroy(tree); tree = NULp;
1311  // Warning: nodes stored as origin in deconstructed PARTs now point to deleted nodes.
1312 
1313  if (!error) {
1314  ++loop_count;
1315  progress->inc();
1316  }
1317  if (!bootstrap_count) { // when waiting for kill
1318  time_t t = time(NULp);
1319  static time_t tlast = 0;
1320 
1321  double diff_seconds = difftime(t, tlast);
1322  if (diff_seconds>3) {
1323  progress->force_update();
1324  tlast = t;
1325  }
1326  }
1327  }
1328  free(names);
1329 
1330  if (aborted || error) {
1331  break;
1332  }
1333 
1334  tree_progress.setNull();
1335 
1336  } while (bootstrap_flag && loop_count != bootstrap_count);
1337 
1338  if (aborted || error) tree_progress->done();
1339  tree_progress.setNull();
1340 
1341  if (!error) {
1342  if (bootstrap_flag) {
1343  if (aborted) {
1344  // continuing to use progress would result in instant abort.
1345  // (abort state is already set in progress-implementation)
1346  // @@@L would need a mechanism to reset that 'abort' flag!
1347 
1348  progress->done();
1349  progress.setNull();
1350  progress = new arb_progress("Collect consensus of bootstrapped trees", 1UL);
1351  }
1352 
1353  tree = ctree->get_consensus_tree(error);
1354  progress->inc();
1355  if (!error) {
1356  error = GBT_is_invalid(tree);
1357  di_assert(!error);
1358  }
1359  }
1360  else {
1361  error = progress->error_if_aborted();
1362  }
1363 
1364  if (!error) {
1365  char *tree_name = aw_root->awar(AWAR_DIST_TREE_STD_NAME)->read_string();
1366  GB_begin_transaction(gb_main);
1367  error = GBT_write_tree(gb_main, tree_name, tree);
1368 
1369  if (!error) {
1370  char *filter_name = AWT_get_combined_filter_name(aw_root, "dist");
1371  int transr = aw_root->awar(AWAR_DIST_CORR_TRANS)->read_int();
1372 
1373  {
1374  const char *comment;
1375  if (enum_trans_to_string[transr]) {
1376  comment = GBS_global_string("PRG=dnadist CORR=%s FILTER=%s PKG=ARB", enum_trans_to_string[transr], filter_name);
1377  }
1378  else {
1380  const char *treename = aw_root->awar(AWAR_DIST_TREE_CURR_NAME)->read_char_pntr();
1381  comment = GBS_global_string("PRG=treedist (from '%s') PKG=ARB", treename);
1382  }
1383 
1384  error = GBT_write_tree_remark(gb_main, tree_name, comment);
1385  }
1386 
1387  if (!error) {
1388  const char *log_message;
1389  if (bootstrap_flag) {
1390  log_message = GBS_global_string("generated consensus tree from %li bootstrap trees%s.",
1391  loop_count,
1392  aborted ? " (aborted by user)" : "");
1393  }
1394  else {
1395  log_message = "calculation finished";
1396  }
1397  error = GBT_log_to_named_trees_remark(gb_main, tree_name, log_message, true);
1398  }
1399 
1400  free(filter_name);
1401  }
1402  error = GB_end_transaction(gb_main, error);
1403  free(tree_name);
1404  }
1405  }
1406 
1407  UNCOVERED();
1408  destroy(tree);
1409 
1410  // aw_status(); // remove 'abort' flag (@@@ got no equiv for arb_progress yet. really needed?)
1411 
1412  if (bootstrap_flag) {
1413  if (all_names) delete all_names;
1414  GLOBAL_MATRIX.forget();
1415  }
1416 #if defined(DEBUG)
1417  else {
1418  di_assert(!all_names);
1419  }
1420 #endif // DEBUG
1421 
1422  if (progress.isSet()) {
1423  progress->done();
1424  }
1425 
1426  if (error) {
1427  aw_message(error);
1428  }
1429  else {
1430  need_recalc.tree = false;
1431  aw_root->awar(AWAR_TREE_REFRESH)->touch();
1432  }
1433 }
1434 
1435 
1437  GB_push_transaction(gb_main);
1438 
1439  GLOBAL_MATRIX.forget();
1440 
1441  AW_root *aw_root = aww->get_root();
1442  char *use = aw_root->awar(AWAR_DIST_ALIGNMENT)->read_string();
1443  long ali_len = GBT_get_alignment_len(gb_main, use);
1444  GB_ERROR error = NULp;
1445 
1446  if (ali_len<=0) {
1447  GB_pop_transaction(gb_main);
1448  error = "Please select a valid alignment";
1449  GB_clear_error();
1450  }
1451  else {
1452  arb_progress progress("Analyzing data");
1453 
1454  char *filter_str = aw_root->awar(AWAR_DIST_FILTER_FILTER)->read_string();
1455  // char *cancel = aw_root->awar(AWAR_DIST_CANCEL_CHARS)->read_string();
1456 
1457  AliView *aliview = NULp;
1458  {
1459  AP_filter *ap_filter = NULp;
1460  long flen = strlen(filter_str);
1461 
1462  if (flen == ali_len) {
1463  ap_filter = new AP_filter(filter_str, "0", ali_len);
1464  }
1465  else {
1466  if (flen) {
1467  aw_message("Warning: your filter len is not equal to the alignment len\nfilter got truncated with zeros or cutted");
1468  ap_filter = new AP_filter(filter_str, "0", ali_len);
1469  }
1470  else {
1471  ap_filter = new AP_filter(ali_len); // unfiltered
1472  }
1473  }
1474 
1475  error = ap_filter->is_invalid();
1476  if (!error) {
1477  AP_weights ap_weights(ap_filter);
1478  aliview = new AliView(gb_main, *ap_filter, ap_weights, use);
1479  }
1480  delete ap_filter;
1481  }
1482 
1483  if (error) {
1484  GB_pop_transaction(gb_main);
1485  }
1486  else {
1487  DI_MATRIX phm(*aliview);
1488 
1489  {
1490  const char *sort_tree_name = aw_root->awar(AWAR_DIST_TREE_SORT_NAME)->read_char_pntr();
1491 
1492  GLOBAL_MATRIX.forget();
1493 
1494  MatrixOrder order(gb_main, sort_tree_name);
1495  error = phm.load(whatToLoad(), order, true, NULp);
1496  }
1497 
1498  GB_pop_transaction(gb_main);
1499 
1500  if (!error) {
1501  progress.subtitle("Search Correction");
1502 
1503  string msg;
1504  DI_TRANSFORMATION detected = phm.detect_transformation(msg);
1505  aw_root->awar(AWAR_DIST_CORR_TRANS)->write_int(detected);
1506  aw_message(msg.c_str());
1507  }
1508  }
1509 
1510  // free(cancel);
1511  delete aliview;
1512 
1513  free(filter_str);
1514  }
1515 
1516  if (error) aw_message(error);
1517 
1518  free(use);
1519 }
1520 
1522  if (gb_main) {
1523  AW_root *aw_root = aww->get_root();
1524  shutdown_macro_recording(aw_root);
1525  aw_root->unlink_awars_from_DB(gb_main);
1526  GB_close(gb_main);
1527  }
1528  GLOBAL_MATRIX.set_changed_cb(NULp);
1529  exit(EXIT_SUCCESS);
1530 }
1531 
1532 static void di_calculate_full_matrix_cb(AW_window *aww, const WeightedFilter *weighted_filter) {
1533  recalculate_matrix_cb = new BoundWindowCallback(aww, makeWindowCallback(di_calculate_full_matrix_cb, weighted_filter));
1534 
1535  GLOBAL_MATRIX.forget_if_not_has_type(DI_MATRIX_FULL);
1536  GB_ERROR error = di_calculate_matrix(aww->get_root(), weighted_filter, 0, true, NULp);
1537  aw_message_if(error);
1539  if (!error) tree_needs_recalc_cb();
1540 }
1541 
1542 static void di_calculate_compressed_matrix_cb(AW_window *aww, WeightedFilter *weighted_filter) {
1543  recalculate_matrix_cb = new BoundWindowCallback(aww, makeWindowCallback(di_calculate_compressed_matrix_cb, weighted_filter));
1544 
1545  GBDATA *gb_main = weighted_filter->get_gb_main();
1546  GB_transaction ta(gb_main);
1547 
1548  AW_root *aw_root = aww->get_root();
1549  char *treename = aw_root->awar(AWAR_DIST_TREE_COMP_NAME)->read_string();
1550  GB_ERROR error = NULp;
1551  TreeNode *tree = GBT_read_tree(gb_main, treename, new SimpleRoot);
1552 
1553  if (!tree) {
1554  error = GB_await_error();
1555  }
1556  else {
1557  {
1558  LocallyModify<MatrixDisplay*> skipRefresh(matrixDisplay, NULp); // skip refresh, until matrix has been compressed
1559 
1560  GLOBAL_MATRIX.forget(); // always forget (as tree might have changed)
1561  error = di_calculate_matrix(aw_root, weighted_filter, 0, true, NULp);
1562  if (!error && !GLOBAL_MATRIX.exists()) {
1563  error = "Failed to calculate your matrix (bug?)";
1564  }
1565  if (!error) {
1566  error = GLOBAL_MATRIX.get()->compress(tree);
1567  }
1568  }
1569  UNCOVERED();
1570  destroy(tree);
1571 
1572  // now force refresh
1573  if (matrixDisplay) {
1574  matrixDisplay->mark(MatrixDisplay::NEED_SETUP);
1575  matrixDisplay->update_display();
1576  }
1577  }
1578  free(treename);
1579  aw_message_if(error);
1581  if (!error) tree_needs_recalc_cb();
1582 }
1583 
1585  AW_root *aw_root = aww->get_root();
1586  char *tree_name = aw_root->awar(AWAR_DIST_TREE_CURR_NAME)->read_string();
1587  aw_root->awar(AWAR_DIST_TREE_SORT_NAME)->write_string(tree_name);
1588  free(tree_name);
1589 }
1591  AW_root *aw_root = aww->get_root();
1592  char *tree_name = aw_root->awar(AWAR_DIST_TREE_CURR_NAME)->read_string();
1593  aw_root->awar(AWAR_DIST_TREE_COMP_NAME)->write_string(tree_name);
1594  free(tree_name);
1595 }
1596 
1598  AW_root *aw_root = aww->get_root();
1599  char *tree_name = aw_root->awar(AWAR_DIST_TREE_CURR_NAME)->read_string();
1600  aw_root->awar(AWAR_DIST_TREE_STD_NAME)->write_string(tree_name);
1601  free(tree_name);
1602 }
1603 
1604 
1607  aws->init(aw_root, "NEIGHBOUR JOINING", "NEIGHBOUR JOINING [ARB_DIST]");
1608  aws->load_xfig("di_ge_ma.fig");
1609  aws->button_length(10);
1610 
1611  WindowCallback close_cb = makeWindowCallback(di_exit, gb_main);
1612 
1613  aws->at("close");
1614  aws->callback(close_cb);
1615  aws->create_button("CLOSE", "CLOSE", "C");
1616 
1617  aws->at("help");
1618  aws->callback(makeHelpCallback("dist.hlp"));
1619  aws->create_button("HELP", "HELP", "H");
1620 
1621  GB_push_transaction(gb_main);
1622 
1623 #if defined(DEBUG)
1624  AWT_create_debug_menu(aws);
1625 #endif // DEBUG
1626 
1627  aws->create_menu("File", "F", AWM_ALL);
1628  insert_macro_menu_entry(aws, false);
1629  aws->insert_menu_topic("quit", "Quit", "Q", "quit.hlp", AWM_ALL, close_cb);
1630 
1631  aws->create_menu("Properties", "P", AWM_ALL);
1632  aws->insert_menu_topic("frame_props", "Frame settings ...", "F", "props_frame.hlp", AWM_ALL, AW_preset_window);
1633  aws->sep______________();
1635  aws->sep______________();
1636  aws->insert_menu_topic("save_props", "Save Properties (dist.arb)", "S", "savedef.hlp", AWM_ALL, AW_save_properties);
1637 
1638  aws->insert_help_topic("ARB_DIST help", "D", "dist.hlp", AWM_ALL, makeHelpCallback("dist.hlp"));
1639 
1640  // ------------------
1641  // left side
1642 
1643  aws->at("which_species");
1645  aws->insert_option("all", "a", "all");
1646  aws->insert_default_option("marked", "m", "marked");
1647  aws->update_option_menu();
1648 
1649  aws->at("which_alignment");
1651 
1652  // filter & weights
1653 
1654  AW_awar *awar_dist_alignment = aws->get_root()->awar_string(AWAR_DIST_ALIGNMENT);
1655  WeightedFilter *weighted_filter = // do NOT free (bound to callbacks)
1656  new WeightedFilter(gb_main, aws->get_root(), AWAR_DIST_FILTER_NAME, AWAR_DIST_COLUMN_STAT_NAME, awar_dist_alignment);
1657 
1658  aws->at("filter_select");
1659  aws->callback(makeCreateWindowCallback(awt_create_select_filter_win, weighted_filter->get_adfiltercbstruct()));
1660  aws->create_button("SELECT_FILTER", AWAR_DIST_FILTER_NAME);
1661 
1662  aws->at("weights_select");
1663  aws->sens_mask(AWM_EXP);
1664  aws->callback(makeCreateWindowCallback(COLSTAT_create_selection_window, weighted_filter->get_column_stat()));
1665  aws->create_button("SELECT_COL_STAT", AWAR_DIST_COLUMN_STAT_NAME);
1666  aws->sens_mask(AWM_ALL);
1667 
1668  aws->at("which_cancel");
1670 
1671  aws->at("cancel_select");
1673  aws->create_button("SELECT_CANCEL_CHARS", "Info", "C");
1674 
1675  aws->at("change_matrix");
1677  aws->create_button("EDIT_MATRIX", "Edit Matrix");
1678 
1679  aws->at("enable");
1681 
1682  aws->at("which_correction");
1684  aws->insert_option("none", "n", (int)DI_TRANSFORMATION_NONE);
1685  aws->insert_option("similarity", "n", (int)DI_TRANSFORMATION_SIMILARITY);
1686  aws->insert_option("jukes-cantor (dna)", "c", (int)DI_TRANSFORMATION_JUKES_CANTOR);
1687  aws->insert_option("felsenstein (dna)", "f", (int)DI_TRANSFORMATION_FELSENSTEIN);
1688  aws->insert_option("olsen (dna)", "o", (int)DI_TRANSFORMATION_OLSEN);
1689  aws->insert_option("felsenstein/voigt (exp)", "1", (int)DI_TRANSFORMATION_FELSENSTEIN_VOIGT);
1690  aws->insert_option("olsen/voigt (exp)", "2", (int)DI_TRANSFORMATION_OLSEN_VOIGT);
1691  aws->insert_option("kimura (pro)", "k", (int)DI_TRANSFORMATION_KIMURA);
1692  aws->insert_option("PAM (protein)", "c", (int)DI_TRANSFORMATION_PAM);
1693  aws->insert_option("Cat. Hall(exp)", "c", (int)DI_TRANSFORMATION_CATEGORIES_HALL);
1694  aws->insert_option("Cat. Barker(exp)", "c", (int)DI_TRANSFORMATION_CATEGORIES_BARKER);
1695  aws->insert_option("Cat.Chem (exp)", "c", (int)DI_TRANSFORMATION_CATEGORIES_CHEMICAL);
1696  aws->insert_option("from selected tree", "t", (int)DI_TRANSFORMATION_FROM_TREE);
1697  aws->insert_default_option("unknown", "u", (int)DI_TRANSFORMATION_NONE);
1698 
1699  aws->update_option_menu();
1700 
1701  aws->at("autodetect"); // auto
1702  aws->callback(makeWindowCallback(di_autodetect_callback, gb_main));
1703  aws->sens_mask(AWM_EXP);
1704  aws->create_button("AUTODETECT_CORRECTION", "AUTODETECT", "A");
1705  aws->sens_mask(AWM_ALL);
1706 
1707  // -------------------
1708  // right side
1709 
1710 
1711  aws->at("mark_distance");
1712  aws->callback(makeWindowCallback(di_mark_by_distance, weighted_filter));
1713  aws->create_autosize_button("MARK_BY_DIST", "Mark all species");
1714 
1715  aws->at("mark_lower");
1717 
1718  aws->at("mark_upper");
1720 
1721  // -----------------
1722 
1723  // tree selection
1724 
1725  aws->at("tree_list");
1727 
1728  aws->at("detect_clusters");
1729  aws->callback(makeCreateWindowCallback(DI_create_cluster_detection_window, weighted_filter));
1730  aws->create_autosize_button("DETECT_CLUSTERS", "Detect homogenous clusters in tree", "D");
1731 
1732  // matrix calculation
1733 
1734  aws->button_length(18);
1735 
1736  aws->at("calculate");
1737  aws->callback(makeWindowCallback(di_calculate_full_matrix_cb, weighted_filter));
1738  aws->create_button("CALC_FULL_MATRIX", "Calculate\nFull Matrix", "F");
1739 
1740  aws->at("compress");
1741  aws->callback(makeWindowCallback(di_calculate_compressed_matrix_cb, weighted_filter));
1742  aws->create_button("CALC_COMPRESSED_MATRIX", "Calculate\nCompressed Matrix", "C");
1743 
1744  recalculate_matrix_cb = new BoundWindowCallback(aws, makeWindowCallback(di_calculate_full_matrix_cb, weighted_filter));
1745 
1746  aws->button_length(13);
1747 
1748  {
1749  static save_matrix_params sparams;
1750 
1752  sparams.weighted_filter = weighted_filter;
1753 
1754  aws->at("save_matrix");
1755  aws->callback(makeCreateWindowCallback(DI_create_save_matrix_window, &sparams));
1756  aws->create_button("SAVE_MATRIX", "Save matrix", "M");
1757 
1758  aws->at("view_matrix");
1759  aws->callback(makeWindowCallback(di_view_matrix_cb, &sparams));
1760  aws->create_button("VIEW_MATRIX", "View matrix", "V");
1761  }
1762 
1763  aws->button_length(22);
1764  aws->at("use_compr_tree");
1766  aws->create_button("USE_COMPRESSION_TREE", "Use to compress", "");
1767  aws->at("use_sort_tree");
1769  aws->create_button("USE_SORT_TREE", "Use to sort", "");
1770 
1771  aws->at("compr_tree_name"); aws->create_input_field(AWAR_DIST_TREE_COMP_NAME, 12);
1772  aws->at("sort_tree_name"); aws->create_input_field(AWAR_DIST_TREE_SORT_NAME, 12);
1773 
1774  // tree calculation
1775 
1776  aws->button_length(18);
1777 
1778  aws->at("t_calculate");
1779  aws->callback(makeWindowCallback(di_calculate_tree_cb, weighted_filter, false));
1780  aws->create_button("CALC_TREE", "Calculate \ntree", "C");
1781 
1782  aws->at("bootstrap");
1783  aws->callback(makeWindowCallback(di_calculate_tree_cb, weighted_filter, true));
1784  aws->create_button("CALC_BOOTSTRAP_TREE", "Calculate \nbootstrap tree");
1785 
1786  recalculate_tree_cb = new BoundWindowCallback(aws, makeWindowCallback(di_calculate_tree_cb, weighted_filter, false));
1787 
1788  aws->button_length(22);
1789  aws->at("use_existing");
1791  aws->create_button("USE_NAME", "Use as new tree name", "");
1792 
1793  aws->at("calc_tree_name");
1795 
1796  aws->at("bcount");
1798 
1799  {
1800  aws->sens_mask(AWM_EXP);
1801 
1802  aws->at("auto_calc_tree");
1803  aws->label("Auto calculate tree");
1805 
1806  aws->at("auto_recalc");
1807  aws->label("Auto recalculate");
1809 
1810  aws->sens_mask(AWM_ALL);
1811  }
1812 
1813  bool disable_autocalc = !ARB_in_expert_mode(aw_root);
1814  if (disable_autocalc) {
1817  }
1818 
1819  GB_pop_transaction(gb_main);
1820  return aws;
1821 }
1822 
1823 // --------------------------------------------------------------------------------
1824 
1825 #ifdef UNIT_TESTS
1826 #include <arb_diff.h>
1827 #include <arb_file.h>
1828 
1829 #ifndef TEST_UNIT_H
1830 #include <test_unit.h>
1831 #endif
1832 
1833 class DIST_testenv : virtual Noncopyable {
1834  GB_shell shell;
1835  GBDATA *gb_main;
1836  AliView *ali_view;
1837 
1838 public:
1839  DIST_testenv(const char *dbname, const char *aliName)
1840  : ali_view(NULp)
1841  {
1842  gb_main = GB_open(dbname, "r");
1843  TEST_REJECT_NULL(gb_main);
1844 
1845  GB_transaction ta(gb_main);
1846 
1847  int aliLength = GBT_get_alignment_len(gb_main, aliName);
1848  TEST_REJECT(aliLength<=0);
1849 
1850  AP_filter filter(aliLength);
1851  if (!filter.is_invalid()) {
1852  AP_weights weights(&filter);
1853  ali_view = new AliView(gb_main, filter, weights, aliName);
1854  }
1855  }
1856  ~DIST_testenv() {
1857  delete ali_view;
1858  GB_close(gb_main);
1859  }
1860 
1861  const AliView& aliview() const { return *ali_view; }
1862  GBDATA *gbmain() const { return gb_main; }
1863 };
1864 
1865 void TEST_matrix() {
1866  for (int iat = GB_AT_RNA; iat<=GB_AT_AA; ++iat) {
1868  // ---------------
1869  // setup
1870  // GB_AT_RNA GB_AT_DNA GB_AT_AA
1871  const char *db_name[]= { NULp, "TEST_trees.arb", "TEST_realign.arb", "TEST_realign.arb", };
1872  const char *ali_name[]= { NULp, "ali_5s", "ali_dna", "ali_pro", };
1873 
1874  TEST_ANNOTATE(GBS_global_string("ali_name=%s", ali_name[at]));
1875  DIST_testenv env(db_name[at], ali_name[at]);
1876 
1877  DI_MATRIX matrix(env.aliview());
1878  MatrixOrder order(env.gbmain(), "tree_abc"); // no such tree!
1879  TEST_EXPECT_NO_ERROR(matrix.load(DI_LOAD_MARKED, order, true, NULp));
1880 
1881  // -------------------------------
1882  // detect_transformation
1883  DI_TRANSFORMATION detected_trans;
1884  {
1885  string msg;
1886 
1887  detected_trans = matrix.detect_transformation(msg);
1889  switch (at) {
1890  case GB_AT_RNA: expected = DI_TRANSFORMATION_NONE; break;
1891  case GB_AT_DNA: expected = DI_TRANSFORMATION_JUKES_CANTOR; break;
1892  case GB_AT_AA: expected = DI_TRANSFORMATION_PAM; break;
1893  case GB_AT_UNKNOWN: di_assert(0); break;
1894  }
1895  TEST_EXPECT_EQUAL(detected_trans, expected);
1896  }
1897 
1898  // ------------------------------
1899  // calculate the matrix
1900 
1901  // @@@ does not test user-defined transformation-matrix!
1902  if (at == GB_AT_AA) {
1903  matrix.calculate_pro(detected_trans, NULp);
1904  }
1905  else {
1906  if (at == GB_AT_RNA) detected_trans = DI_TRANSFORMATION_FELSENSTEIN; // force calculate_overall_freqs
1907  matrix.calculate("", detected_trans, NULp, NULp);
1908  }
1909 
1910  // -----------------------------------
1911  // save in available formats
1912 
1913  for (DI_SAVE_TYPE saveType = DI_SAVE_PHYLIP_COMP; saveType<=DI_SAVE_TABBED; saveType = DI_SAVE_TYPE(saveType+1)) {
1914  const char *savename = "distance/matrix.out";
1915  matrix.save(savename, saveType);
1916 
1917  const char *suffixAT[] = { NULp, "rna", "dna", "pro" };
1918  const char *suffixST[] = { "phylipComp", "readable", "tabbed" };
1919  char *expected = GBS_global_string_copy("distance/matrix.%s.%s.expected", suffixAT[at], suffixST[saveType]);
1920 
1921 // #define TEST_AUTO_UPDATE // uncomment to auto-update expected matrices
1922 
1923 #if defined(TEST_AUTO_UPDATE)
1924  TEST_COPY_FILE(savename, expected);
1925 #else
1926  TEST_EXPECT_TEXTFILES_EQUAL(savename, expected);
1927 #endif // TEST_AUTO_UPDATE
1929 
1930  free(expected);
1931  }
1932  }
1933 }
1934 
1935 #endif // UNIT_TESTS
1936 
1937 // --------------------------------------------------------------------------------
1938 
GB_ERROR GB_begin_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2528
#define AWAR_DIST_SAVE_MATRIX_FILENAME
Definition: DI_matr.cxx:59
void insert_option(AW_label choice_label, const char *mnemonic, const char *var_value, const char *name_of_color=NULp)
#define arb_assert(cond)
Definition: arb_assert.h:245
const char * GB_ERROR
Definition: arb_core.h:25
BoundWindowCallback(AW_window *aww_, const WindowCallback &cb_)
Definition: DI_matr.cxx:82
#define NONE
Definition: GDE_def.h:34
GBDATA * GB_open(const char *path, const char *opent)
Definition: ad_load.cxx:1363
GB_TYPES type
#define AWAR_DIST_SAVE_MATRIX_TYPE
Definition: DI_matr.cxx:58
ColumnStat * get_column_stat()
Definition: gui_aliview.hxx:42
SizeAwareTree * get_consensus_tree(GB_ERROR &error)
Definition: CT_ctree.cxx:150
adfiltercbstruct * get_adfiltercbstruct()
Definition: gui_aliview.hxx:41
void button_length(int length)
Definition: AW_at.cxx:288
void force_update()
Definition: arb_progress.h:371
void sens_mask(AW_active mask)
Definition: AW_window.cxx:127
GBDATA * GBT_first_marked_species_rel_species_data(GBDATA *gb_species_data)
Definition: aditem.cxx:109
static char * y[maxsp+1]
void matrix_needs_recalc_cb()
Definition: DI_matr.cxx:117
return string(buffer, length)
void insert_menu_topic(const char *id, const char *name, const char *mnemonic, const char *help_text_, AW_active mask, const WindowCallback &wcb)
Definition: AW_window.cxx:595
void show_warnings(const string &helpfile)
CONSTEXPR_INLINE unsigned char safeCharIndex(char c)
Definition: dupstr.h:73
void load_xfig(const char *file, bool resize=true)
Definition: AW_window.cxx:720
#define AWAR_DIST_FILTER_ALIGNMENT
Definition: di_awars.hxx:23
void tree_needs_recalc_cb()
Definition: DI_matr.cxx:121
GB_ERROR GB_add_callback(GBDATA *gbd, GB_CB_TYPE type, const DatabaseCallback &dbcb)
Definition: ad_cb.cxx:356
GB_ERROR extract_from_tree(const char *treename, bool *aborted_flag)
Definition: DI_matr.cxx:841
void set(size_t i, size_t j, T val)
Definition: matrix.h:49
~DI_MATRIX()
Definition: DI_matr.cxx:343
void GB_sort(void **array, size_t first, size_t behind_last, gb_compare_function compare, void *client_data)
Definition: arb_sort.cxx:27
bool has_type(DI_MATRIX_TYPE type) const
Definition: di_matr.hxx:215
#define AWAR_DIST_MATRIX_AUTO_CALC_TREE
Definition: DI_matr.cxx:56
AW_window * COLSTAT_create_selection_window(AW_root *aw_root, ColumnStat *column_stat)
Definition: ColumnStat.cxx:376
CONSTEXPR unsigned UPDATE_DELAY
Definition: DI_matr.cxx:110
GB_ERROR GB_end_transaction(GBDATA *gbd, GB_ERROR error)
Definition: arbdb.cxx:2561
void at(int x, int y)
Definition: AW_at.cxx:93
char name[nmlngth+1]
DI_ENTRY(GBDATA *gbd, DI_MATRIX *phmatrix_)
Definition: DI_matr.cxx:280
void AW_create_standard_fileselection(AW_window *aws, const char *awar_prefix)
Definition: aw_file.hxx:30
#define ASSERT_RESULT(Type, Expected, Expr)
Definition: arb_assert.h:336
#define NO_TREE_SELECTED
GB_ERROR calculate_pro(DI_TRANSFORMATION transformation, bool *aborted_flag)
Definition: DI_matr.cxx:753
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
#define AWAR_DIST_WHICH_SPECIES
Definition: di_awars.hxx:20
void create_toggle(const char *awar_name)
Definition: AW_button.cxx:844
void enable_bootstrap()
Definition: AP_filter.cxx:206
TreeNode * GBT_read_tree(GBDATA *gb_main, const char *tree_name, TreeRoot *troot)
Definition: adtree.cxx:837
long read_int() const
Definition: AW_awar.cxx:184
AW_awar * set_minmax(float min, float max)
Definition: AW_awar.cxx:530
AW_window * DI_create_save_matrix_window(AW_root *aw_root, save_matrix_params *save_params)
Definition: DI_matr.cxx:1122
#define AWAR_DIST_ALIGNMENT
Definition: di_awars.hxx:21
static void selected_tree_changed_cb()
Definition: DI_matr.cxx:190
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
static GB_ERROR last_matrix_calculation_error
Definition: DI_matr.cxx:92
CONSTEXPR_INLINE long sum_of_triangular_numbers(const long L)
Definition: triangular.h:30
GB_ERROR calculate(const char *cancel, DI_TRANSFORMATION transformation, bool *aborted_flag, AP_matrix *userdef_matrix)
Definition: DI_matr.cxx:548
long GBT_get_alignment_len(GBDATA *gb_main, const char *aliname)
Definition: adali.cxx:833
#define AWAR_DIST_TREE_SORT_NAME
Definition: DI_matr.cxx:53
AW_DB_selection * awt_create_TREE_selection_list(GBDATA *gb_main, AW_window *aws, const char *varname)
AP_sequence_parsimony * get_nucl_seq()
Definition: di_matr.hxx:86
void AW_POPDOWN(AW_window *window)
Definition: AW_window.cxx:52
~DI_ENTRY()
Definition: DI_matr.cxx:314
void AW_insert_common_property_menu_entries(AW_window_menu_modes *awmm)
Definition: AW_preset.cxx:1445
void AWT_registerTreeAwarCallback(AW_awar *awar, const TreeAwarCallback &tacb, bool triggerIfTreeDataChanges)
void auto_subtitles(const char *prefix)
Definition: arb_progress.h:344
void set_changed_cb(DI_MATRIX_CB cb)
Definition: di_matr.hxx:203
void add_timed_callback(int ms, const TimedCallback &tcb)
Definition: AW_root.cxx:538
bool isNull() const
test if SmartPtr is NULp
Definition: smartptr.h:248
#define AWAR_DIST_FILTER_SIMPLIFY
Definition: di_awars.hxx:26
#define EXIT_SUCCESS
Definition: arb_a2ps.c:154
#define AWAR_DIST_TREE_COMP_NAME
Definition: DI_matr.cxx:54
int GB_unlink(const char *path)
Definition: arb_file.cxx:188
Definition: trnsprob.h:20
AP_sequence * sequence
Definition: di_matr.hxx:84
static size_t get_load_count(LoadWhat what, GBDATA *gb_main, GBDATA **species_list)
Definition: DI_matr.cxx:394
char * unload()
Definition: DI_matr.cxx:334
void mark(UpdateFlag needed)
void create_input_fields(AW_window *aww)
Definition: AP_matrix.cxx:82
bool GBT_is_alignment_protein(GBDATA *gb_main, const char *alignment_name)
Definition: adali.cxx:898
#define ARRAY_ELEMS(array)
Definition: arb_defs.h:19
void setNull()
set SmartPtr to NULp
Definition: smartptr.h:251
CONSTEXPR_INLINE long triangular_number(const long N)
Definition: triangular.h:18
void update_option_menu()
GB_ERROR GB_push_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2494
void add_update_cb()
Definition: DI_matr.cxx:113
GB_ERROR error_if_aborted()
Definition: arb_progress.h:323
void forget_if_not_has_type(DI_MATRIX_TYPE wanted_type)
Definition: di_matr.hxx:218
AW_awar * add_callback(const RootCallback &cb)
Definition: AW_awar.cxx:231
#define AWAR_DIST_MATRIX_DNA_ENABLED
Definition: di_awars.hxx:31
GBDATA * GBT_first_species_rel_species_data(GBDATA *gb_species_data)
Definition: aditem.cxx:121
static int TreeOrderedSpecies_cmp(const void *p1, const void *p2, void *)
Definition: DI_matr.cxx:383
GB_ERROR GBT_write_tree_remark(GBDATA *gb_main, const char *tree_name, const char *remark)
Definition: adtree.cxx:533
static FullNameMap names
const char * read_char_pntr() const
Definition: AW_awar.cxx:168
GB_ERROR link_to_tree(NamedNodes &named, TreeNode *node)
Definition: DI_matr.cxx:776
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:342
static AW_root * SINGLETON
Definition: aw_root.hxx:102
STATIC_ASSERT(ARRAY_ELEMS(enum_trans_to_string)==DI_TRANSFORMATION_COUNT)
static void matrix_changed_cb()
Definition: DI_matr.cxx:94
void applyTo(struct TreeOrderedSpecies **gb_species_array, size_t array_size) const
Definition: DI_matr.cxx:390
WindowCallback makeHelpCallback(const char *helpfile)
Definition: aw_window.hxx:106
char * GBT_read_string(GBDATA *gb_container, const char *fieldpath)
Definition: adtools.cxx:267
__ATTR__USERESULT GB_ERROR insert_tree_weighted(const TreeNode *tree, int leafs, double weight, bool provideProgress)
Definition: CT_ctree.cxx:145
static void di_calculate_full_matrix_cb(AW_window *aww, const WeightedFilter *weighted_filter)
Definition: DI_matr.cxx:1532
#define AWAR_DIST_COLUMN_STAT_NAME
Definition: DI_matr.cxx:51
static SmartPtr< BoundWindowCallback > recalculate_tree_cb
Definition: DI_matr.cxx:90
GB_ERROR GBT_check_tree_name(const char *tree_name)
Definition: adtree.cxx:1085
bool isSet() const
test if SmartPtr is not NULp
Definition: smartptr.h:245
AW_awar * awar_float(const char *var_name, float default_value=0.0, AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:560
GBDATA * gb_species_data
Definition: adname.cxx:33
Generic smart pointer.
Definition: smartptr.h:149
AW_window * DI_create_cluster_detection_window(AW_root *aw_root, WeightedFilter *weightedFilter)
bool aborted()
Definition: arb_progress.h:335
DI_SAVE_TYPE
Definition: di_matr.hxx:93
DI_MATRIX * get()
Definition: di_matr.hxx:192
void AW_save_properties(AW_window *aw)
Definition: AW_preset.cxx:1452
void GB_clear_error()
Definition: arb_msg.cxx:354
AW_window * DI_create_matrix_window(AW_root *aw_root, GBDATA *gb_main)
Definition: DI_matr.cxx:1605
#define false
Definition: ureadseq.h:13
static int weights[MAX_BASETYPES][MAX_BASETYPES]
Definition: ClustalV.cxx:71
const AliView * get_aliview() const
Definition: di_matr.hxx:160
GB_ERROR GBT_write_tree(GBDATA *gb_main, const char *tree_name, TreeNode *tree)
Definition: adtree.cxx:523
#define AWAR_DIST_MIN_DIST
Definition: di_matr.hxx:40
void create_menu(const char *name, const char *mnemonic, AW_active mask=AWM_ALL)
Definition: AW_window.cxx:472
AP_FLOAT get(int i, int j)
Definition: AP_matrix.hxx:47
#define TEST_REJECT(cond)
Definition: test_unit.h:1330
#define TEST_REJECT_NULL(n)
Definition: test_unit.h:1325
TreeNode * neighbourjoining(const char *const *names, const AP_smatrix &smatrix, TreeRoot *troot, bool *aborted_flag)
Definition: NJ.cxx:204
void touch()
Definition: AW_awar.cxx:207
static MatrixDisplay * matrixDisplay
Definition: DI_matr.cxx:65
static __ATTR__USERESULT GB_ERROR di_calculate_matrix(AW_root *aw_root, const WeightedFilter *weighted_filter, bool bootstrap_flag, bool show_warnings, bool *aborted_flag)
Definition: DI_matr.cxx:887
static void error(const char *msg)
Definition: mkptypes.cxx:96
#define AWAR_DIST_MATRIX_AUTO_RECALC
Definition: DI_matr.cxx:49
#define AWAR_DIST_MATRIX_DNA_BASE
Definition: di_awars.hxx:30
#define AWAR_TREE_REFRESH
void AW_create_fileselection_awars(AW_root *awr, const char *awar_base, const char *directories, const char *filter, const char *file_name)
Definition: AW_file.cxx:72
static void di_calculate_tree_cb(AW_window *aww, WeightedFilter *weighted_filter, bool bootstrap_flag)
Definition: DI_matr.cxx:1194
Definition: di_matr.hxx:75
static AW_window * create_dna_matrix_window(AW_root *aw_root)
Definition: DI_matr.cxx:172
AW_window * AW_preset_window(AW_root *root)
Definition: AW_preset.cxx:1920
GBDATA * GBT_next_marked_species(GBDATA *gb_species)
Definition: aditem.cxx:116
#define AWAR_TREE
void label(const char *label)
Definition: AW_window.cxx:102
void insert_help_topic(const char *labeli, const char *mnemonic, const char *helpText, AW_active mask, const WindowCallback &cb)
Definition: AW_window.cxx:569
static void di_define_sort_tree_name_cb(AW_window *aww)
Definition: DI_matr.cxx:1584
TreeNode * GBT_read_tree_and_size(GBDATA *gb_main, const char *tree_name, TreeRoot *troot, int *tree_size)
Definition: adtree.cxx:770
DI_MATRIX(const AliView &aliview)
Definition: DI_matr.cxx:320
di_cattype
Definition: di_protdist.hxx:26
void set_descriptions(int idx, const char *desc)
Definition: AP_matrix.hxx:72
#define AWAR_SPECIES_NAME
GBDATA * get_gb_main() const
Definition: GUI_aliview.cxx:87
AW_window * awt_create_select_filter_win(AW_root *aw_root, adfiltercbstruct *acbs)
Definition: AWT_filter.cxx:365
#define TEST_EXPECT_ZERO_OR_SHOW_ERRNO(iocond)
Definition: test_unit.h:1090
static TreeNode * findNode(TreeNode *node, const char *name)
Definition: DI_matr.cxx:798
#define AWAR_DIST_BOOTSTRAP_COUNT
Definition: DI_matr.cxx:47
void compressed_matrix_needs_recalc_cb()
Definition: DI_matr.cxx:126
static unsigned update_cb(AW_root *aw_root)
Definition: DI_matr.cxx:132
static SearchTree * tree[SEARCH_PATTERNS]
Definition: ED4_search.cxx:629
char * name
Definition: di_matr.hxx:89
static GB_ERROR init(NamedNodes &node, TreeNode *tree, const DI_ENTRY *const *const entries, size_t nentries)
Definition: DI_matr.cxx:809
char * read_string() const
Definition: AW_awar.cxx:198
static void di_define_compression_tree_name_cb(AW_window *aww)
Definition: DI_matr.cxx:1590
AW_awar * awar(const char *awar)
Definition: AW_root.cxx:554
DI_MATRIX_TYPE matrix_type
Definition: di_matr.hxx:154
GB_ERROR GB_pop_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2524
Definition: arbdb.h:86
GB_ERROR DI_create_matrix_variables(AW_root *aw_root, AW_default def, AW_default db)
Definition: DI_matr.cxx:196
bool exists() const
Definition: di_matr.hxx:201
const AP_filter * get_filter() const
Definition: AliView.hxx:42
static const char * enum_trans_to_string[]
Definition: DI_matr.cxx:1172
#define AWAR_DIST_CANCEL_CHARS
Definition: DI_matr.cxx:48
static void * M
Definition: mem.cxx:18
void AW_refresh_fileselection(AW_root *awr, const char *awar_prefix)
Definition: AW_file.cxx:944
const WeightedFilter * weighted_filter
Definition: di_matr.hxx:230
MatrixOrder(GBDATA *gb_main, GB_CSTR sort_tree_name)
Definition: DI_matr.cxx:359
static void di_mark_by_distance(AW_window *aww, WeightedFilter *weighted_filter)
Definition: DI_matr.cxx:981
void create_autosize_button(const char *macro_name, AW_label label, const char *mnemonic=NULp, unsigned xtraSpace=1)
Definition: AW_button.cxx:421
GB_ERROR makedists(bool *aborted_flag)
long GBT_count_marked_species(GBDATA *gb_main)
Definition: aditem.cxx:372
#define AWAR_DIST_MAX_DIST
Definition: di_matr.hxx:41
float read_float() const
Definition: AW_awar.cxx:177
AW_window * DI_create_view_matrix_window(AW_root *awr, MatrixDisplay *disp, save_matrix_params *sparam)
static void auto_calc_changed_cb(AW_root *aw_root)
Definition: DI_matr.cxx:164
void unlink_awars_from_DB(GBDATA *gb_main)
Definition: AW_root.cxx:635
GB_alignment_type
Definition: arbdb_base.h:61
void insert_default_option(AW_label choice_label, const char *mnemonic, const char *var_value, const char *name_of_color=NULp)
AW_DB_selection * awt_create_ALI_selection_list(GBDATA *gb_main, AW_window *aws, const char *varname, const char *ali_type_match)
DI_GLOBAL_MATRIX GLOBAL_MATRIX
Definition: DI_matr.cxx:63
const char * awar_base
Definition: di_matr.hxx:229
AP_smatrix * matrix
Definition: di_matr.hxx:153
void create_input_field(const char *awar_name, int columns=0)
Definition: AW_button.cxx:857
#define AWAR_DIST_TREE_CURR_NAME
Definition: di_awars.hxx:28
bool is_leaf() const
Definition: TreeNode.h:211
AW_awar * awar_int(const char *var_name, long default_value=0, AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:580
DI_ENTRY ** entries
Definition: di_matr.hxx:151
TYPE * ARB_calloc(size_t nelem)
Definition: arb_mem.h:81
#define IF_ASSERTION_USED(x)
Definition: arb_assert.h:308
AliView * create_aliview(const char *aliname, GB_ERROR &error) const
Definition: GUI_aliview.cxx:66
static SmartPtr< BoundWindowCallback > recalculate_matrix_cb
Definition: DI_matr.cxx:89
void DI_create_cluster_awars(AW_root *aw_root, AW_default def, AW_default db)
GBT_LEN intree_distance_to(const TreeNode *other) const
Definition: TreeNode.h:288
GB_ERROR close(GB_ERROR error)
Definition: arbdbpp.cxx:35
void GB_write_flag(GBDATA *gbd, long flag)
Definition: arbdb.cxx:2773
GB_ERROR GBT_is_invalid(const TreeNode *tree)
Definition: adtree.cxx:880
LoadWhat whatToLoad()
Definition: DI_matr.cxx:882
#define AWAR_DIST_SAVE_MATRIX_BASE
Definition: di_matr.hxx:37
void update_from_awars(AW_root *awr)
Definition: AP_matrix.cxx:67
TreeOrderedSpecies(const MatrixOrder &order, GBDATA *gb_spec)
Definition: DI_matr.cxx:353
size_t nentries
Definition: di_matr.hxx:152
static AP_matrix * get_user_matrix()
Definition: DI_matr.cxx:68
#define __ATTR__USERESULT
Definition: attributes.h:58
char * name
Definition: TreeNode.h:174
CONSTEXPR_INLINE long matrix_halfsize(long entries, bool inclusive_diagonal)
Definition: AP_matrix.hxx:26
static void di_save_matrix_cb(AW_window *aww)
Definition: DI_matr.cxx:1108
AW_awar * map(const char *awarn)
Definition: AW_awar.cxx:521
bool ARB_in_expert_mode(AW_root *awr)
void ARB_realloc(TYPE *&tgt, size_t nelem)
Definition: arb_mem.h:43
void subtitle(const char *stitle)
Definition: arb_progress.h:321
GBDATA * GBT_first_species(GBDATA *gb_main)
Definition: aditem.cxx:124
GB_ERROR is_invalid() const
Definition: AP_filter.hxx:123
void GBT_message(GBDATA *gb_main, const char *msg)
Definition: adtools.cxx:238
static GB_ERROR di_recalc_matrix()
Definition: DI_matr.cxx:1080
#define di_assert(cond)
Definition: DI_clusters.cxx:32
void replaceBy(DI_MATRIX *new_global)
Definition: di_matr.hxx:199
void create_awars(AW_root *awr)
Definition: AP_matrix.cxx:47
void auto_increment(int dx, int dy)
Definition: AW_at.cxx:273
#define TEST_EXPECT_NO_ERROR(call)
Definition: test_unit.h:1118
static void di_calculate_compressed_matrix_cb(AW_window *aww, WeightedFilter *weighted_filter)
Definition: DI_matr.cxx:1542
void aw_message(const char *msg)
Definition: AW_status.cxx:1142
AW_option_menu_struct * create_option_menu(const char *awar_name)
GB_ERROR GBT_log_to_named_trees_remark(GBDATA *gb_main, const char *tree_name, const char *log_entry, bool stamp)
Definition: adtree.cxx:556
void insert_macro_menu_entry(AW_window *awm, bool prepend_separator)
Definition: macro_gui.cxx:233
static AP_userdef_matrix userdef_DNA_matrix(AP_MAX, AWAR_DIST_MATRIX_DNA_BASE)
AW_root * get_root()
Definition: aw_window.hxx:359
DI_TRANSFORMATION
Definition: di_matr.hxx:43
void shutdown_macro_recording(AW_root *aw_root)
Definition: trackers.cxx:475
GBDATA * GBT_next_species(GBDATA *gb_species)
Definition: aditem.cxx:128
#define NULp
Definition: cxxforward.h:116
GBDATA * GBT_find_species(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:139
DI_TRANSFORMATION detect_transformation(std::string &msg)
Definition: distanalyse.cxx:17
const char * get_aliname() const
Definition: di_matr.hxx:159
#define __ATTR__NORETURN
Definition: attributes.h:56
GB_ERROR write_string(const char *aw_string)
#define AWAR_DIST_CORR_TRANS
Definition: di_matr.hxx:36
void lazy_load_sequence() const
Definition: AP_sequence.hxx:67
char * GBT_get_default_alignment(GBDATA *gb_main)
Definition: adali.cxx:747
void sep______________()
Definition: AW_window.cxx:753
size_t size() const
Definition: matrix.h:66
T get(size_t i, size_t j) const
Definition: matrix.h:52
const char * save(const char *filename, enum DI_SAVE_TYPE type)
long GBT_get_species_count(GBDATA *gb_main)
Definition: aditem.cxx:207
#define AWAR_DIST_TREE_STD_NAME
Definition: DI_matr.cxx:55
char * AWT_get_combined_filter_name(AW_root *aw_root, GB_CSTR prefix)
Definition: AWT_filter.cxx:334
GB_transaction ta(gb_var)
static void di_view_matrix_cb(AW_window *aww, save_matrix_params *sparam)
Definition: DI_matr.cxx:1091
void callback(const WindowCallback &cb)
Definition: AW_window.cxx:133
void destroy(TreeNode *that)
Definition: TreeNode.h:600
GB_ERROR bind_to_species(GBDATA *gb_species)
Definition: AP_sequence.cxx:24
static RecalcNeeded need_recalc
Definition: DI_matr.cxx:108
GBDATA * gb_main
Definition: adname.cxx:32
size_t get_length() const
Definition: AliView.cxx:66
AW_awar * awar_string(const char *var_name, const char *default_value="", AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:570
char * compress(TreeNode *tree)
GBDATA * GB_search(GBDATA *gbd, const char *fieldpath, GB_TYPES create)
Definition: adquery.cxx:531
void hide_or_notify(const char *error)
Definition: AW_window.cxx:1845
GB_CSTR GBT_get_name_or_description(GBDATA *gb_item)
Definition: aditem.cxx:459
bool defined() const
Definition: di_matr.hxx:125
#define TEST_EXPECT_TEXTFILES_EQUAL(fgot, fwant)
Definition: test_unit.h:1424
DI_MATRIX * swap(DI_MATRIX *other)
Definition: di_matr.hxx:208
std::map< const char *, TreeNode *, charpLess > NamedNodes
Definition: DI_matr.cxx:774
#define AWAR_DIST_FILTER_NAME
Definition: di_awars.hxx:24
#define CONSTEXPR
Definition: cxxforward.h:108
static Params P
Definition: arb_probe.cxx:81
#define AW_ROOT_DEFAULT
Definition: aw_base.hxx:106
GB_ERROR load(LoadWhat what, const MatrixOrder &order, bool show_warnings, GBDATA **species_list) __ATTR__USERESULT
Definition: DI_matr.cxx:415
#define TEST_EXPECT_EQUAL(expr, want)
Definition: test_unit.h:1294
GB_ERROR write_int(long aw_int)
#define AWAR_DIST_FILTER_FILTER
Definition: di_awars.hxx:25
GBDATA * GB_entry(GBDATA *father, const char *key)
Definition: adquery.cxx:334
void inc_and_check_user_abort(GB_ERROR &error)
Definition: arb_progress.h:332
void init(AW_root *root, const char *wid, const char *windowname)
Definition: AW_window.cxx:2845
void aw_message_if(GB_ERROR error)
Definition: aw_msg.hxx:21
bool is_AA
Definition: di_matr.hxx:150
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:194
void GB_close(GBDATA *gbd)
Definition: arbdb.cxx:655
static Score ** U
Definition: align.cxx:67
static AW_window * awt_create_select_cancel_window(AW_root *aw_root)
Definition: DI_matr.cxx:1157
static void di_autodetect_callback(AW_window *aww, GBDATA *gb_main)
Definition: DI_matr.cxx:1436
static __ATTR__NORETURN void di_exit(AW_window *aww, GBDATA *gb_main)
Definition: DI_matr.cxx:1521
LoadWhat
Definition: di_matr.hxx:99
GB_HASH * GBS_create_hash(long estimated_elements, GB_CASE case_sens)
Definition: adhash.cxx:253
static void di_define_save_tree_name_cb(AW_window *aww)
Definition: DI_matr.cxx:1597
void create_button(const char *macro_name, AW_label label, const char *mnemonic=NULp, const char *color=NULp)
Definition: AW_button.cxx:448
#define UNCOVERED()
Definition: arb_assert.h:380
GBDATA * GBT_get_species_data(GBDATA *gb_main)
Definition: aditem.cxx:105