36 #ifndef VIGRA_AXISTAGS_HXX
37 #define VIGRA_AXISTAGS_HXX
40 #include "array_vector.hxx"
41 #include "algorithm.hxx"
43 #include "functorexpression.hxx"
56 enum AxisType { Channels = 1,
63 NonChannel = Space | Angle | Time | Frequency | UnknownAxisType,
64 AllAxes = 2*UnknownAxisType-1 };
66 AxisInfo(std::string key =
"?", AxisType typeFlags = UnknownAxisType,
67 double resolution = 0.0, std::string description =
"")
69 description_(description),
70 resolution_(resolution),
74 std::string key()
const
79 std::string description()
const
84 void setDescription(std::string
const & description)
86 description_ = description;
89 double resolution()
const
94 void setResolution(
double resolution)
96 resolution_ = resolution;
99 AxisType typeFlags()
const
106 bool isUnknown()
const
108 return isType(UnknownAxisType);
111 bool isSpatial()
const
113 return isType(Space);
116 bool isTemporal()
const
121 bool isChannel()
const
123 return isType(Channels);
126 bool isFrequency()
const
128 return isType(Frequency);
136 bool isAngular()
const
138 return isType(Angle);
141 bool isType(AxisType type)
const
143 return (typeFlags() & type) != 0;
146 std::string repr()
const
148 std::string res(
"AxisInfo: '");
149 res += key_ +
"' (type:";
167 if(resolution_ > 0.0)
169 res +=
", resolution=";
173 if(description_ !=
"")
181 AxisInfo toFrequencyDomain(
unsigned int size = 0,
int sign = 1)
const
186 vigra_precondition(!isFrequency(),
187 "AxisInfo::toFrequencyDomain(): axis is already in the Fourier domain.");
188 type = AxisType(Frequency | flags_);
192 vigra_precondition(isFrequency(),
193 "AxisInfo::fromFrequencyDomain(): axis is not in the Fourier domain.");
194 type = AxisType(~Frequency & flags_);
196 AxisInfo res(key(), type, 0.0, description_);
197 if(resolution_ > 0.0 && size > 0u)
198 res.resolution_ = 1.0 / (resolution_ * size);
202 AxisInfo fromFrequencyDomain(
unsigned int size = 0)
const
204 return toFrequencyDomain(size, -1);
207 bool compatible(AxisInfo
const & other)
const
209 return isUnknown() || other.isUnknown() ||
210 ((typeFlags() & ~Frequency) == (other.typeFlags() & ~Frequency) &&
211 key() == other.key());
216 return typeFlags() == other.typeFlags() && key() == other.key();
228 bool operator<(AxisInfo
const & other)
const
230 return (typeFlags() < other.typeFlags()) ||
231 (typeFlags() == other.typeFlags() && key() < other.key());
236 return !(other < *
this);
239 bool operator>(AxisInfo
const & other)
const
241 return other < *
this;
246 return !(*
this < other);
250 static AxisInfo x(
double resolution = 0.0, std::string
const & description =
"")
252 return AxisInfo(
"x", Space, resolution, description);
255 static AxisInfo y(
double resolution = 0.0, std::string
const & description =
"")
257 return AxisInfo(
"y", Space, resolution, description);
260 static AxisInfo z(
double resolution = 0.0, std::string
const & description =
"")
262 return AxisInfo(
"z", Space, resolution, description);
265 static AxisInfo n(
double resolution = 0.0, std::string
const & description =
"")
267 return AxisInfo(
"n", Space, resolution, description);
270 static AxisInfo e(
double resolution = 0.0, std::string
const & description =
"")
272 return AxisInfo(
"e", Edge, resolution, description);
275 static AxisInfo t(
double resolution = 0.0, std::string
const & description =
"")
277 return AxisInfo(
"t", Time, resolution, description);
280 static AxisInfo fx(
double resolution = 0.0, std::string
const & description =
"")
282 return AxisInfo(
"x", AxisType(Space | Frequency), resolution, description);
285 static AxisInfo fy(
double resolution = 0.0, std::string
const & description =
"")
287 return AxisInfo(
"y", AxisType(Space | Frequency), resolution, description);
290 static AxisInfo fz(
double resolution = 0.0, std::string
const & description =
"")
292 return AxisInfo(
"z", AxisType(Space | Frequency), resolution, description);
295 static AxisInfo ft(
double resolution = 0.0, std::string
const & description =
"")
297 return AxisInfo(
"t", AxisType(Time | Frequency), resolution, description);
300 static AxisInfo c(std::string
const & description =
"")
302 return AxisInfo(
"c", Channels, 0.0, description);
305 std::string key_, description_;
321 AxisTags(AxisInfo
const & i1)
326 AxisTags(AxisInfo
const & i1, AxisInfo
const & i2)
332 AxisTags(AxisInfo
const & i1, AxisInfo
const & i2, AxisInfo
const & i3)
339 AxisTags(AxisInfo
const & i1, AxisInfo
const & i2,
340 AxisInfo
const & i3, AxisInfo
const & i4)
348 AxisTags(AxisInfo
const & i1, AxisInfo
const & i2,
349 AxisInfo
const & i3, AxisInfo
const & i4, AxisInfo
const & i5)
358 AxisTags(std::string
const & tags)
360 for(std::string::size_type k=0; k<tags.size(); ++k)
365 push_back(AxisInfo::x());
368 push_back(AxisInfo::y());
371 push_back(AxisInfo::z());
374 push_back(AxisInfo::t());
377 push_back(AxisInfo::c());
381 vigra_precondition(k < tags.size(),
382 "AxisTags(string): invalid input");
386 push_back(AxisInfo::fx());
389 push_back(AxisInfo::fy());
392 push_back(AxisInfo::fz());
395 push_back(AxisInfo::ft());
398 vigra_precondition(
false,
399 "AxisTags(string): invalid input");
403 vigra_precondition(
false,
404 "AxisTags(string): invalid input");
411 std::string toJSON()
const
414 s <<
"{\n \"axes\": [";
415 for(
unsigned int k=0; k<size(); ++k)
421 s <<
" \"key\": \"" << axes_[k].key() <<
"\",\n";
422 s <<
" \"typeFlags\": " << (
unsigned int)axes_[k].typeFlags() <<
",\n";
423 s <<
" \"resolution\": " << std::setprecision(17) << axes_[k].resolution() <<
",\n";
424 s <<
" \"description\": \"" << axes_[k].description() <<
"\"\n";
431 unsigned int size()
const
436 int axisTypeCount(AxisInfo::AxisType type)
const
439 for(
unsigned int k=0; k<size(); ++k)
440 if(axes_[k].isType(type))
445 std::string repr()
const
449 res += axes_[0].key();
450 for(
unsigned int k=1; k<size(); ++k)
453 res += axes_[k].key();
458 bool contains(std::string
const & key)
const
460 return index(key) < (int)size();
463 AxisInfo &
get(
int k)
471 AxisInfo &
get(std::string
const & key)
473 return get(index(key));
476 AxisInfo
const &
get(
int k)
const
484 AxisInfo
const &
get(std::string
const & key)
const
486 return get(index(key));
489 void set(
int k, AxisInfo
const & info)
494 checkDuplicates(k, info);
498 void set(std::string
const & key, AxisInfo
const & info)
500 set(index(key), info);
503 void insert(
int k, AxisInfo
const & i)
514 checkDuplicates(size(), i);
515 axes_.insert(axes_.begin()+k, i);
519 void push_back(AxisInfo
const & i)
521 checkDuplicates(size(), i);
528 ArrayVector<AxisInfo>::iterator i = k < 0
534 void dropAxis(std::string
const & key)
536 dropAxis(index(key));
539 void dropChannelAxis()
541 int k = channelIndex();
543 axes_.erase(axes_.begin() + k, axes_.begin() + k + 1);
546 int index(std::string
const & key)
const
548 for(
unsigned int k=0; k<size(); ++k)
549 if(axes_[k].key() == key)
554 double resolution(
int k)
const
556 return get(k).resolution_;
559 double resolution(std::string
const & key)
const
561 return resolution(index(key));
564 void setResolution(
int k,
double r)
566 get(k).resolution_ = r;
569 void setResolution(std::string
const & key,
double r)
571 setResolution(index(key), r);
574 void scaleResolution(
int k,
double factor)
576 get(k).resolution_ *= factor;
579 void scaleResolution(std::string
const & key,
double factor)
581 get(key).resolution_ *= factor;
584 std::string description(
int k)
const
586 return get(k).description_;
589 std::string description(std::string
const & key)
const
591 return description(index(key));
594 void setDescription(
int k, std::string
const & d)
596 get(k).setDescription(d);
599 void setDescription(std::string
const & key, std::string
const & d)
601 setDescription(index(key), d);
604 void setChannelDescription(std::string
const & description)
606 int k = channelIndex();
608 axes_[k].setDescription(description);
611 void toFrequencyDomain(
int k,
int size = 0,
int sign = 1)
613 get(k) =
get(k).toFrequencyDomain(size,
sign);
616 void toFrequencyDomain(std::string
const & key,
int size = 0,
int sign = 1)
618 toFrequencyDomain(index(key), size,
sign);
621 void fromFrequencyDomain(
int k,
int size = 0)
623 toFrequencyDomain(k, size, -1);
626 void fromFrequencyDomain(std::string
const & key,
int size = 0)
628 toFrequencyDomain(key, size, -1);
631 bool hasChannelAxis()
const
633 return channelIndex() != (int)size();
637 int channelIndex()
const
639 for(
unsigned int k=0; k<size(); ++k)
640 if(axes_[k].isChannel())
645 int innerNonchannelIndex()
const
648 for(; k<(int)size(); ++k)
649 if(!axes_[k].isChannel())
651 for(
int i=k+1; i<(int)size(); ++i)
653 if(axes_[i].isChannel())
655 if(axes_[i] < axes_[k])
661 void swapaxes(
int i1,
int i2)
669 std::swap(axes_[i1], axes_[i2]);
673 void transpose(ArrayVector<T>
const & permutation)
675 if(permutation.size() == 0)
681 vigra_precondition(permutation.size() == size(),
682 "AxisTags::transpose(): Permutation has wrong size.");
683 ArrayVector<AxisInfo> newAxes(size());
684 applyPermutation(permutation.begin(), permutation.end(), axes_.begin(), newAxes.begin());
691 std::reverse(axes_.begin(), axes_.end());
696 permutationToNormalOrder(ArrayVector<T> & permutation)
const
698 permutation.resize(size());
699 indexSort(axes_.begin(), axes_.end(), permutation.begin());
704 permutationToNormalOrder(ArrayVector<T> & permutation, AxisInfo::AxisType types)
const
706 ArrayVector<AxisInfo> matchingAxes;
707 for(
int k=0; k<(int)size(); ++k)
708 if(axes_[k].isType(types))
709 matchingAxes.push_back(axes_[k]);
710 permutation.resize(matchingAxes.size());
711 indexSort(matchingAxes.begin(), matchingAxes.end(), permutation.begin());
716 permutationFromNormalOrder(ArrayVector<T> & inverse_permutation)
const
718 ArrayVector<T> permutation;
719 permutationToNormalOrder(permutation);
720 inverse_permutation.resize(permutation.size());
721 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
726 permutationFromNormalOrder(ArrayVector<T> & inverse_permutation, AxisInfo::AxisType types)
const
728 ArrayVector<T> permutation;
729 permutationToNormalOrder(permutation, types);
730 inverse_permutation.resize(permutation.size());
731 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
735 void permutationToNumpyOrder(ArrayVector<T> & permutation)
const
737 permutationToNormalOrder(permutation);
738 std::reverse(permutation.begin(), permutation.end());
742 void permutationFromNumpyOrder(ArrayVector<T> & inverse_permutation)
const
744 ArrayVector<T> permutation;
745 permutationToNumpyOrder(permutation);
746 inverse_permutation.resize(permutation.size());
747 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
751 void permutationToVigraOrder(ArrayVector<T> & permutation)
const
753 permutation.resize(size());
754 indexSort(axes_.begin(), axes_.end(), permutation.begin());
755 int channel = channelIndex();
756 if(channel < (
int)size())
758 for(
int k=1; k<(int)size(); ++k)
759 permutation[k-1] = permutation[k];
760 permutation.back() = channel;
765 void permutationFromVigraOrder(ArrayVector<T> & inverse_permutation)
const
767 ArrayVector<T> permutation;
768 permutationToVigraOrder(permutation);
769 inverse_permutation.resize(permutation.size());
770 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
774 void permutationToOrder(ArrayVector<T> & permutation, std::string
const & order)
const
778 permutation.resize(size());
781 else if(order ==
"C")
783 permutationToNumpyOrder(permutation);
785 else if(order ==
"F")
787 permutationToNormalOrder(permutation);
789 else if(order ==
"V")
791 permutationToVigraOrder(permutation);
795 vigra_precondition(
false,
796 "AxisTags::permutationToOrder(): unknown order '" + order +
"'.");
801 ArrayVector<UInt32> matchOrdering(AxisTags
const & other)
803 vigra_precondition(size() == other.size(),
804 "AxisTags::matchOrdering(): size mismatch.");
806 ArrayVector<UInt32> permutation(size());
807 for(
unsigned int k = 0; k<size(); ++k)
809 std::string key = other.get(k).key();
813 if(key ==
get(l).key())
816 vigra_precondition(l < size(),
817 "AxisTags::matchOrdering(): key mismatch.");
824 bool compatible(AxisTags
const & other)
const
826 if(size() == 0 || other.size() == 0)
828 if(size() != other.size())
830 for(
unsigned int k=0; k<size(); ++k)
831 if(!axes_[k].compatible(other.axes_[k]))
838 if(size() != other.size())
840 return std::equal(axes_.begin(), axes_.end(), other.axes_.begin());
850 void checkIndex(
int k)
const
852 vigra_precondition(k < (
int)size() && k >= -(
int)size(),
853 "AxisTags::checkIndex(): index out of range.");
856 void checkDuplicates(
int i, AxisInfo
const & info)
860 for(
int k=0; k<(int)size(); ++k)
862 vigra_precondition(k == i || !axes_[k].isChannel(),
863 "AxisTags::checkDuplicates(): can only have one channel axis.");
866 else if(!info.isUnknown())
868 for(
int k=0; k<(int)size(); ++k)
870 vigra_precondition(k == i || axes_[k].key() != info.key(),
871 std::string(
"AxisTags::checkDuplicates(): axis key '" +
872 info.key() +
"' already exists."));
877 ArrayVector<AxisInfo> axes_;
void applyPermutation(IndexIterator index_first, IndexIterator index_last, InIterator in, OutIterator out)
Sort an array according to the given index permutation.
Definition: algorithm.hxx:456
void indexSort(Iterator first, Iterator last, IndexIterator index_first, Compare c)
Return the index permutation that would sort the input array.
Definition: algorithm.hxx:414
void transpose(const MultiArrayView< 2, T, C1 > &v, MultiArrayView< 2, T, C2 > &r)
Definition: matrix.hxx:965
void linearSequence(Iterator first, Iterator last, Value start, Value step)
Fill an array with a sequence of numbers.
Definition: algorithm.hxx:208
bool operator<=(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
less or equal
Definition: fixedpoint.hxx:521
bool operator!=(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
not equal
Definition: fftw3.hxx:841
std::string asString(T t)(...)
bool operator==(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
equal
Definition: fftw3.hxx:825
bool operator<(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
less than
Definition: fixedpoint.hxx:512
bool operator>=(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
greater or equal
Definition: fixedpoint.hxx:539
bool operator>(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
greater
Definition: fixedpoint.hxx:530
T sign(T t)
The sign function.
Definition: mathutil.hxx:591