25 vec intercepts = zeros(signal.n_rows);
26 for (uword i = 1; i < signal.n_rows; ++i){
27 if ((signal(i-1) > 0) && (signal(i) < 0))
30 return find(intercepts);
35 double range = abscissa_step * double(window_size) / 2.0;
36 vec x = linspace(-range, range, window_size);
37 return -height*(x / (std::pow(width, 3) * std::sqrt(2 * datum::pi)))
38 % arma::exp(-(arma::pow(x,2)/2 * std::pow(width, 2)));
41 uvec
Vespucci::Math::PeakFinding::FindPeakCenters(
const vec &signal,
const vec &abscissa, list<umat> &ridges, uword first_scale, uword last_scale, uword search_window, uword min_length, uword max_gap,
const string &max_method)
44 if (!(last_scale - first_scale))
45 throw invalid_argument(
"Invalid last_scale must be larger than first_scale!");
46 if ((last_scale - first_scale) < min_length)
47 throw invalid_argument(
"Invalid scale or minimum length");
48 if (max_method !=
"signal" && max_method !=
"mexh")
49 throw invalid_argument(
"Invalid max_method");
50 field<uvec> centers(last_scale - first_scale);
52 double abscissa_step = (abscissa.max() - abscissa.min()) /
double(abscissa.n_elem);
53 uword window_size = 3*last_scale;
55 for (uword i = first_scale; i < last_scale; ++i){
57 vec derivative = conv(signal, kernel,
"same");
59 uword end = derivative.n_rows - window_size/2;
60 derivative.rows(end, derivative.n_rows - 1).fill(derivative(end));
69 for (i = 0; i < centers.n_rows - min_length; ++i){
70 for (j = 0; j < centers(i).n_rows; ++j){
71 uword initial_center = centers(i)(j);
72 umat current_ridge = {{i, initial_center}};
73 uword
min = initial_center - (search_window / 2);
74 uword
max = initial_center + (search_window / 2);
75 uword current_gap = 0;
76 for (k = i+1; (k < centers.n_elem && current_gap < max_gap); ++k){
77 uvec current_centers = centers(k);
78 for (l = 0; (l < current_centers.n_rows && current_centers(l) <=
max); ++l){
79 Row<uword> current_pair;
80 if ((current_centers.n_rows > l) && (current_centers(l) >=
min)){
81 if (!current_pair.n_elem){
82 current_pair = {k, current_centers(l)};
85 Row<uword> candidate_pair = {k, current_centers(l)};
86 uword dist1 = std::abs(
int(current_centers(l)) -
int(initial_center));
87 uword dist2 = std::abs(
int(current_pair(1)) -
int(initial_center));
88 current_pair = (dist1 < dist2 ? candidate_pair : current_pair);
92 uvec query = find(current_centers == current_pair(1));
94 current_centers.shed_row(query(0));
95 centers(k) = current_centers;
97 current_ridge.insert_rows(current_ridge.n_rows, current_pair);
106 if (current_ridge.n_rows >= min_length) ridges.push_back(current_ridge);
111 for (umat &ridge : ridges){
114 if (max_method ==
"signal"){
115 for (uword i = 0; i < ridge.n_rows; ++i){
116 if (!values.n_rows) values = {signal(ridge(i, 1))};
117 else values = join_vert(values, vec({signal(ridge(i, 1))}) );
121 else if (max_method ==
"mexh"){
122 mat smoothed_signal(signal.n_rows, (last_scale - first_scale) + 1);
123 for (uword i = first_scale; i <= last_scale; ++i){
125 smoothed_signal.col(i-1) = conv(signal, kernel,
"same");
127 for (uword i = 0; i < ridge.n_rows; ++i){
128 if (!values.n_rows) values = vec({smoothed_signal(ridge(i, 1), ridge(i, 0))});
129 else values = join_vert(values, vec({smoothed_signal(ridge(i, 1), ridge(i, 0))}) );
133 cerr <<
"should have thrown invalid_argument earlier!\n";
138 max_indices = find(values == values.max());
139 if (!peak_centers.n_rows) peak_centers = {ridge(max_indices(0), 1)};
140 else peak_centers = join_vert(peak_centers, uvec({ridge(max_indices(0), 1)}));
147 uword k = window_size / 2;
148 vec x = linspace(-k*abscissa_step, k*abscissa_step, window_size);
149 return height * (2 / (sqrt(3*width) * pow(datum::pi, 0.25)))
150 * (ones(x.n_rows) - (pow(x, 2)/pow(width, 2)))
151 % exp(-(pow(x, 2) / 2*pow(width, 2)));
VESPUCCI_EXPORT arma::vec MexicanHatKernel(double abscissa_step, arma::uword window_size, arma::uword width, double height)
VESPUCCI_EXPORT arma::vec DerivGaussKernel(double abscissa_step, arma::uword window_size, arma::uword width, double height)
VESPUCCI_EXPORT arma::uword max(arma::uword a, arma::uword b)
Vespucci::Math::max.
VESPUCCI_EXPORT arma::uword min(arma::uword a, arma::uword b)
Vespucci::Math::min.
A namespace for math functions relating to peak detection and counting.
VESPUCCI_EXPORT arma::uvec FindPeakCenters(const arma::vec &signal, const arma::vec &abscissa, std::list< arma::umat > &ridges, arma::uword first_scale, arma::uword last_scale, arma::uword search_window, arma::uword min_length, arma::uword max_gap, const std::string &max_method)
VESPUCCI_EXPORT arma::uvec FindIntercepts(const arma::vec &signal)