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