NumCpp  2.12.1
A Templatized Header Only C++ Implementation of the Python NumPy Library
DataCube.hpp
Go to the documentation of this file.
1
28#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
41namespace nc
42{
43 //================================================================================
45 template<typename dtype>
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 //============================================================================
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 //============================================================================
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 //============================================================================
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
typename std::deque< NdArray< dtype > >::const_iterator const_iterator
Definition: DataCube.hpp:51
NdArray< dtype > sliceZAll(int32 inIndex) const
Definition: DataCube.hpp:267
iterator begin() noexcept
Definition: DataCube.hpp:107
const NdArray< dtype > & at(uint32 inIndex) const
Definition: DataCube.hpp:87
NdArray< dtype > & at(uint32 inIndex)
Definition: DataCube.hpp:75
NdArray< dtype > & operator[](uint32 inIndex) noexcept
Definition: DataCube.hpp:805
NdArray< dtype > sliceZ(int32 inRow, int32 inCol, Slice inSliceZ) const
Definition: DataCube.hpp:346
DataCube< dtype > sliceZat(Slice inRow, Slice inCol, Slice inSliceZ) const
Definition: DataCube.hpp:777
typename std::deque< NdArray< dtype > >::iterator iterator
Definition: DataCube.hpp:50
NdArray< dtype > sliceZAllat(Slice inRow, int32 inCol) const
Definition: DataCube.hpp:628
uint32 sizeZ() const noexcept
Definition: DataCube.hpp:224
NdArray< dtype > sliceZAll(Slice inRow, int32 inCol) const
Definition: DataCube.hpp:376
DataCube< dtype > sliceZ(Slice inRow, Slice inCol, Slice inSliceZ) const
Definition: DataCube.hpp:491
NdArray< dtype > sliceZat(Slice inRow, int32 inCol, Slice inSliceZ) const
Definition: DataCube.hpp:657
DataCube(uint32 inSize)
Definition: DataCube.hpp:63
DataCube()=default
DataCube< dtype > sliceZAll(Slice inRow, Slice inCol) const
Definition: DataCube.hpp:472
void pop_back() noexcept
Definition: DataCube.hpp:232
NdArray< dtype > sliceZAllat(int32 inRow, Slice inCol) const
Definition: DataCube.hpp:691
NdArray< dtype > sliceZat(int32 inIndex, Slice inSliceZ) const
Definition: DataCube.hpp:530
const Shape & shape() const noexcept
Definition: DataCube.hpp:214
NdArray< dtype > sliceZAll(int32 inRow, int32 inCol) const
Definition: DataCube.hpp:316
iterator end() noexcept
Definition: DataCube.hpp:174
NdArray< dtype > & front() noexcept
Definition: DataCube.hpp:204
NdArray< dtype > sliceZAllat(int32 inIndex) const
Definition: DataCube.hpp:508
NdArray< dtype > & back() noexcept
Definition: DataCube.hpp:97
const NdArray< dtype > & operator[](uint32 inIndex) const noexcept
Definition: DataCube.hpp:817
void dump(const std::string &inFilename) const
Definition: DataCube.hpp:137
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(int32 inRow, int32 inCol) const
Definition: DataCube.hpp:558
const_iterator begin() const noexcept
Definition: DataCube.hpp:117
const_iterator cbegin() const noexcept
Definition: DataCube.hpp:127
NdArray< dtype > sliceZAll(int32 inRow, Slice inCol) const
Definition: DataCube.hpp:424
NdArray< dtype > sliceZ(Slice inRow, int32 inCol, Slice inSliceZ) const
Definition: DataCube.hpp:400
NdArray< dtype > sliceZ(int32 inIndex, Slice inSliceZ) const
Definition: DataCube.hpp:291
NdArray< dtype > sliceZ(int32 inRow, Slice inCol, Slice inSliceZ) const
Definition: DataCube.hpp:448
NdArray< dtype > sliceZat(int32 inRow, Slice inCol, Slice inSliceZ) const
Definition: DataCube.hpp:720
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
Holds 1D and 2D arrays, the main work horse of the NumCpp library.
Definition: NdArrayCore.hpp:139
const Shape & shape() const noexcept
Definition: NdArrayCore.hpp:4511
Slice rSlice(index_type inStartIdx=0, size_type inStepSize=1) const
Definition: NdArrayCore.hpp:1022
self_type & put(index_type inIndex, const value_type &inValue)
Definition: NdArrayCore.hpp:3693
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