NumCpp  2.11.0
A Templatized Header Only C++ Implementation of the Python NumPy Library
DataCube.hpp
Go to the documentation of this file.
1 #pragma once
29 
30 #include <filesystem>
31 #include <limits>
32 #include <string>
33 #include <vector>
34 
36 #include "NumCpp/Core/Shape.hpp"
37 #include "NumCpp/Core/Slice.hpp"
38 #include "NumCpp/Core/Types.hpp"
39 #include "NumCpp/NdArray.hpp"
40 
41 namespace nc
42 {
43  //================================================================================
45  template<typename dtype>
46  class DataCube
47  {
48  public:
49  //================================Typedefs==================================
50  using iterator = typename std::deque<NdArray<dtype>>::iterator;
51  using const_iterator = typename std::deque<NdArray<dtype>>::const_iterator;
52 
53  //============================================================================
56  DataCube() = default;
57 
58  //============================================================================
63  explicit DataCube(uint32 inSize)
64  {
65  cube_.reserve(inSize);
66  }
67 
68  //============================================================================
76  {
77  return cube_.at(inIndex);
78  }
79 
80  //============================================================================
87  [[nodiscard]] const NdArray<dtype>& at(uint32 inIndex) const
88  {
89  return cube_.at(inIndex);
90  }
91 
92  //============================================================================
97  NdArray<dtype>& back() noexcept
98  {
99  return cube_.back();
100  }
101 
102  //============================================================================
107  [[nodiscard]] iterator begin() noexcept
108  {
109  return cube_.begin();
110  }
111 
112  //============================================================================
117  [[nodiscard]] const_iterator begin() const noexcept
118  {
119  return cube_.cbegin();
120  }
121 
122  //============================================================================
127  [[nodiscard]] const_iterator cbegin() const noexcept
128  {
129  return cube_.cbegin();
130  }
131 
132  //============================================================================
137  void dump(const std::string& inFilename) const
138  {
139  std::filesystem::path f(inFilename);
140  if (!f.has_extension())
141  {
142  f.replace_extension("bin");
143  }
144 
145  std::ofstream ofile(f.c_str(), std::ios::binary);
146  if (!ofile.good())
147  {
148  THROW_RUNTIME_ERROR("Could not open the input file:\n\t" + inFilename);
149  }
150 
151  for (auto& ndarray : cube_)
152  {
153  ofile.write(reinterpret_cast<const char*>(ndarray.data()), ndarray.size() * sizeof(dtype));
154  }
155 
156  ofile.close();
157  }
158 
159  //============================================================================
164  bool isempty() noexcept
165  {
166  return cube_.empty();
167  }
168 
169  //============================================================================
174  [[nodiscard]] iterator end() noexcept
175  {
176  return cube_.end();
177  }
178 
179  //============================================================================
184  [[nodiscard]] const_iterator end() const noexcept
185  {
186  return cube_.cend();
187  }
188 
189  //============================================================================
194  [[nodiscard]] const_iterator cend() const noexcept
195  {
196  return cube_.cend();
197  }
198 
199  //============================================================================
204  NdArray<dtype>& front() noexcept
205  {
206  return cube_.front();
207  }
208 
209  //============================================================================
214  [[nodiscard]] const Shape& shape() const noexcept
215  {
216  return elementShape_;
217  }
218 
219  //============================================================================
224  [[nodiscard]] uint32 sizeZ() const noexcept
225  {
226  return static_cast<uint32>(cube_.size());
227  }
228 
229  //============================================================================
232  void pop_back() noexcept
233  {
234  cube_.pop_back();
235  }
236 
237  //============================================================================
242  void push_back(const NdArray<dtype>& inArray)
243  {
244  const Shape inputShape = inArray.shape();
245 
246  if (elementShape_.rows == 0 && elementShape_.cols == 0)
247  {
248  // initialize to the first input array size
249  elementShape_.rows = inputShape.rows;
250  elementShape_.cols = inputShape.cols;
251  }
252 
253  if (inputShape != elementShape_)
254  {
255  THROW_INVALID_ARGUMENT_ERROR("element arrays must all be the same shape");
256  }
257 
258  cube_.push_back(inArray);
259  }
260 
261  //============================================================================
267  [[nodiscard]] NdArray<dtype> sliceZAll(int32 inIndex) const
268  {
269  if (inIndex < 0)
270  {
271  inIndex += elementShape_.size();
272  }
273 
274  NdArray<dtype> returnArray(1, sizeZ());
275 
276  for (uint32 i = 0; i < sizeZ(); ++i)
277  {
278  returnArray[i] = cube_[i][inIndex];
279  }
280 
281  return returnArray;
282  }
283 
284  //============================================================================
291  [[nodiscard]] NdArray<dtype> sliceZ(int32 inIndex, Slice inSliceZ) const
292  {
293  if (inIndex < 0)
294  {
295  inIndex += elementShape_.size();
296  }
297 
298  NdArray<dtype> returnArray(1, inSliceZ.numElements(sizeZ()));
299 
300  uint32 idx = 0;
301  for (int32 i = inSliceZ.start; i < inSliceZ.stop; i += inSliceZ.step)
302  {
303  returnArray[idx++] = cube_[i][inIndex];
304  }
305 
306  return returnArray;
307  }
308 
309  //============================================================================
316  [[nodiscard]] NdArray<dtype> sliceZAll(int32 inRow, int32 inCol) const
317  {
318  if (inRow < 0)
319  {
320  inRow += elementShape_.rows;
321  }
322 
323  if (inCol < 0)
324  {
325  inCol += elementShape_.cols;
326  }
327 
328  NdArray<dtype> returnArray(1, sizeZ());
329 
330  for (uint32 i = 0; i < sizeZ(); ++i)
331  {
332  returnArray[i] = cube_[i](inRow, inCol);
333  }
334 
335  return returnArray;
336  }
337 
338  //============================================================================
346  [[nodiscard]] NdArray<dtype> sliceZ(int32 inRow, int32 inCol, Slice inSliceZ) const
347  {
348  if (inRow < 0)
349  {
350  inRow += elementShape_.rows;
351  }
352 
353  if (inCol < 0)
354  {
355  inCol += elementShape_.cols;
356  }
357 
358  NdArray<dtype> returnArray(1, inSliceZ.numElements(sizeZ()));
359 
360  uint32 idx = 0;
361  for (int32 i = inSliceZ.start; i < inSliceZ.stop; i += inSliceZ.step)
362  {
363  returnArray[idx++] = cube_[i](inRow, inCol);
364  }
365 
366  return returnArray;
367  }
368 
369  //============================================================================
376  [[nodiscard]] NdArray<dtype> sliceZAll(Slice inRow, int32 inCol) const
377  {
378  if (inCol < 0)
379  {
380  inCol += elementShape_.cols;
381  }
382 
383  NdArray<dtype> returnArray(inRow.numElements(elementShape_.rows), sizeZ());
384  for (uint32 i = 0; i < sizeZ(); ++i)
385  {
386  returnArray.put(returnArray.rSlice(), i, cube_[i](inRow, inCol));
387  }
388 
389  return returnArray;
390  }
391 
392  //============================================================================
400  [[nodiscard]] NdArray<dtype> sliceZ(Slice inRow, int32 inCol, Slice inSliceZ) const
401  {
402  if (inCol < 0)
403  {
404  inCol += elementShape_.cols;
405  }
406 
407  NdArray<dtype> returnArray(inRow.numElements(elementShape_.rows), inSliceZ.numElements(sizeZ()));
408  uint32 idx = 0;
409  for (int32 i = inSliceZ.start; i < inSliceZ.stop; i += inSliceZ.step)
410  {
411  returnArray.put(returnArray.rSlice(), idx++, cube_[i](inRow, inCol));
412  }
413 
414  return returnArray;
415  }
416 
417  //============================================================================
424  [[nodiscard]] NdArray<dtype> sliceZAll(int32 inRow, Slice inCol) const
425  {
426  if (inRow < 0)
427  {
428  inRow += elementShape_.rows;
429  }
430 
431  NdArray<dtype> returnArray(inCol.numElements(elementShape_.cols), sizeZ());
432  for (uint32 i = 0; i < sizeZ(); ++i)
433  {
434  returnArray.put(returnArray.rSlice(), i, cube_[i](inRow, inCol));
435  }
436 
437  return returnArray;
438  }
439 
440  //============================================================================
448  [[nodiscard]] NdArray<dtype> sliceZ(int32 inRow, Slice inCol, Slice inSliceZ) const
449  {
450  if (inRow < 0)
451  {
452  inRow += elementShape_.rows;
453  }
454 
455  NdArray<dtype> returnArray(inCol.numElements(elementShape_.cols), inSliceZ.numElements(sizeZ()));
456  uint32 idx = 0;
457  for (int32 i = inSliceZ.start; i < inSliceZ.stop; i += inSliceZ.step)
458  {
459  returnArray.put(returnArray.rSlice(), idx++, cube_[i](inRow, inCol));
460  }
461 
462  return returnArray;
463  }
464 
465  //============================================================================
472  DataCube<dtype> sliceZAll(Slice inRow, Slice inCol) const
473  {
474  DataCube<dtype> returnCube(sizeZ());
475  for (uint32 i = 0; i < sizeZ(); ++i)
476  {
477  returnCube.push_back(cube_[i](inRow, inCol));
478  }
479 
480  return returnCube;
481  }
482 
483  //============================================================================
491  DataCube<dtype> sliceZ(Slice inRow, Slice inCol, Slice inSliceZ) const
492  {
493  DataCube<dtype> returnCube(inSliceZ.numElements(sizeZ()));
494  for (int32 i = inSliceZ.start; i < inSliceZ.stop; i += inSliceZ.step)
495  {
496  returnCube.push_back(cube_[i](inRow, inCol));
497  }
498 
499  return returnCube;
500  }
501 
502  //============================================================================
508  [[nodiscard]] NdArray<dtype> sliceZAllat(int32 inIndex) const
509  {
510  if (inIndex < 0)
511  {
512  inIndex += elementShape_.size();
513  }
514 
515  if (static_cast<uint32>(inIndex) >= elementShape_.size())
516  {
517  THROW_INVALID_ARGUMENT_ERROR("inIndex exceeds matrix dimensions.");
518  }
519 
520  return sliceZAll(inIndex);
521  }
522 
523  //============================================================================
530  [[nodiscard]] NdArray<dtype> sliceZat(int32 inIndex, Slice inSliceZ) const
531  {
532  if (inIndex < 0)
533  {
534  inIndex += elementShape_.size();
535  }
536 
537  if (static_cast<uint32>(inIndex) >= elementShape_.size())
538  {
539  THROW_INVALID_ARGUMENT_ERROR("inIndex exceeds matrix dimensions.");
540  }
541 
542  auto numElements = inSliceZ.numElements(sizeZ());
543  if (numElements > sizeZ())
544  {
545  THROW_INVALID_ARGUMENT_ERROR("inIndex exceeds matrix dimensions.");
546  }
547 
548  return sliceZ(inIndex, inSliceZ);
549  }
550 
551  //============================================================================
558  [[nodiscard]] NdArray<dtype> sliceZAllat(int32 inRow, int32 inCol) const
559  {
560  if (inRow < 0)
561  {
562  inRow += elementShape_.rows;
563  }
564 
565  if (inCol < 0)
566  {
567  inCol += elementShape_.cols;
568  }
569 
570  if (static_cast<uint32>(inRow) >= elementShape_.rows)
571  {
572  THROW_INVALID_ARGUMENT_ERROR("inRow exceeds matrix dimensions.");
573  }
574 
575  if (static_cast<uint32>(inCol) >= elementShape_.cols)
576  {
577  THROW_INVALID_ARGUMENT_ERROR("inCol exceeds matrix dimensions.");
578  }
579 
580  return sliceZAll(inRow, inCol);
581  }
582 
583  //============================================================================
591  [[nodiscard]] NdArray<dtype> sliceZat(int32 inRow, int32 inCol, Slice inSliceZ) const
592  {
593  if (inRow < 0)
594  {
595  inRow += elementShape_.rows;
596  }
597 
598  if (inCol < 0)
599  {
600  inCol += elementShape_.cols;
601  }
602 
603  if (static_cast<uint32>(inRow) >= elementShape_.rows)
604  {
605  THROW_INVALID_ARGUMENT_ERROR("inRow exceeds matrix dimensions.");
606  }
607  if (static_cast<uint32>(inCol) >= elementShape_.cols)
608  {
609  THROW_INVALID_ARGUMENT_ERROR("inCol exceeds matrix dimensions.");
610  }
611 
612  auto numElements = inSliceZ.numElements(sizeZ());
613  if (numElements > sizeZ())
614  {
615  THROW_INVALID_ARGUMENT_ERROR("Index exceeds matrix dimensions.");
616  }
617 
618  return sliceZ(inRow, inCol, inSliceZ);
619  }
620 
621  //============================================================================
628  [[nodiscard]] NdArray<dtype> sliceZAllat(Slice inRow, int32 inCol) const
629  {
630  auto numRows = inRow.numElements(elementShape_.rows);
631  if (numRows > elementShape_.rows)
632  {
633  THROW_INVALID_ARGUMENT_ERROR("inRow exceeds matrix dimensions.");
634  }
635 
636  if (inCol < 0)
637  {
638  inCol += elementShape_.cols;
639  }
640 
641  if (static_cast<uint32>(inCol) >= elementShape_.cols)
642  {
643  THROW_INVALID_ARGUMENT_ERROR("inCol exceeds matrix dimensions.");
644  }
645 
646  return sliceZAll(inRow, inCol);
647  }
648 
649  //============================================================================
657  [[nodiscard]] NdArray<dtype> sliceZat(Slice inRow, int32 inCol, Slice inSliceZ) const
658  {
659  auto numRows = inRow.numElements(elementShape_.rows);
660  if (numRows > elementShape_.rows)
661  {
662  THROW_INVALID_ARGUMENT_ERROR("inRow exceeds matrix dimensions.");
663  }
664 
665  if (inCol < 0)
666  {
667  inCol += elementShape_.cols;
668  }
669 
670  if (static_cast<uint32>(inCol) >= elementShape_.cols)
671  {
672  THROW_INVALID_ARGUMENT_ERROR("inCol exceeds matrix dimensions.");
673  }
674 
675  auto numElements = inSliceZ.numElements(sizeZ());
676  if (numElements > sizeZ())
677  {
678  THROW_INVALID_ARGUMENT_ERROR("Index exceeds matrix dimensions.");
679  }
680 
681  return sliceZ(inRow, inCol, inSliceZ);
682  }
683 
684  //============================================================================
691  [[nodiscard]] NdArray<dtype> sliceZAllat(int32 inRow, Slice inCol) const
692  {
693  auto numCols = inCol.numElements(elementShape_.cols);
694  if (numCols > elementShape_.cols)
695  {
696  THROW_INVALID_ARGUMENT_ERROR("inCol exceeds matrix dimensions.");
697  }
698 
699  if (inRow < 0)
700  {
701  inRow += elementShape_.rows;
702  }
703 
704  if (static_cast<uint32>(inRow) >= elementShape_.rows)
705  {
706  THROW_INVALID_ARGUMENT_ERROR("inRow exceeds matrix dimensions.");
707  }
708 
709  return sliceZAll(inRow, inCol);
710  }
711 
712  //============================================================================
720  [[nodiscard]] NdArray<dtype> sliceZat(int32 inRow, Slice inCol, Slice inSliceZ) const
721  {
722  auto numCols = inCol.numElements(elementShape_.cols);
723  if (numCols > elementShape_.cols)
724  {
725  THROW_INVALID_ARGUMENT_ERROR("inCol exceeds matrix dimensions.");
726  }
727 
728  if (inRow < 0)
729  {
730  inRow += elementShape_.rows;
731  }
732 
733  if (static_cast<uint32>(inRow) >= elementShape_.rows)
734  {
735  THROW_INVALID_ARGUMENT_ERROR("inRow exceeds matrix dimensions.");
736  }
737 
738  auto numElements = inSliceZ.numElements(sizeZ());
739  if (numElements > sizeZ())
740  {
741  THROW_INVALID_ARGUMENT_ERROR("Index exceeds matrix dimensions.");
742  }
743 
744  return sliceZ(inRow, inCol, inSliceZ);
745  }
746 
747  //============================================================================
755  {
756  if (inRow.numElements(elementShape_.rows) > elementShape_.rows)
757  {
758  THROW_INVALID_ARGUMENT_ERROR("inRow exceeds matrix dimensions.");
759  }
760 
761  if (inCol.numElements(elementShape_.cols) > elementShape_.cols)
762  {
763  THROW_INVALID_ARGUMENT_ERROR("inCol exceeds matrix dimensions.");
764  }
765 
766  return sliceZAll(inRow, inCol);
767  }
768 
769  //============================================================================
777  DataCube<dtype> sliceZat(Slice inRow, Slice inCol, Slice inSliceZ) const
778  {
779  if (inRow.numElements(elementShape_.rows) > elementShape_.rows)
780  {
781  THROW_INVALID_ARGUMENT_ERROR("inRow exceeds matrix dimensions.");
782  }
783 
784  if (inCol.numElements(elementShape_.cols) > elementShape_.cols)
785  {
786  THROW_INVALID_ARGUMENT_ERROR("inCol exceeds matrix dimensions.");
787  }
788 
789  auto numElements = inSliceZ.numElements(sizeZ());
790  if (numElements > sizeZ())
791  {
792  THROW_INVALID_ARGUMENT_ERROR("Index exceeds matrix dimensions.");
793  }
794 
795  return sliceZ(inRow, inCol, inSliceZ);
796  }
797 
798  //============================================================================
805  NdArray<dtype>& operator[](uint32 inIndex) noexcept
806  {
807  return cube_[inIndex];
808  }
809 
810  //============================================================================
817  const NdArray<dtype>& operator[](uint32 inIndex) const noexcept
818  {
819  return cube_[inIndex];
820  }
821 
822  private:
823  //================================Attributes==================================
824  std::vector<NdArray<dtype>> cube_{};
825  Shape elementShape_{ 0, 0 };
826  };
827 } // namespace nc
#define THROW_RUNTIME_ERROR(msg)
Definition: Error.hpp:40
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:37
Convenience container for holding a uniform array of NdArrays.
Definition: DataCube.hpp:47
void push_back(const NdArray< dtype > &inArray)
Definition: DataCube.hpp:242
NdArray< dtype > sliceZAll(int32 inRow, int32 inCol) const
Definition: DataCube.hpp:316
NdArray< dtype > sliceZAll(int32 inRow, Slice inCol) const
Definition: DataCube.hpp:424
NdArray< dtype > & operator[](uint32 inIndex) noexcept
Definition: DataCube.hpp:805
const Shape & shape() const noexcept
Definition: DataCube.hpp:214
typename std::deque< NdArray< dtype > >::const_iterator const_iterator
Definition: DataCube.hpp:51
DataCube< dtype > sliceZat(Slice inRow, Slice inCol, Slice inSliceZ) const
Definition: DataCube.hpp:777
NdArray< dtype > & front() noexcept
Definition: DataCube.hpp:204
DataCube< dtype > sliceZ(Slice inRow, Slice inCol, Slice inSliceZ) const
Definition: DataCube.hpp:491
const NdArray< dtype > & operator[](uint32 inIndex) const noexcept
Definition: DataCube.hpp:817
iterator begin() noexcept
Definition: DataCube.hpp:107
NdArray< dtype > sliceZat(int32 inIndex, Slice inSliceZ) const
Definition: DataCube.hpp:530
DataCube< dtype > sliceZAllat(Slice inRow, Slice inCol) const
Definition: DataCube.hpp:754
NdArray< dtype > sliceZat(int32 inRow, int32 inCol, Slice inSliceZ) const
Definition: DataCube.hpp:591
typename std::deque< NdArray< dtype > >::iterator iterator
Definition: DataCube.hpp:50
DataCube< dtype > sliceZAll(Slice inRow, Slice inCol) const
Definition: DataCube.hpp:472
uint32 sizeZ() const noexcept
Definition: DataCube.hpp:224
NdArray< dtype > sliceZ(int32 inRow, int32 inCol, Slice inSliceZ) const
Definition: DataCube.hpp:346
NdArray< dtype > sliceZat(Slice inRow, int32 inCol, Slice inSliceZ) const
Definition: DataCube.hpp:657
NdArray< dtype > sliceZat(int32 inRow, Slice inCol, Slice inSliceZ) const
Definition: DataCube.hpp:720
NdArray< dtype > sliceZ(int32 inIndex, Slice inSliceZ) const
Definition: DataCube.hpp:291
NdArray< dtype > sliceZAll(int32 inIndex) const
Definition: DataCube.hpp:267
DataCube(uint32 inSize)
Definition: DataCube.hpp:63
NdArray< dtype > sliceZAllat(int32 inIndex) const
Definition: DataCube.hpp:508
NdArray< dtype > sliceZ(int32 inRow, Slice inCol, Slice inSliceZ) const
Definition: DataCube.hpp:448
DataCube()=default
NdArray< dtype > & at(uint32 inIndex)
Definition: DataCube.hpp:75
void pop_back() noexcept
Definition: DataCube.hpp:232
iterator end() noexcept
Definition: DataCube.hpp:174
NdArray< dtype > sliceZ(Slice inRow, int32 inCol, Slice inSliceZ) const
Definition: DataCube.hpp:400
NdArray< dtype > sliceZAllat(int32 inRow, int32 inCol) const
Definition: DataCube.hpp:558
const NdArray< dtype > & at(uint32 inIndex) const
Definition: DataCube.hpp:87
void dump(const std::string &inFilename) const
Definition: DataCube.hpp:137
NdArray< dtype > & back() noexcept
Definition: DataCube.hpp:97
bool isempty() noexcept
Definition: DataCube.hpp:164
const_iterator cend() const noexcept
Definition: DataCube.hpp:194
const_iterator end() const noexcept
Definition: DataCube.hpp:184
NdArray< dtype > sliceZAllat(Slice inRow, int32 inCol) const
Definition: DataCube.hpp:628
const_iterator begin() const noexcept
Definition: DataCube.hpp:117
const_iterator cbegin() const noexcept
Definition: DataCube.hpp:127
NdArray< dtype > sliceZAllat(int32 inRow, Slice inCol) const
Definition: DataCube.hpp:691
NdArray< dtype > sliceZAll(Slice inRow, int32 inCol) const
Definition: DataCube.hpp:376
Holds 1D and 2D arrays, the main work horse of the NumCpp library.
Definition: NdArrayCore.hpp:138
self_type & put(index_type inIndex, const value_type &inValue)
Definition: NdArrayCore.hpp:3646
Slice rSlice(index_type inStartIdx=0, size_type inStepSize=1) const
Definition: NdArrayCore.hpp:975
const Shape & shape() const noexcept
Definition: NdArrayCore.hpp:4464
A Shape Class for NdArrays.
Definition: Core/Shape.hpp:41
uint32 rows
Definition: Core/Shape.hpp:44
uint32 cols
Definition: Core/Shape.hpp:45
uint32 size() const noexcept
Definition: Core/Shape.hpp:104
A Class for slicing into NdArrays.
Definition: Slice.hpp:45
int32 step
Definition: Slice.hpp:50
int32 start
Definition: Slice.hpp:48
uint32 numElements(uint32 inArraySize)
Definition: Slice.hpp:195
int32 stop
Definition: Slice.hpp:49
dtype f(GeneratorType &generator, dtype inDofN, dtype inDofD)
Definition: f.hpp:56
Definition: Cartesian.hpp:40
std::int32_t int32
Definition: Types.hpp:36
std::uint32_t uint32
Definition: Types.hpp:40