Persistence_heat_maps.h
1 /* This file is part of the Gudhi Library. The Gudhi library
2  * (Geometric Understanding in Higher Dimensions) is a generic C++
3  * library for computational topology.
4  *
5  * Author(s): Pawel Dlotko
6  *
7  * Copyright (C) 2016 Inria
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #ifndef PERSISTENCE_HEAT_MAPS_H_
24 #define PERSISTENCE_HEAT_MAPS_H_
25 
26 // gudhi include
27 #include <gudhi/read_persistence_from_file.h>
28 #include <gudhi/common_persistence_representations.h>
29 
30 // standard include
31 #include <vector>
32 #include <sstream>
33 #include <iostream>
34 #include <cmath>
35 #include <limits>
36 #include <algorithm>
37 #include <utility>
38 #include <string>
39 #include <functional>
40 
41 namespace Gudhi {
42 namespace Persistence_representations {
43 
48 std::vector<std::vector<double> > create_Gaussian_filter(size_t pixel_radius, double sigma) {
49  bool dbg = false;
50  // we are computing the kernel mask to 2 standard deviations away from the center. We discretize it in a grid of a
51  // size 2*pixel_radius times 2*pixel_radius.
52 
53  double r = 0;
54  double sigma_sqr = sigma * sigma;
55 
56  // sum is for normalization
57  double sum = 0;
58 
59  // initialization of a kernel:
60  std::vector<std::vector<double> > kernel(2 * pixel_radius + 1);
61  for (size_t i = 0; i != kernel.size(); ++i) {
62  std::vector<double> v(2 * pixel_radius + 1, 0);
63  kernel[i] = v;
64  }
65 
66  if (dbg) {
67  std::cerr << "Kernel initialize \n";
68  std::cerr << "pixel_radius : " << pixel_radius << std::endl;
69  std::cerr << "kernel.size() : " << kernel.size() << std::endl;
70  getchar();
71  }
72 
73  for (int x = -pixel_radius; x <= static_cast<int>(pixel_radius); x++) {
74  for (int y = -pixel_radius; y <= static_cast<int>(pixel_radius); y++) {
75  double real_x = 2 * sigma * x / pixel_radius;
76  double real_y = 2 * sigma * y / pixel_radius;
77  r = sqrt(real_x * real_x + real_y * real_y);
78  kernel[x + pixel_radius][y + pixel_radius] = (exp(-(r * r) / sigma_sqr)) / (3.141592 * sigma_sqr);
79  sum += kernel[x + pixel_radius][y + pixel_radius];
80  }
81  }
82 
83  // normalize the kernel
84  for (size_t i = 0; i != kernel.size(); ++i) {
85  for (size_t j = 0; j != kernel[i].size(); ++j) {
86  kernel[i][j] /= sum;
87  }
88  }
89 
90  if (dbg) {
91  std::cerr << "Here is the kernel : \n";
92  for (size_t i = 0; i != kernel.size(); ++i) {
93  for (size_t j = 0; j != kernel[i].size(); ++j) {
94  std::cerr << kernel[i][j] << " ";
95  }
96  std::cerr << std::endl;
97  }
98  }
99  return kernel;
100 }
101 
102 /*
103 * There are various options to scale the points depending on their location. One can for instance:
104 * (1) do nothing (scale all of them with the weight 1), as in the function constant_function
105 * (2) Scale them by the distance to the diagonal. This is implemented in function
106 * (3) Scale them with the square of their distance to diagonal. This is implemented in function
107 * (4) Scale them with
108 */
109 
116  public:
117  double operator()(const std::pair<double, double>& point_in_diagram) { return 1; }
118 };
119 
126  public:
127  double operator()(const std::pair<double, double>& point_in_diagram) {
128  // (point_in_diagram.first+point_in_diagram.second)/2.0
129  return sqrt(pow((point_in_diagram.first - (point_in_diagram.first + point_in_diagram.second) / 2.0), 2) +
130  pow((point_in_diagram.second - (point_in_diagram.first + point_in_diagram.second) / 2.0), 2));
131  }
132 };
133 
140  public:
141  double operator()(const std::pair<double, double>& point_in_diagram) {
142  return pow((point_in_diagram.first - (point_in_diagram.first + point_in_diagram.second) / 2.0), 2) +
143  pow((point_in_diagram.second - (point_in_diagram.first + point_in_diagram.second) / 2.0), 2);
144  }
145 };
146 
153  public:
154  double operator()(const std::pair<double, double>& point_in_diagram) {
155  return atan(point_in_diagram.second - point_in_diagram.first);
156  }
157 };
158 
167  public:
168  weight_by_setting_maximal_interval_to_have_length_one(double len) : letngth_of_maximal_interval(len) {}
169  double operator()(const std::pair<double, double>& point_in_diagram) {
170  return (point_in_diagram.second - point_in_diagram.first) / this->letngth_of_maximal_interval;
171  }
172 
173  private:
174  double letngth_of_maximal_interval;
175 };
176 
184 // This class implements the following concepts: Vectorized_topological_data, Topological_data_with_distances,
185 // Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product
186 template <typename Scalling_of_kernels = constant_scaling_function>
188  public:
194  Scalling_of_kernels f;
195  this->f = f;
196  this->erase_below_diagonal = false;
197  this->min_ = this->max_ = 0;
198  this->set_up_parameters_for_basic_classes();
199  }
200 
214  Persistence_heat_maps(const std::vector<std::pair<double, double> >& interval,
215  std::vector<std::vector<double> > filter = create_Gaussian_filter(5, 1),
216  bool erase_below_diagonal = false, size_t number_of_pixels = 1000,
217  double min_ = std::numeric_limits<double>::max(),
218  double max_ = std::numeric_limits<double>::max());
219 
241  Persistence_heat_maps(const char* filename, std::vector<std::vector<double> > filter = create_Gaussian_filter(5, 1),
242  bool erase_below_diagonal = false, size_t number_of_pixels = 1000,
243  double min_ = std::numeric_limits<double>::max(),
244  double max_ = std::numeric_limits<double>::max(),
245  unsigned dimension = std::numeric_limits<unsigned>::max());
246 
252  void compute_mean(const std::vector<Persistence_heat_maps*>& maps);
253 
259  void compute_median(const std::vector<Persistence_heat_maps*>& maps);
260 
264  void compute_percentage_of_active(const std::vector<Persistence_heat_maps*>& maps, size_t cutoff = 1);
265 
266  // put to file subroutine
272  void print_to_file(const char* filename) const;
273 
278  void load_from_file(const char* filename);
279 
283  inline bool check_if_the_same(const Persistence_heat_maps& second) const {
284  bool dbg = false;
285  if (this->heat_map.size() != second.heat_map.size()) {
286  if (dbg)
287  std::cerr << "this->heat_map.size() : " << this->heat_map.size()
288  << " \n second.heat_map.size() : " << second.heat_map.size() << std::endl;
289  return false;
290  }
291  if (this->min_ != second.min_) {
292  if (dbg) std::cerr << "this->min_ : " << this->min_ << ", second.min_ : " << second.min_ << std::endl;
293  return false;
294  }
295  if (this->max_ != second.max_) {
296  if (dbg) std::cerr << "this->max_ : " << this->max_ << ", second.max_ : " << second.max_ << std::endl;
297  return false;
298  }
299  // in the other case we may assume that the persistence images are defined on the same domain.
300  return true;
301  }
302 
306  inline double get_min() const { return this->min_; }
307 
311  inline double get_max() const { return this->max_; }
312 
316  bool operator==(const Persistence_heat_maps& rhs) const {
317  bool dbg = false;
318  if (!this->check_if_the_same(rhs)) {
319  if (dbg) std::cerr << "The domains are not the same \n";
320  return false; // in this case, the domains are not the same, so the maps cannot be the same.
321  }
322  for (size_t i = 0; i != this->heat_map.size(); ++i) {
323  for (size_t j = 0; j != this->heat_map[i].size(); ++j) {
324  if (!almost_equal(this->heat_map[i][j], rhs.heat_map[i][j])) {
325  if (dbg) {
326  std::cerr << "this->heat_map[" << i << "][" << j << "] = " << this->heat_map[i][j] << std::endl;
327  std::cerr << "rhs.heat_map[" << i << "][" << j << "] = " << rhs.heat_map[i][j] << std::endl;
328  }
329  return false;
330  }
331  }
332  }
333  return true;
334  }
335 
339  bool operator!=(const Persistence_heat_maps& rhs) const { return !((*this) == rhs); }
340 
344  void plot(const char* filename) const;
345 
346  template <typename Operation_type>
347  friend Persistence_heat_maps operation_on_pair_of_heat_maps(const Persistence_heat_maps& first,
348  const Persistence_heat_maps& second,
349  Operation_type operation) {
350  // first check if the heat maps are compatible
351  if (!first.check_if_the_same(second)) {
352  std::cerr << "Sizes of the heat maps are not compatible. The program will now terminate \n";
353  throw "Sizes of the heat maps are not compatible. The program will now terminate \n";
354  }
355  Persistence_heat_maps result;
356  result.min_ = first.min_;
357  result.max_ = first.max_;
358  result.heat_map.reserve(first.heat_map.size());
359  for (size_t i = 0; i != first.heat_map.size(); ++i) {
360  std::vector<double> v;
361  v.reserve(first.heat_map[i].size());
362  for (size_t j = 0; j != first.heat_map[i].size(); ++j) {
363  v.push_back(operation(first.heat_map[i][j], second.heat_map[i][j]));
364  }
365  result.heat_map.push_back(v);
366  }
367  return result;
368  } // operation_on_pair_of_heat_maps
369 
375  Persistence_heat_maps result;
376  result.min_ = this->min_;
377  result.max_ = this->max_;
378  result.heat_map.reserve(this->heat_map.size());
379  for (size_t i = 0; i != this->heat_map.size(); ++i) {
380  std::vector<double> v;
381  v.reserve(this->heat_map[i].size());
382  for (size_t j = 0; j != this->heat_map[i].size(); ++j) {
383  v.push_back(this->heat_map[i][j] * scalar);
384  }
385  result.heat_map.push_back(v);
386  }
387  return result;
388  }
389 
394  return operation_on_pair_of_heat_maps(first, second, std::plus<double>());
395  }
400  return operation_on_pair_of_heat_maps(first, second, std::minus<double>());
401  }
405  friend Persistence_heat_maps operator*(double scalar, const Persistence_heat_maps& A) {
406  return A.multiply_by_scalar(scalar);
407  }
411  friend Persistence_heat_maps operator*(const Persistence_heat_maps& A, double scalar) {
412  return A.multiply_by_scalar(scalar);
413  }
417  Persistence_heat_maps operator*(double scalar) { return this->multiply_by_scalar(scalar); }
422  *this = *this + rhs;
423  return *this;
424  }
429  *this = *this - rhs;
430  return *this;
431  }
436  *this = *this * x;
437  return *this;
438  }
443  if (x == 0) throw("In operator /=, division by 0. Program terminated.");
444  *this = *this * (1 / x);
445  return *this;
446  }
447 
448  // Implementations of functions for various concepts.
449 
454  std::vector<double> vectorize(int number_of_function) const;
459  size_t number_of_vectorize_functions() const { return this->number_of_functions_for_vectorization; }
460 
468  double project_to_R(int number_of_function) const;
473  size_t number_of_projections_to_R() const { return this->number_of_functions_for_projections_to_reals; }
474 
481  double distance(const Persistence_heat_maps& second_, double power = 1) const;
482 
487  void compute_average(const std::vector<Persistence_heat_maps*>& to_average);
488 
494  double compute_scalar_product(const Persistence_heat_maps& second_) const;
495 
496  // end of implementation of functions needed for concepts.
497 
501  std::pair<double, double> get_x_range() const { return std::make_pair(this->min_, this->max_); }
502 
506  std::pair<double, double> get_y_range() const { return this->get_x_range(); }
507 
508  protected:
509  // private methods
510  std::vector<std::vector<double> > check_and_initialize_maps(const std::vector<Persistence_heat_maps*>& maps);
511  size_t number_of_functions_for_vectorization;
512  size_t number_of_functions_for_projections_to_reals;
513  void construct(const std::vector<std::pair<double, double> >& intervals_,
514  std::vector<std::vector<double> > filter = create_Gaussian_filter(5, 1),
515 
516  bool erase_below_diagonal = false, size_t number_of_pixels = 1000,
517  double min_ = std::numeric_limits<double>::max(), double max_ = std::numeric_limits<double>::max());
518 
519  void set_up_parameters_for_basic_classes() {
520  this->number_of_functions_for_vectorization = 1;
521  this->number_of_functions_for_projections_to_reals = 1;
522  }
523 
524  // data
525  Scalling_of_kernels f;
526  bool erase_below_diagonal;
527  double min_;
528  double max_;
529  std::vector<std::vector<double> > heat_map;
530 };
531 
532 // if min_ == max_, then the program is requested to set up the values itself based on persistence intervals
533 template <typename Scalling_of_kernels>
534 void Persistence_heat_maps<Scalling_of_kernels>::construct(const std::vector<std::pair<double, double> >& intervals_,
535  std::vector<std::vector<double> > filter,
536  bool erase_below_diagonal, size_t number_of_pixels,
537  double min_, double max_) {
538  bool dbg = false;
539  if (dbg) std::cerr << "Entering construct procedure \n";
540  Scalling_of_kernels f;
541  this->f = f;
542 
543  if (dbg) std::cerr << "min and max passed to construct() procedure: " << min_ << " " << max_ << std::endl;
544 
545  if (min_ == max_) {
546  if (dbg) std::cerr << "min and max parameters will be determined based on intervals \n";
547  // in this case, we want the program to set up the min_ and max_ values by itself.
548  min_ = std::numeric_limits<int>::max();
549  max_ = -std::numeric_limits<int>::max();
550 
551  for (size_t i = 0; i != intervals_.size(); ++i) {
552  if (intervals_[i].first < min_) min_ = intervals_[i].first;
553  if (intervals_[i].second > max_) max_ = intervals_[i].second;
554  }
555  // now we have the structure filled in, and moreover we know min_ and max_ values of the interval, so we know the
556  // range.
557 
558  // add some more space:
559  min_ -= fabs(max_ - min_) / 100;
560  max_ += fabs(max_ - min_) / 100;
561  }
562 
563  if (dbg) {
564  std::cerr << "min_ : " << min_ << std::endl;
565  std::cerr << "max_ : " << max_ << std::endl;
566  std::cerr << "number_of_pixels : " << number_of_pixels << std::endl;
567  getchar();
568  }
569 
570  this->min_ = min_;
571  this->max_ = max_;
572 
573  // initialization of the structure heat_map
574  std::vector<std::vector<double> > heat_map_;
575  for (size_t i = 0; i != number_of_pixels; ++i) {
576  std::vector<double> v(number_of_pixels, 0);
577  heat_map_.push_back(v);
578  }
579  this->heat_map = heat_map_;
580 
581  if (dbg) std::cerr << "Done creating of the heat map, now we will fill in the structure \n";
582 
583  for (size_t pt_nr = 0; pt_nr != intervals_.size(); ++pt_nr) {
584  // compute the value of intervals_[pt_nr] in the grid:
585  int x_grid =
586  static_cast<int>((intervals_[pt_nr].first - this->min_) / (this->max_ - this->min_) * number_of_pixels);
587  int y_grid =
588  static_cast<int>((intervals_[pt_nr].second - this->min_) / (this->max_ - this->min_) * number_of_pixels);
589 
590  if (dbg) {
591  std::cerr << "point : " << intervals_[pt_nr].first << " , " << intervals_[pt_nr].second << std::endl;
592  std::cerr << "x_grid : " << x_grid << std::endl;
593  std::cerr << "y_grid : " << y_grid << std::endl;
594  }
595 
596  // x_grid and y_grid gives a center of the kernel. We want to have its lower left corner. To get this, we need to
597  // shift x_grid and y_grid by a grid diameter.
598  x_grid -= filter.size() / 2;
599  y_grid -= filter.size() / 2;
600  // note that the numbers x_grid and y_grid may be negative.
601 
602  if (dbg) {
603  std::cerr << "After shift : \n";
604  std::cerr << "x_grid : " << x_grid << std::endl;
605  std::cerr << "y_grid : " << y_grid << std::endl;
606  }
607 
608  double scaling_value = this->f(intervals_[pt_nr]);
609 
610  for (size_t i = 0; i != filter.size(); ++i) {
611  for (size_t j = 0; j != filter.size(); ++j) {
612  // if the point (x_grid+i,y_grid+j) is the correct point in the grid.
613  if (((x_grid + i) >= 0) && (x_grid + i < this->heat_map.size()) && ((y_grid + j) >= 0) &&
614  (y_grid + j < this->heat_map.size())) {
615  if (dbg) {
616  std::cerr << y_grid + j << " " << x_grid + i << std::endl;
617  }
618  this->heat_map[y_grid + j][x_grid + i] += scaling_value * filter[i][j];
619  if (dbg) {
620  std::cerr << "Position : (" << x_grid + i << "," << y_grid + j
621  << ") got increased by the value : " << filter[i][j] << std::endl;
622  }
623  }
624  }
625  }
626  }
627 
628  // now it remains to cut everything below diagonal if the user wants us to.
629  if (erase_below_diagonal) {
630  for (size_t i = 0; i != this->heat_map.size(); ++i) {
631  for (size_t j = i; j != this->heat_map.size(); ++j) {
632  this->heat_map[i][j] = 0;
633  }
634  }
635  }
636 } // construct
637 
638 template <typename Scalling_of_kernels>
640  const std::vector<std::pair<double, double> >& interval, std::vector<std::vector<double> > filter,
641  bool erase_below_diagonal, size_t number_of_pixels, double min_, double max_) {
642  this->construct(interval, filter, erase_below_diagonal, number_of_pixels, min_, max_);
643  this->set_up_parameters_for_basic_classes();
644 }
645 
646 template <typename Scalling_of_kernels>
648  std::vector<std::vector<double> > filter,
649  bool erase_below_diagonal, size_t number_of_pixels,
650  double min_, double max_, unsigned dimension) {
651  std::vector<std::pair<double, double> > intervals_;
652  if (dimension == std::numeric_limits<unsigned>::max()) {
653  intervals_ = read_persistence_intervals_in_one_dimension_from_file(filename);
654  } else {
655  intervals_ = read_persistence_intervals_in_one_dimension_from_file(filename, dimension);
656  }
657  this->construct(intervals_, filter, erase_below_diagonal, number_of_pixels, min_, max_);
658  this->set_up_parameters_for_basic_classes();
659 }
660 
661 template <typename Scalling_of_kernels>
663  const std::vector<Persistence_heat_maps*>& maps) {
664  // checking if all the heat maps are of the same size:
665  for (size_t i = 0; i != maps.size(); ++i) {
666  if (maps[i]->heat_map.size() != maps[0]->heat_map.size()) {
667  std::cerr << "Sizes of Persistence_heat_maps are not compatible. The program will terminate now \n";
668  throw "Sizes of Persistence_heat_maps are not compatible. The program will terminate now \n";
669  }
670  if (maps[i]->heat_map[0].size() != maps[0]->heat_map[0].size()) {
671  std::cerr << "Sizes of Persistence_heat_maps are not compatible. The program will terminate now \n";
672  throw "Sizes of Persistence_heat_maps are not compatible. The program will terminate now \n";
673  }
674  }
675  std::vector<std::vector<double> > heat_maps(maps[0]->heat_map.size());
676  for (size_t i = 0; i != maps[0]->heat_map.size(); ++i) {
677  std::vector<double> v(maps[0]->heat_map[0].size(), 0);
678  heat_maps[i] = v;
679  }
680  return heat_maps;
681 }
682 
683 template <typename Scalling_of_kernels>
684 void Persistence_heat_maps<Scalling_of_kernels>::compute_median(const std::vector<Persistence_heat_maps*>& maps) {
685  std::vector<std::vector<double> > heat_maps = this->check_and_initialize_maps(maps);
686 
687  std::vector<double> to_compute_median(maps.size());
688  for (size_t i = 0; i != heat_maps.size(); ++i) {
689  for (size_t j = 0; j != heat_maps[i].size(); ++j) {
690  for (size_t map_no = 0; map_no != maps.size(); ++map_no) {
691  to_compute_median[map_no] = maps[map_no]->heat_map[i][j];
692  }
693  std::nth_element(to_compute_median.begin(), to_compute_median.begin() + to_compute_median.size() / 2,
694  to_compute_median.end());
695  heat_maps[i][j] = to_compute_median[to_compute_median.size() / 2];
696  }
697  }
698  this->heat_map = heat_maps;
699  this->min_ = maps[0]->min_;
700  this->max_ = maps[0]->max_;
701 }
702 
703 template <typename Scalling_of_kernels>
704 void Persistence_heat_maps<Scalling_of_kernels>::compute_mean(const std::vector<Persistence_heat_maps*>& maps) {
705  std::vector<std::vector<double> > heat_maps = this->check_and_initialize_maps(maps);
706  for (size_t i = 0; i != heat_maps.size(); ++i) {
707  for (size_t j = 0; j != heat_maps[i].size(); ++j) {
708  double mean = 0;
709  for (size_t map_no = 0; map_no != maps.size(); ++map_no) {
710  mean += maps[map_no]->heat_map[i][j];
711  }
712  heat_maps[i][j] = mean / static_cast<double>(maps.size());
713  }
714  }
715  this->heat_map = heat_maps;
716  this->min_ = maps[0]->min_;
717  this->max_ = maps[0]->max_;
718 }
719 
720 template <typename Scalling_of_kernels>
722  const std::vector<Persistence_heat_maps*>& maps, size_t cutoff) {
723  std::vector<std::vector<double> > heat_maps = this->check_and_initialize_maps(maps);
724 
725  for (size_t i = 0; i != heat_maps.size(); ++i) {
726  for (size_t j = 0; j != heat_maps[i].size(); ++j) {
727  size_t number_of_active_levels = 0;
728  for (size_t map_no = 0; map_no != maps.size(); ++map_no) {
729  if (maps[map_no]->heat_map[i][j]) number_of_active_levels++;
730  }
731  if (number_of_active_levels > cutoff) {
732  heat_maps[i][j] = number_of_active_levels;
733  } else {
734  heat_maps[i][j] = 0;
735  }
736  }
737  }
738  this->heat_map = heat_maps;
739  this->min_ = maps[0]->min_;
740  this->max_ = maps[0]->max_;
741 }
742 
743 template <typename Scalling_of_kernels>
744 void Persistence_heat_maps<Scalling_of_kernels>::plot(const char* filename) const {
745  std::ofstream out;
746  std::stringstream gnuplot_script;
747  gnuplot_script << filename << "_GnuplotScript";
748 
749  out.open(gnuplot_script.str().c_str());
750  out << "plot '-' matrix with image" << std::endl;
751  for (size_t i = 0; i != this->heat_map.size(); ++i) {
752  for (size_t j = 0; j != this->heat_map[i].size(); ++j) {
753  out << this->heat_map[i][j] << " ";
754  }
755  out << std::endl;
756  }
757  out.close();
758  std::cout << "To visualize, install gnuplot and type the command: gnuplot -persist -e \"load \'"
759  << gnuplot_script.str().c_str() << "\'\"" << std::endl;
760 }
761 
762 template <typename Scalling_of_kernels>
764  std::ofstream out;
765  out.open(filename);
766 
767  // First we store this->min_ and this->max_ values:
768  out << this->min_ << " " << this->max_ << std::endl;
769  for (size_t i = 0; i != this->heat_map.size(); ++i) {
770  for (size_t j = 0; j != this->heat_map[i].size(); ++j) {
771  out << this->heat_map[i][j] << " ";
772  }
773  out << std::endl;
774  }
775  out.close();
776 }
777 
778 template <typename Scalling_of_kernels>
780  bool dbg = false;
781 
782  std::ifstream in;
783  in.open(filename);
784 
785  // checking if the file exist / if it was open.
786  if (!in.good()) {
787  std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n";
788  throw "The persistence landscape file do not exist. The program will now terminate \n";
789  }
790 
791  // now we read the file one by one.
792 
793  in >> this->min_ >> this->max_;
794  if (dbg) {
795  std::cerr << "Reading the following values of min and max : " << this->min_ << " , " << this->max_ << std::endl;
796  }
797 
798  std::string temp;
799  std::getline(in, temp);
800  while (in.good()) {
801  std::getline(in, temp);
802  std::stringstream lineSS;
803  lineSS << temp;
804 
805  std::vector<double> line_of_heat_map;
806  while (lineSS.good()) {
807  double point;
808 
809  lineSS >> point;
810  line_of_heat_map.push_back(point);
811  if (dbg) {
812  std::cout << point << " ";
813  }
814  }
815  if (dbg) {
816  std::cout << std::endl;
817  getchar();
818  }
819 
820  if (in.good()) this->heat_map.push_back(line_of_heat_map);
821  }
822  in.close();
823  if (dbg) std::cout << "Done \n";
824 }
825 
826 // Concretizations of virtual methods:
827 template <typename Scalling_of_kernels>
828 std::vector<double> Persistence_heat_maps<Scalling_of_kernels>::vectorize(int number_of_function) const {
829  // convert this->heat_map into one large vector:
830  size_t size_of_result = 0;
831  for (size_t i = 0; i != this->heat_map.size(); ++i) {
832  size_of_result += this->heat_map[i].size();
833  }
834 
835  std::vector<double> result;
836  result.reserve(size_of_result);
837 
838  for (size_t i = 0; i != this->heat_map.size(); ++i) {
839  for (size_t j = 0; j != this->heat_map[i].size(); ++j) {
840  result.push_back(this->heat_map[i][j]);
841  }
842  }
843 
844  return result;
845 }
846 
847 template <typename Scalling_of_kernels>
849  // first we need to check if (*this) and second are defined on the same domain and have the same dimensions:
850  if (!this->check_if_the_same(second)) {
851  std::cerr << "The persistence images are of non compatible sizes. We cannot therefore compute distance between "
852  "them. The program will now terminate";
853  throw "The persistence images are of non compatible sizes. The program will now terminate";
854  }
855 
856  // if we are here, we know that the two persistence images are defined on the same domain, so we can start computing
857  // their distances:
858 
859  double distance = 0;
860  if (power < std::numeric_limits<double>::max()) {
861  for (size_t i = 0; i != this->heat_map.size(); ++i) {
862  for (size_t j = 0; j != this->heat_map[i].size(); ++j) {
863  distance += pow(fabs(this->heat_map[i][j] - second.heat_map[i][j]), power);
864  }
865  }
866  } else {
867  // in this case, we compute max norm distance
868  for (size_t i = 0; i != this->heat_map.size(); ++i) {
869  for (size_t j = 0; j != this->heat_map[i].size(); ++j) {
870  if (distance < fabs(this->heat_map[i][j] - second.heat_map[i][j])) {
871  distance = fabs(this->heat_map[i][j] - second.heat_map[i][j]);
872  }
873  }
874  }
875  }
876  return distance;
877 }
878 
879 template <typename Scalling_of_kernels>
880 double Persistence_heat_maps<Scalling_of_kernels>::project_to_R(int number_of_function) const {
881  double result = 0;
882  for (size_t i = 0; i != this->heat_map.size(); ++i) {
883  for (size_t j = 0; j != this->heat_map[i].size(); ++j) {
884  result += this->heat_map[i][j];
885  }
886  }
887  return result;
888 }
889 
890 template <typename Scalling_of_kernels>
892  const std::vector<Persistence_heat_maps*>& to_average) {
893  this->compute_mean(to_average);
894 }
895 
896 template <typename Scalling_of_kernels>
898  // first we need to check if (*this) and second are defined on the same domain and have the same dimensions:
899  if (!this->check_if_the_same(second)) {
900  std::cerr << "The persistence images are of non compatible sizes. We cannot therefore compute distance between "
901  "them. The program will now terminate";
902  throw "The persistence images are of non compatible sizes. The program will now terminate";
903  }
904 
905  // if we are here, we know that the two persistence images are defined on the same domain, so we can start computing
906  // their scalar product:
907  double scalar_prod = 0;
908  for (size_t i = 0; i != this->heat_map.size(); ++i) {
909  for (size_t j = 0; j != this->heat_map[i].size(); ++j) {
910  scalar_prod += this->heat_map[i][j] * second.heat_map[i][j];
911  }
912  }
913  return scalar_prod;
914 }
915 
916 } // namespace Persistence_representations
917 } // namespace Gudhi
918 
919 #endif // PERSISTENCE_HEAT_MAPS_H_
size_t number_of_vectorize_functions() const
Definition: Persistence_heat_maps.h:459
void compute_percentage_of_active(const std::vector< Persistence_heat_maps *> &maps, size_t cutoff=1)
Definition: Persistence_heat_maps.h:721
size_t number_of_projections_to_R() const
Definition: Persistence_heat_maps.h:473
bool check_if_the_same(const Persistence_heat_maps &second) const
Definition: Persistence_heat_maps.h:283
double get_min() const
Definition: Persistence_heat_maps.h:306
std::pair< double, double > get_x_range() const
Definition: Persistence_heat_maps.h:501
void compute_average(const std::vector< Persistence_heat_maps *> &to_average)
Definition: Persistence_heat_maps.h:891
void load_from_file(const char *filename)
Definition: Persistence_heat_maps.h:779
bool operator==(const Persistence_heat_maps &rhs) const
Definition: Persistence_heat_maps.h:316
A class implementing persistence heat maps.
Definition: Persistence_heat_maps.h:187
Persistence_heat_maps multiply_by_scalar(double scalar) const
Definition: Persistence_heat_maps.h:374
std::vector< double > vectorize(int number_of_function) const
Definition: Persistence_heat_maps.h:828
Persistence_heat_maps operator/=(double x)
Definition: Persistence_heat_maps.h:442
double project_to_R(int number_of_function) const
Definition: Persistence_heat_maps.h:880
std::pair< double, double > get_y_range() const
Definition: Persistence_heat_maps.h:506
Persistence_heat_maps operator*=(double x)
Definition: Persistence_heat_maps.h:435
Persistence_heat_maps operator*(double scalar)
Definition: Persistence_heat_maps.h:417
friend Persistence_heat_maps operator-(const Persistence_heat_maps &first, const Persistence_heat_maps &second)
Definition: Persistence_heat_maps.h:399
Definition: SimplicialComplexForAlpha.h:26
void compute_median(const std::vector< Persistence_heat_maps *> &maps)
Definition: Persistence_heat_maps.h:684
void plot(const char *filename) const
Definition: Persistence_heat_maps.h:744
friend Persistence_heat_maps operator*(const Persistence_heat_maps &A, double scalar)
Definition: Persistence_heat_maps.h:411
void print_to_file(const char *filename) const
Definition: Persistence_heat_maps.h:763
double compute_scalar_product(const Persistence_heat_maps &second_) const
Definition: Persistence_heat_maps.h:897
friend Persistence_heat_maps operator+(const Persistence_heat_maps &first, const Persistence_heat_maps &second)
Definition: Persistence_heat_maps.h:393
double distance(const Persistence_heat_maps &second_, double power=1) const
Definition: Persistence_heat_maps.h:848
friend Persistence_heat_maps operator*(double scalar, const Persistence_heat_maps &A)
Definition: Persistence_heat_maps.h:405
Persistence_heat_maps()
Definition: Persistence_heat_maps.h:193
void compute_mean(const std::vector< Persistence_heat_maps *> &maps)
Definition: Persistence_heat_maps.h:704
Persistence_heat_maps operator+=(const Persistence_heat_maps &rhs)
Definition: Persistence_heat_maps.h:421
bool operator!=(const Persistence_heat_maps &rhs) const
Definition: Persistence_heat_maps.h:339
double get_max() const
Definition: Persistence_heat_maps.h:311
Persistence_heat_maps operator-=(const Persistence_heat_maps &rhs)
Definition: Persistence_heat_maps.h:428
GUDHI  Version 2.2.0  - C++ library for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding.  - Copyright : GPL v3 Generated on Thu Jun 14 2018 15:00:54 for GUDHI by Doxygen 1.8.13