Loading...
Searching...
No Matches
Sampler.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30*/
31#ifndef DRAIN_SAMPLER_H_
32#define DRAIN_SAMPLER_H_
33
34
35#include <iostream>
36#include <string>
37
38
39
40#include "drain/util/BeanLike.h"
41#include "drain/util/IosFormat.h"
42#include "drain/util/Range.h"
43#include "drain/util/ReferenceMap.h"
44#include "drain/util/StringMapper.h"
45#include "drain/image/Image.h"
46
47namespace drain
48{
49
50namespace image
51{
52
54
59
63 inline
64 //SamplePicker(ReferenceMap & variableMap) : variableMap(variableMap) {
66 infoMap["width"].link(width = 0);
67 infoMap["height"].link(height = 0);
68 }
69
70 virtual inline
71 ~SamplePicker(){};
72
73 void setSize(int w, int h){
74 width = w;
75 height = h;
76 }
77
79 virtual
80 inline
81 void setPosition(int i, int j) const {
82 current_i = i;
83 current_j = j;
84 current_j2 = height-1 - j;
85 }
86
87 // TODO: min/max coord control, like CoordHandler for checking min and max.
88 //bool checkPosition()
89
91 //virtual
92 //void writeHeader(char commentPrefix, std::ostream & ostr) const {};
93
94
96 mutable int current_i = 0;
97
99 mutable int current_j = 0;
100
102 mutable int current_j2 = 0;
103
104 int width = 0;
105 int height = 0;
106
109
113
114};
115
117
120class ImageReader : public SamplePicker {
121
122public:
123
124 inline
125 ImageReader(ReferenceMap2<> & ref) : SamplePicker(ref) {//static int dummy;
126 variableMap.link("i", current_i = 0);
127 variableMap.link("j", current_j = 0);
128 variableMap.link("j2", current_j2 = 0);
129 }
130
136 inline
137 bool getValue(const ImageFrame & image, double & value) const {
138 //value = image.get<double>(current_i, current_j);
139 // if (mode==SCALED ?
140 value = image.getScaled(current_i, current_j);
141 //value = image.get<double>(current_i, current_j);
142 //std::cerr << current_i << ',' << current_j << '\t' << value << '\n';
143 return true;
144 }
145
149 inline
150 bool handleValue(const ImageFrame & data, double & value) const {
151 return true;
152 }
153
154
155};
156
158
162class Sampler : public BeanLike {
163
164public:
165
166 Sampler();
167
168 inline
169 Sampler(const Sampler &sampler) : BeanLike(sampler){
170 parameters.copyStruct(sampler.getParameters(), sampler, *this);
171 };
172
173 // Named conf, to separate ImageMod::parameters (BeanLike)
174 //ReferenceMap conf;
175
176 int iStep = 10;
177 int jStep = 0;
178
179 drain::Range<int> iRange = {-1,1};
180 drain::Range<int> jRange = {-1,1};
181
183 std::string commentPrefix = "#";
184
185
186 // was already DEPRECATING...
188 bool skipVoid = false ;
189 //std::string skipVoid = "false";
190 std::string voidComment = "void";
191
192 // NEW
193 std::string handleVoid = "null"; // "false","skip"
194
195
197 mutable
199
201 char getCommentChar() const;
202
204 std::string getFormat(const std::string & formatStr) const;
205
206
208
219 template <class D, class P>
220 void sample(const std::map<std::string, D> & images, const P & picker, const std::string & formatStr, std::ostream & ostr = std::cout) const { // std::string format copy ok
221
222 drain::Logger mout(getImgLog(), __FUNCTION__, getName());
223
224 if (images.empty()){
225 mout.error("no image data (channels) provided: " );
226 return;
227 }
228
229 const bool SKIP_VOID = (handleVoid == "skip") || (skipVoid == true);
230
231 const bool MARK_VOID = (handleVoid != "skip");
232
233 double voidMarker = NAN;
234 if (handleVoid != "null"){
235 StringTools::convert(handleVoid, voidMarker);
236 }
237
238 // Save initial formatting data
239
240 //mout.special("fieldWidth: " , fieldWidth , ", fillChar=" , fillChar );
241 mout.attention("variables (initially): " , variableMap.getKeys() );
242
244 // Note: supports leading minus sign
245 drain::StringMapper formatter("-?[a-zA-Z0-9_]+"); // WAS: "-?[a-zA-Z0-9_]+" with odd "-?"
246 // format = drain::StringTools::replace(format, "\\n", "\n");
247 // format = drain::StringTools::replace(format, "\\t", "\t");
248 std::string format = getFormat(formatStr);
249 formatter.parse(format, true); // convert escaped, eg. "\\n" -> "\n"
250 formatter.iosFormat.copyFrom(ostr);
251 mout.special("iosFormat: ", formatter.iosFormat);
252
253 // std::string format = getFormat(formatStr);
254
255 // Service: associate file keys with data
256 // mout.debug("check minus" );
257 std::map<std::string, double> values;
258 static const std::string minusStr("-");
259 for (typename std::map<std::string, D>::const_iterator it = images.begin(); it != images.end(); ++it){
260 const std::string & key = it->first;
261 mout.debug2("referencing: " , key , ',' , minusStr , key );
262 variableMap.link(key+"_raw", values[key+"_raw"]=0);
263 variableMap.link(key, values[key]=0);
264 variableMap.link(minusStr+key, values[minusStr+key]=0);
265 }
266 mout.debug("variables: " , variableMap );
267
268
269
270 const int iStep = this->iStep;
271 const int jStep = (this->jStep > 0) ? this->jStep : iStep;
272
273 const char commentChar = getCommentChar();
274 if (commentChar){
276
277 // ostr << commentChar << " TEST\n";
278 // picker.writeHeader(commentChar, ostr);
279 // ostr << commentChar << " size='" << picker.width << 'x' << picker.height << "'\n";
280
281 ostr << commentChar << commentChar << " input properties " << '\n';
282
283 for (const auto & entry: picker.infoMap){
284 ostr << commentChar << ' ' << entry.first << '=';
285 //it->second.valueToJSON(ostr);
286 Sprinter::toStream(ostr, entry.second, Sprinter::jsonLayout);
287 ostr << '\n';
288 }
289
290 ostr << commentChar << commentChar << " sampling parameters " << '\n';
291
292 for (const auto & entry: parameters){
293 ostr << commentChar << ' ' << entry.first << '=';
294 // it->second.valueToJSON(ostr);
295 Sprinter::toStream(ostr, entry.second, Sprinter::jsonLayout);
296 ostr << '\n';
297 }
298 if (!formatStr.empty())
299 ostr << commentChar << " format='" << formatStr << "'\n"; // formatStr instead of format, to save double slash \\n \\t
300 else
301 ostr << commentChar << " format='" << format << "'\n";
302
303 ostr << commentChar << commentChar << " resulting geometry " << '\n';
304 const int iN = picker.width/iStep;
305 const int jN = picker.height/jStep;
306 ostr << commentChar << " rows=" << iN << "\n";
307 ostr << commentChar << " rols=" << jN << "\n";
308 ostr << commentChar << " samples=" << (iN*jN) << "\n";
309
310
311 }
312
313
314 int iStart = this->iRange.min; // this->iStart;
315 if (iStart < 0)
316 iStart = iStep/2;
317
318 int jStart = this->jRange.min; //jStart;
319 if (jStart < 0)
320 jStart = jStep/2;
321
322 int iEnd = this->iRange.max; // iEnd;
323 if (iEnd < iStart)
324 iEnd = picker.width-1;
325
326 int jEnd = this->jRange.max; // jEnd;
327 if (jEnd < jStart)
328 jEnd = picker.height-1;
329
330 mout.attention(DRAIN_LOG(iStart));
331 mout.attention(DRAIN_LOG(iStep));
332 mout.attention(DRAIN_LOG(iEnd));
333 mout.attention(DRAIN_LOG(jStart));
334 mout.attention(DRAIN_LOG(jStep));
335 mout.attention(DRAIN_LOG(jEnd));
336
337 // Main loop: traverse image area with (i,j)
338 // SamplePicker has set variableMap references (ie. geographical coords j2=(height-1-j) ).
339 double x;
340 bool dataOk;
341 for (int j = jStart; j<=jEnd; j+=jStep){
342 for (int i = iStart; i<=iEnd; i+=iStep){
343
344 picker.setPosition(i, j);
345
346 // SLOW, but works... // TODO speedup with iterator
347 dataOk = true;
348 for (typename std::map<std::string, D>::const_iterator it = images.begin(); it != images.end(); ++it){
349 const std::string & quantity = it->first;
350 const D & data = it->second;
351
352 /* OLD:
353 if (!picker.getValue(data, x)){
354 dataOk = false;
355 if (MARK_VOID){
356 x = voidMarker;
357 }
358 }
359 */
360
361
362 if (picker.getValue(data, x)){
363 // If returns true, also raw value should be stored.
364 values[quantity+"_raw"] = x;
365 }
366
367 if (!picker.handleValue(data, x)){
368 // If returns false, value was invalid
369 dataOk = false;
370 if (MARK_VOID){
371 x = voidMarker;
372 }
373 }
374
375 //else if (x != 0) std::cerr << x << '\t';
376
377 values[quantity] = x;
378 values[minusStr+quantity] = -x;
379 }
380
381 if (dataOk || !SKIP_VOID){
382 //if (dataOk || (skipVoid==0)){
383 //formatter.toStream(ostr, variableMap, true);
384 formatter.toStream(ostr, variableMap, -1); // leaves ${variable} ?
385 if ((!dataOk) && (commentChar))
386 ostr << ' ' << commentChar << voidComment;
387 ostr << '\n';
388 }
389 }
390 // formatter.expand(map, true);
391 }
392 mout.warn("last values: " , variableMap );
393 //mout.warn("formatter " , formatter );
394
395 }
396
397
398};
399
400
401
402}
403}
404
405
406#endif /*POINT_H_*/
407
408// Drain
Something which has a name, a description and possibly some parameters of varying type.
Definition BeanLike.h:58
virtual const std::string & getName() const
Return the name of an instance.
Definition BeanLike.h:80
A map of FlexVariable:s.
Definition VariableMap.h:138
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:313
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition Log.h:431
Logger & debug(const TT &... args)
Debug information.
Definition Log.h:667
Logger & special(const TT &... args)
Other useful information.
Definition Log.h:532
Logger & attention(const TT &... args)
Possible error, but execution can continue. Special type of Logger::warn().
Definition Log.h:477
Logger & error(const TT &... args)
Echoes.
Definition Log.h:417
Logger & debug2(const TT &... args)
Debug information.
Definition Log.h:677
Definition Range.h:52
A map of references to base type scalars, arrays or std::string; changing values in either are equiva...
Definition ReferenceMap.h:69
ref_t & link(const std::string &key, F &x)
Associates a map entry with a variable.
Definition ReferenceMap.h:84
void copyStruct(const ReferenceMap &m, const T &src, T &dst, extLinkPolicy policy=RESERVE)
Experimental. Copies references and values of a structure to another.
Definition ReferenceMap.h:415
static std::ostream & toStream(std::ostream &ostr, const std::initializer_list< T > &x, const SprinterLayout &layout=defaultLayout)
New (experimental)
Definition Sprinter.h:423
static const SprinterLayout jsonLayout
Resembles JSON structure: {"a":1,"b":22,"c":3}.
Definition Sprinter.h:224
Definition StringMapper.h:114
StringMapper & parse(const std::string &s, bool convertEscaped=false)
Converts a std::string containing variables like in "Hello, ${NAME}!" to a list of StringLet's.
Definition StringMapper.cpp:68
std::ostream & toStream(std::ostream &ostr) const
Output a concatenated chain of stringlets: literals as such and variables surrounded with "${" and "}...
Definition StringMapper.h:204
static void convert(const std::string &s, T &dst)
Conversion from std::string to basic types, including std::string.
Definition StringTools.h:634
Image with static geometry.
Definition ImageFrame.h:62
double getScaled(size_t i, size_t j) const
Get intensity in original physical scale.
Definition ImageFrame.h:282
Reads image channels, returning scaled (physical) values.
Definition Sampler.h:120
bool handleValue(const ImageFrame &data, double &value) const
Definition Sampler.h:150
bool getValue(const ImageFrame &image, double &value) const
Definition Sampler.h:137
Utility for sampling images (2D data), outputting formatted text data.
Definition Sampler.h:162
char getCommentChar() const
Returns character, also supporting numeric ASCII values between 32 and 128.
Definition Sampler.cpp:58
std::string commentPrefix
Escape std::string for prefixing text no to be handled as data values.
Definition Sampler.h:183
ReferenceMap2 variableMap
Interface that links coordinates and image data.
Definition Sampler.h:198
std::string getFormat(const std::string &formatStr) const
Use given format or generate default "${var},${var2}, ...".
Definition Sampler.cpp:90
bool skipVoid
Skip lines, if contain missing values.
Definition Sampler.h:188
void sample(const std::map< std::string, D > &images, const P &picker, const std::string &formatStr, std::ostream &ostr=std::cout) const
Main function.
Definition Sampler.h:220
Definition DataSelector.cpp:1277
Interprets data values for Sampler.
Definition Sampler.h:58
int current_j2
Vertical inversed coordinate.
Definition Sampler.h:102
ReferenceMap2 & variableMap
Definition Sampler.h:112
int current_i
Optional utility. Called prior to writing the actual data to output stream.
Definition Sampler.h:96
SamplePicker(ReferenceMap2<> &variableMap)
Definition Sampler.h:65
FlexVariableMap infoMap
Information to be should in output file header.
Definition Sampler.h:108
int current_j
Vertical coordinate.
Definition Sampler.h:99
virtual void setPosition(int i, int j) const
Sets current position in image coordinates. To be redefined to compute also geographical projections,...
Definition Sampler.h:81