ARB
DI_clusters.cxx
Go to the documentation of this file.
1 // =============================================================== //
2 // //
3 // File : DI_clusters.cxx //
4 // Purpose : Detect clusters of homologous sequences in tree //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in October 2009 //
7 // Institute of Microbiology (Technical University Munich) //
8 // http://www.arb-home.de/ //
9 // //
10 // =============================================================== //
11 
12 #include "di_clusters.hxx"
13 #include "di_clustertree.hxx"
14 #include "di_foundclusters.hxx"
15 #include "di_awars.hxx"
16 
17 #include <AP_seq_protein.hxx>
18 #include <AP_seq_dna.hxx>
19 
20 #include <awt_sel_boxes.hxx>
21 
22 #include <aw_awars.hxx>
23 #include <aw_msg.hxx>
24 #include <arb_progress.h>
25 #include <arb_msg_nospam.h>
26 #include <aw_root.hxx>
27 
28 #include <list>
29 
30 using namespace std;
31 
32 #define di_assert(cond) arb_assert(cond)
33 
34 // --------------
35 // awars
36 
37 #define AWAR_CLUSTER_PREFIX AWAR_DIST_PREFIX "cluster/"
38 #define AWAR_CLUSTER_PREFIX_TEMP "/tmp/" AWAR_DIST_PREFIX
39 
40 #define AWAR_CLUSTER_MAXDIST AWAR_CLUSTER_PREFIX "maxdist"
41 #define AWAR_CLUSTER_MINSIZE AWAR_CLUSTER_PREFIX "minsize"
42 #define AWAR_CLUSTER_AUTOMARK AWAR_CLUSTER_PREFIX "automark"
43 #define AWAR_CLUSTER_MARKREP AWAR_CLUSTER_PREFIX "markrep"
44 #define AWAR_CLUSTER_SELECTREP AWAR_CLUSTER_PREFIX "selrep"
45 #define AWAR_CLUSTER_ORDER AWAR_CLUSTER_PREFIX "order"
46 
47 #define AWAR_CLUSTER_GRP_PREFIX AWAR_CLUSTER_PREFIX "group/"
48 #define AWAR_CLUSTER_GRP_PREFIX_TMP "/tmp/" AWAR_CLUSTER_GRP_PREFIX
49 
50 #define AWAR_CLUSTER_GROUP_WHAT AWAR_CLUSTER_GRP_PREFIX "all"
51 #define AWAR_CLUSTER_GROUP_EXISTING AWAR_CLUSTER_GRP_PREFIX "existing"
52 #define AWAR_CLUSTER_GROUP_NOTFOUND AWAR_CLUSTER_GRP_PREFIX "notfound"
53 #define AWAR_CLUSTER_GROUP_IDENTITY AWAR_CLUSTER_GRP_PREFIX "identity"
54 #define AWAR_CLUSTER_GROUP_PREFIX AWAR_CLUSTER_GRP_PREFIX "prefix"
55 #define AWAR_CLUSTER_GROUP_PREFIX_MATCH AWAR_CLUSTER_GRP_PREFIX "prefix_match"
56 #define AWAR_CLUSTER_GROUP_SUFFIX AWAR_CLUSTER_GRP_PREFIX "suffix"
57 #define AWAR_CLUSTER_GROUP_PARTSEP AWAR_CLUSTER_GRP_PREFIX "separator"
58 #define AWAR_CLUSTER_GROUP_EXAMPLE AWAR_CLUSTER_GRP_PREFIX_TMP "example"
59 
60 #define AWAR_CLUSTER_SELECTED AWAR_CLUSTER_PREFIX_TEMP "selected" // ID of currently selected cluster (or zero)
61 #define AWAR_CLUSTER_RESTORE_LABEL AWAR_CLUSTER_PREFIX_TEMP "rlabel" // label of restore button
62 
63 enum Group_What {
66 };
67 
71 };
72 
77 };
78 
84 };
85 
86 // ----------------------------------------
87 
89 
91 
92 // ------------------------
93 
95  di_assert(global_data);
96  global_data->free();
97  // do not delete 'global_data' itself, it will be reused when window is opened again
98 }
99 
100 // ------------------------
101 // Update contents
102 
103 static void update_cluster_sellist() {
104  global_data->update_cluster_selection_list();
105  // @@@ update result info line
106 }
107 static void update_restore_label(AW_window *aww) {
108  AW_root *aw_root = aww->get_root();
109  AW_awar *awar = aw_root->awar(AWAR_CLUSTER_RESTORE_LABEL);
110  unsigned size = global_data->count(STORED_CLUSTERS);
111  const char *label = size ? GBS_global_string("Stored: %u", size) : "None stored";
112 
113  awar->write_string(label);
114 }
115 static void update_all(AW_window *aww) {
118 }
119 
120 static void save_results_recursive(ClusterTree *subtree) {
121  if (subtree->get_state() == CS_IS_CLUSTER) {
122  global_data->add(new Cluster(subtree), SHOWN_CLUSTERS);
123  }
124  if (!subtree->is_leaf()) {
125  save_results_recursive(subtree->get_leftson());
126  save_results_recursive(subtree->get_rightson());
127  }
128 }
129 static void save_results(ClusterTreeRoot *tree) {
130  global_data->clear(SHOWN_CLUSTERS);
131  save_results_recursive(tree->get_root_node());
133 }
134 
135 static void calculate_clusters(AW_window *aww) {
136  GBDATA *gb_main = global_data->get_gb_main();
137  GB_ERROR error = NULp;
138 
139  arb_progress progress("Detecting clusters");
140 
141  // calculate ClusterTree
142  ClusterTreeRoot *tree = NULp;
143  {
144  GB_transaction ta(gb_main);
145  AW_root *aw_root = aww->get_root();
146 
147  {
148  char *use = aw_root->awar(AWAR_DIST_ALIGNMENT)->read_string();
149  AliView *aliview = global_data->weighted_filter.create_aliview(use, error);
150 
151  if (aliview) {
152  AP_sequence *seq = GBT_is_alignment_protein(gb_main, use)
153  ? (AP_sequence*)new AP_sequence_protein(aliview)
154  : new AP_sequence_parsimony(aliview);
155 
156  float maxDistance = aw_root->awar(AWAR_CLUSTER_MAXDIST)->read_float();
157  unsigned minClusterSize = aw_root->awar(AWAR_CLUSTER_MINSIZE)->read_int();
158 
159  tree = new ClusterTreeRoot(aliview, seq, maxDistance/100, minClusterSize);
160 
161  delete seq;
162  }
163  free(use);
164  }
165 
166  if (!error) {
167  progress.subtitle("Loading tree");
168  {
169  char *tree_name = aw_root->awar(AWAR_DIST_TREE_CURR_NAME)->read_string();
170  error = tree->loadFromDB(tree_name);
171  free(tree_name);
172  }
173 
174  if (!error) error = tree->linkToDB(NULp, NULp);
175  }
176  }
177 
178  if (!error) {
179  error = tree->find_clusters();
180  if (!error) save_results(tree);
181  }
182 
183  delete tree;
184 
185  if (error) aw_message(error);
186 }
187 
188 DECLARE_CBTYPE_FVV_AND_BUILDERS(ClusterCallback, void, ClusterPtr); // generates makeClusterCallback
189 
190 inline bool is_cluster(ID id) {
191  // 0 is 'no cluster' and -1 is used for list header
192  return id>0;
193 }
194 
195 static int with_affected_clusters_do(AW_root *aw_root, AffectedClusters affected, bool warn_if_none_affected, ClusterCallback cb) {
196  // returns number of affected clusters
197  int affCount = 0;
198  if (affected == SEL_CLUSTER) {
199  AW_awar *awar = aw_root->awar(AWAR_CLUSTER_SELECTED);
200  ID selID = awar->read_int();
201 
202  if (is_cluster(selID)) {
203  ClusterPtr selCluster = global_data->clusterWithID(selID);
204  cl_assert(!selCluster.isNull());
205  cb(selCluster);
206  affCount++;
207  }
208  else if (warn_if_none_affected) {
209  aw_message("No cluster is selected");
210  }
211  }
212  else {
213  unsigned shown = global_data->count(SHOWN_CLUSTERS);
214  if (shown) {
215  ClusterIDs clusters(global_data->get_clusterIDs(SHOWN_CLUSTERS)); // intended copy!
216  ClusterIDsIter cli_end = clusters.end();
217  for (ClusterIDsIter cli = clusters.begin(); cli != cli_end; ++cli) {
218  ClusterPtr cluster = global_data->clusterWithID(*cli);
219  cb(cluster);
220  affCount++;
221  }
222  }
223  else if (warn_if_none_affected) {
224  aw_message("There are no clusters in the list");
225  }
226  }
227  return affCount;
228 }
229 
230 // -------------
231 // mark
232 
234  DBItemSetIter sp_end = members.end();
235  for (DBItemSetIter sp = members.begin(); sp != sp_end; ++sp) {
236  bool is_rep = *sp == representative;
237  bool mark = false;
238 
239  switch (mmode) {
240  case CMM_ALL: mark = true; break;
241  case CMM_ONLY_REP: mark = is_rep; break;
242  case CMM_ALL_BUT_REP: mark = !is_rep; break;
243  }
244 
245  if (mark) GB_write_flag(*sp, 1);
246  }
247 }
248 
249 static void mark_cluster(ClusterPtr cluster, ClusterMarkMode markRep) {
250  cluster->mark_all_members(markRep);
251 }
252 static void select_representative(ClusterPtr cluster) {
253  GBDATA *gb_species = cluster->get_representative();
254  GB_transaction ta(gb_species);
255  global_data->get_aw_root()->awar(AWAR_SPECIES_NAME)->write_string(null2empty(GBT_get_name(gb_species)));
256 }
257 
258 static void mark_clusters(AW_window *, AffectedClusters affected, bool warn_if_none_affected) {
259  AW_root *aw_root = global_data->get_aw_root();
260  GBDATA *gb_main = global_data->get_gb_main();
261 
262  GB_transaction ta(gb_main);
264 
265  GBT_mark_all(gb_main, 0); // unmark all
266  with_affected_clusters_do(aw_root, affected, warn_if_none_affected, makeClusterCallback(mark_cluster, markRep));
267  aw_root->awar(AWAR_TREE_REFRESH)->touch();
268 }
269 
270 static void select_cluster_cb(AW_root *aw_root) {
271  GB_transaction ta(global_data->get_gb_main());
272 
273  bool auto_mark = aw_root->awar(AWAR_CLUSTER_AUTOMARK)->read_int();
274  if (auto_mark) mark_clusters(NULp, SEL_CLUSTER, false);
275 
276  bool selRep = aw_root->awar(AWAR_CLUSTER_SELECTREP)->read_int();
277  if (selRep) {
278  int selected = with_affected_clusters_do(aw_root, SEL_CLUSTER, false, makeClusterCallback(select_representative));
279  if (!selected) aw_root->awar(AWAR_SPECIES_NAME)->write_string(""); // deselect species
280  }
281 }
282 
283 static void select_cluster(ID id) {
284  global_data->get_aw_root()->awar(AWAR_CLUSTER_SELECTED)->write_int(id);
285 }
286 
287 
288 // -------------------
289 // Sort order
290 
291 
292 static void sort_order_changed_cb(AW_root *aw_root) {
294  global_data->changeSortOrder(order);
296 }
297 
298 // --------------
299 // group
300 
301 class GroupTree;
302 typedef map<string, GroupTree*> Species2Tip;
303 
304 struct GroupTreeRoot FINAL_TYPE : public ARB_seqtree_root {
305  GroupTreeRoot(AliView *aliView, AP_sequence *seqTempl, bool add_delete_callbacks);
306  ~GroupTreeRoot() OVERRIDE { predelete(); }
307  inline TreeNode *makeNode() const OVERRIDE;
308  inline void destroyNode(TreeNode *node) const OVERRIDE;
309 };
310 
311 class GroupTree FINAL_TYPE : public ARB_countedTree {
312  unsigned leaf_count; // total number of leafs in subtree
313  unsigned tagged_count; // tagged leafs
314 
315  void update_tag_counters();
316  unsigned get_leaf_count() const OVERRIDE { return leaf_count; }
317 protected:
318  ~GroupTree() OVERRIDE {}
319  friend class GroupTreeRoot;
320 public:
321 
322  explicit GroupTree(GroupTreeRoot *root)
323  : ARB_countedTree(root),
324  leaf_count(0),
325  tagged_count(0)
326  {}
327 
328  // ARB_countedTree interface
329  void init_tree() OVERRIDE { update_leaf_counters(); }
330  // ARB_countedTree interface end
331 
333 
334  void map_species2tip(Species2Tip& mapping);
335 
336  unsigned update_leaf_counters();
337 
338  void tag_leaf() {
339  di_assert(is_leaf());
340  tagged_count = 1;
341  get_father()->update_tag_counters();
342  }
343  unsigned get_tagged_count() const { return tagged_count; }
344  void clear_tags();
345 
346  float tagged_rate() const { return float(get_tagged_count())/get_leaf_count(); }
347 };
348 
349 GroupTreeRoot::GroupTreeRoot(AliView *aliView, AP_sequence *seqTempl, bool add_delete_callbacks)
350  : ARB_seqtree_root(aliView, seqTempl, add_delete_callbacks)
351 {}
352 inline TreeNode *GroupTreeRoot::makeNode() const { return new GroupTree(const_cast<GroupTreeRoot*>(this)); }
353 inline void GroupTreeRoot::destroyNode(TreeNode *node) const { delete DOWNCAST(GroupTree*,node); }
354 
355 
356 unsigned GroupTree::update_leaf_counters() {
357  if (is_leaf()) leaf_count = 1;
358  else leaf_count = get_leftson()->update_leaf_counters() + get_rightson()->update_leaf_counters();
359  return leaf_count;
360 }
361 
362 void GroupTree::clear_tags() {
363  if (!is_leaf() && tagged_count) {
364  get_leftson()->clear_tags();
365  get_rightson()->clear_tags();
366  }
367  tagged_count = 0;
368 }
369 
370 void GroupTree::map_species2tip(Species2Tip& mapping) {
371  if (is_leaf()) {
372  if (name) mapping[name] = this;
373  }
374  else {
375  get_leftson()->map_species2tip(mapping);
376  get_rightson()->map_species2tip(mapping);
377  }
378 }
379 
380 void GroupTree::update_tag_counters() {
381  di_assert(!is_leaf());
382  GroupTree *node = this;
383  while (node) {
384  node->tagged_count = node->get_leftson()->get_tagged_count() + node->get_rightson()->get_tagged_count();
385  node = node->get_father();
386  }
387 }
388 
389 struct GroupChanges {
390  unsigned created;
391  unsigned skipped;
392  unsigned overwritten;
393  unsigned deleted;
394  unsigned restored;
395 
396  void clear() { created = skipped = overwritten = deleted = restored = 0; }
397  bool exist() const { return created||overwritten||deleted||restored; }
398 
399  void show_message() {
400  string msg;
401 
402  if (created) msg += GBS_global_string("%u created ", created);
403  if (overwritten) msg += GBS_global_string("%u overwritten ", overwritten);
404  if (skipped) msg += GBS_global_string("%u skipped ", skipped);
405  if (deleted) msg += GBS_global_string("%u deleted ", deleted);
406  if (restored) msg += GBS_global_string("%u restored ", restored);
407 
408  if (!msg.empty()) {
409  msg = string("Group changes: ")+msg;
410  aw_message(msg.c_str());
411  }
412  }
413 
415 };
416 
417 
418 // ---------------------
419 // GroupBuilder
420 
421 class GroupBuilder : virtual Noncopyable {
422  GBDATA *gb_main;
423  string tree_name;
424  GroupTreeRoot *tree_root;
425  Group_Action action; // create or delete ?
426  Species2Tip species2tip; // map speciesName -> leaf
427  ARB_ERROR error;
428  ClusterPtr bad_cluster; // error occurred here (is set)
429  Group_Existing existing;
430  unsigned existing_count; // counts existing groups
431  Group_NotFound notfound;
432  float matchRatio; // needed identity of subtree and cluster
433  float maxDist; // max. Distance used for calculation
434  string cluster_prefix; // prefix for cluster name
435  string cluster_suffix_def; // suffix-definition for cluster name
436  string separator; // separator for parts of cluster name
437  GroupChanges changes; // count tree modifications
438  bool del_match_prefixes; // only delete groups, where prefix matches
439 
440  GroupTree *find_group_position(GroupTree *subtree, unsigned cluster_size);
441  float get_max_distance() const { return maxDist; }
442  void load_tree();
443 
444  DEFINE_DOWNCAST_ACCESSORS(GroupTree, get_root_node, tree_root->get_root_node());
445 
446  bool shall_delete_group(const char *name) const {
447  return !del_match_prefixes || matches_current_prefix(name);
448  }
449 
450 public:
451  GroupBuilder(GBDATA *gb_main_, Group_Action action_)
452  : gb_main(gb_main_),
453  tree_root(NULp),
454  action(action_),
455  error(NULp),
456  existing_count(0)
457  {
458  AW_root *awr = global_data->get_aw_root();
459 
460  tree_name = awr->awar(AWAR_DIST_TREE_CURR_NAME)->read_char_pntr();
463  del_match_prefixes = awr->awar(AWAR_CLUSTER_GROUP_PREFIX_MATCH)->read_int();
464  matchRatio = awr->awar(AWAR_CLUSTER_GROUP_IDENTITY)->read_int()/100.0;
465  maxDist = awr->awar(AWAR_CLUSTER_MAXDIST)->read_float();
466  cluster_prefix = awr->awar(AWAR_CLUSTER_GROUP_PREFIX)->read_char_pntr();
467  cluster_suffix_def = awr->awar(AWAR_CLUSTER_GROUP_SUFFIX)->read_char_pntr();
468  separator = awr->awar(AWAR_CLUSTER_GROUP_PARTSEP)->read_char_pntr();
469  }
470  ~GroupBuilder() { delete tree_root; }
471 
472  ARB_ERROR get_error() const { return error; }
473  ClusterPtr get_bad_cluster() const { return bad_cluster; }
474 
476 
477  GroupTree *find_best_matching_subtree(ClusterPtr cluster);
478  void update_group(ClusterPtr cluster); // create or delete group for cluster
479  string generate_group_name(ClusterPtr cluster, const GroupTree *group_node);
480 
481  bool matches_current_prefix(const char *groupname) const {
482  return strstr(groupname, cluster_prefix.c_str()) == groupname;
483  }
484 };
485 
486 void GroupBuilder::load_tree() {
487  di_assert(!tree_root);
488 
489  tree_root = new GroupTreeRoot(new AliView(gb_main), NULp, false);
490  error = tree_root->loadFromDB(tree_name.c_str());
491 
492  if (error) {
493  delete tree_root;
494  tree_root = NULp;
495  }
496  else {
497  changes.clear();
498 
499  GroupTree *tree = get_root_node();
500  tree->update_leaf_counters();
501  tree->map_species2tip(species2tip);
502  }
503 }
505  di_assert(!error);
506  if (changes.exist()) {
507  di_assert(tree_root);
508  error = tree_root->saveToDB();
509 
510  AW_root *awr = global_data->get_aw_root();
511  awr->awar(AWAR_TREE_REFRESH)->touch();
512 
513  if (!error) {
514  changes.show_message();
515  changes.clear();
516  }
517  }
518  return error;
519 }
520 
521 GroupTree *GroupBuilder::find_group_position(GroupTree *subtree, unsigned cluster_size) {
522  // searches for best group in subtree matching the cluster
523 
524  GroupTree *groupPos = NULp;
525  if (subtree->get_tagged_count() == cluster_size) {
526  groupPos = find_group_position(subtree->get_leftson(), cluster_size);
527  if (!groupPos) groupPos = find_group_position(subtree->get_rightson(), cluster_size);
528 
529  if (!groupPos) { // consider 'subtree'
530  if (subtree->tagged_rate() >= matchRatio) {
531  groupPos = subtree;
532  }
533  }
534  }
535  return groupPos;
536 }
537 
539  const GroupBuilder& builder;
540  bool selects(const ARB_seqtree& tree) const OVERRIDE {
541  const char *groupname = tree.get_group_name();
542  bool hasClusterPrefix = groupname && builder.matches_current_prefix(groupname);
543  return !hasClusterPrefix;
544  }
545 public:
546  HasntCurrentClusterPrefix(const GroupBuilder& builder_) : builder(builder_) {}
547 };
548 
549 string concatenate_name_parts(const list<string>& namepart, const string& separator) {
550  string concat;
551  for (list<string>::const_iterator p = namepart.begin(); p != namepart.end(); ++p) {
552  if (!p->empty()) {
553  if (!concat.empty()) concat += separator;
554  concat += *p;
555  }
556  }
557  return concat;
558 }
559 
561  bool selects(const ARB_seqtree& tree) const OVERRIDE { return tree.is_root_node(); }
562 };
563 
564 string GroupBuilder::generate_group_name(ClusterPtr cluster, const GroupTree *group_node) {
565  list<string> namepart;
566  namepart.push_back(cluster_prefix);
567 
568  string orgname_suffix;
569  if (existing == EXISTING_GROUP_APPEND_ORG) {
570  char *old_name = group_node->name;
571  if (old_name) {
572  char *original = originalGroupName(old_name);
573  if (!original && !matches_current_prefix(old_name)) {
574  original = ARB_strdup(old_name); // use existing name as original name
575  }
576  if (original) {
577  orgname_suffix = string(" {was:")+original+"}";
578  free(original);
579  }
580  }
581  }
582 
583  string text;
584  for (int i = 0; cluster_suffix_def[i]; ++i) {
585  if (cluster_suffix_def[i] == '%') {
586  ++i;
587  if (cluster_suffix_def[i] == '%') {
588  text += '%';
589  }
590  else {
591  string expanded;
592  switch(cluster_suffix_def[i]) {
593  case 'p': expanded = cluster->get_upgroup_info(group_node, HasntCurrentClusterPrefix(*this), separator); break;
594  case 'P': expanded = cluster->get_upgroup_info(group_node, UseAnyTree(), separator); break;
595  case 't': expanded = cluster->get_upgroup_info(group_node, UseTreeRoot(), separator); break;
596  case 'd': expanded = GBS_global_string("~%.3f", cluster->get_mean_distance()); break;
597  case 'D': expanded = GBS_global_string("<=%.1f%%", get_max_distance()); break;
598  case 'e': expanded = null2empty(group_node->name); break;
599  case 'o': {
600  int matchRate = int(group_node->tagged_rate()*100+0.5);
601  if (matchRate<100) expanded = string(GBS_global_string("%i%%", matchRate))+separator+"of";
602  break;
603  }
604  default:
605  text += '%';
606  text += cluster_suffix_def[i];
607  break;
608  }
609 
610  if (!expanded.empty()) {
611  namepart.push_back(text);
612  text = "";
613  namepart.push_back(expanded);
614  }
615  }
616  }
617  else {
618  text += cluster_suffix_def[i];
619  }
620  }
621  namepart.push_back(text);
622 
623  return concatenate_name_parts(namepart, separator) + orgname_suffix;
624 }
625 
627  GroupTree *group_node = NULp;
628  if (!error) {
629  if (!tree_root) load_tree();
630  if (!error) {
631  const DBItemSet& members = cluster->get_members();
632 
633  // mark cluster members in tree
634  {
635  GB_transaction ta(gb_main);
636  DBItemSetIter sp_end = members.end();
637  for (DBItemSetIter sp = members.begin(); sp != sp_end && !error; ++sp) {
638  const char *name = GBT_get_name(*sp);
639  di_assert(name);
640  if (name) {
641  Species2Tip::const_iterator found = species2tip.find(name);
642  if (found == species2tip.end()) {
643  error = GBS_global_string("Species '%s' is not in '%s'", name, tree_name.c_str());
644  }
645  else {
646  GroupTree *leaf = found->second;
647  leaf->tag_leaf();
648  }
649  }
650  }
651  }
652 
653  if (!error) {
654  // top-down search for best matching node
655  group_node = find_group_position(get_root_node(), cluster->get_member_count());
656  }
657  }
658  }
659  return group_node;
660 }
661 
663  if (!error) {
664  GroupTree *group_node = find_best_matching_subtree(cluster);
665  if (!error) {
666  if (!group_node) { // no matching subtree found
667  switch (notfound) {
668  case NOTFOUND_WARN:
669  case NOTFOUND_ABORT: {
670  const char *msg = GBS_global_string("Could not find matching subtree for cluster '%s'", cluster->get_list_display(NULp));
671  if (notfound == NOTFOUND_ABORT) error = msg;
672  else aw_message(msg);
673  break;
674  }
675  case NOTFOUND_IGNORE: break; // silently ignore
676  }
677  }
678  else { // found subtree for group
679  switch (action) {
680  case GROUP_CREATE: {
681  char *old_name = group_node->name;
682 
683  if (old_name && existing == EXISTING_GROUP_ABORT) {
684  error = GBS_global_string("Existing group '%s' is in the way", old_name);
685  }
686  else {
687  if (old_name && existing == EXISTING_GROUP_SKIP) {
688  changes.skipped++;
689  }
690  else {
691  string new_name = generate_group_name(cluster, group_node);
692 
693  if (old_name) changes.overwritten++; else changes.created++;
694 
695  free(old_name);
696  group_node->name = ARB_strdup(new_name.c_str());
697 
698  // @@@ DRY that.. it's spread everywhere through libs :(
699  if (!group_node->gb_node) {
700  GBDATA *gb_tree = group_node->get_tree_root()->get_gb_tree();
701  GB_transaction ta(gb_tree);
702  GBDATA *gb_node = GB_create_container(gb_tree, "node");
703  if (!gb_node) {
704  error = GB_await_error();
705  }
706  else {
707  error = GBT_write_int(gb_node, "id", 0);
708  }
709 
710  if (!error) {
711  group_node->gb_node = gb_node;
712  }
713  }
714  if (group_node->gb_node && !error) {
715  GB_transaction ta(group_node->gb_node);
716  error = GBT_write_name_to_groupData(group_node->gb_node, true, group_node->name, true);
717  // @@@ if INT-field "keeled" exists -> set to 0
718  }
719 
720  cluster->update_description(group_node); // change list display
721  }
722  }
723  break;
724  }
725  case GROUP_DELETE: {
726  if (group_node->name && shall_delete_group(group_node->name)) {
727  char *original = originalGroupName(group_node->name);
728 
729  if (original) {
730  freeset(group_node->name, original); // restore original name
731  if (group_node->gb_node) {
732  error = GBT_write_name_to_groupData(group_node->gb_node, true, group_node->name, true);
733  // @@@ original keeled state is not restored here
734  }
735  changes.restored++;
736  }
737  else {
738  freenull(group_node->name);
739  group_node->gb_node = NULp; // forget ref to group data (@@@ need to delete group data from DB?)
740  changes.deleted++;
741  }
742 
743  cluster->update_description(group_node); // change list display
744  }
745  break;
746  }
747  }
748  }
749  }
750 
751  if (error) bad_cluster = cluster;
752  get_root_node()->clear_tags();
753  }
754 }
755 
756 static void update_example(AW_root *aw_root) {
757  ID selID = aw_root->awar(AWAR_CLUSTER_SELECTED)->read_int();
758  string value;
759 
760  if (is_cluster(selID)) {
761  ClusterPtr selCluster = global_data->clusterWithID(selID);
762  cl_assert(!selCluster.isNull());
763 
764  GroupBuilder builder(global_data->get_gb_main(), GROUP_CREATE);
765  GroupTree *group_node = builder.find_best_matching_subtree(selCluster);
766 
767  GB_ERROR error = builder.get_error().deliver();
768 
769  if (error) value = GBS_global_string("<error: %s>", error);
770  else if (group_node) value = builder.generate_group_name(selCluster, group_node);
771  else value = "<no matching subtree found>";
772  }
773  else value = "<no cluster selected>";
774  aw_root->awar(AWAR_CLUSTER_GROUP_EXAMPLE)->write_string(value.c_str());
775 }
776 
777 static void update_cluster_group(ClusterPtr cluster, GroupBuilder *groupBuilder) {
778  if (!groupBuilder->get_error()) {
779  groupBuilder->update_group(cluster);
780  }
781 }
782 
783 static void accept_proposed_names(ClusterPtr cluster, bool accept) {
784  cluster->accept_proposed(accept);
785 }
786 
787 static void group_clusters(AW_window *, Group_Action action) {
788  AW_root *aw_root = global_data->get_aw_root();
790  AffectedClusters affected = what == GROUP_LISTED ? ALL_CLUSTERS : SEL_CLUSTER;
791 
792  GroupBuilder groupBuilder(global_data->get_gb_main(), action);
793 
794  GB_transaction ta(global_data->get_gb_main());
795 
796  {
797  MessageSpamFilter suppress("problematic group names");
798  with_affected_clusters_do(aw_root, affected, true, makeClusterCallback(update_cluster_group, &groupBuilder));
799  }
800 
801  ARB_ERROR error = groupBuilder.get_error();
802  if (error) {
803  ClusterPtr bad = groupBuilder.get_bad_cluster();
804  if (!bad.isNull()) {
805  select_cluster(bad->get_ID());
806  aw_message("Problematic cluster has been highlighted");
807  }
808  }
809  else {
810  error = groupBuilder.save_modified_tree();
811  }
812 
813  error = ta.close(error);
814 
815  bool accept = !error;
816  aw_message_if(error);
817  // careful! the following code will invalidate error, so don't use below
818 
819  with_affected_clusters_do(aw_root, affected, false, makeClusterCallback(accept_proposed_names, accept)); // just affects display
820  global_data->update_cluster_selection_list();
821 }
822 
823 static void popup_group_clusters_window(AW_window *aw_clusterList) {
824  static AW_window_simple *aws = NULp;
825 
826  if (!aws) {
827  AW_root *aw_root = aw_clusterList->get_root();
828 
829  aws = new AW_window_simple;
830  aws->init(aw_root, "cluster_groups", "Cluster groups");
831 
832  aws->auto_space(10, 10);
833 
834  aws->callback(AW_POPDOWN);
835  aws->create_button("CLOSE", "CLOSE", "C");
836 
837  aws->callback(makeHelpCallback("cluster_group.hlp"));
838  aws->create_button("HELP", "HELP");
839 
840  aws->at_newline();
841 
842  aws->label("For");
843  aws->create_option_menu(AWAR_CLUSTER_GROUP_WHAT);
844  aws->insert_option ("selected cluster", "s", GROUP_SELECTED);
845  aws->insert_default_option("listed clusters", "l", GROUP_LISTED);
846  aws->update_option_menu();
847 
848  aws->at_newline();
849 
850  aws->label("with a min. cluster/subtree identity (%) of");
851  aws->create_input_field(AWAR_CLUSTER_GROUP_IDENTITY, 4);
852 
853  aws->at_newline();
854 
855  aws->label("-> if no matching subtree found");
856  aws->create_option_menu(AWAR_CLUSTER_GROUP_NOTFOUND);
857  aws->insert_default_option("abort", "a", NOTFOUND_ABORT);
858  aws->insert_option ("warn", "w", NOTFOUND_WARN);
859  aws->insert_option ("ignore", "i", NOTFOUND_IGNORE);
860  aws->update_option_menu();
861 
862  aws->at_newline();
863 
864  aws->callback(makeWindowCallback(group_clusters, GROUP_CREATE));
865  aws->create_autosize_button("CREATE_GROUPS", "create groups!");
866 
867  aws->label("If group exists");
868  aws->create_option_menu(AWAR_CLUSTER_GROUP_EXISTING);
869  aws->insert_default_option("abort", "a", EXISTING_GROUP_ABORT);
870  aws->insert_option ("skip", "s", EXISTING_GROUP_SKIP);
871  aws->insert_option ("overwrite (caution!)", "o", EXISTING_GROUP_OVERWRITE);
872  aws->insert_option ("append original", "p", EXISTING_GROUP_APPEND_ORG);
873  aws->update_option_menu();
874 
875  aws->at_newline();
876 
877  aws->callback(makeWindowCallback(group_clusters, GROUP_DELETE));
878  aws->create_autosize_button("DELETE_GROUPS", "delete groups!");
879 
880  aws->create_text_toggle(AWAR_CLUSTER_GROUP_PREFIX_MATCH, "(all)", "(where prefix matches)", 30);
881 
882  aws->at_newline(); aws->label("Name prefix:"); aws->create_input_field(AWAR_CLUSTER_GROUP_PREFIX, 20);
883  aws->at_newline(); aws->label("Name suffix:"); aws->create_input_field(AWAR_CLUSTER_GROUP_SUFFIX, 20);
884  aws->at_newline(); aws->label("Separator:"); aws->create_input_field(AWAR_CLUSTER_GROUP_PARTSEP, 3);
885 
886  aws->at_newline();
887  aws->button_length(60);
888  aws->label("=>");
889  aws->create_button(NULp, AWAR_CLUSTER_GROUP_EXAMPLE);
890 
891  aws->window_fit();
892  }
893 
894  aws->activate();
895 }
896 
897 // ---------------
898 // delete
899 
900 static void delete_selected_cluster(ClusterPtr cluster) {
901  int pos = global_data->get_pos(cluster, SHOWN_CLUSTERS);
902  int nextId = global_data->idAtPos(pos+1, SHOWN_CLUSTERS);
903  select_cluster(nextId);
904  global_data->remove(cluster, SHOWN_CLUSTERS);
905 }
906 static void delete_clusters(AW_window *aww, AffectedClusters affected) {
907  switch (affected) {
908  case SEL_CLUSTER:
909  with_affected_clusters_do(aww->get_root(), affected, true, makeClusterCallback(delete_selected_cluster));
910  break;
911  case ALL_CLUSTERS:
912  select_cluster(0);
913  global_data->clear(SHOWN_CLUSTERS);
914  break;
915  }
916 
918 }
919 
920 // ----------------------
921 // store/restore
922 
923 static void store_selected_cluster(ClusterPtr cluster) {
924  int pos = global_data->get_pos(cluster, SHOWN_CLUSTERS);
925  int nextId = global_data->idAtPos(pos+1, SHOWN_CLUSTERS);
926 
927  select_cluster(nextId);
928  global_data->store(cluster->get_ID());
929 }
930 static void store_clusters(AW_window *aww, AffectedClusters affected) {
931  switch (affected) {
932  case SEL_CLUSTER:
933  with_affected_clusters_do(aww->get_root(), affected, true, makeClusterCallback(store_selected_cluster));
934  break;
935  case ALL_CLUSTERS:
936  select_cluster(0);
937  global_data->store_all();
938  break;
939  }
940 
941  update_all(aww);
942 }
943 
944 
945 static void restore_clusters(AW_window *aww) {
946  global_data->restore_all();
947  update_all(aww);
948 }
949 static void swap_clusters(AW_window *aww) {
950  global_data->swap_all();
951  select_cluster(0);
952  update_all(aww);
953 }
954 
955 // ---------------------------------
956 // cluster detection window
957 
959  static AW_window_simple *aws = NULp;
960  if (!aws) {
961  cl_assert(!global_data);
962  global_data = new ClustersData(*weightedFilter);
963 
964  aws = new AW_window_simple;
965  aws->init(aw_root, "DETECT_CLUSTERS", "Detect clusters in tree");
966  aws->load_xfig("di_clusters.fig");
967 
968  aws->on_hide(di_forget_global_data);
969 
970  // -------------------
971  // upper area
972 
973  aws->at("close");
974  aws->callback(AW_POPDOWN);
975  aws->create_button("CLOSE", "CLOSE");
976 
977  aws->at("help");
978  aws->callback(makeHelpCallback("di_clusters.hlp"));
979  aws->create_button("HELP", "HELP");
980 
981  aws->at("max_dist");
982  aws->d_callback(makeWindowCallback(calculate_clusters));
983  aws->create_input_field(AWAR_CLUSTER_MAXDIST, 12);
984 
985  aws->at("min_size");
986  aws->d_callback(makeWindowCallback(calculate_clusters));
987  aws->create_input_field(AWAR_CLUSTER_MINSIZE, 5);
988 
989  aws->at("calculate");
990  aws->callback(calculate_clusters);
991  aws->create_autosize_button("CALC", "Detect clusters");
992 
993  aws->button_length(20);
994  aws->at("tree_name");
995  aws->create_button(NULp, AWAR_DIST_TREE_CURR_NAME);
996 
997  // -------------------
998  // lower area
999 
1000  aws->button_length(10);
1001 
1002  // column 1
1003 
1004  aws->at("select_rep"); aws->create_toggle(AWAR_CLUSTER_SELECTREP);
1005  aws->at("mark"); aws->callback(makeWindowCallback(mark_clusters, SEL_CLUSTER, true)); aws->create_button("MARK", "Mark");
1006  aws->at("auto_mark"); aws->create_toggle(AWAR_CLUSTER_AUTOMARK);
1007 
1008  aws->at("mark_what");
1009  aws->create_option_menu(AWAR_CLUSTER_MARKREP);
1010  aws->insert_default_option("cluster w/o repr.", "d", CMM_ALL_BUT_REP);
1011  aws->insert_option ("whole cluster", "b", CMM_ALL);
1012  aws->insert_option ("only representative", "s", CMM_ONLY_REP);
1013  aws->update_option_menu();
1014 
1015  aws->at("mark_all"); aws->callback(makeWindowCallback(mark_clusters, ALL_CLUSTERS, true)); aws->create_button("MARKALL", "Mark all");
1016 
1017  // column 2
1018 
1019  aws->button_length(18);
1020 
1021  aws->at("group"); aws->callback(popup_group_clusters_window); aws->create_button("GROUP", "Cluster groups..");
1022 
1023  aws->at("sort");
1024  aws->create_option_menu(AWAR_CLUSTER_ORDER);
1025  aws->insert_default_option("by mean distance", "d", SORT_BY_MEANDIST);
1026  aws->insert_option ("by min bases used", "b", SORT_BY_MIN_BASES);
1027  aws->insert_option ("by size", "s", SORT_BY_CLUSTERSIZE);
1028  aws->insert_option ("by tree position", "p", SORT_BY_TREEPOSITION);
1029  aws->insert_option ("by min distance", "i", SORT_BY_MIN_DIST);
1030  aws->insert_option ("by max distance", "x", SORT_BY_MAX_DIST);
1031  aws->insert_option ("reverse", "r", SORT_REVERSE);
1032  aws->update_option_menu();
1033 
1034  // store/restore
1035 
1036  aws->at("store_all"); aws->callback(makeWindowCallback(store_clusters, ALL_CLUSTERS)); aws->create_button("STOREALL", "Store all");
1037  aws->at("store"); aws->callback(makeWindowCallback(store_clusters, SEL_CLUSTER)); aws->create_button("STORESEL", "Store selected");
1038  aws->at("restore"); aws->callback(restore_clusters); aws->create_button("RESTORE", AWAR_CLUSTER_RESTORE_LABEL);
1039  aws->at("swap"); aws->callback(swap_clusters); aws->create_button("Swap", "Swap stored");
1040 
1041  // column 4
1042 
1043  aws->at("clear"); aws->callback(makeWindowCallback(delete_clusters, ALL_CLUSTERS)); aws->create_button("CLEAR", "Clear list");
1044  aws->at("delete"); aws->callback(makeWindowCallback(delete_clusters, SEL_CLUSTER)); aws->create_button("DEL", "Delete selected");
1045 
1046  // --------------------
1047  // clusterlist
1048 
1049  aws->at("cluster_list");
1050  global_data->clusterList = aws->create_selection_list(AWAR_CLUSTER_SELECTED);
1052 
1055  sort_order_changed_cb(aw_root);
1056  }
1057 
1058  return aws;
1059 }
1060 
1062  aw_root->awar_float(AWAR_CLUSTER_MAXDIST, 3.0, def)->set_minmax(0.0, 100.0);
1063  aw_root->awar_int (AWAR_CLUSTER_MINSIZE, 7, def)->set_minmax(2, INT_MAX);
1064  aw_root->awar_int (AWAR_CLUSTER_AUTOMARK, 1, def);
1066  aw_root->awar_int (AWAR_CLUSTER_SELECTREP, 1, def);
1067 
1068  aw_root->awar_int (AWAR_CLUSTER_ORDER, SORT_BY_MEANDIST, def);
1069  aw_root->awar_string(AWAR_CLUSTER_RESTORE_LABEL, "None stored", def);
1070 
1073 
1074  aw_root->awar_int (AWAR_CLUSTER_GROUP_IDENTITY, 100, def)->set_minmax(1, 100);
1075  aw_root->awar_int (AWAR_CLUSTER_GROUP_PREFIX_MATCH, 1, def);
1076  aw_root->awar_string(AWAR_CLUSTER_GROUP_EXAMPLE, "", def);
1077 
1083 
1084  aw_root->awar_int(AWAR_TREE_REFRESH, 0, db);
1085 
1086  update_example(aw_root);
1087 }
1088 
GBDATA * get_representative() const
GBDATA * get_gb_main() const
#define AWAR_CLUSTER_SELECTREP
Definition: DI_clusters.cxx:44
const DBItemSet & get_members() const
static void mark_cluster(ClusterPtr cluster, ClusterMarkMode markRep)
~GroupTreeRoot() OVERRIDE
#define AWAR_CLUSTER_SELECTED
Definition: DI_clusters.cxx:60
size_t count(ClusterSubset subset)
const char * get_list_display(const DisplayFormat *format) const
static void save_results(ClusterTreeRoot *tree)
string concatenate_name_parts(const list< string > &namepart, const string &separator)
char * originalGroupName(const char *groupname)
double get_mean_distance() const
static void update_all(AW_window *aww)
return string(buffer, length)
#define AWAR_CLUSTER_GROUP_PREFIX_MATCH
Definition: DI_clusters.cxx:55
static void select_representative(ClusterPtr cluster)
unsigned deleted
long GBT_mark_all(GBDATA *gb_main, int flag)
Definition: aditem.cxx:295
#define AWAR_CLUSTER_GROUP_EXISTING
Definition: DI_clusters.cxx:51
void changeSortOrder(ClusterOrder newOrder)
#define DEFINE_TREE_RELATIVES_ACCESSORS(TreeType)
Definition: TreeNode.h:613
GroupTree(GroupTreeRoot *root)
void update_cluster_selection_list()
static void select_cluster(ID id)
ID idAtPos(int pos, ClusterSubset subset)
#define AWAR_CLUSTER_MARKREP
Definition: DI_clusters.cxx:43
#define AWAR_CLUSTER_GROUP_IDENTITY
Definition: DI_clusters.cxx:53
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
long read_int() const
Definition: AW_awar.cxx:184
AW_awar * set_minmax(float min, float max)
Definition: AW_awar.cxx:530
static void save_results_recursive(ClusterTree *subtree)
#define AWAR_DIST_ALIGNMENT
Definition: di_awars.hxx:21
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
unsigned overwritten
STL namespace.
void init_tree() OVERRIDE
void AW_POPDOWN(AW_window *window)
Definition: AW_window.cxx:52
#define AWAR_CLUSTER_GROUP_NOTFOUND
Definition: DI_clusters.cxx:52
~GroupTree() OVERRIDE
Group_NotFound
Definition: DI_clusters.cxx:73
bool isNull() const
test if SmartPtr is NULp
Definition: smartptr.h:248
float tagged_rate() const
unsigned created
static void delete_clusters(AW_window *aww, AffectedClusters affected)
bool GBT_is_alignment_protein(GBDATA *gb_main, const char *alignment_name)
Definition: adali.cxx:898
void update_description(const ARB_countedTree *ct)
static void restore_clusters(AW_window *aww)
FILE * seq
Definition: rns.c:46
#define cb(action)
#define DOWNCAST(totype, expr)
Definition: downcast.h:141
static void update_cluster_sellist()
AW_awar * add_callback(const RootCallback &cb)
Definition: AW_awar.cxx:231
#define AWAR_CLUSTER_GROUP_PREFIX
Definition: DI_clusters.cxx:54
void add(ClusterPtr clus, ClusterSubset subset)
const char * read_char_pntr() const
Definition: AW_awar.cxx:168
string generate_group_name(ClusterPtr cluster, const GroupTree *group_node)
POS_TREE1 * get_father() const
Definition: probe_tree.h:49
std::string get_upgroup_info(const ARB_countedTree *ct, const ARB_tree_predicate &keep_group_name, const std::string &separator)
GroupTree * find_best_matching_subtree(ClusterPtr cluster)
static void update_cluster_group(ClusterPtr cluster, GroupBuilder *groupBuilder)
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:342
HasntCurrentClusterPrefix(const GroupBuilder &builder_)
GBDATA * GB_create_container(GBDATA *father, const char *key)
Definition: arbdb.cxx:1829
WindowCallback makeHelpCallback(const char *helpfile)
Definition: aw_window.hxx:106
static void store_selected_cluster(ClusterPtr cluster)
static void update_example(AW_root *aw_root)
DECLARE_CBTYPE_FVV_AND_BUILDERS(ClusterCallback, void, ClusterPtr)
AffectedClusters
Definition: DI_clusters.cxx:88
ARB_ERROR get_error() const
AliDataPtr concat(AliDataPtr left, AliDataPtr right)
Definition: insdel.cxx:584
#define AWAR_CLUSTER_GROUP_WHAT
Definition: DI_clusters.cxx:50
std::set< GBDATA * > DBItemSet
Definition: dbitem_set.h:22
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
AW_root * get_aw_root() const
AW_window * DI_create_cluster_detection_window(AW_root *aw_root, WeightedFilter *weightedFilter)
#define AWAR_CLUSTER_GROUP_SUFFIX
Definition: DI_clusters.cxx:56
static void select_cluster_cb(AW_root *aw_root)
const ClusterIDs & get_clusterIDs(ClusterSubset subset)
ClusterPtr get_bad_cluster() const
static void group_clusters(AW_window *, Group_Action action)
void show_message()
std::vector< ID > ClusterIDs
void touch()
Definition: AW_awar.cxx:207
static void error(const char *msg)
Definition: mkptypes.cxx:96
#define AWAR_TREE_REFRESH
bool is_root_node() const
Definition: TreeNode.h:432
Group_Action
Definition: DI_clusters.cxx:68
ARB_ERROR save_modified_tree()
int32_t ID
void store(ID id)
#define AWAR_SPECIES_NAME
DBItemSet::const_iterator DBItemSetIter
Definition: dbitem_set.h:23
ClusterMarkMode
Group_Existing
Definition: DI_clusters.cxx:79
ID get_ID() const
#define AWAR_CLUSTER_GROUP_EXAMPLE
Definition: DI_clusters.cxx:58
static SearchTree * tree[SEARCH_PATTERNS]
Definition: ED4_search.cxx:629
char * read_string() const
Definition: AW_awar.cxx:198
static void calculate_clusters(AW_window *aww)
AW_awar * awar(const char *awar)
Definition: AW_root.cxx:554
static void store_clusters(AW_window *aww, AffectedClusters affected)
bool is_cluster(ID id)
void clear(ClusterSubset subset)
static void swap_clusters(AW_window *aww)
float read_float() const
Definition: AW_awar.cxx:177
void remove(ClusterPtr clus, ClusterSubset subset)
static int with_affected_clusters_do(AW_root *aw_root, AffectedClusters affected, bool warn_if_none_affected, ClusterCallback cb)
static void update_restore_label(AW_window *aww)
bool exist() const
void accept_proposed(bool accept)
#define AWAR_DIST_TREE_CURR_NAME
Definition: di_awars.hxx:28
#define AWAR_CLUSTER_GROUP_PARTSEP
Definition: DI_clusters.cxx:57
AW_awar * awar_int(const char *var_name, long default_value=0, AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:580
GroupBuilder(GBDATA *gb_main_, Group_Action action_)
AliView * create_aliview(const char *aliname, GB_ERROR &error) const
Definition: GUI_aliview.cxx:66
void DI_create_cluster_awars(AW_root *aw_root, AW_default def, AW_default db)
xml element
GB_ERROR close(GB_ERROR error)
Definition: arbdbpp.cxx:35
ClusterIDs::const_iterator ClusterIDsIter
void GB_write_flag(GBDATA *gbd, long flag)
Definition: arbdb.cxx:2773
static void mark_clusters(AW_window *, AffectedClusters affected, bool warn_if_none_affected)
#define OVERRIDE
Definition: cxxforward.h:112
ClusterPtr clusterWithID(ID id) const
void subtitle(const char *stitle)
Definition: arb_progress.h:321
#define cl_assert(cond)
#define AWAR_CLUSTER_ORDER
Definition: DI_clusters.cxx:45
void update_group(ClusterPtr cluster)
Group_What
Definition: DI_clusters.cxx:63
#define di_assert(cond)
Definition: DI_clusters.cxx:32
void aw_message(const char *msg)
Definition: AW_status.cxx:1142
bool matches_current_prefix(const char *groupname) const
AW_root * get_root()
Definition: aw_window.hxx:359
static void delete_selected_cluster(ClusterPtr cluster)
#define NULp
Definition: cxxforward.h:116
GB_ERROR GBT_write_name_to_groupData(GBDATA *gb_group, bool createNameEntry, const char *new_group_name, bool pedantic)
Definition: adtree.cxx:325
bool is_leaf() const
Definition: probe_tree.h:67
size_t get_member_count() const
#define AWAR_CLUSTER_RESTORE_LABEL
Definition: DI_clusters.cxx:61
GB_ERROR write_string(const char *aw_string)
#define AWAR_CLUSTER_AUTOMARK
Definition: DI_clusters.cxx:42
static ClustersData * global_data
Definition: DI_clusters.cxx:90
const char * GBT_get_name(GBDATA *gb_item)
Definition: aditem.cxx:468
map< string, GroupTree * > Species2Tip
unsigned restored
unsigned get_tagged_count() const
WeightedFilter & weighted_filter
static void sort_order_changed_cb(AW_root *aw_root)
GB_transaction ta(gb_var)
GB_ERROR GBT_write_int(GBDATA *gb_container, const char *fieldpath, long content)
Definition: adtools.cxx:471
GBDATA * gb_main
Definition: adname.cxx:32
AW_awar * awar_string(const char *var_name, const char *default_value="", AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:570
AW_selection_list * clusterList
void tag_leaf()
static void di_forget_global_data(AW_window *)
Definition: DI_clusters.cxx:94
#define AWAR_CLUSTER_MINSIZE
Definition: DI_clusters.cxx:41
const char * get_group_name() const
Definition: TreeNode.h:486
static void accept_proposed_names(ClusterPtr cluster, bool accept)
GB_ERROR write_int(long aw_int)
void aw_message_if(GB_ERROR error)
Definition: aw_msg.hxx:21
static void popup_group_clusters_window(AW_window *aw_clusterList)
unsigned skipped
const char * label
#define AWAR_CLUSTER_MAXDIST
Definition: DI_clusters.cxx:40
ClusterOrder
void mark_all_members(ClusterMarkMode mmode) const