yoda is hosted by Hepforge, IPPP Durham
YODA - Yet more Objects for Data Analysis 2.1.0
Scatter.h
Go to the documentation of this file.
1// -*- C++ -*-
2//
3// This file is part of YODA -- Yet more Objects for Data Analysis
4// Copyright (C) 2008-2025 The YODA collaboration (see AUTHORS for details)
5//
6#ifndef YODA_Scatter_h
7#define YODA_Scatter_h
8
10#include "YODA/Point.h"
11#include "YODA/Transformation.h"
12#include "YODA/Utils/Traits.h"
13#include "YODA/Utils/ndarray.h"
14#include <vector>
15#include <set>
16#include <string>
17#include <utility>
18#include <memory>
19
20namespace YODA {
21
23 namespace {
24
25 // Checks that the first half of tuple arguments
26 // can be cast to double and the second half
27 // to pair<double,double>
28 template<class T, class U, typename = void>
29 struct HalfValsHalfPairs : std::false_type { };
30 //
31 template<class T, size_t... Is>
32 struct HalfValsHalfPairs<T, std::index_sequence<Is...>,
33 std::enable_if_t<( std::is_same<double,
34 std::common_type_t<std::tuple_element_t<Is,T>...,
35 double>>::value && // first half double
36 std::is_same<std::pair<double,double>,
37 std::common_type_t<std::tuple_element_t<sizeof...(Is)+Is,T>...,
38 std::pair<double,double>>>::value // second half pair<double,double>
39 )>> : std::true_type { };
40 }
41
43 class Scatter {
44 public:
45
47
49 virtual ~Scatter() {}
50
52
53
55 virtual size_t dim() const noexcept = 0;
56
57
59
60
62 virtual void reset() = 0;
63
65 //virtual void scale(size_t i, double scale) = 0;
66
68
69
71
72
74 virtual size_t numPoints() const = 0;
75
76
79
81 virtual void rmPoint(size_t index) = 0;
82
84 virtual void rmPoints(std::vector<size_t> indices) {
85 // remove points in decreasing order, so the numbering isn't invalidated mid-loop:
86 std::sort(indices.begin(), indices.end(), std::greater<size_t>()); //< reverse-sort
87 for (size_t i : indices) rmPoint(i);
88 }
89
91
92
99
100 // /// Insert a new point, defined as the x value and no errors
101 // void addPoint(double x) {
102 // Point1D thisPoint=Point1D(x);
103 // thisPoint.setParentAO(this);
104 // _points.insert(thisPoint);
105 // }
106
107 // /// Insert a new point, defined as the x value and symmetric errors
108 // void addPoint(double x, double ex) {
109 // Point1D thisPoint=Point1D(x, ex);
110 // thisPoint.setParentAO(this);
111 // _points.insert(thisPoint);
112 // }
113
114 // /// Insert a new point, defined as the x value and an asymmetric error pair
115 // void addPoint(double x, const std::pair<double,double>& ex) {
116 // Point1D thisPoint=Point1D(x, ex);
117 // thisPoint.setParentAO(this);
118 // _points.insert(thisPoint);
119 // }
120
121 // /// Insert a new point, defined as the x value and explicit asymmetric errors
122 // void addPoint(double x, double exminus, double explus) {
123 // Point1D thisPoint=Point1D(x, exminus, explus);
124 // thisPoint.setParentAO(this);
125 // _points.insert(thisPoint);
126 // }
127
128 // /// Insert a collection of new points
129 // void addPoints(const Points& pts) {
130 // for (const Point1D& pt : pts) addPoint(pt);
131 // }
132
134
135
136 // /// Equality operator
137 // bool operator == (const Scatter1D& other) {
138 // return _points == other._points;
139 // }
140
141 // /// Non-equality operator
142 // bool operator != (const Scatter1D& other) {
143 // return ! operator == (other);
144 // }
145
146 };
147
148
149
150
152 template <size_t N>
153 class ScatterND : public AnalysisObject, public Scatter {
154 protected:
155
156 // Convenient aliases
157 using Pair = std::pair<double,double>;
158 using ValVec = std::vector<double>;
159 using PairVec = std::vector<Pair>;
160 using ValList = std::initializer_list<double>;
161 using PairList = std::initializer_list<Pair>;
162
163 // extract the content type of an array Arr
164 template<typename Arr>
165 using containedType = std::decay_t<decltype(*std::declval<Arr>().begin())>;
166
167 // check if content type of an array Arr is Pair
168 template<typename Arr>
169 using containsPair = typename std::is_same<containedType<Arr>, Pair>;
170
171 // succeeds if the first argument is vector<vector<double> (or similar iterable)
172 // and the second argument is vector<vector<Pair>> (or similar iterable)
173 template<typename T, typename U>
174 using enableIfNestedArrayWithPair = std::enable_if_t<(isIterable<T,U,containedType<T>,containedType<U>> &&
176
177 // check if every element in parameter pack can be cast to double
178 template<typename... Args>
179 using isAllVals = std::is_same<double, std::common_type_t<Args..., double>>;
180
181 // check if every element in first half of parameter pack can be
182 // cast to double and every element in the second half to Pair
183 // (based on helper struct defined at the top of the file)
184 template<typename... Args>
185 using isHalfValsHalfPairs = HalfValsHalfPairs<std::tuple<Args...>, std::make_index_sequence<N>>;
186
187 public:
188
189 // Typedefs
190 using NdVal = Utils::ndarray<double, N>;
191 using NdValPair = Utils::ndarray<std::pair<double,double>, N>;
193 using Points = std::vector<Point>;
194 using Ptr = std::shared_ptr<ScatterND>;
195 using AnalysisObject::operator =;
196
197
200
202 ScatterND(const std::string& path = "", const std::string& title="")
203 : AnalysisObject("Scatter"+std::to_string(N)+"D", path, title) { }
204
207 const std::string& path="", const std::string& title="")
208 : AnalysisObject("Scatter"+std::to_string(N)+"D", path, title),
209 _points(points) { }
210
213 const std::string& path="", const std::string& title="")
214 : AnalysisObject("Scatter"+std::to_string(N)+"D", path, title),
215 _points(std::move(points)) { }
216
218 template <typename ValRange = std::initializer_list<ValList>,
219 typename = std::enable_if_t<isIterable<ValRange, containedType<ValRange>>>> // enable if is nested array
220 ScatterND(ValRange&& positions, const std::string& path="", const std::string& title="")
221 : AnalysisObject("Scatter"+std::to_string(N)+"D", path, title) {
222 for (size_t i = 0; i < positions.size(); ++i) {
223 addPoint(PointND<N>(std::forward<containedType<ValRange>>(positions[i])));
224 }
225 }
226
228 template <typename ValRange = std::initializer_list<ValList>,
229 typename = std::enable_if_t<isIterable<ValRange, containedType<ValRange>>>> // enable if is nested array
230 ScatterND(ValRange&& positions, ValRange&& errors, const std::string& path="", const std::string& title="")
231 : AnalysisObject("Scatter"+std::to_string(N)+"D", path, title) {
232 if (positions.size() != errors.size()) throw RangeError("Number of errors doesn't match number of positions");
233 for (size_t i = 0; i < positions.size(); ++i) {
234 addPoint(PointND<N>(std::forward<containedType<ValRange>>(positions[i]),
235 std::forward<containedType<ValRange>>(errors[i])));
236 }
237 }
238
240 template <typename ValRange = std::initializer_list<ValList>,
241 typename PairRange = std::initializer_list<PairList>,
242 typename = enableIfNestedArrayWithPair<ValRange,PairRange>>
243 ScatterND(ValRange&& positions, PairRange&& errors, const std::string& path="", const std::string& title="")
244 : AnalysisObject("Scatter"+std::to_string(N)+"D", path, title) {
245 if (positions.size() != errors.size()) throw RangeError("Number of error pairs doesn't match number of positions");
246 for (size_t i = 0; i < positions.size(); ++i) {
247 addPoint(PointND<N>(std::forward<containedType<ValRange>>(positions[i]),
248 std::forward<containedType<PairRange>>(errors[i])));
249 }
250 }
251
253 ScatterND(const ScatterND<N>& s, const std::string& path = "")
254 : AnalysisObject("Scatter"+std::to_string(N)+"D", (path != "")? path : s.path(), s, s.title()),
255 _points(s._points) { }
256
258 ScatterND(ScatterND<N>&& s, const std::string& path = "")
259 : AnalysisObject("Scatter"+std::to_string(N)+"D", (path != "")? path : s.path(), s, s.title()),
260 _points(std::move(s._points)) {
261 }
262
263
266 if (this != &s) {
268 _points = s._points;
269 }
270 return *this;
271 }
272
275 if (this != &s) {
277 _points = std::move(s._points);
278 }
279 return *this;
280 }
281
284 return ScatterND<N>(*this);
285 }
286
289 return new ScatterND<N>(*this);
290 }
291
293
295 size_t dim() const noexcept { return N; }
296
299
301 void reset() {
302 _points.clear();
303 }
304
306 void scale(const NdVal& scales) {
307 for (PointND<N>& p : _points) p.scale(scales);
308 }
309
310 void scale(const std::vector<double>& scales) {
311 if (scales.size() != N) throw RangeError("Expected " + std::to_string(N) + " scale factors");
312 for (PointND<N>& p : _points) p.scale(scales);
313 }
314
316 void scale(const size_t i, double factor) {
317 if (i >= N) throw RangeError("Invalid axis int, must be in range 0..dim-1");
318 for (PointND<N>& p : _points) p.scale(i, factor);
319 }
320
322 void scaleVal(const size_t i, double factor) {
323 if (i >= N) throw RangeError("Invalid axis int, must be in range 0..dim-1");
324 for (PointND<N>& p : _points) p.scaleVal(i, factor);
325 }
326
328 void scaleErr(const size_t i, double factor) {
329 if (i >= N) throw RangeError("Invalid axis int, must be in range 0..dim-1");
330 for (PointND<N>& p : _points) p.scaleErr(i, factor);
331 }
332
334
335
337
338
341
343 size_t numPoints() const {
344 return _points.size();
345 }
346
347
350 return _points;
351 }
352
353
355 const Points& points() const {
356 return _points;
357 }
358
359
361 PointND<N>& point(size_t index) {
362 return _points.at(index);
363 }
364
365
367 const PointND<N>& point(size_t index) const {
368 return _points.at(index);
369 }
370
372
373
376
379 _points.push_back(pt);
380 return *this;
381 }
382
385 _points.push_back(std::move(pt));
386 return *this;
387 }
388
390 template <typename ValRange = ValList,
391 typename = std::enable_if_t<isIterable<ValRange>>>
392 ScatterND<N>& addPoint(ValRange&& pos) {
393 _points.push_back(PointND<N>(std::forward<ValRange>(pos)));
394 return *this;
395 }
396
398 template <typename ValRange = ValList,
399 typename = std::enable_if_t<isIterable<ValRange>>>
400 ScatterND<N>& addPoint(ValRange&& pos, ValRange&& err) {
401 _points.push_back(PointND<N>(std::forward<ValRange>(pos), std::forward<ValRange>(err)));
402 return *this;
403 }
404
406 template <typename ValRange = ValList,
407 typename = std::enable_if_t<isIterable<ValRange>>>
408 ScatterND<N>& addPoint(ValRange&& pos, ValRange&& errdn, ValRange&& errup) {
409 _points.push_back(PointND<N>(std::forward<ValRange>(pos),
410 std::forward<ValRange>(errdn),
411 std::forward<ValRange>(errup)));
412 return *this;
413 }
414
416 template <typename ValRange = ValList, typename PairRange = PairList>
417 auto addPoint(ValRange&& pos, PairRange&& err)
418 -> std::enable_if_t<(isIterable<ValRange,PairRange> && containsPair<PairRange>::value), ScatterND<N>>& {
419 _points.push_back(PointND<N>(pos, err));
420 return *this;
421 }
422
444 template<typename... Args>
445 auto addPoint(Args&&... args)
446 -> std::enable_if_t<(sizeof...(Args) == 2*N || sizeof...(Args) == 3*N), ScatterND<N>>& {
447 return addPoint_aux(std::make_tuple(std::forward<Args>(args)...), std::make_index_sequence<N>{});
448 }
449
450 protected:
451
467 template<typename... Args, size_t... Is>
468 auto addPoint_aux(std::tuple<Args...>&& t, std::index_sequence<Is...>)
469 -> std::enable_if_t<(isAllVals<Args...>::value), ScatterND<N>>& {
470 if constexpr(sizeof...(Args) == 2*N) { // Case 1: symmetric errors
471 _points.push_back(
472 PointND<N>( ValVec{ static_cast<double>(std::get<Is>(t))...},
473 PairVec{{static_cast<double>(std::get<N+Is>(t)),
474 static_cast<double>(std::get<N+Is>(t))}...} ));
475 }
476 else { // Case 2: asymmetric errors
477 _points.push_back(PointND<N>( ValVec{ static_cast<double>(std::get<Is>(t))...},
478 PairVec{{static_cast<double>(std::get<N+2*Is>(t)),
479 static_cast<double>(std::get<N+2*Is+1>(t))}...} ));
480 }
481 return *this;
482 }
483
484
498 template<typename... Args, size_t... Is>
499 auto addPoint_aux(std::tuple<Args...>&& t, std::index_sequence<Is...>) // Case 3: error pairs
500 -> std::enable_if_t<(sizeof...(Args) == 2*N && isHalfValsHalfPairs<Args...>::value), ScatterND<N>>& {
501 _points.push_back(PointND<N>( ValVec{ static_cast<double>(std::get<Is>(t))...},
502 PairVec{ static_cast<Pair>(std::get<N+Is>(t))...} ));
503 return *this;
504 }
505
506
507 public:
508
511 for (const PointND<N>& pt : pts) addPoint(pt);
512 return *this;
513 }
514
515 void rmPoint(size_t index) {
516 _points.erase(_points.begin()+index);
517 }
518
520
522
523
524 size_t lengthContent(bool fixed_length = false) const noexcept {
525 if (fixed_length) return 0;
526 return numPoints() * Point::DataSize::value;
527 }
528
529 std::vector<double> serializeContent(bool fixed_length = false) const noexcept {
530
531 if (fixed_length) return { }; // cannot guarantee fixed length
532
533 std::vector<double> rtn;
534 rtn.reserve(lengthContent());
535 for (size_t i = 0; i < numPoints(); ++i) {
536 std::vector<double> pdata = point(i)._serializeContent();
537 rtn.insert(std::end(rtn),
538 std::make_move_iterator(std::begin(pdata)),
539 std::make_move_iterator(std::end(pdata)));
540 }
541 return rtn;
542 }
543
544 void deserializeContent(const std::vector<double>& data) {
545
546 if (data.size() % Point::DataSize::value)
547 throw UserError("Length of serialized data should be a multiple of "+std::to_string(Point::DataSize::value)+"!");
548
549 const size_t nPoints = data.size()/Point::DataSize::value;
550 const auto itr = data.cbegin();
551 reset();
552 for (size_t i = 0; i < nPoints; ++i) {
553 addPoint(Point());
554 auto first = itr + i*Point::DataSize::value;
555 auto last = first + Point::DataSize::value;
556 point(i)._deserializeContent(std::vector<double>{first, last});
557 }
558
559 }
560
561 // @}
562
565
568 addPoints(other.points());
569 return *this;
570 }
571
574 addPoints(std::move(other._points));
575 return *this;
576 }
577
579 ScatterND<N>& combineWith(const std::vector< ScatterND<N> >& others) {
580 for (const ScatterND<N>& s : others) combineWith(s);
581 return *this;
582 }
583
585 ScatterND<N>& combineWith(std::vector< ScatterND<N> >&& others) {
586 for (ScatterND<N>&& s : others) combineWith(std::move(s));
587 return *this;
588 }
589
591
594
596 ValVec vals(const size_t i) const {
597 if (i >= N) throw RangeError("Invalid axis int, must be in range 0..dim-1");
598 ValVec rtn; rtn.reserve(_points.size());
599 for (const auto& pt : _points) {
600 rtn.push_back( pt.val(i) );
601 }
602 return rtn;
603 }
604
606 ValVec mins(const size_t i) const {
607 if (i >= N) throw RangeError("Invalid axis int, must be in range 0..dim-1");
608 ValVec rtn; rtn.reserve(_points.size());
609 for (const auto& pt : _points) {
610 rtn.push_back( pt.min(i) );
611 }
612 return rtn;
613 }
614
616 ValVec maxs(const size_t i) const {
617 if (i >= N) throw RangeError("Invalid axis int, must be in range 0..dim-1");
618 ValVec rtn; rtn.reserve(_points.size());
619 for (const auto& pt : _points) {
620 rtn.push_back( pt.max(i) );
621 }
622 return rtn;
623 }
624
626 double min(const size_t i) const {
627 if (i >= N) throw RangeError("Invalid axis int, must be in range 0..dim-1");
628 const ValVec cvals = vals(i);
629 return *std::min_element(cvals.begin(), cvals.end());
630 }
631
633 double max(const size_t i) const {
634 if (i >= N) throw RangeError("Invalid axis int, must be in range 0..dim-1");
635 const ValVec cvals = vals(i);
636 return *std::max_element(cvals.begin(), cvals.end());
637 }
638
640 PairVec errs(const size_t i) const {
641 if (i >= N) throw RangeError("Invalid axis int, must be in range 0..dim-1");
642 PairVec rtn; rtn.reserve(_points.size());
643 for (const auto& pt : _points) {
644 rtn.push_back( pt.errs(i) );
645 }
646 return rtn;
647 }
648
650 ValVec errAvgs(const size_t i) const {
651 if (i >= N) throw RangeError("Invalid axis int, must be in range 0..dim-1");
652 ValVec rtn; rtn.reserve(_points.size());
653 for (const auto& pt : _points) {
654 rtn.push_back( pt.errAvg(i) );
655 }
656 return rtn;
657 }
658
660 ValVec xVals() const { return vals(0); }
661
663 template<size_t axisN = N, typename = std::enable_if_t<(axisN >= 2)>>
664 ValVec yVals() const { return vals(1); }
665
667 template<size_t axisN = N, typename = std::enable_if_t<(axisN >= 3)>>
668 ValVec zVals() const { return vals(2); }
669
671 ValVec xMins() const { return mins(0); }
672
674 template<size_t axisN = N, typename = std::enable_if_t<(axisN >= 2)>>
675 ValVec yMins() const { return mins(1); }
676
678 template<size_t axisN = N, typename = std::enable_if_t<(axisN >= 3)>>
679 ValVec zMins() const { return mins(2); }
680
682 ValVec xMaxs() const { return maxs(0); }
683
685 template<size_t axisN = N, typename = std::enable_if_t<(axisN >= 2)>>
686 ValVec yMaxs() const { return maxs(1); }
687
689 template<size_t axisN = N, typename = std::enable_if_t<(axisN >= 3)>>
690 ValVec zMaxs() const { return maxs(2); }
691
693 double xMin() const { return min(0); }
694
696 template<size_t axisN = N, typename = std::enable_if_t<(axisN >= 2)>>
697 double yMin() const { return min(1); }
698
700 template<size_t axisN = N, typename = std::enable_if_t<(axisN >= 3)>>
701 double zMin() const { return min(2); }
702
704 double xMax() const { return max(0); }
705
707 template<size_t axisN = N, typename = std::enable_if_t<(axisN >= 2)>>
708 double yMax() const { return max(1); }
709
711 template<size_t axisN = N, typename = std::enable_if_t<(axisN >= 3)>>
712 double zMax() const { return max(2); }
713
715 PairVec xErrs() const { return errs(0); }
716
718 template<size_t axisN = N, typename = std::enable_if_t<(axisN >= 2)>>
719 PairVec yErrs() const { return errs(1); }
720
722 template<size_t axisN = N, typename = std::enable_if_t<(axisN >= 3)>>
723 PairVec zErrs() const { return errs(2); }
724
726 ValVec xErrAvgs() const { return errAvgs(0); }
727
729 template<size_t axisN = N, typename = std::enable_if_t<(axisN >= 2)>>
730 ValVec yErrAvgs() const { return errAvgs(1); }
731
733 template<size_t axisN = N, typename = std::enable_if_t<(axisN >= 3)>>
734 ValVec zErrAvgs() const { return errAvgs(2); }
735
737
740
741 // @brief Render information about this AO
742 void _renderYODA(std::ostream& os, const int width = 13) const noexcept {
743
744 os << "# ";
745 for (size_t i = 0; i < N; ++i) {
746 os << std::setw(width - int(i? 0 : 2)) << std::left << ("val" + std::to_string(i+1)) << "\t"
747 << std::setw(width) << std::left << ("err" + std::to_string(i+1) + "-") << "\t"
748 << std::setw(width) << std::left << ("err" + std::to_string(i+1) + "+") << "\t";
749 }
750 os << "\n";
751
752 for (const auto& pt : _points) {
753 pt._renderYODA(os, width);
754 }
755 }
756
757 // @brief Render information about this AO
758 void _renderFLAT(std::ostream& os, const int width = 13) const noexcept { _renderYODA(os, width); }
759
761
764
765 std::vector<Pair> edges(const size_t i) const {
766 if (i >= N) throw RangeError("Invalid axis int, must be in range 0..dim-1");
767 std::vector<Pair> rtn;
768 rtn.resize(numPoints());
769 size_t j = 0;
770 for (const Point& p : points()) {
771 rtn[j++] = std::make_pair(p.min(i), p.max(i));
772 }
773 std::sort(rtn.begin(), rtn.end());
774 rtn.erase(std::unique(rtn.begin(), rtn.end()), rtn.end());
775 return rtn;
776 }
777
779
780 private:
781
782 Points _points;
783
784 };
785
786
789
790 template <int N>
792 a.combineWith(b);
793 return a;
794 }
795
796 template <int N>
798 a.combineWith(std::move(b));
799 return a;
800 }
801
802 template <int N>
803 inline ScatterND<N> combine(const std::vector< ScatterND<N> >& scatters) {
804 ScatterND<N> rtn;
805 rtn.combineWith(scatters);
806 return rtn;
807 }
808
809 template <int N>
810 inline ScatterND<N> combine(std::vector< ScatterND<N> >&& scatters) {
811 ScatterND<N> rtn;
812 rtn.combineWith(std::move(scatters));
813 return rtn;
814 }
815
817
818
820
821
822 // /// @name Combining scatters: global operators, assuming aligned points
823 // /// @{
824
825 // /// Add two scatters
826 // template <size_t N>
827 // Scatter add(const Scatter& first, const Scatter& second);
828
829
830 // /// Add two scatters
831 // template <size_t N>
832 // inline Scatter operator + (const Scatter& first, const Scatter& second) {
833 // return add(first, second);
834 // }
835
836
837 // /// Subtract two scatters
838 // template <size_t N>
839 // Scatter subtract(const Scatter& first, const Scatter& second);
840
841
842 // /// Subtract two scatters
843 // template <size_t N>
844 // inline Scatter operator - (const Scatter& first, const Scatter& second) {
845 // return subtract(first, second);
846 // }
847
848
849 // /// Divide two scatters
850 // template <size_t N>
851 // Scatter divide(const Scatter& numer, const Scatter& denom);
852
853
854 // /// Divide two scatters
855 // template <size_t N>
856 // inline Scatter operator / (const Scatter& numer, const Scatter& denom) {
857 // return divide(numer, denom);
858 // }
859
860 // /// @}
861
862
864
865
868
869 template<size_t N>
870 inline void transform(ScatterND<N>& s, const Trf<N>& fn, const size_t i) {
871 for (auto& p : s.points()) {
872 p.transform(i, fn);
873 }
874 }
875
876 template<size_t N, typename FN>
877 inline void transform(ScatterND<N>& s, const FN& fn, const size_t i) {
878 transform(s, Trf<N>(fn), i);
879 }
880
881 template<size_t N, typename FN>
882 inline void transformX(ScatterND<N>& s, const FN& fn) {
883 transform(s, fn, 0);
884 }
885
886 template<size_t N, typename FN>
887 inline void transformY(ScatterND<N>& s, const FN& fn) {
888 transform(s, fn, 1);
889 }
890
891 template<size_t N, typename FN>
892 inline void transformZ(ScatterND<N>& s, const FN& fn) {
893 transform(s, fn, 2);
894 }
895
897
900
905 using S1D = Scatter1D;
906 using S2D = Scatter2D;
907 using S3D = Scatter3D;
908 using S4D = Scatter4D;
909
911
912
913}
914
915#endif
AnalysisObject is the base class for histograms and scatters.
virtual AnalysisObject & operator=(const AnalysisObject &ao) noexcept
Default copy assignment operator.
const std::string title() const
Get the AO title.
const std::string path() const
Get the AO path.
Error for e.g. use of invalid bin ranges.
Definition Exceptions.h:34
A generic data type which is just a collection of n-dim data points with errors.
Definition Scatter.h:153
auto addPoint_aux(std::tuple< Args... > &&t, std::index_sequence< Is... >) -> std::enable_if_t<(sizeof...(Args)==2 *N &&isHalfValsHalfPairs< Args... >::value), ScatterND< N > > &
Definition Scatter.h:499
typename std::is_same< containedType< Arr >, Pair > containsPair
Definition Scatter.h:169
std::decay_t< decltype(*std::declval< Arr >().begin())> containedType
Definition Scatter.h:165
std::vector< Pair > edges(const size_t i) const
Definition Scatter.h:765
double zMin() const
Axis-specific alias.
Definition Scatter.h:701
size_t numPoints() const
Number of points in the scatter.
Definition Scatter.h:343
double yMin() const
Axis-specific alias.
Definition Scatter.h:697
ScatterND(const ScatterND< N > &s, const std::string &path="")
Copy constructor with optional new path.
Definition Scatter.h:253
void scale(const size_t i, double factor)
Scale value and error along direction i.
Definition Scatter.h:316
ScatterND< N > * newclone() const
Make a copy on the heap, via 'new'.
Definition Scatter.h:288
PointND< N > & point(size_t index)
Get a reference to the point with index index.
Definition Scatter.h:361
ValVec xErrAvgs() const
Axis-specific alias.
Definition Scatter.h:726
std::enable_if_t<(isIterable< T, U, containedType< T >, containedType< U > > &&containsPair< containedType< U > >::value)> enableIfNestedArrayWithPair
Definition Scatter.h:175
double zMax() const
Axis-specific alias.
Definition Scatter.h:712
size_t lengthContent(bool fixed_length=false) const noexcept
Length of serialized content vector for MPI reduce operations.
Definition Scatter.h:524
ScatterND< N > & addPoint(ValRange &&pos, ValRange &&errdn, ValRange &&errup)
Insert a new point from position and asymmetric error arrays (of N elements)
Definition Scatter.h:408
ValVec maxs(const size_t i) const
Get the positive error vector along axis i.
Definition Scatter.h:616
ScatterND< N > clone() const
Make a copy on the stack.
Definition Scatter.h:283
double max(const size_t i) const
Get the largest central value along axis i.
Definition Scatter.h:633
ValVec yVals() const
Axis-specific alias.
Definition Scatter.h:664
size_t dim() const noexcept
Dimension of this data object.
Definition Scatter.h:295
HalfValsHalfPairs< std::tuple< Args... >, std::make_index_sequence< N > > isHalfValsHalfPairs
Definition Scatter.h:185
const PointND< N > & point(size_t index) const
Get the point with index index (const version)
Definition Scatter.h:367
auto addPoint(Args &&... args) -> std::enable_if_t<(sizeof...(Args)==2 *N||sizeof...(Args)==3 *N), ScatterND< N > > &
Definition Scatter.h:445
ScatterND(ScatterND< N > &&s, const std::string &path="")
Move constructor with optional new path.
Definition Scatter.h:258
std::initializer_list< Pair > PairList
Definition Scatter.h:161
PairVec zErrs() const
Axis-specific alias.
Definition Scatter.h:723
ValVec vals(const size_t i) const
Get the coordinate vector along axis i.
Definition Scatter.h:596
void rmPoint(size_t index)
Remove the point with index index.
Definition Scatter.h:515
ScatterND(ValRange &&positions, PairRange &&errors, const std::string &path="", const std::string &title="")
Constructor from vectors of values for positions and a single set of symmetric errors.
Definition Scatter.h:243
ScatterND< N > & addPoint(const PointND< N > &pt)
Insert a new point.
Definition Scatter.h:378
void scaleErr(const size_t i, double factor)
Scale error along direction i.
Definition Scatter.h:328
const Points & points() const
Get the collection of points (const version)
Definition Scatter.h:355
ScatterND< N > & combineWith(const ScatterND< N > &other)
Definition Scatter.h:567
Utils::ndarray< std::pair< double, double >, N > NdValPair
Definition Scatter.h:191
PairVec yErrs() const
Axis-specific alias.
Definition Scatter.h:719
ValVec xMaxs() const
Axis-specific alias.
Definition Scatter.h:682
ValVec mins(const size_t i) const
Get the lowest value vector along axis i.
Definition Scatter.h:606
void scaleVal(const size_t i, double factor)
Scale value along direction i.
Definition Scatter.h:322
ScatterND< N > & combineWith(std::vector< ScatterND< N > > &&others)
Definition Scatter.h:585
ScatterND< N > & operator=(const ScatterND< N > &s)
Assignment operator.
Definition Scatter.h:265
Utils::ndarray< double, N > NdVal
Definition Scatter.h:190
ScatterND< N > & combineWith(const std::vector< ScatterND< N > > &others)
Definition Scatter.h:579
std::vector< Pair > PairVec
Definition Scatter.h:159
PointND< N > Point
Definition Scatter.h:192
ScatterND(const std::string &path="", const std::string &title="")
Empty constructor.
Definition Scatter.h:202
void deserializeContent(const std::vector< double > &data)
Content deserialisation for MPI reduce operations.
Definition Scatter.h:544
ScatterND(Points &&points, const std::string &path="", const std::string &title="")
Constructor from a set of rvalue points.
Definition Scatter.h:212
double min(const size_t i) const
Get the smallest central value along axis i.
Definition Scatter.h:626
ValVec xMins() const
Axis-specific alias.
Definition Scatter.h:671
PairVec errs(const size_t i) const
Get the error pairs along axis i.
Definition Scatter.h:640
auto addPoint_aux(std::tuple< Args... > &&t, std::index_sequence< Is... >) -> std::enable_if_t<(isAllVals< Args... >::value), ScatterND< N > > &
Definition Scatter.h:468
Points & points()
Get the collection of points.
Definition Scatter.h:349
std::vector< Point > Points
Definition Scatter.h:193
ScatterND(ValRange &&positions, const std::string &path="", const std::string &title="")
Constructor from a vector of position values with no errors.
Definition Scatter.h:220
ValVec zErrAvgs() const
Axis-specific alias.
Definition Scatter.h:734
ScatterND< N > & addPoint(ValRange &&pos)
Insert a new point from a position array (of N elements)
Definition Scatter.h:392
double yMax() const
Axis-specific alias.
Definition Scatter.h:708
ValVec xVals() const
Axis-specific alias.
Definition Scatter.h:660
std::is_same< double, std::common_type_t< Args..., double > > isAllVals
Definition Scatter.h:179
ValVec errAvgs(const size_t i) const
Get the average error along axis i.
Definition Scatter.h:650
ValVec zVals() const
Axis-specific alias.
Definition Scatter.h:668
ScatterND< N > & addPoints(Points pts)
Insert a collection of new points.
Definition Scatter.h:510
PairVec xErrs() const
Axis-specific alias.
Definition Scatter.h:715
ValVec zMins() const
Axis-specific alias.
Definition Scatter.h:679
void reset()
Clear all points.
Definition Scatter.h:301
ScatterND< N > & combineWith(ScatterND< N > &&other)
Definition Scatter.h:573
void scale(const NdVal &scales)
Scaling.
Definition Scatter.h:306
std::shared_ptr< ScatterND > Ptr
Definition Scatter.h:194
ScatterND< N > & addPoint(ValRange &&pos, ValRange &&err)
Insert a new point from position and symmetric error arrays (of N elements)
Definition Scatter.h:400
ValVec yMins() const
Axis-specific alias.
Definition Scatter.h:675
ScatterND(const Points &points, const std::string &path="", const std::string &title="")
Constructor from a set of points.
Definition Scatter.h:206
auto addPoint(ValRange &&pos, PairRange &&err) -> std::enable_if_t<(isIterable< ValRange, PairRange > &&containsPair< PairRange >::value), ScatterND< N > > &
Insert a new point from a position and error-pair array.
Definition Scatter.h:417
void scale(const std::vector< double > &scales)
Definition Scatter.h:310
std::pair< double, double > Pair
Definition Scatter.h:157
ValVec yMaxs() const
Axis-specific alias.
Definition Scatter.h:686
std::initializer_list< double > ValList
Definition Scatter.h:160
ScatterND(ValRange &&positions, ValRange &&errors, const std::string &path="", const std::string &title="")
Constructor from vectors of values for positions and a single set of symmetric errors.
Definition Scatter.h:230
double xMin() const
Axis-specific alias.
Definition Scatter.h:693
std::vector< double > ValVec
Definition Scatter.h:158
double xMax() const
Axis-specific alias.
Definition Scatter.h:704
std::vector< double > serializeContent(bool fixed_length=false) const noexcept
Content serialisation for MPI reduce operations.
Definition Scatter.h:529
ScatterND< N > & addPoint(PointND< N > &&pt)
Insert a new rvalue point.
Definition Scatter.h:384
ValVec yErrAvgs() const
Axis-specific alias.
Definition Scatter.h:730
ValVec zMaxs() const
Axis-specific alias.
Definition Scatter.h:690
A base class for common operations on scatter types (Scatter1D, etc.)
Definition Scatter.h:43
virtual ~Scatter()
Virtual destructor for inheritance.
Definition Scatter.h:49
virtual size_t numPoints() const =0
Scaling along direction i.
virtual void reset()=0
Clear all points.
virtual size_t dim() const noexcept=0
Dimension of this data object.
virtual void rmPoint(size_t index)=0
Remove the point with index index.
virtual void rmPoints(std::vector< size_t > indices)
Safely remove the points with indices indices.
Definition Scatter.h:84
Error for problems introduced outside YODA, to put it nicely.
Definition Exceptions.h:86
Anonymous namespace to limit visibility.
void transform(BinnedEstimate< AxisT... > &est, const Trf< 1 > &fn)
ScatterND< 3 > Scatter3D
Definition Scatter.h:903
Scatter4D S4D
Definition Scatter.h:908
void transformX(ScatterND< N > &s, const FN &fn)
Definition Scatter.h:882
void transformY(ScatterND< N > &s, const FN &fn)
Definition Scatter.h:887
ScatterND< 4 > Scatter4D
Definition Scatter.h:904
void transformZ(ScatterND< N > &s, const FN &fn)
Definition Scatter.h:892
ScatterND< N > combine(ScatterND< N > a, const ScatterND< N > &b)
Definition Scatter.h:791
ScatterND< 1 > Scatter1D
Definition Scatter.h:901
ScatterND< 2 > Scatter2D
Definition Scatter.h:902