PageRenderTime 54ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/container/ClassContainerBase.cxx

https://gitlab.com/ineris/GPEC
C++ | 2189 lines | 1722 code | 399 blank | 68 comment | 348 complexity | f811424b32b6a6b5187de0553fdbb5ee MD5 | raw file
Possible License(s): GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. // Copyright (C) 2013-2015 INERIS
  2. // Author(s) : Edouard Debry
  3. //
  4. // This file is part of GPEC.
  5. //
  6. // GPEC is free software: you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // GPEC is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with GPEC. If not, see <http://www.gnu.org/licenses/>.
  18. #ifndef GPEC_FILE_CLASS_CONTAINER_BASE_CXX
  19. #include "ClassContainerBase.hxx"
  20. namespace GPEC
  21. {
  22. // Set number of time steps.
  23. template<class T>
  24. inline void ClassContainerBase<T>::set_Nt()
  25. {
  26. Nt_ = 0;
  27. if (date_begin_ < date_end_)
  28. Nt_ = get_time_index(date_end_.GetSecondsFrom(date_begin_), delta_t_);
  29. }
  30. // Set number of days.
  31. template<class T>
  32. inline void ClassContainerBase<T>::set_Nd()
  33. {
  34. Nd_ = 0;
  35. if (date_begin_ < date_end_)
  36. Nd_ = date_end_.GetDaysFrom(date_begin_);
  37. if (Nd_ * Nt_day_ < Nt_)
  38. Nd_++;
  39. }
  40. // Get location index.
  41. template<class T>
  42. inline int ClassContainerBase<T>::get_location_index(const int &t, const int &location) const
  43. {
  44. if (data_(t).GetSize() == Nl_)
  45. return location;
  46. int l;
  47. for (l = 0; l < data_(t).GetSize(); l++)
  48. if (location_index_(t)(l) > location)
  49. return data_(t).GetSize();
  50. else if (location_index_(t)(l) == location)
  51. break;
  52. return l;
  53. }
  54. // Construct.
  55. template<class T>
  56. void ClassContainerBase<T>::construct(const string &prefix_base)
  57. {
  58. // Read configuration.
  59. Ops::Ops ops(this->configuration_file_);
  60. ops.SetPrefix("general.");
  61. delta_t_ = ops.Get<T>("Delta_t");
  62. // Custom values for species.
  63. value_min_ = ops.Get<T>(species_ + ".value_min", "", T(CONTAINER_VALUE_MIN));
  64. value_max_ = ops.Get<T>(species_ + ".value_max", "", T(CONTAINER_VALUE_MAX));
  65. // Set type and name of container.
  66. ops.SetPrefix(prefix_base);
  67. if (type_.empty())
  68. type_ = ops.Get<string>(name_ + ".type", "", name_);
  69. #ifdef GPEC_WITH_LOGGER
  70. if (! ops.Exists(type_))
  71. *(this->log_ptr_) << Warning() << "Container type \"" << type_
  72. << "\" not found in configuration file \"" << ClassGPEC::configuration_file_ << "\"." << endl;
  73. #endif
  74. // Set time step.
  75. ops.SetPrefix(prefix_base + type_ + ".");
  76. delta_t_ = ops.Get<T>("Delta_t", "", delta_t_);
  77. // If type appears to be already filtered.
  78. if (type_.substr(0, 4) == "peak" || type_.substr(0, 4) == "mean")
  79. delta_t_ = T(86400);
  80. if (delta_t_ > T(0))
  81. Nt_day_ = get_time_index<T>(T(86400), delta_t_);
  82. else
  83. throw GPEC::Error("Negative or null time step in configuration.");
  84. ops.Close();
  85. }
  86. // Init.
  87. template<class T>
  88. void ClassContainerBase<T>::Init()
  89. {
  90. Ops::Ops ops(ClassGPEC::configuration_file_);
  91. #ifdef GPEC_WITH_LOGGER
  92. *(ClassGPEC::log_ptr_) << Bgreen() << Fblack() << Info() << Reset()
  93. << "Init static data for base container class." << endl;
  94. #endif
  95. ops.SetPrefix("general.forecast.");
  96. forecast_min_ = ops.Get<int>("min");
  97. forecast_max_ = ops.Get<int>("max");
  98. #ifdef GPEC_WITH_LOGGER
  99. *(ClassGPEC::log_ptr_) << Fgreen() << Debug() << Reset() << "forecast_min = " << forecast_min_ << endl;
  100. *(ClassGPEC::log_ptr_) << Fgreen() << Debug() << Reset() << "forecast_max = " << forecast_max_ << endl;
  101. *(ClassGPEC::log_ptr_) << Bgreen() << Fblack() << User(0, "EXPLANATION") << Reset()
  102. << "Minimal and maximal forecast days used in GPEC : 0 means today, 1 tomorrow,"
  103. << " ..., and negative means an analysis, change with care." << endl;
  104. #endif
  105. ops.Close();
  106. }
  107. // Constructors.
  108. template<class T>
  109. ClassContainerBase<T>::ClassContainerBase()
  110. : ClassGPEC(), type_(""), name_(""), comment_(""),
  111. species_(""), date_begin_(DATE_END_DEFAULT), date_end_(DATE_BEGIN_DEFAULT), Nt_(0),
  112. Nt_day_(0), Nd_(0), delta_t_(T(0)), Nl_(0), value_min_(T(0)), value_max_(T(1.e9))
  113. {
  114. return;
  115. }
  116. template<class T>
  117. ClassContainerBase<T>::ClassContainerBase(const string &type,
  118. const string &name,
  119. const string &species,
  120. const string &prefix_base)
  121. : ClassGPEC(), type_(type), name_(name), comment_(""),
  122. species_(species), date_begin_(DATE_END_DEFAULT), date_end_(DATE_BEGIN_DEFAULT), Nt_(0),
  123. Nt_day_(0), Nd_(0), delta_t_(T(0)), Nl_(0), value_min_(T(0)), value_max_(T(1.e9))
  124. {
  125. construct(prefix_base);
  126. return;
  127. }
  128. template<class T>
  129. ClassContainerBase<T>::ClassContainerBase(const string &name,
  130. const string &species,
  131. const string &prefix_base)
  132. : ClassGPEC(), type_(""), name_(name), comment_(""),
  133. species_(species), date_begin_(DATE_END_DEFAULT), date_end_(DATE_BEGIN_DEFAULT), Nt_(0),
  134. Nt_day_(0), Nd_(0), delta_t_(T(0)), Nl_(0), value_min_(T(0)), value_max_(T(1.e9))
  135. {
  136. construct(prefix_base);
  137. return;
  138. }
  139. // Destructor.
  140. template<class T>
  141. ClassContainerBase<T>::~ClassContainerBase()
  142. {
  143. return;
  144. }
  145. // Clear data.
  146. template<class T>
  147. void ClassContainerBase<T>::Clear()
  148. {
  149. Nt_ = 0;
  150. Nd_ = 0;
  151. date_begin_.SetDate(DATE_END_DEFAULT);
  152. date_end_.SetDate(DATE_BEGIN_DEFAULT);
  153. forecast_.Clear();
  154. location_index_.Clear();
  155. data_.Clear();
  156. string comment = "cleared container";
  157. AddComment(comment);
  158. }
  159. template<class T>
  160. void ClassContainerBase<T>::PartialClear()
  161. {
  162. for (int t = 0; t < Nt_; t++)
  163. {
  164. location_index_(t).Clear();
  165. if (data_(t).GetSize() > 0)
  166. data_(t).Resize(1);
  167. }
  168. }
  169. // Copy constructor.
  170. template<class T>
  171. void ClassContainerBase<T>::Copy(const ClassContainerBase<T> &container, const string name)
  172. {
  173. // Name of copy may be different.
  174. name_ = name;
  175. // Everything else is identical.
  176. type_ = container.type_;
  177. species_ = container.species_;
  178. date_begin_ = container.date_begin_;
  179. date_end_ = container.date_end_;
  180. Nt_ = container.Nt_;
  181. Nd_ = container.Nd_;
  182. Nt_day_ = container.Nt_day_;
  183. delta_t_ = container.delta_t_;
  184. Nl_ = container.Nl_;
  185. location_index_ = container.location_index_;
  186. data_ = container.data_;
  187. forecast_ = container.forecast_;
  188. AddComment("copied from container \"" + container.name_ + "/" + container.type_ + "\"");
  189. ClassGPEC::Copy(container);
  190. }
  191. template<class T>
  192. bool ClassContainerBase<T>::HasSameStructure(const ClassContainerBase<T> &container) const
  193. {
  194. return Nl_ == container.Nl_;
  195. }
  196. // Checks if same time structure.
  197. template<class T>
  198. bool ClassContainerBase<T>::HasSameTimeStructure(const ClassContainerBase<T> &container) const
  199. {
  200. if (date_begin_ != container.date_begin_ ||
  201. Nt_ != container.Nt_ ||
  202. Nd_ != container.Nd_ ||
  203. Nt_day_ != container.Nt_day_)
  204. return false;
  205. return true;
  206. }
  207. template<class T>
  208. void ClassContainerBase<T>::SameTimeStructureAs(const ClassContainerBase<T> &container)
  209. {
  210. if (delta_t_ != container.delta_t_)
  211. throw GPEC::Error("Cannot put same time structure between containers with different time steps.");
  212. int t_beg(0), t_end(Nt_);
  213. if (date_begin_ < container.date_begin_)
  214. t_beg = GetDateIndex(container.date_begin_);
  215. if (date_end_ > container.date_end_)
  216. t_end = GetDateIndex(container.date_end_);
  217. RestrictDate(t_beg, t_end);
  218. Date date_beg(date_begin_), date_end(date_end_);
  219. if (date_begin_ > container.date_begin_)
  220. date_beg = container.date_begin_;
  221. if (date_end_ < container.date_end_)
  222. date_end = container.date_end_;
  223. ExtendDate(get_int_from_date(date_beg),
  224. get_int_from_date(date_end));
  225. }
  226. // Set methods.
  227. template<class T>
  228. void ClassContainerBase<T>::SetName(const string &name)
  229. {
  230. name_ = name;
  231. }
  232. template<class T>
  233. void ClassContainerBase<T>::SetType(const string &type)
  234. {
  235. type_ = type;
  236. }
  237. template<class T>
  238. void ClassContainerBase<T>::SetSpecies(const string &species)
  239. {
  240. species_ = species;
  241. }
  242. template<class T>
  243. void ClassContainerBase<T>::Set(const ClassContainerBase<T> &container, const string &prefix_base)
  244. {
  245. Clear();
  246. type_ = container.type_;
  247. name_ = container.name_;
  248. species_ = container.species_;
  249. construct(prefix_base);
  250. }
  251. template<class T> template<class U>
  252. void ClassContainerBase<T>::SetData(const Date &date_begin,
  253. const Date &date_end,
  254. const Vector1I &time,
  255. const Vector1I &location,
  256. const Vector1I &forecast,
  257. Vector<U> &data,
  258. const bool mask_negative_value)
  259. {
  260. if (data.GetSize() != time.GetSize() ||
  261. data.GetSize() != location.GetSize())
  262. throw GPEC::Error("Data vectors given in argument are not of equal size.");
  263. Clear();
  264. date_begin_ = date_begin;
  265. date_end_ = date_end;
  266. set_Nt();
  267. set_Nd();
  268. if (forecast.GetSize() != Nt_)
  269. throw GPEC::Error("Forecast vector should be of size " + to_str(Nt_) + ".");
  270. for (int i = 0; i < time.GetSize(); i++)
  271. check_index(0, Nt_, time(i));
  272. for (int i = 0; i < location.GetSize(); i++)
  273. check_index(0, Nl_, location(i));
  274. forecast_.Reallocate(Nt_);
  275. location_index_.Reallocate(Nt_);
  276. data_.Reallocate(Nt_);
  277. Vector1I Nl(Nt_);
  278. Nl.Zero();
  279. Vector<int> mask = check_data<U>(U(value_min_), U(value_max_), data);
  280. // Treat negative values as low values.
  281. if (! mask_negative_value)
  282. for (int i = 0; i < data.GetSize(); i++)
  283. if (mask(i) == -3)
  284. mask(i) = 1;
  285. // Negative values may appear for some sequential aggregation algorithms
  286. // that do not garantee positiveness. However, it usually appears because
  287. // of very low simulation values, and it should not be considered as an error.
  288. for (int i = 0; i < data.GetSize(); i++)
  289. if (mask(i) == 0)
  290. Nl(time(i))++;
  291. else
  292. {
  293. #ifdef GPEC_WITH_LOGGER
  294. *(this->log_ptr_) << User(0, "BAD-VALUE") << "At time " << time(i) << " and location "
  295. << location(i) << " got value " << data(i) << " ." << endl;
  296. #endif
  297. if (mask(i) > 0)
  298. {
  299. #ifdef GPEC_WITH_LOGGER
  300. *(this->log_ptr_) << User(0, "LOW-HIGH-VALUE") << "At time " << time(i) << " and location "
  301. << location(i) << " got value " << data(i) << " ." << endl;
  302. #endif
  303. Nl(time(i))++;
  304. data(i) = min<U>(max<U>(value_min_, data(i)), value_max_);
  305. }
  306. }
  307. for (int t = 0; t < Nt_; t++)
  308. if (Nl(t) > 0)
  309. {
  310. forecast_(t).Reallocate(1);
  311. check_index(forecast_min_, forecast_max_, forecast(t));
  312. forecast_(t)(0) = forecast(t);
  313. location_index_(t).Reallocate(Nl(t));
  314. data_(t).Reallocate(Nl(t));
  315. }
  316. Vector1I l(Nt_);
  317. l.Zero();
  318. for (int i = 0; i < data.GetSize(); i++)
  319. if (mask(i) >= 0)
  320. {
  321. int t = time(i);
  322. location_index_(t)(l(t)) = location(i);
  323. data_(t)(l(t)) = T(data(i));
  324. l(t)++;
  325. }
  326. for (int t = 0; t < Nt_; t++)
  327. for (int l = 1; l < location_index_(t).GetSize(); l++)
  328. if (location_index_(t)(l - 1) > location_index_(t)(l))
  329. {
  330. Sort(location_index_(t), data_(t));
  331. break;
  332. }
  333. // Location index not necessary if all locations are present.
  334. for (int t = 0; t < Nt_; t++)
  335. if (location_index_(t).GetSize() == Nl_)
  336. location_index_(t).Clear();
  337. }
  338. template<class T>
  339. void ClassContainerBase<T>::SetValueMin(const T &value_min)
  340. {
  341. value_min_ = value_min;
  342. }
  343. template<class T>
  344. void ClassContainerBase<T>::SetValueMax(const T &value_max)
  345. {
  346. value_max_ = value_max;
  347. }
  348. template<class T>
  349. void ClassContainerBase<T>::SetValue(const int &t,
  350. const int &location,
  351. const T &value)
  352. {
  353. if (value < value_min_ || value >= value_max_)
  354. return;
  355. check_index(0, Nt_, t);
  356. check_index(0, Nl_, location);
  357. int l = get_location_index(t, location);
  358. if (l < data_(t).GetSize())
  359. data_(t)(l) = value;
  360. }
  361. template<class T>
  362. void ClassContainerBase<T>::AddComment(const string add_comment)
  363. {
  364. comment_ += "At " + get_current_time() + ": " + add_comment + ".\n";
  365. }
  366. template<class T>
  367. void ClassContainerBase<T>::SetComment(const string &comment)
  368. {
  369. comment_ = comment;
  370. }
  371. // Check container.
  372. template<class T>
  373. void ClassContainerBase<T>::CheckContainer() const
  374. {
  375. if (Nt_ != location_index_.GetSize() ||
  376. Nt_ != data_.GetSize() ||
  377. Nt_ != forecast_.GetSize())
  378. throw GPEC::Error(string("Location index, forecast or data vector length does")
  379. + string(" not correspond to the number of time steps."));
  380. for (int t = 0; t < Nt_; t++)
  381. if (data_(t).GetSize() < Nl_)
  382. {
  383. if (location_index_(t).GetSize() != data_(t).GetSize())
  384. throw GPEC::Error("At time " + to_str(t) + ", sizes of location index and data vectors differ.");
  385. for (int l = 1; l < location_index_(t).GetSize(); l++)
  386. if (location_index_(t)(l - 1) >= location_index_(t)(l))
  387. throw GPEC::Error("At time " + to_str(t) + ", location indexes are not stored in ascending order.");
  388. }
  389. else if (data_(t).GetSize() == Nl_)
  390. {
  391. if (location_index_(t).GetSize() > 0)
  392. throw GPEC::Error("At time " + to_str(t) + ", location index vector should be empty.");
  393. }
  394. else
  395. throw GPEC::Error("At time " + to_str(t) + ", data vector greater than number of locations.");
  396. }
  397. // Find missing time steps.
  398. template<class T>
  399. void ClassContainerBase<T>::FindMissingTimeStep(Vector1I &missing_time_step) const
  400. {
  401. #ifdef GPEC_WITH_LOGGER
  402. *(this->log_ptr_) << Info() << "Looking for missing time steps ..." << endl;
  403. #endif
  404. for (int t = 0; t < Nt_; t++)
  405. if (data_(t).GetSize() == 0)
  406. missing_time_step.PushBack(t);
  407. #ifdef GPEC_WITH_LOGGER
  408. *(this->log_ptr_) << Info(1) << "... found " << missing_time_step.GetSize() << " of them." << endl;
  409. #endif
  410. }
  411. // Operations.
  412. template<class T>
  413. void ClassContainerBase<T>::Add(const T &value)
  414. {
  415. for (int t = 0; t < Nt_; t++)
  416. for (int l = 0; l < data_(t).GetSize(); l++)
  417. data_(t)(l) += value;
  418. }
  419. template<class T>
  420. void ClassContainerBase<T>::Mlt(const T &value)
  421. {
  422. for (int t = 0; t < Nt_; t++)
  423. for (int l = 0; l < data_(t).GetSize(); l++)
  424. data_(t)(l) *= value;
  425. }
  426. template<class T>
  427. void ClassContainerBase<T>::Set(const T &value)
  428. {
  429. for (int t = 0; t < Nt_; t++)
  430. for (int l = 0; l < data_(t).GetSize(); l++)
  431. data_(t)(l) = value;
  432. }
  433. // Print.
  434. template<class T>
  435. void ClassContainerBase<T>::Print(string &str, const bool &with_data) const
  436. {
  437. ostringstream sout;
  438. if (with_data)
  439. for (int t = 0; t < Nt_; t++)
  440. {
  441. Date date = date_begin_;
  442. date.AddSeconds(t * delta_t_);
  443. sout << setw(15) << left << date.GetDate("%y-%m-%d_%h");
  444. sout << setw(6) << left << "(" + to_str(t) + ")";
  445. Vector1T data;
  446. if (data_(t).GetSize() == Nl_)
  447. data = data_(t);
  448. else
  449. {
  450. data.Resize(Nl_);
  451. data.Fill(this->bad_value_);
  452. int loc(-1), l(0);
  453. while (++loc < Nl_ && l < location_index_(t).GetSize())
  454. if (location_index_(t)(l) == loc)
  455. data(loc) = data_(t)(l++);
  456. }
  457. for (int loc = 0; loc < Nl_; loc++)
  458. sout << setw(12) << setprecision(8) << left << data(loc);
  459. sout << endl;
  460. }
  461. for (int t = 0; t < Nt_; t++)
  462. {
  463. Date date = date_begin_;
  464. date.AddSeconds(t * delta_t_);
  465. sout << setw(15) << left << date.GetDate("%y-%m-%d_%h");
  466. sout << setw(8) << right << "(" + to_str(t) + ")";
  467. sout << setw(8) << right << data_(t).GetSize() << "/" << Nl_;
  468. if (forecast_(t).GetSize() > 0)
  469. sout << setw(4) << right << "D" << showpos << forecast_(t)(0);
  470. if (data_(t).GetSize() > 0)
  471. sout << setw(8) << right << noshowpos << fixed << setprecision(2) << Norm1(data_(t)) / T(data_(t).GetSize())
  472. << setw(8) << right << noshowpos << fixed << setprecision(2) << data_(t).GetNormInf();
  473. sout << endl;
  474. }
  475. sout << "Container: " << name_ << "/" << type_ << endl
  476. << "Species: " << this->species_ << endl;
  477. sout << "Date: " << date_begin_.GetDate("%y-%m-%d_%h") << " ---> "
  478. << date_end_.GetDate("%y-%m-%d_%h") << " (excluded)" << endl
  479. << "Time step = " << setprecision(1) << fixed << delta_t_ << " seconds" << endl
  480. << "Number of time steps = " << Nt_ << endl
  481. << "Number of days = " << Nd_ << endl;
  482. if (! comment_.empty())
  483. {
  484. sout << "Comment:" << endl;
  485. vector<string> ls = split(comment_, "\n");
  486. for (int i = 0; i < int(ls.size()); i++)
  487. sout << " " << ls[i] << endl;
  488. }
  489. str = sout.str();
  490. }
  491. // Get methods.
  492. template<class T>
  493. string ClassContainerBase<T>::GetType() const
  494. {
  495. return type_;
  496. }
  497. template<class T>
  498. string ClassContainerBase<T>::GetName() const
  499. {
  500. return name_;
  501. }
  502. template<class T>
  503. string ClassContainerBase<T>::GetComment() const
  504. {
  505. return comment_;
  506. }
  507. template<class T>
  508. string ClassContainerBase<T>::GetSpecies() const
  509. {
  510. return species_;
  511. }
  512. template<class T>
  513. int ClassContainerBase<T>::GetLocationIndex(const int &t, const int &location) const
  514. {
  515. return get_location_index(t, location);
  516. }
  517. template<class T>
  518. inline int ClassContainerBase<T>::GetNlTotal() const
  519. {
  520. int NlTotal(0);
  521. for (int t = 0; t < data_.GetSize(); t++)
  522. NlTotal += data_(t).GetSize();
  523. return NlTotal;
  524. }
  525. template<class T>
  526. int ClassContainerBase<T>::GetNl(const int &t) const
  527. {
  528. return data_(t).GetSize();
  529. }
  530. template<class T>
  531. int ClassContainerBase<T>::GetNlocation() const
  532. {
  533. return Nl_;
  534. }
  535. template<class T>
  536. int ClassContainerBase<T>::GetNt() const
  537. {
  538. return Nt_;
  539. }
  540. template<class T>
  541. int ClassContainerBase<T>::GetNtDay() const
  542. {
  543. return Nt_day_;
  544. }
  545. template<class T>
  546. int ClassContainerBase<T>::GetNd() const
  547. {
  548. return Nd_;
  549. }
  550. template<class T>
  551. T ClassContainerBase<T>::GetDeltat() const
  552. {
  553. return delta_t_;
  554. }
  555. template<class T>
  556. int ClassContainerBase<T>::GetDateIndex(const Date &date) const
  557. {
  558. return get_time_index<T>(date.GetSecondsFrom(date_begin_), delta_t_);
  559. }
  560. template<class T>
  561. Date ClassContainerBase<T>::GetDate(const int &t) const
  562. {
  563. Date date(date_begin_);
  564. date.AddSeconds(t * delta_t_);
  565. return date;
  566. }
  567. template<class T>
  568. Date ClassContainerBase<T>::GetDateBegin() const
  569. {
  570. return date_begin_;
  571. }
  572. template<class T>
  573. Date ClassContainerBase<T>::GetDateEnd() const
  574. {
  575. return date_end_;
  576. }
  577. template<class T>
  578. string ClassContainerBase<T>::GetDateStr(const int &t,
  579. const string format) const
  580. {
  581. return GetDate(t).GetDate(format);
  582. }
  583. template<class T>
  584. int ClassContainerBase<T>::GetDateIndexStr(const string &date_str) const
  585. {
  586. Date date(date_str);
  587. return GetDateIndex(date);
  588. }
  589. template<class T>
  590. string ClassContainerBase<T>::GetDateBeginStr(const string format) const
  591. {
  592. return date_begin_.GetDate(format);
  593. }
  594. template<class T>
  595. string ClassContainerBase<T>::GetDateEndStr(const string format) const
  596. {
  597. return date_end_.GetDate(format);
  598. }
  599. template<class T>
  600. T ClassContainerBase<T>::GetValue(const int &t, const int &location) const
  601. {
  602. check_index(0, Nt_, t);
  603. check_index(0, Nl_, location);
  604. int l = get_location_index(t, location);
  605. if (l < data_(t).GetSize())
  606. return data_(t)(l);
  607. else
  608. return this->bad_value_;
  609. }
  610. template<class T>
  611. inline T ClassContainerBase<T>::GetValueRaw(const int &t, const int &l) const
  612. {
  613. return data_(t)(l);
  614. }
  615. template<class T>
  616. int ClassContainerBase<T>::GetForecastDay(const int &t) const
  617. {
  618. check_index(0, Nt_, t);
  619. if (forecast_(t).GetSize() > 0)
  620. return forecast_(t)(0);
  621. else
  622. return int(this->bad_value_);
  623. }
  624. template<class T>
  625. T ClassContainerBase<T>::GetForecastDayMean(int t_begin, int t_end) const
  626. {
  627. if (t_end == 0)
  628. t_end = Nt_;
  629. int sum(0), count(0);
  630. for (int t = t_begin; t < t_end; t++)
  631. if (forecast_(t).GetSize() > 0)
  632. {
  633. sum += forecast_(t)(0);
  634. count++;
  635. }
  636. if (count > 0)
  637. return T(sum) / T(count);
  638. else
  639. return this->bad_value_;
  640. }
  641. template<class T>
  642. inline void ClassContainerBase<T>::CollectData(Vector1I &time,
  643. Vector1I& location,
  644. Vector1T &data) const
  645. {
  646. int Nsize(Nt_ * Nl_);
  647. time.Reallocate(Nsize);
  648. location.Reallocate(Nsize);
  649. data.Reallocate(Nsize);
  650. int i(0);
  651. for (int t = 0; t < Nt_; t++)
  652. if (data_(t).GetSize() == Nl_)
  653. for (int l = 0; l < Nl_; l++)
  654. {
  655. time(i) = t;
  656. location(i) = l;
  657. data(i++) = data_(t)(l);
  658. }
  659. else
  660. for (int l = 0; l < data_(t).GetSize(); l++)
  661. {
  662. time(i) = t;
  663. location(i) = location_index_(t)(l);
  664. data(i++) = data_(t)(l);
  665. }
  666. time.Resize(i);
  667. location.Resize(i);
  668. data.Resize(i);
  669. }
  670. template<class T>
  671. inline void ClassContainerBase<T>::CollectDataPeriod(const int &t_begin,
  672. const int &t_end,
  673. Vector1I &time,
  674. Vector1I& location,
  675. Vector1T &data) const
  676. {
  677. time.Clear();
  678. location.Clear();
  679. data.Clear();
  680. check_index(0, Nt_, t_begin);
  681. check_index(t_begin + 1, Nt_ + 1, t_end);
  682. int Nsize((t_end - t_begin) * Nl_);
  683. time.Reallocate(Nsize);
  684. location.Reallocate(Nsize);
  685. data.Reallocate(Nsize);
  686. int i(0);
  687. for (int t = t_begin; t < t_end; t++)
  688. if (data_(t).GetSize() == Nl_)
  689. for (int l = 0; l < data_(t).GetSize(); l++)
  690. {
  691. time(i) = t;
  692. location(i) = l;
  693. data(i++) = data_(t)(l);
  694. }
  695. else
  696. for (int l = 0; l < data_(t).GetSize(); l++)
  697. {
  698. time(i) = t;
  699. location(i) = location_index_(t)(l);
  700. data(i++) = data_(t)(l);
  701. }
  702. time.Resize(i);
  703. location.Resize(i);
  704. data.Resize(i);
  705. }
  706. template<class T>
  707. inline void ClassContainerBase<T>::CollectDataLocation(const int &location,
  708. Vector1I &time,
  709. Vector1T &data) const
  710. {
  711. time.Clear();
  712. data.Clear();
  713. check_index(0, Nl_, location);
  714. time.Reallocate(Nt_);
  715. data.Reallocate(Nt_);
  716. int i(0);
  717. for (int t = 0; t < Nt_; t++)
  718. {
  719. int l = get_location_index(t, location);
  720. if (l < data_(t).GetSize())
  721. {
  722. time(i) = t;
  723. data(i++) = data_(t)(l);
  724. }
  725. }
  726. time.Resize(i);
  727. data.Resize(i);
  728. }
  729. template<class T>
  730. inline void ClassContainerBase<T>::CollectDataTime(const int &t,
  731. Vector1I &location,
  732. Vector1T &data) const
  733. {
  734. location.Clear();
  735. data.Clear();
  736. if (data_(t).GetSize() == Nl_)
  737. {
  738. location.Reallocate(Nl_);
  739. location.Fill();
  740. }
  741. else
  742. location = location_index_(t);
  743. data = data_(t);
  744. }
  745. template<class T>
  746. inline void ClassContainerBase<T>::CollectDataTimeAtLocation(const int &t,
  747. const Vector1I &location,
  748. Vector1I &location_index,
  749. Vector1T &data) const
  750. {
  751. location_index.Reallocate(location.GetSize());
  752. data.Reallocate(location.GetSize());
  753. int j(0);
  754. if (data_(t).GetSize() == Nl_)
  755. for (int i = 0; i < location.GetSize(); i++)
  756. {
  757. location_index(j) = location(i);
  758. data(j++) = data_(t)(location(i));
  759. }
  760. else
  761. {
  762. int i(0), l(0);
  763. while (l < location_index_(t).GetSize() && i < location.GetSize())
  764. if (location_index_(t)(l) > location(i))
  765. i++;
  766. else if (location_index_(t)(l) < location(i))
  767. l++;
  768. else
  769. {
  770. location_index(j) = location(i);
  771. data(j++) = data_(t)(l);
  772. i++;
  773. l++;
  774. }
  775. }
  776. location_index.Resize(j);
  777. data.Resize(j);
  778. }
  779. template<class T>
  780. void ClassContainerBase<T>::CollectDataRaw(Vector1T &data,
  781. const bool with_bad_value) const
  782. {
  783. Vector1I time, location;
  784. Vector1T data_tmp;
  785. CollectData(time, location, data_tmp);
  786. if (with_bad_value)
  787. {
  788. data.Reallocate(Nt_ * Nl_);
  789. data.Fill(this->bad_value_);
  790. for (int i = 0; i < data_tmp.GetSize(); i++)
  791. data(Nl_ * time(i) + location(i)) = data_tmp(i);
  792. }
  793. else
  794. data = data_tmp;
  795. }
  796. template<class T>
  797. void ClassContainerBase<T>::CollectDataLocationRaw(const int &location,
  798. Vector1T &data,
  799. const bool with_bad_value) const
  800. {
  801. Vector1I time;
  802. Vector1T data_tmp;
  803. CollectDataLocation(location, time, data_tmp);
  804. if (with_bad_value)
  805. {
  806. data.Reallocate(Nt_);
  807. data.Fill(this->bad_value_);
  808. for (int i = 0; i < data_tmp.GetSize(); i++)
  809. data(time(i)) = data_tmp(i);
  810. }
  811. else
  812. data = data_tmp;
  813. }
  814. template<class T>
  815. void ClassContainerBase<T>::CollectDataTimeRaw(const int &t,
  816. Vector1T &data,
  817. const bool with_bad_value) const
  818. {
  819. Vector1I location;
  820. Vector1T data_tmp;
  821. CollectDataTime(t, location, data_tmp);
  822. if (with_bad_value)
  823. {
  824. data.Reallocate(Nl_);
  825. data.Fill(this->bad_value_);
  826. for (int i = 0; i < data_tmp.GetSize(); i++)
  827. data(location(i)) = data_tmp(i);
  828. }
  829. else
  830. data = data_tmp;
  831. }
  832. template<class T>
  833. void ClassContainerBase<T>::CollectDataPeriodRaw(const int &t_begin,
  834. const int &t_end,
  835. Vector1T &data,
  836. const bool with_bad_value) const
  837. {
  838. Vector1I time, location;
  839. Vector1T data_tmp;
  840. CollectDataPeriod(t_begin, t_end, time, location, data_tmp);
  841. if (with_bad_value)
  842. {
  843. data.Reallocate((t_end - t_begin) * Nl_);
  844. data.Fill(this->bad_value_);
  845. for (int i = 0; i < data_tmp.GetSize(); i++)
  846. data(Nl_ * (time(i) - t_begin) + location(i)) = data_tmp(i);
  847. }
  848. else
  849. data = data_tmp;
  850. }
  851. // Remove or keep locations.
  852. template<class T>
  853. void ClassContainerBase<T>::RemoveTimeStep(const Vector1I &time_step)
  854. {
  855. // Abruptly remove some time steps.
  856. for (int i = 0; i < time_step.GetSize(); i++)
  857. {
  858. int t = time_step(i);
  859. forecast_(t).Clear();
  860. location_index_(t).Clear();
  861. data_(t).Clear();
  862. }
  863. }
  864. template<class T>
  865. void ClassContainerBase<T>::RemoveLocation(const Vector1I &location)
  866. {
  867. Vector1I location_ascending = location;
  868. Sort(location_ascending);
  869. Vector1I location_keep(Nl_);
  870. int l(-1), i(0), j(0);
  871. while (++l < Nl_)
  872. if (i < location_ascending.GetSize())
  873. {
  874. if (l == location_ascending(i))
  875. i++;
  876. else
  877. location_keep(j++) = l;
  878. }
  879. else
  880. location_keep(j++) = l;
  881. location_keep.Resize(j);
  882. KeepLocation(location_keep);
  883. }
  884. template<class T>
  885. void ClassContainerBase<T>::KeepLocation(const Vector1I &location)
  886. {
  887. Vector1I location_ascending = location;
  888. Sort(location_ascending);
  889. for (int t = 0; t < Nt_; t++)
  890. {
  891. Vector1I location_index_new(data_(t).GetSize());
  892. Vector1T data_new(data_(t).GetSize());
  893. int i(0), count(0);
  894. if (data_(t).GetSize() == Nl_)
  895. {
  896. int l(-1);
  897. while (++l < Nl_ && i < location_ascending.GetSize())
  898. if (l == location_ascending(i))
  899. {
  900. location_index_new(count) = l;
  901. data_new(count++) = data_(t)(l);
  902. i++;
  903. }
  904. }
  905. else
  906. {
  907. int l(0);
  908. while (l < location_index_(t).GetSize() && i < location_ascending.GetSize())
  909. if (location_index_(t)(l) > location_ascending(i))
  910. i++;
  911. else if (location_index_(t)(l) < location_ascending(i))
  912. l++;
  913. else
  914. {
  915. location_index_new(count) = location_index_(t)(l);
  916. data_new(count++) = data_(t)(l);
  917. l++;
  918. i++;
  919. }
  920. }
  921. location_index_new.Resize(count);
  922. data_new.Resize(count);
  923. if (count == 0)
  924. forecast_(t).Clear();
  925. location_index_(t) = location_index_new;
  926. data_(t) = data_new;
  927. }
  928. AddComment("kept " + to_str(location.GetSize()) + " locations");
  929. }
  930. // Restrict or extend date range.
  931. template<class T>
  932. void ClassContainerBase<T>::RestrictDate(const int &t_begin, const int &t_end)
  933. {
  934. check_index(0, Nt_, t_begin);
  935. check_index(t_begin + 1, Nt_ + 1, t_end);
  936. Nt_ = t_end - t_begin;
  937. date_begin_.AddSeconds(t_begin * delta_t_);
  938. date_end_ = date_begin_;
  939. date_end_.AddSeconds(Nt_ * delta_t_);
  940. set_Nd();
  941. for (int t = 0; t < Nt_; t++)
  942. {
  943. int t_offset(t_begin + t);
  944. forecast_(t) = forecast_(t_offset);
  945. location_index_(t) = location_index_(t_offset);
  946. data_(t) = data_(t_offset);
  947. }
  948. forecast_.Resize(Nt_);
  949. location_index_.Resize(Nt_);
  950. data_.Resize(Nt_);
  951. AddComment("restricted container between time steps " + to_str(t_begin)
  952. + " and " + to_str(t_end) + " (excluded)");
  953. }
  954. template<class T>
  955. void ClassContainerBase<T>::ExtendDate(const int &date_begin_int, const int &date_end_int)
  956. {
  957. Date date_begin_ext = get_date_from_int(date_begin_int);
  958. Date date_end_ext = get_date_from_int(date_end_int);
  959. if (date_begin_ext > date_begin_ && date_end_ext <= date_end_)
  960. return;
  961. int t_old = get_time_index<T>(date_begin_.GetSecondsFrom(date_begin_ext), delta_t_);
  962. int Nt_old(Nt_);
  963. date_begin_ = date_begin_ext;
  964. date_end_ = date_end_ext;
  965. set_Nt();
  966. set_Nd();
  967. forecast_.Resize(Nt_);
  968. location_index_.Resize(Nt_);
  969. data_.Resize(Nt_);
  970. if (t_old != 0)
  971. for (int t = Nt_old - 1; t >= 0; t--)
  972. {
  973. int t_new(t + t_old);
  974. forecast_(t_new) = forecast_(t);
  975. location_index_(t_new) = location_index_(t);
  976. data_(t_new) = data_(t);
  977. forecast_(t).Clear();
  978. location_index_(t).Clear();
  979. data_(t).Clear();
  980. }
  981. AddComment("extended container between dates " + date_begin_ext.GetDate("%y-%m-%d_%h")
  982. + " and " + date_end_ext.GetDate("%y-%m-%d_%h") + " (excluded)");
  983. }
  984. // Merge.
  985. template<class T>
  986. void ClassContainerBase<T>::Merge(const ClassContainerBase<T> &container,
  987. const bool overwrite)
  988. {
  989. if (delta_t_ != container.delta_t_)
  990. throw GPEC::Error("Not equal time step between containers.");
  991. if (Nl_ != container.Nl_)
  992. throw GPEC::Error("Not equal number of locations between containers.");
  993. Date date_begin_merge = min<Date>(date_begin_, container.date_begin_);
  994. Date date_end_merge = max<Date>(date_end_, container.date_end_);
  995. // Extend current container to merge dates.
  996. ExtendDate(get_int_from_date(date_begin_merge),
  997. get_int_from_date(date_end_merge));
  998. // Merge with other container.
  999. int t_merge(0);
  1000. Date date_running(date_begin_merge);
  1001. while (date_running < date_end_merge)
  1002. {
  1003. if (date_running >= container.date_begin_ &&
  1004. date_running < container.date_end_)
  1005. {
  1006. int t = container.GetDateIndex(date_running);
  1007. if (data_(t_merge).GetSize() == 0)
  1008. {
  1009. forecast_(t_merge) = container.forecast_(t);
  1010. location_index_(t_merge) = container.location_index_(t);
  1011. data_(t_merge) = container.data_(t);
  1012. }
  1013. else
  1014. {
  1015. int l(0), l_merge(0), count(0);
  1016. if (container.data_(t).GetSize() == Nl_ && data_(t_merge).GetSize() == Nl_ && overwrite)
  1017. {
  1018. data_(t_merge) = container.data_(t);
  1019. count = Nl_;
  1020. }
  1021. else if (container.data_(t).GetSize() == Nl_)
  1022. {
  1023. while (l < Nl_ && l_merge < location_index_(t_merge).GetSize())
  1024. if (l < location_index_(t_merge)(l_merge))
  1025. {
  1026. location_index_(t_merge).PushBack(l);
  1027. data_(t_merge).PushBack(container.data_(t)(l));
  1028. l++;
  1029. count++;
  1030. }
  1031. else if (l == location_index_(t_merge)(l_merge))
  1032. {
  1033. if (overwrite)
  1034. {
  1035. data_(t_merge)(l_merge) = container.data_(t)(l);
  1036. count++;
  1037. }
  1038. l++;
  1039. l_merge++;
  1040. }
  1041. }
  1042. else if (data_(t_merge).GetSize() == Nl_ && overwrite)
  1043. {
  1044. for (l = 0; l < container.data_(t).GetSize(); l++)
  1045. data_(t)(container.location_index_(t)(l)) = container.data_(t)(l);
  1046. count = container.data_(t).GetSize();
  1047. }
  1048. else
  1049. {
  1050. while (l < container.location_index_(t).GetSize() &&
  1051. l_merge < location_index_(t_merge).GetSize())
  1052. if (container.location_index_(t)(l) > location_index_(t_merge)(l_merge))
  1053. l_merge++;
  1054. else if (container.location_index_(t)(l) < location_index_(t_merge)(l_merge))
  1055. {
  1056. location_index_(t_merge).PushBack(container.location_index_(t)(l));
  1057. data_(t_merge).PushBack(container.data_(t)(l));
  1058. l++;
  1059. count++;
  1060. }
  1061. else
  1062. {
  1063. if (overwrite)
  1064. {
  1065. data_(t_merge)(l_merge) = container.data_(t)(l);
  1066. count++;
  1067. }
  1068. l++;
  1069. l_merge++;
  1070. }
  1071. }
  1072. if (count > 0)
  1073. forecast_(t_merge).PushBack(container.forecast_(t)(0));
  1074. }
  1075. if (data_(t_merge).GetSize() > 0)
  1076. for (int l = 1; l < location_index_(t_merge).GetSize(); l++)
  1077. if (location_index_(t_merge)(l - 1) > location_index_(t_merge)(l))
  1078. {
  1079. Sort(location_index_(t_merge), data_(t_merge));
  1080. break;
  1081. }
  1082. }
  1083. t_merge++;
  1084. date_running.AddSeconds(delta_t_);
  1085. }
  1086. string add_comment = "merged with container \"" + container.name_ + "/" + container.type_ + "\"";
  1087. if (overwrite)
  1088. add_comment += ", with option overwrite";
  1089. AddComment(add_comment);
  1090. }
  1091. // Filter data.
  1092. template<class T> template<class F>
  1093. void ClassContainerBase<T>::FilterTime(const int h_frequency, const int h_offset,
  1094. string prefix_type,
  1095. const int h_begin, int h_end, const T ratio)
  1096. {
  1097. if (h_frequency == 1)
  1098. return;
  1099. if (abs(h_offset) >= h_frequency)
  1100. throw GPEC::Error("The absolute offset filter cannot equal or exceed the filter frequency.");
  1101. // Only relevant if data frequency is less than daily.
  1102. T delta_t_new = h_frequency * delta_t_;
  1103. if (delta_t_new > T(86400))
  1104. throw GPEC::Error("In GPEC, the time step cannot exceed one day.");
  1105. if (h_end == 0)
  1106. h_end = h_frequency;
  1107. int count_min = int(ratio * h_frequency);
  1108. int t_begin(0), t_end(Nt_);
  1109. int Nt_new = int((Nt_ - h_offset) / h_frequency + 1.e-5);
  1110. if ((Nt_ - h_offset) % h_frequency > count_min)
  1111. Nt_new++;
  1112. else
  1113. t_end -= (Nt_ - h_offset) % h_frequency;
  1114. date_begin_.AddSeconds((h_frequency / 2 + h_offset) * delta_t_);
  1115. if (h_offset > 0)
  1116. t_begin = h_offset;
  1117. else if (h_offset < 0)
  1118. if ((h_frequency + h_offset) < count_min)
  1119. {
  1120. Nt_new--;
  1121. t_begin = h_frequency + h_offset;
  1122. date_begin_.AddSeconds(h_frequency * delta_t_ );
  1123. }
  1124. Vector2I forecast_new(Nt_new);
  1125. Vector2I location_index_new(Nt_new);
  1126. Vector2T data_new(Nt_new);
  1127. for (int t = 0; t < Nt_new; t++)
  1128. {
  1129. forecast_new(t).Reallocate(1);
  1130. location_index_new(t).Reallocate(Nl_);
  1131. data_new(t).Reallocate(Nl_);
  1132. }
  1133. Vector1I index(Nt_new);
  1134. index.Zero();
  1135. F filter;
  1136. for (int location = 0; location < Nl_; location++)
  1137. {
  1138. Vector1I forecast_frequency(Nt_new);
  1139. forecast_frequency.Zero();
  1140. Vector1T data_frequency(Nt_new);
  1141. data_frequency.Fill(filter.Begin());
  1142. Vector1I count(Nt_new);
  1143. count.Zero();
  1144. int h(0), h_count(0);
  1145. for (int t = t_begin; t < t_end; t++)
  1146. {
  1147. int l = get_location_index(t, location);
  1148. if (l < data_(t).GetSize())
  1149. if (h_count >= h_begin)
  1150. if (h_count < h_end)
  1151. {
  1152. forecast_frequency(h) += forecast_(t)(0);
  1153. filter.Do(data_(t)(l), data_frequency(h));
  1154. count(h)++;
  1155. }
  1156. h_count++;
  1157. if (h_count == h_frequency)
  1158. {
  1159. h++;
  1160. h_count = 0;
  1161. }
  1162. }
  1163. for (int h = 0; h < Nt_new; h++)
  1164. if (count(h) > count_min)
  1165. {
  1166. forecast_new(h)(0) = int(rint(T(forecast_frequency(h)) / T(count(h))));
  1167. location_index_new(h)(index(h)) = location;
  1168. data_new(h)(index(h)) = filter.End(count(h), data_frequency(h));
  1169. index(h)++;
  1170. }
  1171. }
  1172. for (int t = 0; t < Nt_new; t++)
  1173. {
  1174. if (index(t) == 0)
  1175. forecast_new(t).Clear();
  1176. if (index(t) == Nl_)
  1177. location_index_new(t).Clear();
  1178. else
  1179. location_index_new(t).Resize(index(t));
  1180. data_new(t).Resize(index(t));
  1181. }
  1182. // Update attributes.
  1183. date_end_ = date_begin_;
  1184. date_end_.AddSeconds(Nt_new * delta_t_new);
  1185. Nt_ = Nt_new;
  1186. delta_t_ = delta_t_new;
  1187. set_Nd();
  1188. Nt_day_ = int(T(86400) / delta_t_);
  1189. forecast_ = forecast_new;
  1190. location_index_ = location_index_new;
  1191. data_ = data_new;
  1192. AddComment("filtered " + filter.Name() + " with frequency " + to_str(h_frequency)
  1193. + " and offset " + to_str(h_offset) + ", between " + to_str(h_begin) + " and " + to_str(h_end));
  1194. // Prefix type with something to say we filtered time.
  1195. if (prefix_type.empty())
  1196. {
  1197. prefix_type = filter.Name();
  1198. if (h_frequency < 24)
  1199. prefix_type += to_str(h_frequency);
  1200. }
  1201. if (prefix_type != "-")
  1202. type_ = prefix_type + type_;
  1203. }
  1204. // Filter time steps with two few data.
  1205. template<class T>
  1206. void ClassContainerBase<T>::FilterTimeStep(const int location_min)
  1207. {
  1208. #ifdef GPEC_WITH_LOGGER
  1209. *(this->log_ptr_) << Info() << "Filter time steps with"
  1210. << " number of locations < " << location_min << endl;
  1211. #endif
  1212. int count_filtered(0);
  1213. for (int t = 0; t < Nt_; t++)
  1214. if (data_(t).GetSize() < location_min)
  1215. {
  1216. count_filtered++;
  1217. #ifdef GPEC_WITH_LOGGER
  1218. *(this->log_ptr_) << Debug(2) << "Filter time step "
  1219. << t << " with number of locations = "
  1220. << data_(t).GetSize() << endl;
  1221. #endif
  1222. location_index_(t).Clear();
  1223. data_(t).Clear();
  1224. forecast_(t).Clear();
  1225. }
  1226. #ifdef GPEC_WITH_LOGGER
  1227. *(this->log_ptr_) << Debug(1) << "Filtered "
  1228. << count_filtered << " time steps." << endl;
  1229. #endif
  1230. AddComment("filtered " + to_str(count_filtered) + " time steps");
  1231. }
  1232. // Filter value.
  1233. template<class T>
  1234. void ClassContainerBase<T>::FilterValue(T value_min, T value_max,
  1235. const bool keep_threshold)
  1236. {
  1237. value_min = value_min == T(0) ? value_min_ : value_min;
  1238. value_max = value_max == T(1e9) ? value_max_ : value_max;
  1239. if (value_min < value_min_ || value_max > value_max_)
  1240. return;
  1241. #ifdef GPEC_WITH_LOGGER
  1242. *(this->log_ptr_) << Debug() << "Filter values below "
  1243. << value_min << " and above " << value_max
  1244. << ", filtered values are "
  1245. << (keep_threshold ? "REPLACED by min or max" : "REMOVED")
  1246. << endl;
  1247. #endif
  1248. int count_filtered(0);
  1249. for (int t = 0; t < Nt_; t++)
  1250. {
  1251. int Nl = data_(t).GetSize();
  1252. int i(0);
  1253. if (Nl > 0)
  1254. {
  1255. if (location_index_(t).GetSize() == 0)
  1256. {
  1257. location_index_(t).Reallocate(Nl);
  1258. location_index_(t).Fill();
  1259. }
  1260. for (int l = 0; l < Nl; l++)
  1261. if (data_(t)(l) < value_min)
  1262. {
  1263. count_filtered++;
  1264. #ifdef GPEC_WITH_LOGGER
  1265. *(this->log_ptr_) << Debug(2) << "Filter value "
  1266. << setprecision(2) << fixed << data_(t)(l) << " at location "
  1267. << l << " and time " << t << endl;
  1268. #endif
  1269. if (keep_threshold)
  1270. {
  1271. location_index_(t)(i) = location_index_(t)(l);
  1272. data_(t)(i++) = value_min;
  1273. }
  1274. }
  1275. else if (data_(t)(l) > value_max)
  1276. {
  1277. count_filtered++;
  1278. #ifdef GPEC_WITH_LOGGER
  1279. *(this->log_ptr_) << Debug(2) << "Filter value "
  1280. << setprecision(2) << fixed << data_(t)(l) << " at location "
  1281. << l << " and time " << t << endl;
  1282. #endif
  1283. if (keep_threshold)
  1284. {
  1285. location_index_(t)(i) = location_index_(t)(l);
  1286. data_(t)(i++) = value_max;
  1287. }
  1288. }
  1289. else
  1290. {
  1291. location_index_(t)(i) = location_index_(t)(l);
  1292. data_(t)(i++) = data_(t)(l);
  1293. }
  1294. location_index_(t).Resize(i);
  1295. data_(t).Resize(i);
  1296. if (data_(t).GetSize() == 0)
  1297. forecast_(t).Clear();
  1298. if (data_(t).GetSize() == Nl_)
  1299. location_index_(t).Clear();
  1300. }
  1301. }
  1302. #ifdef GPEC_WITH_LOGGER
  1303. *(this->log_ptr_) << Debug(1) << "Filtered "
  1304. << count_filtered << " values." << endl;
  1305. #endif
  1306. AddComment("filtered " + to_str(count_filtered) + " values below "
  1307. + to_str(value_min) + " and above " + to_str(value_max));
  1308. }
  1309. // Filter values below or above given multiple of standard deviation.
  1310. template<class T>
  1311. void ClassContainerBase<T>::FilterStandardDeviation(const T multiple_std,
  1312. const int location_min,
  1313. int t_begin, int t_end,
  1314. const bool keep_threshold)
  1315. {
  1316. if (multiple_std <= T(0))
  1317. throw GPEC::Error("Standard deviation multiple should be strictly positive");
  1318. check_index(0, Nt_, t_begin);
  1319. t_end = t_end == 0 ? Nt_ : t_end;
  1320. #ifdef GPEC_WITH_LOGGER
  1321. *(this->log_ptr_) << Info() << "Filter values with "
  1322. << multiple_std << " x standard deviation between timesteps ["
  1323. << t_begin << ", " << t_end << "[" << endl;
  1324. #endif
  1325. int count_filtered(0);
  1326. // At each time step, compute the mean and standard deviation value
  1327. // and remove values which are superior or inferior to mean +- std * multiple_std.
  1328. for (int t = t_begin; t < t_end; t++)
  1329. if (data_(t).GetSize() > location_min)
  1330. {
  1331. int Nl = data_(t).GetSize();
  1332. // Compute mean and std.
  1333. T mean = Norm1(data_(t)) / T(Nl);
  1334. T std(T(0));
  1335. for (int l = 0; l < Nl; l++)
  1336. {
  1337. T tmp = data_(t)(l) - mean;
  1338. std += tmp * tmp;
  1339. }
  1340. std = sqrt(std / T(Nl));
  1341. T min = mean - std * multiple_std;
  1342. min = min < T(0) ? T(0) : min;
  1343. T max = mean + std * multiple_std;
  1344. #ifdef GPEC_WITH_LOGGER
  1345. *(this->log_ptr_) << Debug(2) << "At time t = "
  1346. << t << ", filter values below "
  1347. << setprecision(2) << fixed << min
  1348. << " and above " << setprecision(2)
  1349. << fixed << max << endl;
  1350. #endif
  1351. // Now filter.
  1352. int i(0);
  1353. if (location_index_(t).GetSize() == 0)
  1354. {
  1355. location_index_(t).Reallocate(Nl);
  1356. location_index_(t).Fill();
  1357. }
  1358. for (int l = 0; l < Nl; l++)
  1359. if (data_(t)(l) < min)
  1360. {
  1361. count_filtered++;
  1362. if (keep_threshold)
  1363. {
  1364. location_index_(t)(i) = location_index_(t)(l);
  1365. data_(t)(i++) = min;
  1366. }
  1367. #ifdef GPEC_WITH_LOGGER
  1368. *(this->log_ptr_) << Debug(3) << "Filter value "
  1369. << setprecision(2) << fixed << data_(t)(l) << " at location "
  1370. << l << " and time " << t << endl;
  1371. #endif
  1372. }
  1373. else if (data_(t)(l) > max)
  1374. {
  1375. count_filtered++;
  1376. if (keep_threshold)
  1377. {
  1378. location_index_(t)(i) = location_index_(t)(l);
  1379. data_(t)(i++) = max;
  1380. }
  1381. #ifdef GPEC_WITH_LOGGER
  1382. *(this->log_ptr_) << Debug(3) << "Filter value "
  1383. << setprecision(2) << fixed << data_(t)(l) << " at location "
  1384. << l << " and time " << t << endl;
  1385. #endif
  1386. }
  1387. else
  1388. {
  1389. location_index_(t)(i) = location_index_(t)(l);
  1390. data_(t)(i++) = data_(t)(l);
  1391. }
  1392. location_index_(t).Resize(i);
  1393. data_(t).Resize(i);
  1394. if (data_(t).GetSize() == 0)
  1395. forecast_(t).Clear();
  1396. if (data_(t).GetSize() == Nl_)
  1397. location_index_(t).Clear();
  1398. }
  1399. #ifdef GPEC_WITH_LOGGER
  1400. *(this->log_ptr_) << Debug(1) << "Filtered "
  1401. << count_filtered << " values." << endl;
  1402. #endif
  1403. AddComment("filtered " + to_str(count_filtered) + " values with"
  1404. + " standard deviation times " + to_str(multiple_std));
  1405. }
  1406. // Filter values below or above given percentile.
  1407. template<class T>
  1408. void ClassContainerBase<T>::FilterPercentile(const T &percentile, int t_begin, int t_end,
  1409. const bool keep_threshold)
  1410. {
  1411. if (percentile <= T(0) || percentile >= T(1))
  1412. throw GPEC::Error("Percentile should be between ]0, 1[, got " + to_str(percentile));
  1413. check_index(0, Nt_, t_begin);
  1414. t_end = t_end == 0 ? Nt_ : t_end;
  1415. #ifdef GPEC_WITH_LOGGER
  1416. *(this->log_ptr_) << Info() << "Filter values with percentile "
  1417. << percentile << " between timesteps ["
  1418. << t_begin << ", " << t_end << "[" << endl;
  1419. #endif
  1420. int count_filtered(0);
  1421. // At each…

Large files files are truncated, but you can click here to view the full file