36 #ifndef VIGRA_AXISTAGS_HXX
37 #define VIGRA_AXISTAGS_HXX
39 #include "utilities.hxx"
40 #include "array_vector.hxx"
41 #include "algorithm.hxx"
43 #include "functorexpression.hxx"
56 enum AxisType { Channels = 1,
62 NonChannel = Space | Angle | Time | Frequency | UnknownAxisType,
63 AllAxes = 2*UnknownAxisType-1 };
65 AxisInfo(std::string key =
"?", AxisType typeFlags = UnknownAxisType,
66 double resolution = 0.0, std::string description =
"")
68 description_(description),
69 resolution_(resolution),
73 std::string key()
const
78 std::string description()
const
83 void setDescription(std::string
const & description)
85 description_ = description;
88 double resolution()
const
93 void setResolution(
double resolution)
95 resolution_ = resolution;
98 AxisType typeFlags()
const
105 bool isUnknown()
const
107 return isType(UnknownAxisType);
110 bool isSpatial()
const
112 return isType(Space);
115 bool isTemporal()
const
120 bool isChannel()
const
122 return isType(Channels);
125 bool isFrequency()
const
127 return isType(Frequency);
130 bool isAngular()
const
132 return isType(Angle);
135 bool isType(AxisType type)
const
137 return (typeFlags() & type) != 0;
140 std::string repr()
const
142 std::string res(
"AxisInfo: '");
143 res += key_ +
"' (type:";
161 if(resolution_ > 0.0)
163 res +=
", resolution=";
167 if(description_ !=
"")
175 AxisInfo toFrequencyDomain(
unsigned int size = 0,
int sign = 1)
const
180 vigra_precondition(!isFrequency(),
181 "AxisInfo::toFrequencyDomain(): axis is already in the Fourier domain.");
182 type = AxisType(Frequency | flags_);
186 vigra_precondition(isFrequency(),
187 "AxisInfo::fromFrequencyDomain(): axis is not in the Fourier domain.");
188 type = AxisType(~Frequency & flags_);
190 AxisInfo res(key(), type, 0.0, description_);
191 if(resolution_ > 0.0 && size > 0u)
192 res.resolution_ = 1.0 / (resolution_ * size);
196 AxisInfo fromFrequencyDomain(
unsigned int size = 0)
const
198 return toFrequencyDomain(size, -1);
201 bool compatible(AxisInfo
const & other)
const
203 return isUnknown() || other.isUnknown() ||
204 ((typeFlags() & ~Frequency) == (other.typeFlags() & ~Frequency) &&
205 key() == other.key());
210 return typeFlags() == other.typeFlags() && key() == other.key();
222 bool operator<(AxisInfo
const & other)
const
224 return (typeFlags() < other.typeFlags()) ||
225 (typeFlags() == other.typeFlags() && key() < other.key());
230 return !(other < *
this);
233 bool operator>(AxisInfo
const & other)
const
235 return other < *
this;
240 return !(*
this < other);
244 static AxisInfo x(
double resolution = 0.0, std::string
const & description =
"")
246 return AxisInfo(
"x", Space, resolution, description);
249 static AxisInfo y(
double resolution = 0.0, std::string
const & description =
"")
251 return AxisInfo(
"y", Space, resolution, description);
254 static AxisInfo z(
double resolution = 0.0, std::string
const & description =
"")
256 return AxisInfo(
"z", Space, resolution, description);
259 static AxisInfo t(
double resolution = 0.0, std::string
const & description =
"")
261 return AxisInfo(
"t", Time, resolution, description);
264 static AxisInfo fx(
double resolution = 0.0, std::string
const & description =
"")
266 return AxisInfo(
"x", AxisType(Space | Frequency), resolution, description);
269 static AxisInfo fy(
double resolution = 0.0, std::string
const & description =
"")
271 return AxisInfo(
"y", AxisType(Space | Frequency), resolution, description);
274 static AxisInfo fz(
double resolution = 0.0, std::string
const & description =
"")
276 return AxisInfo(
"z", AxisType(Space | Frequency), resolution, description);
279 static AxisInfo ft(
double resolution = 0.0, std::string
const & description =
"")
281 return AxisInfo(
"t", AxisType(Time | Frequency), resolution, description);
284 static AxisInfo c(std::string
const & description =
"")
286 return AxisInfo(
"c", Channels, 0.0, description);
289 std::string key_, description_;
305 AxisTags(AxisInfo
const & i1)
310 AxisTags(AxisInfo
const & i1, AxisInfo
const & i2)
316 AxisTags(AxisInfo
const & i1, AxisInfo
const & i2, AxisInfo
const & i3)
323 AxisTags(AxisInfo
const & i1, AxisInfo
const & i2,
324 AxisInfo
const & i3, AxisInfo
const & i4)
332 AxisTags(AxisInfo
const & i1, AxisInfo
const & i2,
333 AxisInfo
const & i3, AxisInfo
const & i4, AxisInfo
const & i5)
344 std::string toJSON()
const
347 s <<
"{\n \"axes\": [";
348 for(
unsigned int k=0; k<size(); ++k)
354 s <<
" \"key\": \"" << axes_[k].key() <<
"\",\n";
355 s <<
" \"typeFlags\": " << (
unsigned int)axes_[k].typeFlags() <<
",\n";
356 s <<
" \"resolution\": " << std::setprecision(17) << axes_[k].resolution() <<
",\n";
357 s <<
" \"description\": \"" << axes_[k].description() <<
"\"\n";
364 unsigned int size()
const
369 int axisTypeCount(AxisInfo::AxisType type)
const
372 for(
unsigned int k=0; k<size(); ++k)
373 if(axes_[k].isType(type))
378 std::string repr()
const
382 res += axes_[0].key();
383 for(
unsigned int k=1; k<size(); ++k)
386 res += axes_[k].key();
391 AxisInfo &
get(
int k)
399 AxisInfo &
get(std::string
const & key)
401 return get(index(key));
404 AxisInfo
const &
get(
int k)
const
412 AxisInfo
const &
get(std::string
const & key)
const
414 return get(index(key));
417 void set(
int k, AxisInfo
const & info)
422 checkDuplicates(k, info);
426 void set(std::string
const & key, AxisInfo
const & info)
428 set(index(key), info);
431 void insert(
int k, AxisInfo
const & i)
442 checkDuplicates(size(), i);
443 axes_.insert(axes_.begin()+k, i);
447 void push_back(AxisInfo
const & i)
449 checkDuplicates(size(), i);
456 ArrayVector<AxisInfo>::iterator i = k < 0
462 void dropAxis(std::string
const & key)
464 dropAxis(index(key));
467 void dropChannelAxis()
469 int k = channelIndex();
471 axes_.erase(axes_.begin() + k, axes_.begin() + k + 1);
474 int index(std::string
const & key)
const
476 for(
unsigned int k=0; k<size(); ++k)
477 if(axes_[k].key() == key)
482 double resolution(
int k)
const
484 return get(k).resolution_;
487 double resolution(std::string
const & key)
const
489 return resolution(index(key));
492 void setResolution(
int k,
double r)
494 get(k).resolution_ = r;
497 void setResolution(std::string
const & key,
double r)
499 setResolution(index(key), r);
502 void scaleResolution(
int k,
double factor)
504 get(k).resolution_ *= factor;
507 void scaleResolution(std::string
const & key,
double factor)
509 get(key).resolution_ *= factor;
512 std::string description(
int k)
const
514 return get(k).description_;
517 std::string description(std::string
const & key)
const
519 return description(index(key));
522 void setDescription(
int k, std::string
const & d)
524 get(k).setDescription(d);
527 void setDescription(std::string
const & key, std::string
const & d)
529 setDescription(index(key), d);
532 void setChannelDescription(std::string
const & description)
534 int k = channelIndex();
536 axes_[k].setDescription(description);
539 void toFrequencyDomain(
int k,
int size = 0,
int sign = 1)
541 get(k) =
get(k).toFrequencyDomain(size,
sign);
544 void toFrequencyDomain(std::string
const & key,
int size = 0,
int sign = 1)
546 toFrequencyDomain(index(key), size,
sign);
549 void fromFrequencyDomain(
int k,
int size = 0)
551 toFrequencyDomain(k, size, -1);
554 void fromFrequencyDomain(std::string
const & key,
int size = 0)
556 toFrequencyDomain(key, size, -1);
559 bool hasChannelAxis()
const
561 return channelIndex() != (int)size();
565 int channelIndex()
const
567 for(
unsigned int k=0; k<size(); ++k)
568 if(axes_[k].isChannel())
573 int innerNonchannelIndex()
const
576 for(; k<(int)size(); ++k)
577 if(!axes_[k].isChannel())
579 for(
int i=k+1; i<(int)size(); ++i)
581 if(axes_[i].isChannel())
583 if(axes_[i] < axes_[k])
589 void swapaxes(
int i1,
int i2)
597 std::swap(axes_[i1], axes_[i2]);
601 void transpose(ArrayVector<T>
const & permutation)
603 if(permutation.size() == 0)
609 vigra_precondition(permutation.size() == size(),
610 "AxisTags::transpose(): Permutation has wrong size.");
611 ArrayVector<AxisInfo> newAxes(size());
612 applyPermutation(permutation.begin(), permutation.end(), axes_.begin(), newAxes.begin());
619 std::reverse(axes_.begin(), axes_.end());
624 permutationToNormalOrder(ArrayVector<T> & permutation)
const
626 permutation.resize(size());
627 indexSort(axes_.begin(), axes_.end(), permutation.begin());
632 permutationToNormalOrder(ArrayVector<T> & permutation, AxisInfo::AxisType types)
const
634 ArrayVector<AxisInfo> matchingAxes;
635 for(
int k=0; k<(int)size(); ++k)
636 if(axes_[k].isType(types))
637 matchingAxes.push_back(axes_[k]);
638 permutation.resize(matchingAxes.size());
639 indexSort(matchingAxes.begin(), matchingAxes.end(), permutation.begin());
644 permutationFromNormalOrder(ArrayVector<T> & inverse_permutation)
const
646 ArrayVector<T> permutation;
647 permutationToNormalOrder(permutation);
648 inverse_permutation.resize(permutation.size());
649 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
654 permutationFromNormalOrder(ArrayVector<T> & inverse_permutation, AxisInfo::AxisType types)
const
656 ArrayVector<T> permutation;
657 permutationToNormalOrder(permutation, types);
658 inverse_permutation.resize(permutation.size());
659 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
663 void permutationToNumpyOrder(ArrayVector<T> & permutation)
const
665 permutationToNormalOrder(permutation);
666 std::reverse(permutation.begin(), permutation.end());
670 void permutationFromNumpyOrder(ArrayVector<T> & inverse_permutation)
const
672 ArrayVector<T> permutation;
673 permutationToNumpyOrder(permutation);
674 inverse_permutation.resize(permutation.size());
675 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
679 void permutationToVigraOrder(ArrayVector<T> & permutation)
const
681 permutation.resize(size());
682 indexSort(axes_.begin(), axes_.end(), permutation.begin());
683 int channel = channelIndex();
684 if(channel < (
int)size())
686 for(
int k=1; k<(int)size(); ++k)
687 permutation[k-1] = permutation[k];
688 permutation.back() = channel;
693 void permutationFromVigraOrder(ArrayVector<T> & inverse_permutation)
const
695 ArrayVector<T> permutation;
696 permutationToVigraOrder(permutation);
697 inverse_permutation.resize(permutation.size());
698 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
702 void permutationToOrder(ArrayVector<T> & permutation, std::string
const & order)
const
706 permutation.resize(size());
709 else if(order ==
"C")
711 permutationToNumpyOrder(permutation);
713 else if(order ==
"F")
715 permutationToNormalOrder(permutation);
717 else if(order ==
"V")
719 permutationToVigraOrder(permutation);
723 vigra_precondition(
false,
724 "AxisTags::permutationToOrder(): unknown order '" + order +
"'.");
729 ArrayVector<UInt32> matchOrdering(AxisTags
const & other)
731 vigra_precondition(size() == other.size(),
732 "AxisTags::matchOrdering(): size mismatch.");
734 ArrayVector<UInt32> permutation(size());
735 for(
unsigned int k = 0; k<size(); ++k)
737 std::string key = other.get(k).key();
741 if(key ==
get(l).key())
744 vigra_precondition(l < size(),
745 "AxisTags::matchOrdering(): key mismatch.");
752 bool compatible(AxisTags
const & other)
const
754 if(size() == 0 || other.size() == 0)
756 if(size() != other.size())
758 for(
unsigned int k=0; k<size(); ++k)
759 if(!axes_[k].compatible(other.axes_[k]))
766 if(size() != other.size())
768 return std::equal(axes_.begin(), axes_.end(), other.axes_.begin());
778 void checkIndex(
int k)
const
780 vigra_precondition(k < (
int)size() && k >= -(
int)size(),
781 "AxisTags::checkIndex(): index out of range.");
784 void checkDuplicates(
int i, AxisInfo
const & info)
788 for(
int k=0; k<(int)size(); ++k)
790 vigra_precondition(k == i || !axes_[k].isChannel(),
791 "AxisTags::checkDuplicates(): can only have one channel axis.");
794 else if(!info.isUnknown())
796 for(
int k=0; k<(int)size(); ++k)
798 vigra_precondition(k == i || axes_[k].key() != info.key(),
799 std::string(
"AxisTags::checkDuplicates(): axis key '" +
800 info.key() +
"' already exists."));
805 ArrayVector<AxisInfo> axes_;