MI - Fimex
Utils.h
Go to the documentation of this file.
1 /*
2  * Fimex
3  *
4  * (C) Copyright 2008, met.no
5  *
6  * Project Info: https://wiki.met.no/fimex/start
7  *
8  * This library is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  * License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21  * USA.
22  */
23 
24 #ifndef UTILS_H_
25 #define UTILS_H_
26 
27 #include <vector>
28 #include <utility>
29 #include <iterator>
30 #include <sstream>
31 #include <cmath>
32 #include <boost/date_time/posix_time/posix_time_types.hpp>
33 #include <boost/math/special_functions/fpclassify.hpp>
34 #include <boost/regex.hpp>
35 #include <limits>
36 #include "fimex/CDMException.h"
37 #include "fimex/UnitsConverter.h"
38 #include <boost/shared_array.hpp>
39 
40 namespace MetNoFimex
41 {
45 int round(double num);
46 
51 std::string trim(const std::string& str);
52 
60 template<class InputIterator>
61 std::string join(InputIterator start, InputIterator end, std::string delim = ",")
62 {
63  if (start == end) return "";
64  std::ostringstream buffer;
65  InputIterator current = start++;
66  while (start != end) {
67  buffer << *current << delim;
68  current = start++;
69  }
70  buffer << *current;
71  return buffer.str();
72 }
73 
85 template<typename InputIterator>
87 find_closest_distinct_elements(InputIterator start, InputIterator end, double x)
88 {
89  using namespace std;
92  InputIterator cur = start;
94  double v1Diff, v2Diff;
95  if (start != end) {
96  v1 = *start;
97  v1Diff = abs(x-*start);
98  v2Diff = v1Diff;
99  }
100  while (cur != end) {
101  double vDiff = fabs(x-*cur);
102  if (vDiff <= v2Diff) {
103  if (vDiff < v1Diff) {
104  retVal2 = retVal1;
105  v2Diff = v1Diff;
106  v1 = *cur;
107  retVal1 = distance(start, cur);
108  v1Diff = vDiff;
109  } else if (*cur != v1) {
110  retVal2 = distance(start, cur);
111  v2Diff = vDiff;
112  }
113  } // else nothing to be done
114  cur++;
115  }
116  return make_pair<typename iterator_traits<InputIterator>::difference_type, typename iterator_traits<InputIterator>::difference_type>(retVal1, retVal2);
117 }
118 
132 template<typename InputIterator>
134 find_closest_neighbor_distinct_elements(InputIterator start, InputIterator end, double x)
135 {
136  using namespace std;
137  if (start == end)
138  return make_pair<typename iterator_traits<InputIterator>::difference_type, typename iterator_traits<InputIterator>::difference_type>(0, 0);
139 
140  InputIterator lowest = start;
141  InputIterator heighest = start;
142  InputIterator cur = start;
143  double lowDiff = x - *cur;
144  double heighDiff = *cur -x;
145  double maxDiff = std::numeric_limits<double>::max();
146  if (lowDiff < 0)
147  lowDiff = maxDiff;
148  if (heighDiff < 0)
149  heighDiff = maxDiff;
150  while (++cur != end) {
151  if (*cur <= x) {
152  double diff = x - *cur;
153  if (diff < lowDiff) {
154  lowDiff = diff;
155  lowest = cur;
156  }
157  } else {
158  double diff = *cur - x;
159  if (diff < heighDiff) {
160  heighDiff = diff;
161  heighest = cur;
162  }
163  }
164  }
165  if (lowDiff == maxDiff ||
166  heighDiff == maxDiff) {
167  // extrapolating
168  return find_closest_distinct_elements(start, end, x);
169  }
170 
171  return make_pair<typename iterator_traits<InputIterator>::difference_type, typename iterator_traits<InputIterator>::difference_type>(distance(start, lowest), distance(start, heighest));
172 
173 }
181 template<class InputIterator>
182 std::string joinPtr(InputIterator start, InputIterator end, std::string delim = ",")
183 {
184  if (start == end) return "";
185  std::ostringstream buffer;
186  InputIterator current = start++;
187  while (start != end) {
188  buffer << **current << delim;
189  current = start++;
190  }
191  buffer << **current;
192  return buffer.str();
193 }
194 
204 std::vector<std::string> tokenize(const std::string& str, const std::string& delimiters = " ");
205 
206 
211 
215 template<typename T>
217  std::ostringstream buffer;
218  buffer << in;
219  return buffer.str();
220 }
221 
225 template<>
227 
228 
229 template<typename T>
231  T retVal;
232  std::stringstream buffer;
233  buffer << s;
234  buffer >> retVal;
235  return retVal;
236 }
237 
241 template<typename T>
242 struct Varargs {
246  Varargs& operator()(T arg) {args.push_back(arg); return *this;}
247  Varargs(T arg) {args.push_back(arg);}
248 };
249 
250 
256 template<typename T>
258  while (in < -180) {
259  in += 360;
260  }
261  while (in > 180) {
262  in -= 360;
263  }
264  return in;
265 }
266 
267 
268 
269 typedef long epoch_seconds;
274 epoch_seconds posixTime2epochTime(const boost::posix_time::ptime& time);
275 
281 template<typename T>
282 std::vector<T> tokenizeDotted(const std::string& str, const std::string& delimiter = ",") throw(CDMException)
283 {
284  std::vector<std::string> tokens = tokenize(str, delimiter);
285  std::vector<T> vals;
286  for (std::vector<std::string>::iterator tok = tokens.begin(); tok != tokens.end(); ++tok) {
287  std::string current = trim(*tok);
288  if (current == "...") {
289  size_t currentPos = vals.size();
290  if (currentPos < 2) {
291  throw CDMException("tokenizeDotted: cannot use ... expansion at position " + type2string(currentPos-1) +", need at least two values before");
292  }
293  T last = vals[currentPos-1];
294  T dist = last - vals[currentPos-2];
295  T curVal = last + dist;
296  // positive if values get larger, negative if curVal gets samller
297  double direction = (dist > 0) ? 1 : -1;
298  if (++tok != tokens.end()) {
299  T afterDotVal = string2type<T>(*tok);
300  // expand the dots until before the afterDotVal, compare against rounding error
301  double roundError = direction*dist*-1.e-5;
302  while ((curVal - afterDotVal)*direction < roundError) {
303  vals.push_back(curVal);
304  curVal += dist;
305  }
306  // add the afterDotVal
307  vals.push_back(afterDotVal);
308  }
309  } else {
310  T val = string2type<T>(current);
311  vals.push_back(val);
312  }
313  }
314  return vals;
315 }
316 
318 template<typename OUT>
319 struct staticCast {
320  template<typename IN>
321  OUT operator()(const IN& in) { return static_cast<OUT>(in); }
322 };
323 
329 template<typename C>
330 int mifi_isnan(C x) {
331  return boost::math::isnan(x);
332 }
333 
345 void scanFiles(std::vector<std::string>& files, const std::string& dir, int depth, const boost::regex& regexp, bool matchFileOnly);
353 void globFiles(std::vector<std::string>& files, const std::string& glob);
354 
358 template<typename IN, typename OUT>
359 class ScaleValue : public std::unary_function<IN, OUT>
360 {
361 private:
362  IN oldFill_;
363  double oldScaleNewScaleInv_;
364  double oldOffsetMinusNewOffsetNewScaleInv_;
365  OUT newFill_;
366 public:
367  ScaleValue(double oldFill, double oldScale, double oldOffset, double newFill, double newScale, double newOffset) :
368  oldFill_(static_cast<IN>(oldFill)), oldScaleNewScaleInv_(oldScale/newScale),
369  oldOffsetMinusNewOffsetNewScaleInv_((oldOffset-newOffset)/newScale),
370  newFill_(static_cast<OUT>(newFill)) {}
371  OUT operator()(const IN& in) const {
372  return (in == oldFill_ || mifi_isnan<IN>(in))
373  ? newFill_
374  : static_cast<OUT>(oldScaleNewScaleInv_*in + oldOffsetMinusNewOffsetNewScaleInv_);
375  //(((oldScale_*in + oldOffset_)-newOffset_)/newScale_);
376  // => ((oldScale_*in + oldOffsetMinusNewOffset_)*newScaleInv_);
377  // => oldScaleNewScale_ * in + oldOffsetMinusNewOffsetNewScale_
378  }
379 };
380 
384 template<typename IN, typename OUT>
385 class ScaleValueUnits : public std::unary_function<IN, OUT>
386 {
387 private:
388  IN oldFill_;
389  double oldScale_;
390  double oldOffset_;
391  boost::shared_ptr<UnitsConverter> uconv_;
392  OUT newFill_;
393  double newScaleInv_;
394  double newOffset_;
395 public:
396  ScaleValueUnits(double oldFill, double oldScale, double oldOffset, boost::shared_ptr<UnitsConverter> uconv, double newFill, double newScale, double newOffset) :
397  oldFill_(static_cast<IN>(oldFill)), oldScale_(oldScale), oldOffset_(oldOffset),
398  uconv_(uconv),
399  newFill_(static_cast<OUT>(newFill)), newScaleInv_(1/newScale), newOffset_(newOffset) {}
400  OUT operator()(const IN& in) const {
401  return (in == oldFill_ || mifi_isnan<IN>(in))
402  ? newFill_
403  : static_cast<OUT>((uconv_->convert(oldScale_*in + oldOffset_)-newOffset_)*newScaleInv_);
404  }
405 };
406 
407 
411 template<typename IN, typename OUT>
413 {
414 private:
415  IN oldFill_;
416  OUT newFill_;
417 public:
418  ChangeMissingValue(double oldFill, double newFill) :
419  oldFill_(static_cast<IN>(oldFill)), newFill_(static_cast<OUT>(newFill)) {}
420  OUT operator()(const IN& in) const {
421  return (in == oldFill_ || mifi_isnan(in))
422  ? newFill_
423  : static_cast<OUT>(in);
424  }
425 };
426 
435 template<typename T>
437  SharedArrayConstCastDeleter( boost::shared_array<T> ptr ) : ptr(ptr) {};
438  template<typename C> void operator()(C*) {}
439 protected:
440  boost::shared_array<T> ptr;
441 };
445 template<typename T>
446 boost::shared_array<const T> makeSharedArrayConst(const boost::shared_array<T>& sa) {
447  return boost::shared_array<const T>(sa.get(), SharedArrayConstCastDeleter<T>(sa));
448 }
449 
450 
451 }
452 
453 #endif /*UTILS_H_*/
Definition: Utils.h:359
basic_string< char > string
SharedArrayConstCastDeleter(boost::shared_array< T > ptr)
Definition: Utils.h:437
T string2type(std::string s)
Definition: Utils.h:230
Definition: Utils.h:385
Varargs & operator()(T arg)
Definition: Utils.h:246
int round(double num)
boost::shared_array< const T > makeSharedArrayConst(const boost::shared_array< T > &sa)
Definition: Utils.h:446
ScaleValueUnits(double oldFill, double oldScale, double oldOffset, boost::shared_ptr< UnitsConverter > uconv, double newFill, double newScale, double newOffset)
Definition: Utils.h:396
Definition: Utils.h:242
epoch_seconds posixTime2epochTime(const boost::posix_time::ptime &time)
OUT operator()(const IN &in) const
Definition: Utils.h:371
STL namespace.
std::vector< T > tokenizeDotted(const std::string &str, const std::string &delimiter=",")
Definition: Utils.h:282
int mifi_isnan(C x)
Definition: Utils.h:330
OUT operator()(const IN &in) const
Definition: Utils.h:400
basic_ostringstream< char > ostringstream
basic_stringstream< char > stringstream
Definition: CDMException.h:36
std::string string2lowerCase(const std::string &str)
void scanFiles(std::vector< std::string > &files, const std::string &dir, int depth, const boost::regex &regexp, bool matchFileOnly)
Varargs(T arg)
Definition: Utils.h:247
ScaleValue(double oldFill, double oldScale, double oldOffset, double newFill, double newScale, double newOffset)
Definition: Utils.h:367
Definition: C_CDMReader.h:35
std::string join(InputIterator start, InputIterator end, std::string delim=",")
Definition: Utils.h:61
std::string type2string< double >(double in)
void operator()(C *)
Definition: Utils.h:438
const_iterator end() const
void push_back(const value_type &__x)
Definition: Utils.h:319
size_type size() const
const_iterator begin() const
iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
OUT operator()(const IN &in) const
Definition: Utils.h:420
void globFiles(std::vector< std::string > &files, const std::string &glob)
std::string trim(const std::string &str)
std::pair< typename std::iterator_traits< InputIterator >::difference_type, typename std::iterator_traits< InputIterator >::difference_type > find_closest_neighbor_distinct_elements(InputIterator start, InputIterator end, double x)
Definition: Utils.h:134
std::string type2string(T in)
Definition: Utils.h:216
std::pair< typename std::iterator_traits< InputIterator >::difference_type, typename std::iterator_traits< InputIterator >::difference_type > find_closest_distinct_elements(InputIterator start, InputIterator end, double x)
Definition: Utils.h:87
ChangeMissingValue(double oldFill, double newFill)
Definition: Utils.h:418
long epoch_seconds
Definition: Utils.h:269
Definition: Utils.h:412
std::string joinPtr(InputIterator start, InputIterator end, std::string delim=",")
Definition: Utils.h:182
boost::shared_array< T > ptr
Definition: Utils.h:440
void str(const __string_type &__s)
OUT operator()(const IN &in)
Definition: Utils.h:321
_Iterator::difference_type difference_type
_Iterator::value_type value_type
std::vector< std::string > tokenize(const std::string &str, const std::string &delimiters=" ")
T normalizeLongitude180(T in)
Definition: Utils.h:257
std::vector< T > args
Definition: Utils.h:244