Mercurial > hg > svcore
comparison base/ColumnOp.h @ 1266:dd190086db73 3.0-integration
Tests and fixes for distribute(). Although this version of interpolated distribution passes these tests, it isn't right visually -- the expected values in the tests are offset. To be continued.
author | Chris Cannam |
---|---|
date | Thu, 17 Nov 2016 14:33:20 +0000 |
parents | e2e66bfd4a88 |
children | 9ef1cc26024c |
comparison
equal
deleted
inserted
replaced
1265:e2e66bfd4a88 | 1266:dd190086db73 |
---|---|
16 #ifndef COLUMN_OP_H | 16 #ifndef COLUMN_OP_H |
17 #define COLUMN_OP_H | 17 #define COLUMN_OP_H |
18 | 18 |
19 #include "BaseTypes.h" | 19 #include "BaseTypes.h" |
20 | 20 |
21 #include <cmath> | |
22 #include <vector> | 21 #include <vector> |
23 #include <algorithm> | |
24 #include <iostream> | |
25 | 22 |
26 /** | 23 /** |
27 * Display normalization types for columns in e.g. grid plots. | 24 * Display normalization types for columns in e.g. grid plots. |
28 * | 25 * |
29 * Max1 means to normalize to max value = 1.0. | 26 * Max1 means to normalize to max value = 1.0. |
56 | 53 |
57 /** | 54 /** |
58 * Scale the given column using the given gain multiplier. | 55 * Scale the given column using the given gain multiplier. |
59 */ | 56 */ |
60 static Column applyGain(const Column &in, double gain) { | 57 static Column applyGain(const Column &in, double gain) { |
61 | 58 if (gain == 1.0) return in; |
62 if (gain == 1.0) { | |
63 return in; | |
64 } | |
65 Column out; | 59 Column out; |
66 out.reserve(in.size()); | 60 out.reserve(in.size()); |
67 for (auto v: in) { | 61 for (auto v: in) out.push_back(float(v * gain)); |
68 out.push_back(float(v * gain)); | |
69 } | |
70 return out; | 62 return out; |
71 } | 63 } |
72 | 64 |
73 /** | 65 /** |
74 * Scale an FFT output downward by half the FFT size. | 66 * Scale an FFT output downward by half the FFT size. |
75 */ | 67 */ |
76 static Column fftScale(const Column &in, int fftSize) { | 68 static Column fftScale(const Column &in, int fftSize); |
77 return applyGain(in, 2.0 / fftSize); | |
78 } | |
79 | 69 |
80 /** | 70 /** |
81 * Determine whether an index points to a local peak. | 71 * Determine whether an index points to a local peak. |
82 */ | 72 */ |
83 static bool isPeak(const Column &in, int ix) { | 73 static bool isPeak(const Column &in, int ix) { |
101 | 91 |
102 /** | 92 /** |
103 * Return a column containing only the local peak values (all | 93 * Return a column containing only the local peak values (all |
104 * others zero). | 94 * others zero). |
105 */ | 95 */ |
106 static Column peakPick(const Column &in) { | 96 static Column peakPick(const Column &in); |
107 | |
108 std::vector<float> out(in.size(), 0.f); | |
109 for (int i = 0; in_range_for(in, i); ++i) { | |
110 if (isPeak(in, i)) { | |
111 out[i] = in[i]; | |
112 } | |
113 } | |
114 | |
115 return out; | |
116 } | |
117 | 97 |
118 /** | 98 /** |
119 * Return a column normalized from the input column according to | 99 * Return a column normalized from the input column according to |
120 * the given normalization scheme. | 100 * the given normalization scheme. |
101 * | |
102 * Note that the sum or max (as appropriate) used for | |
103 * normalisation will be calculated from the absolute values of | |
104 * the column elements, should any of them be negative. | |
121 */ | 105 */ |
122 static Column normalize(const Column &in, ColumnNormalization n) { | 106 static Column normalize(const Column &in, ColumnNormalization n); |
123 | 107 |
124 if (n == ColumnNormalization::None || in.empty()) { | |
125 return in; | |
126 } | |
127 | |
128 float scale = 1.f; | |
129 | |
130 if (n == ColumnNormalization::Sum1) { | |
131 | |
132 float sum = 0.f; | |
133 | |
134 for (auto v: in) { | |
135 sum += v; | |
136 } | |
137 | |
138 if (sum != 0.f) { | |
139 scale = 1.f / sum; | |
140 } | |
141 } else { | |
142 | |
143 float max = *max_element(in.begin(), in.end()); | |
144 | |
145 if (n == ColumnNormalization::Max1) { | |
146 if (max != 0.f) { | |
147 scale = 1.f / max; | |
148 } | |
149 } else if (n == ColumnNormalization::Hybrid) { | |
150 if (max > 0.f) { | |
151 scale = log10f(max + 1.f) / max; | |
152 } | |
153 } | |
154 } | |
155 | |
156 return applyGain(in, scale); | |
157 } | |
158 | |
159 /** | 108 /** |
160 * Distribute the given column into a target vector of a different | 109 * Distribute the given column into a target vector of a different |
161 * size, optionally using linear interpolation. The binfory vector | 110 * size, optionally using linear interpolation. The binfory vector |
162 * contains a mapping from y coordinate (i.e. index into the | 111 * contains a mapping from y coordinate (i.e. index into the |
163 * target vector) to bin (i.e. index into the source column). The | 112 * target vector) to bin (i.e. index into the source column). The |
167 */ | 116 */ |
168 static Column distribute(const Column &in, | 117 static Column distribute(const Column &in, |
169 int h, | 118 int h, |
170 const std::vector<double> &binfory, | 119 const std::vector<double> &binfory, |
171 int minbin, | 120 int minbin, |
172 bool interpolate) { | 121 bool interpolate); |
173 | |
174 std::vector<float> out(h, 0.f); | |
175 int bins = int(in.size()); | |
176 | |
177 for (int y = 0; y < h; ++y) { | |
178 | |
179 double sy0 = binfory[y] - minbin; | |
180 double sy1 = sy0 + 1; | |
181 if (y+1 < h) { | |
182 sy1 = binfory[y+1] - minbin; | |
183 } | |
184 | |
185 std::cerr << "y = " << y << " of " << h << ", sy0 = " << sy0 << ", sy1 = " << sy1 << std::endl; | |
186 | |
187 if (interpolate && fabs(sy1 - sy0) < 1.0) { | |
188 | |
189 double centre = (sy0 + sy1) / 2; | |
190 double dist = (centre - 0.5) - rint(centre - 0.5); | |
191 int bin = int(centre); | |
192 | |
193 int other = (dist < 0 ? (bin-1) : (bin+1)); | |
194 | |
195 if (bin < 0) bin = 0; | |
196 if (bin >= bins) bin = bins-1; | |
197 | |
198 if (other < 0 || other >= bins) { | |
199 other = bin; | |
200 } | |
201 | |
202 double prop = 1.0 - fabs(dist); | |
203 | |
204 double v0 = in[bin]; | |
205 double v1 = in[other]; | |
206 | |
207 out[y] = float(prop * v0 + (1.0 - prop) * v1); | |
208 | |
209 } else { // not interpolating this one | |
210 | |
211 int by0 = int(sy0 + 0.0001); | |
212 int by1 = int(sy1 + 0.0001); | |
213 if (by1 < by0 + 1) by1 = by0 + 1; | |
214 if (by1 >= bins) by1 = bins - 1; | |
215 | |
216 for (int bin = by0; bin <= by1; ++bin) { | |
217 | |
218 float value = in[bin]; | |
219 | |
220 if (bin == by0 || value > out[y]) { | |
221 out[y] = value; | |
222 } | |
223 } | |
224 } | |
225 } | |
226 | |
227 return out; | |
228 } | |
229 | 122 |
230 }; | 123 }; |
231 | 124 |
232 #endif | 125 #endif |
233 | 126 |