Logo Coherent WaveBurst  
Reference Guide
Logo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
wavegraph.cc
Go to the documentation of this file.
1 #include "wavegraph.hh"
2 
3 // Predicate function used to trim lines of text from double white spaces
4 bool bothspaces(char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); }
5 
6 // Symbols for admissible keys in the header of the graph file
14 };
15 
16 
17 graph_header_code header_hash (std::string const& str) {
18 // Hash function for the header of the graph file
19  if (str == "stride") return xstride;
20  if (str == "span") return xspan;
21  if (str == "scalemin") return xscalemin;
22  if (str == "scalemax") return xscalemax;
23  if (str == "nscales") return xnscales;
24  if (str == "samp_freq") return xsamp_freq;
25 }
26 
27 ClassImp(wavegraph)
28 
29 ////////////////////////////////////////////////////////////////////////////////
30 /* BEGIN_HTML
31 
32 <p>Wavegraph is a graph-based clustering algorithm for coherent WaveBurst (cWB).
33 Wavegraph generates structured clusters of pixels in the time-frequency-scale
34 energy maps computed by cWB. The structure of the clusters is dictated by an
35 auxiliary user-provided directed graph. Admissible clusters are one-dimensional
36 paths in this graph. Wavegraph finds paths of connected pixels that maximizes a
37 figure-of-merit related to the cumulated sum of the time-frequency-scale energy
38 along the path plus a regularization term.</p>
39 
40 <p>Wavegraph clustering analyses the data segment by successive blocks. The
41 block duration corresponds to that of the input graph. The algorithm collects
42 paths from the analysis of each blocks and then it sorts them and selects
43 distinct path that do not overlap significantly in time.</p>
44 
45 <p>A graph connects nodes together. A node is associated to a
46 (time-frequency-scale) pixel. The node object contains only geometrical
47 information. For instance it includes the list of nodes to which it is connected
48 (its ancestors). The pixel object contains physical information (center of time,
49 frequency and scale bin in physical units) but it does not include any
50 connectivity information.</p>
51 
52 <p>The wavegraph class includes methods for building and searching the graph.
53 The wavegraph object is an ordered lists of nodes with some auxiliary information.</p>
54 
55 END_HTML */
56 ////////////////////////////////////////////////////////////////////////////////
57 
58 void
59 wavegraph::add_node(const int nodeidx, const int timeidx, const int freqidx, const int scaleidx,
60  const double value_avg, const double value_stdev,
61  const bool endnode, const nodeids& node_ancestors) {
62  // Add a node to graph object
63  //
64  // Input: nodeidx = node index (should match the node rank in the graph -- this is for debugging purpose)
65  // timeidx = time index of the node
66  // freqidx = frequency index of the node
67  // scaleidx = scale index of the node
68  // value_avg = average value of the node
69  // value_stdev = value standard deviation of the node
70  // endnode = flag saying if the node is an endnode or not
71  // node_ancestors = list of indices of the node ancestors
72 
73  wavenode node = {
74  nodeidx, // node id in graph
75  timeidx, // time index
76  freqidx, // freq index
77  scaleidx, // scale index
78  value_avg, // node average value
79  value_stdev, // value standard deviation
80  endnode, // flag is true if node is end node
81  node_ancestors // ancestors of the node
82  };
83 
84  add_node(node);
85 
86 }
87 
88 void
90  // Add a node to graph object
91  //
92  // Input: node = node to append to graph
93 
94  graph.push_back(node);
95 
96 }
97 
98 void
99 wavegraph::create(const std::string& srcfile){
100 // Create the graph from the given source file
101 //
102 // Input: srcfile = file name
103 //
104 // The file format is as follows
105 //
106 // # Comments
107 // %% stride=XX span=XX scalemin=XX scalemax=XX nscales=XX samp_freq=XX
108 // 0 II TT FF SS E AA BB CC ... << first node
109 // 1 II TT FF SS E AA BB CC ... << second node
110 // ... etc ...
111 //
112 // II, TT, FF and SS: ID and time, freq and scale indices (integers)
113 // E: true if the node is an end node (boolean)
114 // AA, BB, CC, ...: node ancestors (there may be none)
115 //
116 
117 #ifdef NDEBUG
118  std::cout << "debug flag1 create: open file\n";
119 #endif
120 
121  std::ifstream source;
122  source.open(srcfile.c_str(), std::ifstream::in);
123 
124  clear();
125 
126 #ifdef NDEBUG
127  std::cout << "debug flag2 create: read file\n";
128 #endif
129 
130  std::string line;
131  int count_nodes=0;
132 
133  // read line
134  while ( std::getline(source,line) ){
135 
136  // ignore if empty line
137  if (line.empty())
138  continue;
139 
140  // ignore if commented
141  if (line[0] == '#')
142  continue;
143 
144  // parse header
145  if ((line[0] == '%')&(line[1] == '%')) {
146 
147  // trim leading characters and multiple spaces
148  line.erase(0,3);
149  std::string::iterator line_end = std::unique(line.begin(), line.end(), bothspaces);
150  line.erase(line_end, line.end());
151 
152  std::string delimiter_fields = " ";
153  std::string delimiter_values = "=";
154  size_t pos_field = 0;
155  while (true) {
156 
157  // extract field
158  pos_field = line.find(delimiter_fields);
159  std::string field = line.substr(0, pos_field);
160  if (field.empty())
161  continue;
162 
163  //std::cout << "line: " << line << "\n";
164  //std::cout << "field: " << field << "\n";
165 
166  // read token and values from field
167  size_t pos_value = field.find(delimiter_values);
168  std::string token = field.substr(0, pos_value);
169  field.erase(0, pos_value + delimiter_values.length());
170  std::string value = field.substr(0, pos_value);
171 
172  // set variables
173  switch (header_hash(token)) {
174  case xstride:
175  stride=atoi(value.c_str());
176  break;
177  case xspan:
178  span=atoi(value.c_str());
179  break;
180  case xscalemin:
181  scalemin=atoi(value.c_str());
182  break;
183  case xscalemax:
184  scalemax=atoi(value.c_str());
185  break;
186  case xnscales:
187  nscales=atoi(value.c_str());
188  break;
189  case xsamp_freq:
190  samp_freq=atoi(value.c_str());
191  break;
192  default:
193  std::cout << "Invalid token: " << token << "\n";
194  throw std::invalid_argument("Error: Graph file has an invalid header");
195  }
196 
197  // break if all done
198  if (pos_field == std::string::npos)
199  break;
200 
201  // erase processed field from header line
202  line.erase(0, pos_field + delimiter_fields.length());
203  }
204 
205 #ifdef NDEBUG
206  std::cout << "header: stride= " << stride << " span=" << span;
207  std::cout << " scalemin=" << scalemin << " scalemax=" << scalemax;
208  std::cout << " nscales=" << nscales << " samp_freq=" << samp_freq << "\n";
209 #endif
210 
211  // go to next line
212  continue;
213  }
214 
215 #ifdef NDEBUG
216  std::cout << line << "\n";
217 #endif
218 
219  // parse data
220  nodeids ancestors;
221  std::stringstream streamline(line);
222 
223  // read nodeid
224  int nodeid;
225  streamline >> nodeid;
226 
227  if (nodeid != count_nodes)
228  throw std::invalid_argument("Error: Invalid file");
229 
230  // read time index
231  int time_idx;
232  streamline >> time_idx;
233 
234  // read freq index
235  int freq_idx;
236  streamline >> freq_idx;
237 
238  // read scale index
239  int scale_idx;
240  streamline >> scale_idx;
241 
242  // read average graph value -- not used by wavegraph
243  double value_avg;
244  streamline >> value_avg;
245 
246  // read standard deviation of graph value -- not used by wavegraph
247  double value_stdev;
248  streamline >> value_stdev;
249 
250  // read end_node flag
251  bool endnode_flag;
252  streamline >> endnode_flag;
253 
254  // read node ancestors sequentially
255  while (true) {
256  int node;
257  bool read_ok = static_cast<bool> (streamline >> node);
258  if (!read_ok)
259  break;
260  ancestors.insert(node);
261  }
262 
263  // add node to graph
264  add_node(nodeid, time_idx, freq_idx, scale_idx, value_avg, value_stdev, endnode_flag, ancestors);
265  ancestors.clear();
266 
267  count_nodes++;
268  }
269 
270 #ifdef NDEBUG
271  print();
272 #endif
273 
274  source.close();
275 }
276 
277 void
279  // Print graph to standard output
280 
281  std::cout << "stride=" << stride << " span=" << span;
282  std::cout << " scalemin=" << scalemin << " scalemax=" << scalemax;
283  std::cout << " nscales=" << nscales << "samp_freq" << samp_freq << "\n";
284 
285  for (int node_id=0; node_id != graph.size(); ++node_id) {
286  std::cout << node_id << " (" << nodeid(node_id) << "): ";
287 
288  if (get_ancestors(node_id).empty()) {
289  std::cout << " [no ancestor] \n";
290  continue;
291  }
292 
293  nodeids::iterator anc;
294  for (anc = get_ancestors(node_id).begin(); anc != get_ancestors(node_id).end(); ++anc)
295  std::cout << *anc << " ";
296 
297  if (is_endnode(node_id))
298  std::cout << "*";
299 
300  std::cout << "\n";
301  }
302 }
303 
304 bool
306 // Test whether the node order defined by the node IDs is a topological order.
307 // The first nodes have no ancestor. The graph must be acyclic.
308 //
309 // Output: result of the test
310 
311  std::set<int> marked_nodes;
312 
313  bool result=true;
314 
315  // loop on nodes
316  for (int nodeid=0; nodeid != graph.size(); ++nodeid) {
317 
318  // std::set<node_type>::iterator node;
319  // std::cout << "looking to " << nodeid << ":\n";
320  // for (node = marked_nodes.begin(); node != marked_nodes.end(); ++node) {
321  // std::cout << *node << " ";
322  // }
323  // std::cout << "\n";
324 
325  // if node has no ancestor, mark the node and continue
326  if (get_ancestors(nodeid).empty()) {
327  marked_nodes.insert(nodeid);
328  continue;
329  }
330 
331  // loop on the node ancestors
332  nodeids::iterator anc;
333  for (anc = get_ancestors(nodeid).begin(); anc != get_ancestors(nodeid).end(); ++anc) {
334  // if one of the ancestors is NOT in marked_nodes, the graph is NOT topologically sorted
335  if ( marked_nodes.find(*anc) == marked_nodes.end() )
336  return false;
337  }
338  // mark current node
339  marked_nodes.insert(nodeid);
340 
341  }
342 
343  // the graph is topologically sorted
344  return true;
345 };
346 
347 void
348 wavegraph::heaviest_path(std::vector<double>& total_weight, std::vector<int>& total_length,
349  std::vector<int>& best_ancestor, const std::vector<double> weights) {
350 // Calculation of the "heaviest path" from the entry nodes (nodes with no
351 // ancestor) to each node of the graph, that has the largest total weight ( =
352 // sum of the weights of the node in the path). Uses dynamic programming.
353 //
354 // Input: weights = mapping from the node to its weight
355 // Output: total_weight = mapping from each node to the total weight of the heaviest path
356 // Output: total_length = mapping from each node to the total length of the heaviest path
357 // best_ancestor = mapping from each node to the node ancestor in the heaviest path
358 // (or -1 if none)
359 //
360 
361  for (int nodeid=0; nodeid != graph.size(); ++nodeid) {
362 
363 #ifdef NDEBUG
364  std::cout << "debug flag1 heaviest_path: looking at node " << nodeid << ":";
365 #endif
366 
367  nodeids ancestors=get_ancestors(nodeid);
368 
369  // case with no ancestors
370  if (ancestors.empty()) {
371 #ifdef NDEBUG
372  std::cout << "[no ancestors]\n";
373 #endif
374  total_weight[nodeid] = weights[nodeid];
375  total_length[nodeid] = 1;
376  best_ancestor[nodeid] = -1;
377  continue;
378  }
379 
380  // case with one ancestor
381  nodeids::const_iterator first = ancestors.begin();
382  if (ancestors.size() == 1) {
383 #ifdef NDEBUG
384  std::cout << "[one ancestor] select " << *first <<"\n";
385 #endif
386  total_weight.at(nodeid) = total_weight.at(*first)+weights.at(nodeid);
387  total_length.at(nodeid) = total_length.at(*first)+1;
388  best_ancestor.at(nodeid) = *first;
389  continue;
390  }
391 
392 #ifdef NDEBUG
393  std::cout << "[many ancestors] find max ";
394 #endif
395 
396  // case with many ancestors
397  double best_weight = total_weight.at(*first);
398  int best_length = total_length.at(*first);
399  int best_anc = *first;
400  for (nodeids::const_iterator anc = ancestors.begin(); anc != ancestors.end(); ++anc) {
401 
402  if (total_weight.at(*anc) > best_weight) {
403  best_weight = total_weight.at(*anc);
404  best_length = total_length.at(*anc);
405  best_anc = *anc;
406  }
407  }
408 
409 #ifdef NDEBUG
410  std::cout << "select " << best_anc << "\n";
411 #endif
412 
413  total_weight.at(nodeid) = best_weight+weights.at(nodeid);
414  total_length.at(nodeid) = best_length+1;
415  best_ancestor.at(nodeid) = best_anc;
416 
417  }
418 }
419 
420 bool wavegraph::is_compatible(const std::vector< WSeries<double>* >& data)
421 {
422 
423  // assert that the graph and cWB data cube have the same scale axis
424  if (log2(get_scale(data.front())) != scalemin) {
425 
426 #ifdef NDEBUG
427  std::cout << "data scalemin= " << log2(get_scale(data.front())) << ", graph scalemin= " << scalemin << "\n";
428 #endif
429 
430  std::cerr << "Error: min scale of graph does not match that of data\n";
431  return false;
432  }
433 
434  if (log2(get_scale(data.back())) != scalemax) {
435 
436 #ifdef NDEBUG
437  std::cout << "data scalemax= " << log2(get_scale(data.back())) << ", graph scalemax= " << scalemax << "\n";
438 #endif
439 
440  std::cerr << "Error: max scale of graph does not match that of data\n";
441  return false;
442  }
443 
444  if (data.size() != nscales) {
445 #ifdef NDEBUG
446  std::cout << "data nscales= " << data.size() << ", graph nscales= " << nscales << "\n";
447 #endif
448 
449  std::cerr << "Error: scale axis of graph does not match that of data\n";
450  return false;
451  }
452 
453  if (nscales != scalemax-scalemin+1) {
454  std::cerr << "Error: scale axis sampling is not contiguous\n";
455  return false;
456  }
457 
458  if (data.front()->rate() != samp_freq) {
459  std::cerr << "Error: sampling frequency of the graph does not match that of data\n";
460  return false;
461  }
462 
463  return true;
464 
465 }
466 
467 double median(std::vector<double> & vec)
468 {
469  size_t n = vec.size() / 2;
470  nth_element(vec.begin(), vec.begin()+n, vec.end());
471  return vec[n];
472 }
473 
474 std::vector<cluster>
475 wavegraph::clustering(const double threshold, const std::vector< WSeries<double>* >& data, const double strip_edges, const int path_halfwidth, const double penal_factor, const std::vector<double>& energy_thresholds){
476 // Compute clusters using wavegraph clustering. Main steps in pseudo-code:
477 //
478 // while data are available (avoid edges as required by strip_edges)
479 // fill the weight table of the graph with current data block
480 // compute the heaviest path for this block
481 // if its total weight > threshold
482 // trace back (the list of nodes of) this path and store
483 // endif
484 // go to next block
485 // endwhile
486 // sort paths by their total weight
487 // convert paths into clusters
488 // retain univocal clusters that do not overlap in time
489 //
490 // Input: threshold = selection threshold on path total weight
491 // data = list of Wilson Daubechies Meyer transforms computed by cWB
492 // Each WSeries in the list corresponds to a given scale (or "resolution").
493 // The list should go contiguously from the smallest to the largest scale.
494 // strip_edges = remove strip_edges seconds at the segment edges to prevent contamination
495 // by edge artifacts
496 // path_halfwidth = half width of the path (path weight is computed summing weights of +/- path_halfwidth pixels)
497 // penal_factor = leading factor of length penalization term
498 // energy_thresholds = vector of thresholds optionally applied to pixel energy
499 // one threshold per scale (no selection if threshold is 0)
500 
501  if (! is_compatible(data))
502  throw std::invalid_argument("Error: graph and data are incompatible");
503 
504  // compute initial and end offsets to strip the edges from analysis
505  int strip_scalemax = 0;
506  if (strip_edges > 0)
507  strip_scalemax = strip_edges*(2*data.back()->resolution());
508 
509 #ifdef NDEBUG
510  std::cout << "debug flag0 clustering: main loop\n";
511  std::cout << "strip_max = " << strip_scalemax << "\n";
512 #endif
513 
514  // compute median noise level for each frequency and for each scale
515  std::vector < std::vector<double> > noise_levels;
516  for (int k=0; k<data.size(); k++) {
517  std::vector<double> noise_level(num_of_freq_bins(data[k]));
518  for (int m=0; m<num_of_freq_bins(data[k]); m++) {
519  std::vector<double> non_zero_data;
520  for (int n=0; n<num_of_time_bins(data[k]); n++) {
521  double value = get_map00(data[k],n,m);
522  if (value > 0)
523  non_zero_data.push_back(value);
524  }
525  if (non_zero_data.empty())
526  noise_level.push_back(0.0);
527  else
528  noise_level.push_back(median(non_zero_data));
529  }
530  noise_levels.push_back(noise_level);
531  }
532 
533 #ifdef NDEBUG
534  std::cout << "noise level estimates:\n";
535  for (int k=0; k<noise_levels.size(); k++) {
536  std::cout << "scale=" << k << ": ";
537  for (int m=0; m<noise_levels[k].size(); m++) {
538  std::cout << noise_levels[k].at(m) << " ";
539  }
540  std::cout << "\n";
541  }
542 #endif
543 
544  //
545  // main loop: this loop runs by blocks of pixels in the max scale plane.
546  // The max scale is the last element in the data vector [hence data.back()]
547  //
548  std::vector<wavepath> selected_paths;
549 
550  int end_scalemax = num_of_time_bins(data.back())-get_span()-strip_scalemax;
551  for (int block_offset_scalemax = strip_scalemax; block_offset_scalemax <= end_scalemax; block_offset_scalemax += get_stride()) {
552 
553 #ifdef NDEBUG
554  std::cout << "debug flag1 clustering: feed weight table\n";
555 #endif
556 
557  // fill the weight table of the graph with current data block
558  std::vector<double> weights(size(),0.0);
559  for (int nodeid=0; nodeid != size(); ++nodeid) {
560  int node_offset = block_offset_scalemax * pow(2,scalemax-(scalemin+scale(nodeid)));
561  int time_index = node_offset + time(nodeid);
562 #ifdef NDEBUG
563  //std::cout << "debug flag2 clustering: accessing pixel t=" << node_offset+time(nodeid);
564  //std::cout << " f=" << freq(nodeid) << " scale=" << scale(nodeid) << " with block_offset=" << block_offset_scalemax << "\n";
565  if ((node_offset+time(nodeid) >= num_of_time_bins(data.at(scale(nodeid)))) | (freq(nodeid) >= num_of_freq_bins(data.at(scale(nodeid))))) {
566  std::cout << "debug flag2 clustering: accessing pixel t=" << node_offset+time(nodeid);
567  std::cout << " f=" << freq(nodeid) << " scale=" << scale(nodeid) << " with block_offset=" << block_offset_scalemax << "/" << end_scalemax << "\n";
568  std::cout << "at scale index= " << scale(nodeid);
569  std::cout << ": num of time bins= " << num_of_time_bins(data.at(scale(nodeid)));
570  std::cout << ", num of freq bins= " << num_of_freq_bins(data.at(scale(nodeid))) << "\n";
571  throw std::string("Error: requested position exceed allocated limits");
572  }
573 #endif
574  double pixel_data = get_map00(data.at(scale(nodeid)),time_index,freq(nodeid));
575  weights[nodeid]= pixel_data > energy_thresholds.at(scale(nodeid)) ? pixel_data : 0.0 ; // apply energy threshold
576  // if non zero path_width, sum over
577  for (int n=1; n<=path_halfwidth; ++n) {
578  pixel_data = get_map00(data.at(scale(nodeid)),time_index-n,freq(nodeid));
579  weights[nodeid]+= pixel_data > energy_thresholds.at(scale(nodeid)) ? pixel_data : 0.0 ; // apply energy threshold
580  pixel_data = get_map00(data.at(scale(nodeid)),time_index+n,freq(nodeid));
581  weights[nodeid]+= pixel_data > energy_thresholds.at(scale(nodeid)) ? pixel_data : 0.0 ; // apply energy threshold
582  }
583  weights[nodeid]-=penal_factor*(2*path_halfwidth+1)*noise_levels.at(scale(nodeid)).at(freq(nodeid));
584  }
585 
586 #ifdef NDEBUG
587  std::cout << "debug flag2 clustering: dynamic programming\n";
588 #endif
589 
590  // compute the heaviest path for this block
591  std::vector<double> total_weights(size());
592  std::vector<int> total_lengths(size());;
593  std::vector<int> best_ancestors(size());;
594  heaviest_path(total_weights,total_lengths,best_ancestors,weights);
595 
596 #ifdef NDEBUG
597  std::cout << "debug flag3 clustering: select and reconstruct best paths\n";
598 #endif
599 
600  // select path in block with largest total_weight
601  int best_node_id=-1;
602  double best_weight=0;
603  for (int node_id=0; node_id != size(); ++node_id) {
604 
605  // if its total weight > path_length * threshold
606  if (is_endnode(node_id) & (total_weights[node_id] >= total_lengths[node_id]*(2*path_halfwidth+1)*threshold)) {
607  if (total_weights[node_id] > best_weight) {
608  best_weight = total_weights[node_id];
609  best_node_id = node_id;
610  }
611  }
612  }
613 
614  // trace back (the list of nodes of) this path and store
615  if (best_node_id>0) {
616  wavepath path;
617  path.clear();
618 
619  int node=best_node_id;
620  // paths use the maximum scale as the reference scale
621  path.init(get_node(node),block_offset_scalemax,nscales-1,total_weights[node]);
622 
623 #ifdef NDEBUG
624  std::cout << "path: " << node;
625 #endif
626  while (true) {
627  node = best_ancestors.at(node);
628 #ifdef NDEBUG
629  std::cout << "->" << node;
630 #endif
631  if (node == -1)
632  break;
633  path.add_node(get_node(node));
634  }
635 #ifdef NDEBUG
636  std::cout << "\n";
637  path.print();
638 #endif
639 
640  // store the best path (largest total weight)
641  selected_paths.push_back(path);
642  }
643 
644 #ifdef NDEBUG
645  std::cout << selected_paths.size() << " paths selected\n";
646 #endif
647 
648  // go to next block
649  //block_offset_scalemax+=get_stride();
650  }
651 
652 #ifdef NDEBUG
653  std::cout << "debug flag4 clustering: sort selected paths\n";
654 #endif
655 
656  // sort paths by their total weight
657  std::sort(selected_paths.begin(), selected_paths.end(), compare_paths);
658 
659 #ifdef NDEBUG
660  std::cout << selected_paths.size() << " selected paths\n";
661  // wavepath best_path=selected_paths.front();
662  // std::cout << "best path is:\n";
663  // best_path.print();
664 #endif
665 
666  // convert paths to clusters
667  std::vector<cluster> clusters;
668  std::vector<wavepath>::const_iterator this_path;
669  for (this_path = selected_paths.begin(); this_path != selected_paths.end(); ++this_path)
670  clusters.push_back(((wavepath) *this_path).convert_to_cluster(log2(get_scale(data.front())),data.back()->resolution(),path_halfwidth));
671 
672 #ifdef NDEBUG
673  std::cout << clusters.size() << " selected clusters\n";
674 #endif
675 
676  // retain univocal clusters that are distinct in time
677  std::vector<cluster> univocal_clusters;
678  univocal_clusters=select_clusters_distinct_in_time(clusters,get_span()/(2*data.back()->resolution()));
679 
680 #ifdef NDEBUG
681  std::cout << univocal_clusters.size() << " univocal clusters\n";
682  if ( !univocal_clusters.empty() ) {
683  cluster best_cluster=univocal_clusters.front();
684  std::cout << "best cluster is:\n";
685  cluster::const_iterator this_pixel;
686  for (this_pixel=best_cluster.begin(); this_pixel != best_cluster.end(); ++this_pixel) {
687  std::cout << "timeix=" << ((pixel) *this_pixel).timeix << " freqix=" << ((pixel) *this_pixel).freqix << " scaleix=" << ((pixel) *this_pixel).scaleix << " : ";
688  std::cout << " time=" << ((pixel) *this_pixel).time << " freq=" << ((pixel) *this_pixel).freq << " log_2 scale=" << ((pixel) *this_pixel).log2scale << "\n";
689  }
690  }
691 #endif
692 
693  return univocal_clusters;
694 
695 }
std::vector< cluster > clustering(const double threshold, const std::vector< WSeries< double > * > &data, const double strip_edges, const int path_halfwidth, const double penal_factor, const std::vector< double > &energy_thresholds)
Definition: wavegraph.cc:475
par[0] value
bool is_compatible(const std::vector< WSeries< double > * > &data)
Definition: wavegraph.cc:420
std::vector< pixel > cluster
Definition: wavepath.hh:43
int num_of_time_bins(WSeries< double > *WS)
Definition: wavegraph.hh:33
int n
Definition: cwb_net.C:10
int time(int id)
Definition: wavegraph.hh:83
int nodeid(int id)
Definition: wavegraph.hh:81
double median(std::vector< double > &vec)
Definition: wavegraph.cc:467
int nscales
Definition: wavegraph.hh:111
int m
Definition: cwb_net.C:10
std::vector< cluster > select_clusters_distinct_in_time(std::vector< cluster > &sorted_clusters, const double precision)
Definition: wavepath.cc:148
void heaviest_path(std::vector< double > &total_weight, std::vector< int > &total_length, std::vector< int > &best_ancestor, const std::vector< double > weights)
Definition: wavegraph.cc:348
float get_map00(WSeries< double > *WS, int index)
Definition: wavegraph.hh:40
void init(const wavenode node, const int offset, const int refscaleidx, const double path_weight)
Definition: wavepath.cc:45
nodes graph
Definition: wavegraph.hh:106
graph_header_code
Definition: wavegraph.cc:7
wavenode get_node(int id)
Definition: wavegraph.hh:77
char str[1024]
int stride
Definition: wavegraph.hh:108
int size()
Definition: wavegraph.hh:75
int scalemax
Definition: wavegraph.hh:110
std::set< int > nodeids
Definition: wavepath.hh:19
bool is_topologically_sorted()
Definition: wavegraph.cc:305
int num_of_freq_bins(WSeries< double > *WS)
Definition: wavegraph.hh:30
bool bothspaces(char lhs, char rhs)
Definition: wavegraph.cc:4
void add_node(const int nodeidx, const int timeidx, const int freqidx, const int scaleidx, const double value_avg, const double value_stdev, const bool endnode, const nodeids &ancestors)
Definition: wavegraph.cc:59
int is_endnode(int id)
Definition: wavegraph.hh:89
nodeids get_ancestors(int id)
Definition: wavegraph.hh:79
int k
int scalemin
Definition: wavegraph.hh:109
int get_span()
Definition: wavegraph.hh:91
TObjArray * token
void create(const std::string &srcfile)
Definition: wavegraph.cc:99
int get_scale(WSeries< double > *WS)
Definition: wavegraph.hh:27
void clear()
Definition: wavepath.hh:66
TLine * line
Definition: compare_bkg.C:482
ifstream in
int get_stride()
Definition: wavegraph.hh:93
bool compare_paths(const wavepath &path1, const wavepath &path2)
Definition: wavepath.cc:5
int samp_freq
Definition: wavegraph.hh:112
void add_node(const wavenode node)
Definition: wavepath.cc:63
void clear()
Definition: wavegraph.hh:65
int scale(int id)
Definition: wavegraph.hh:87
void print()
Definition: wavegraph.cc:278
Definition: mdc.hh:201
graph_header_code header_hash(std::string const &str)
Definition: wavegraph.cc:17
int freq(int id)
Definition: wavegraph.hh:85
void print()
Definition: wavepath.cc:73