[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

vigra/axistags.hxx |

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*               Copyright 2010-2011 by Ullrich Koethe                  */
    00004 /*                                                                      */
    00005 /*    This file is part of the VIGRA computer vision library.           */
    00006 /*    The VIGRA Website is                                              */
    00007 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
    00008 /*    Please direct questions, bug reports, and contributions to        */
    00009 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
    00010 /*        vigra@informatik.uni-hamburg.de                               */
    00011 /*                                                                      */
    00012 /*    Permission is hereby granted, free of charge, to any person       */
    00013 /*    obtaining a copy of this software and associated documentation    */
    00014 /*    files (the "Software"), to deal in the Software without           */
    00015 /*    restriction, including without limitation the rights to use,      */
    00016 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
    00017 /*    sell copies of the Software, and to permit persons to whom the    */
    00018 /*    Software is furnished to do so, subject to the following          */
    00019 /*    conditions:                                                       */
    00020 /*                                                                      */
    00021 /*    The above copyright notice and this permission notice shall be    */
    00022 /*    included in all copies or substantial portions of the             */
    00023 /*    Software.                                                         */
    00024 /*                                                                      */
    00025 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
    00026 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
    00027 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
    00028 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
    00029 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
    00030 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
    00031 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
    00032 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
    00033 /*                                                                      */
    00034 /************************************************************************/
    00035
    00036 #ifndef VIGRA_AXISTAGS_HXX
    00037 #define VIGRA_AXISTAGS_HXX
    00038
    00039 #include "utilities.hxx"
    00040 #include "array_vector.hxx"
    00041 #include "algorithm.hxx"
    00042 #include "error.hxx"
    00043 #include "functorexpression.hxx"
    00044 #include <string>
    00045 #include <sstream>
    00046 #include <iomanip>
    00047
    00048 namespace vigra {
    00049
    00050 class AxisInfo
    00051 {
    00052   public:
    00053
    00054     // this particular assignment of bits to types is crucial for
    00055     // canonical axis ordering
    00056     enum AxisType { Channels = 1,
    00057                     Space = 2,
    00058                     Angle = 4,
    00059                     Time = 8,
    00060                     Frequency = 16,
    00061                     UnknownAxisType = 32,
    00062                     NonChannel = Space | Angle | Time | Frequency | UnknownAxisType,
    00063                     AllAxes = 2*UnknownAxisType-1 };
    00064
    00065     AxisInfo(std::string key = "?", AxisType typeFlags = UnknownAxisType,
    00066              double resolution = 0.0, std::string description = "")
    00067     : key_(key),
    00068       description_(description),
    00069       resolution_(resolution),
    00070       flags_(typeFlags)
    00071     {}
    00072
    00073     std::string key() const
    00074     {
    00075         return key_;
    00076     }
    00077
    00078     std::string description() const
    00079     {
    00080         return description_;
    00081     }
    00082
    00083     void setDescription(std::string const & description)
    00084     {
    00085         description_ = description;
    00086     }
    00087
    00088     double resolution() const
    00089     {
    00090         return resolution_;
    00091     }
    00092
    00093     void setResolution(double resolution)
    00094     {
    00095         resolution_ = resolution;
    00096     }
    00097
    00098     AxisType typeFlags() const
    00099     {
    00100         return flags_ == 0
    00101                   ? UnknownAxisType
    00102                   : flags_;
    00103     }
    00104
    00105     bool isUnknown() const
    00106     {
    00107         return isType(UnknownAxisType);
    00108     }
    00109
    00110     bool isSpatial() const
    00111     {
    00112         return isType(Space);
    00113     }
    00114
    00115     bool isTemporal() const
    00116     {
    00117         return isType(Time);
    00118     }
    00119
    00120     bool isChannel() const
    00121     {
    00122         return isType(Channels);
    00123     }
    00124
    00125     bool isFrequency() const
    00126     {
    00127         return isType(Frequency);
    00128     }
    00129
    00130     bool isAngular() const
    00131     {
    00132         return isType(Angle);
    00133     }
    00134
    00135     bool isType(AxisType type) const
    00136     {
    00137         return (typeFlags() & type) != 0;
    00138     }
    00139
    00140     std::string repr() const
    00141     {
    00142         std::string res("AxisInfo: '");
    00143         res += key_ + "' (type:";
    00144         if(isUnknown())
    00145         {
    00146             res += " none";
    00147         }
    00148         else
    00149         {
    00150             if(isChannel())
    00151                 res += " Channels";
    00152             if(isSpatial())
    00153                 res += " Space";
    00154             if(isTemporal())
    00155                 res += " Time";
    00156             if(isAngular())
    00157                 res += " Angle";
    00158             if(isFrequency())
    00159                 res += " Frequency";
    00160         }
    00161         if(resolution_ > 0.0)
    00162         {
    00163             res += ", resolution=";
    00164             res += asString(resolution_);
    00165         }
    00166         res += ")";
    00167         if(description_ != "")
    00168         {
    00169             res += " ";
    00170             res += description_;
    00171         }
    00172         return res;
    00173     }
    00174
    00175     AxisInfo toFrequencyDomain(unsigned int size = 0, int sign = 1) const
    00176     {
    00177         AxisType type;
    00178         if(sign == 1)
    00179         {
    00180             vigra_precondition(!isFrequency(),
    00181                 "AxisInfo::toFrequencyDomain(): axis is already in the Fourier domain.");
    00182             type = AxisType(Frequency | flags_);
    00183         }
    00184         else
    00185         {
    00186             vigra_precondition(isFrequency(),
    00187                 "AxisInfo::fromFrequencyDomain(): axis is not in the Fourier domain.");
    00188             type = AxisType(~Frequency & flags_);
    00189         }
    00190         AxisInfo res(key(), type, 0.0, description_);
    00191         if(resolution_ > 0.0 && size > 0u)
    00192             res.resolution_ = 1.0 / (resolution_ * size);
    00193         return res;
    00194     }
    00195
    00196     AxisInfo fromFrequencyDomain(unsigned int size = 0) const
    00197     {
    00198         return toFrequencyDomain(size, -1);
    00199     }
    00200
    00201     bool compatible(AxisInfo const & other) const
    00202     {
    00203         return isUnknown() || other.isUnknown() ||
    00204                ((typeFlags() & ~Frequency) == (other.typeFlags() & ~Frequency) &&
    00205                  key() == other.key());
    00206     }
    00207
    00208     bool operator==(AxisInfo const & other) const
    00209     {
    00210         return typeFlags() == other.typeFlags() && key() == other.key();
    00211     }
    00212
    00213     bool operator!=(AxisInfo const & other) const
    00214     {
    00215         return !operator==(other);
    00216     }
    00217
    00218     // the primary ordering is according to axis type:
    00219     //     Channels < Space < Angle < Time < Frequency < Unknown
    00220     // the secondary ordering is the lexicographic ordering of the keys
    00221     //     "x" < "y" < "z"
    00222     bool operator<(AxisInfo const & other) const
    00223     {
    00224         return (typeFlags() < other.typeFlags()) ||
    00225                 (typeFlags() == other.typeFlags() && key() < other.key());
    00226     }
    00227
    00228     bool operator<=(AxisInfo const & other) const
    00229     {
    00230         return !(other < *this);
    00231     }
    00232
    00233     bool operator>(AxisInfo const & other) const
    00234     {
    00235         return other < *this;
    00236     }
    00237
    00238     bool operator>=(AxisInfo const & other) const
    00239     {
    00240         return !(*this < other);
    00241     }
    00242
    00243     // factory functions for standard tags
    00244     static AxisInfo x(double resolution = 0.0, std::string const & description = "")
    00245     {
    00246         return AxisInfo("x", Space, resolution, description);
    00247     }
    00248
    00249     static AxisInfo y(double resolution = 0.0, std::string const & description = "")
    00250     {
    00251         return AxisInfo("y", Space, resolution, description);
    00252     }
    00253
    00254     static AxisInfo z(double resolution = 0.0, std::string const & description = "")
    00255     {
    00256         return AxisInfo("z", Space, resolution, description);
    00257     }
    00258
    00259     static AxisInfo t(double resolution = 0.0, std::string const & description = "")
    00260     {
    00261         return AxisInfo("t", Time, resolution, description);
    00262     }
    00263
    00264     static AxisInfo fx(double resolution = 0.0, std::string const & description = "")
    00265     {
    00266         return AxisInfo("x", AxisType(Space | Frequency), resolution, description);
    00267     }
    00268
    00269     static AxisInfo fy(double resolution = 0.0, std::string const & description = "")
    00270     {
    00271         return AxisInfo("y", AxisType(Space | Frequency), resolution, description);
    00272     }
    00273
    00274     static AxisInfo fz(double resolution = 0.0, std::string const & description = "")
    00275     {
    00276         return AxisInfo("z", AxisType(Space | Frequency), resolution, description);
    00277     }
    00278
    00279     static AxisInfo ft(double resolution = 0.0, std::string const & description = "")
    00280     {
    00281         return AxisInfo("t", AxisType(Time | Frequency), resolution, description);
    00282     }
    00283
    00284     static AxisInfo c(std::string const & description = "")
    00285     {
    00286         return AxisInfo("c", Channels, 0.0, description);
    00287     }
    00288
    00289     std::string key_, description_;
    00290     double resolution_;
    00291     AxisType flags_;
    00292 };
    00293
    00294 class AxisTags
    00295 {
    00296   public:
    00297
    00298     AxisTags()
    00299     {}
    00300
    00301     AxisTags(int size)
    00302     : axes_(size)
    00303     {}
    00304
    00305     AxisTags(AxisInfo const & i1)
    00306     {
    00307         push_back(i1);
    00308     }
    00309
    00310     AxisTags(AxisInfo const & i1, AxisInfo const & i2)
    00311     {
    00312         push_back(i1);
    00313         push_back(i2);
    00314     }
    00315
    00316     AxisTags(AxisInfo const & i1, AxisInfo const & i2, AxisInfo const & i3)
    00317     {
    00318         push_back(i1);
    00319         push_back(i2);
    00320         push_back(i3);
    00321     }
    00322
    00323     AxisTags(AxisInfo const & i1, AxisInfo const & i2,
    00324              AxisInfo const & i3, AxisInfo const & i4)
    00325     {
    00326         push_back(i1);
    00327         push_back(i2);
    00328         push_back(i3);
    00329         push_back(i4);
    00330     }
    00331
    00332     AxisTags(AxisInfo const & i1, AxisInfo const & i2,
    00333              AxisInfo const & i3, AxisInfo const & i4, AxisInfo const & i5)
    00334     {
    00335         push_back(i1);
    00336         push_back(i2);
    00337         push_back(i3);
    00338         push_back(i4);
    00339         push_back(i5);
    00340     }
    00341
    00342     // static AxisTags fromJSON(std::string const & repr);
    00343
    00344     std::string toJSON() const
    00345     {
    00346         std::stringstream s;
    00347         s << "{\n  \"axes\": [";
    00348         for(unsigned int k=0; k<size(); ++k)
    00349         {
    00350             if(k > 0)
    00351                 s << ",";
    00352             s << "\n";
    00353             s << "    {\n";
    00354             s << "      \"key\": \"" << axes_[k].key() << "\",\n";
    00355             s << "      \"typeFlags\": " << (unsigned int)axes_[k].typeFlags() << ",\n";
    00356             s << "      \"resolution\": " << std::setprecision(17) << axes_[k].resolution() << ",\n";
    00357             s << "      \"description\": \"" << axes_[k].description() << "\"\n";
    00358             s << "    }";
    00359         }
    00360         s << "\n  ]\n}";
    00361         return s.str();
    00362     }
    00363
    00364     unsigned int size() const
    00365     {
    00366         return axes_.size();
    00367     }
    00368
    00369     int axisTypeCount(AxisInfo::AxisType type) const
    00370     {
    00371         int res = 0;
    00372         for(unsigned int k=0; k<size(); ++k)
    00373             if(axes_[k].isType(type))
    00374                 ++res;
    00375         return res;
    00376     }
    00377
    00378     std::string repr() const
    00379     {
    00380         std::string res;
    00381         if(size() > 0)
    00382             res += axes_[0].key();
    00383         for(unsigned int k=1; k<size(); ++k)
    00384         {
    00385             res += " ";
    00386             res += axes_[k].key();
    00387         }
    00388         return res;
    00389     }
    00390
    00391     AxisInfo & get(int k)
    00392     {
    00393         checkIndex(k);
    00394         if(k < 0)
    00395             k += size();
    00396         return axes_[k];
    00397     }
    00398
    00399     AxisInfo & get(std::string const & key)
    00400     {
    00401         return get(index(key));
    00402     }
    00403
    00404     AxisInfo const & get(int k) const
    00405     {
    00406         checkIndex(k);
    00407         if(k < 0)
    00408             k += size();
    00409         return axes_[k];
    00410     }
    00411
    00412     AxisInfo const & get(std::string const & key) const
    00413     {
    00414         return get(index(key));
    00415     }
    00416
    00417     void set(int k, AxisInfo const & info)
    00418     {
    00419         checkIndex(k);
    00420         if(k < 0)
    00421             k += size();
    00422         checkDuplicates(k, info);
    00423         axes_[k] = info;
    00424     }
    00425
    00426     void set(std::string const & key, AxisInfo const & info)
    00427     {
    00428         set(index(key), info);
    00429     }
    00430
    00431     void insert(int k, AxisInfo const & i)
    00432     {
    00433         if(k == (int)size())
    00434         {
    00435             push_back(i);
    00436         }
    00437         else
    00438         {
    00439             checkIndex(k);
    00440             if(k < 0)
    00441                 k += size();
    00442             checkDuplicates(size(), i);
    00443             axes_.insert(axes_.begin()+k, i);
    00444         }
    00445     }
    00446
    00447     void push_back(AxisInfo const & i)
    00448     {
    00449         checkDuplicates(size(), i);
    00450         axes_.push_back(i);
    00451     }
    00452
    00453     void dropAxis(int k)
    00454     {
    00455         checkIndex(k);
    00456         ArrayVector<AxisInfo>::iterator i = k < 0
    00457                                                  ? axes_.end() + k
    00458                                                  : axes_.begin() + k;
    00459         axes_.erase(i, i+1);
    00460     }
    00461
    00462     void dropAxis(std::string const & key)
    00463     {
    00464         dropAxis(index(key));
    00465     }
    00466
    00467     void dropChannelAxis()
    00468     {
    00469         int k = channelIndex();
    00470         if(k < (int)size())
    00471             axes_.erase(axes_.begin() + k, axes_.begin() + k + 1);
    00472     }
    00473
    00474     int index(std::string const & key) const
    00475     {
    00476         for(unsigned int k=0; k<size(); ++k)
    00477             if(axes_[k].key() == key)
    00478                 return k;
    00479         return (int)size();
    00480     }
    00481
    00482     double resolution(int k) const
    00483     {
    00484         return get(k).resolution_;
    00485     }
    00486
    00487     double resolution(std::string const & key) const
    00488     {
    00489         return resolution(index(key));
    00490     }
    00491
    00492     void setResolution(int k, double r)
    00493     {
    00494         get(k).resolution_ = r;
    00495     }
    00496
    00497     void setResolution(std::string const & key, double r)
    00498     {
    00499         setResolution(index(key), r);
    00500     }
    00501
    00502     void scaleResolution(int k, double factor)
    00503     {
    00504         get(k).resolution_ *= factor;
    00505     }
    00506
    00507     void scaleResolution(std::string const & key, double factor)
    00508     {
    00509         get(key).resolution_ *= factor;
    00510     }
    00511
    00512     std::string description(int k) const
    00513     {
    00514         return get(k).description_;
    00515     }
    00516
    00517     std::string description(std::string const & key) const
    00518     {
    00519         return description(index(key));
    00520     }
    00521
    00522     void setDescription(int k, std::string const & d)
    00523     {
    00524         get(k).setDescription(d);
    00525     }
    00526
    00527     void setDescription(std::string const & key, std::string const & d)
    00528     {
    00529         setDescription(index(key), d);
    00530     }
    00531
    00532     void setChannelDescription(std::string const & description)
    00533     {
    00534         int k = channelIndex();
    00535         if(k < (int)size())
    00536             axes_[k].setDescription(description);
    00537     }
    00538
    00539     void toFrequencyDomain(int k, int size = 0, int sign = 1)
    00540     {
    00541         get(k) = get(k).toFrequencyDomain(size, sign);
    00542     }
    00543
    00544     void toFrequencyDomain(std::string const & key, int size = 0, int sign = 1)
    00545     {
    00546         toFrequencyDomain(index(key), size, sign);
    00547     }
    00548
    00549     void fromFrequencyDomain(int k, int size = 0)
    00550     {
    00551         toFrequencyDomain(k, size, -1);
    00552     }
    00553
    00554     void fromFrequencyDomain(std::string const & key, int size = 0)
    00555     {
    00556         toFrequencyDomain(key, size, -1);
    00557     }
    00558
    00559     bool hasChannelAxis() const
    00560     {
    00561         return channelIndex() != (int)size();
    00562     }
    00563
    00564     // FIXME: cache the results of these functions?
    00565     int channelIndex() const
    00566     {
    00567         for(unsigned int k=0; k<size(); ++k)
    00568             if(axes_[k].isChannel())
    00569                 return k;
    00570         return (int)size();
    00571     }
    00572
    00573     int innerNonchannelIndex() const
    00574     {
    00575         int k = 0;
    00576         for(; k<(int)size(); ++k)
    00577             if(!axes_[k].isChannel())
    00578                 break;
    00579         for(int i=k+1; i<(int)size(); ++i)
    00580         {
    00581             if(axes_[i].isChannel())
    00582                 continue;
    00583             if(axes_[i] < axes_[k])
    00584                 k = i;
    00585         }
    00586         return k;
    00587     }
    00588
    00589     void swapaxes(int i1, int i2)
    00590     {
    00591         checkIndex(i1);
    00592         checkIndex(i2);
    00593         if(i1 < 0)
    00594             i1 += size();
    00595         if(i2 < 0)
    00596             i2 += size();
    00597         std::swap(axes_[i1], axes_[i2]);
    00598     }
    00599
    00600     template <class T>
    00601     void transpose(ArrayVector<T> const & permutation)
    00602     {
    00603         if(permutation.size() == 0)
    00604         {
    00605             transpose();
    00606         }
    00607         else
    00608         {
    00609             vigra_precondition(permutation.size() == size(),
    00610                 "AxisTags::transpose(): Permutation has wrong size.");
    00611             ArrayVector<AxisInfo> newAxes(size());
    00612             applyPermutation(permutation.begin(), permutation.end(), axes_.begin(), newAxes.begin());
    00613             axes_.swap(newAxes);
    00614         }
    00615     }
    00616
    00617     void transpose()
    00618     {
    00619         std::reverse(axes_.begin(), axes_.end());
    00620     }
    00621
    00622     template <class T>
    00623     void
    00624     permutationToNormalOrder(ArrayVector<T> & permutation) const
    00625     {
    00626         permutation.resize(size());
    00627         indexSort(axes_.begin(), axes_.end(), permutation.begin());
    00628     }
    00629
    00630     template <class T>
    00631     void
    00632     permutationToNormalOrder(ArrayVector<T> & permutation, AxisInfo::AxisType types) const
    00633     {
    00634         ArrayVector<AxisInfo> matchingAxes;
    00635         for(int k=0; k<(int)size(); ++k)
    00636             if(axes_[k].isType(types))
    00637                 matchingAxes.push_back(axes_[k]);
    00638         permutation.resize(matchingAxes.size());
    00639         indexSort(matchingAxes.begin(), matchingAxes.end(), permutation.begin());
    00640     }
    00641
    00642     template <class T>
    00643     void
    00644     permutationFromNormalOrder(ArrayVector<T> & inverse_permutation) const
    00645     {
    00646         ArrayVector<T> permutation;
    00647         permutationToNormalOrder(permutation);
    00648         inverse_permutation.resize(permutation.size());
    00649         indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
    00650     }
    00651
    00652     template <class T>
    00653     void
    00654     permutationFromNormalOrder(ArrayVector<T> & inverse_permutation, AxisInfo::AxisType types) const
    00655     {
    00656         ArrayVector<T> permutation;
    00657         permutationToNormalOrder(permutation, types);
    00658         inverse_permutation.resize(permutation.size());
    00659         indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
    00660     }
    00661
    00662     template <class T>
    00663     void permutationToNumpyOrder(ArrayVector<T> & permutation) const
    00664     {
    00665         permutationToNormalOrder(permutation);
    00666         std::reverse(permutation.begin(), permutation.end());
    00667     }
    00668
    00669     template <class T>
    00670     void permutationFromNumpyOrder(ArrayVector<T> & inverse_permutation) const
    00671     {
    00672         ArrayVector<T> permutation;
    00673         permutationToNumpyOrder(permutation);
    00674         inverse_permutation.resize(permutation.size());
    00675         indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
    00676     }
    00677
    00678     template <class T>
    00679     void permutationToVigraOrder(ArrayVector<T> & permutation) const
    00680     {
    00681         permutation.resize(size());
    00682         indexSort(axes_.begin(), axes_.end(), permutation.begin());
    00683         int channel = channelIndex();
    00684         if(channel < (int)size())
    00685         {
    00686             for(int k=1; k<(int)size(); ++k)
    00687                 permutation[k-1] = permutation[k];
    00688             permutation.back() = channel;
    00689         }
    00690     }
    00691
    00692     template <class T>
    00693     void permutationFromVigraOrder(ArrayVector<T> & inverse_permutation) const
    00694     {
    00695         ArrayVector<T> permutation;
    00696         permutationToVigraOrder(permutation);
    00697         inverse_permutation.resize(permutation.size());
    00698         indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
    00699     }
    00700
    00701     template <class T>
    00702     void permutationToOrder(ArrayVector<T> & permutation, std::string const & order) const
    00703     {
    00704         if(order == "A")
    00705         {
    00706             permutation.resize(size());
    00707             linearSequence(permutation.begin(), permutation.end());
    00708         }
    00709         else if(order == "C")
    00710         {
    00711             permutationToNumpyOrder(permutation);
    00712         }
    00713         else if(order == "F")
    00714         {
    00715             permutationToNormalOrder(permutation);
    00716         }
    00717         else if(order == "V")
    00718         {
    00719             permutationToVigraOrder(permutation);
    00720         }
    00721         else
    00722         {
    00723             vigra_precondition(false,
    00724                 "AxisTags::permutationToOrder(): unknown order '" + order + "'.");
    00725         }
    00726     }
    00727
    00728 #if 0
    00729     ArrayVector<UInt32> matchOrdering(AxisTags const & other)
    00730     {
    00731         vigra_precondition(size() == other.size(),
    00732             "AxisTags::matchOrdering(): size mismatch.");
    00733
    00734         ArrayVector<UInt32> permutation(size());
    00735         for(unsigned int k = 0; k<size(); ++k)
    00736         {
    00737             std::string key = other.get(k).key();
    00738             unsigned int l=0;
    00739             for(; l<size(); ++l)
    00740             {
    00741                 if(key == get(l).key())
    00742                     break;
    00743             }
    00744             vigra_precondition(l < size(),
    00745                 "AxisTags::matchOrdering(): key mismatch.");
    00746             permutation[k] = l;
    00747         }
    00748         return permutation;
    00749     }
    00750 #endif
    00751
    00752     bool compatible(AxisTags const & other) const
    00753     {
    00754         if(size() == 0 || other.size() == 0)
    00755             return true;
    00756         if(size() != other.size())
    00757             return false;
    00758         for(unsigned int k=0; k<size(); ++k)
    00759             if(!axes_[k].compatible(other.axes_[k]))
    00760                 return false;
    00761         return true;
    00762     }
    00763
    00764     bool operator==(AxisTags const & other) const
    00765     {
    00766         if(size() != other.size())
    00767             return false;
    00768         return std::equal(axes_.begin(), axes_.end(), other.axes_.begin());
    00769     }
    00770
    00771     bool operator!=(AxisTags const & other) const
    00772     {
    00773         return !operator==(other);
    00774     }
    00775
    00776   protected:
    00777
    00778     void checkIndex(int k) const
    00779     {
    00780         vigra_precondition(k < (int)size() && k >= -(int)size(),
    00781             "AxisTags::checkIndex(): index out of range.");
    00782     }
    00783
    00784     void checkDuplicates(int i, AxisInfo const & info)
    00785     {
    00786         if(info.isChannel())
    00787         {
    00788             for(int k=0; k<(int)size(); ++k)
    00789             {
    00790                 vigra_precondition(k == i || !axes_[k].isChannel(),
    00791                      "AxisTags::checkDuplicates(): can only have one channel axis.");
    00792             }
    00793         }
    00794         else if(!info.isUnknown())
    00795         {
    00796             for(int k=0; k<(int)size(); ++k)
    00797             {
    00798                 vigra_precondition(k == i || axes_[k].key() != info.key(),
    00799                      std::string("AxisTags::checkDuplicates(): axis key '" +
    00800                                   info.key() + "' already exists."));
    00801             }
    00802         }
    00803     }
    00804
    00805     ArrayVector<AxisInfo> axes_;
    00806 };
    00807
    00808 // #if 0
    00809 // struct PyGetFunctor
    00810 // {
    00811     // AxisInfo const & operator()(python::object const & o) const
    00812     // {
    00813         // return python::extract<AxisInfo const &>(o)();
    00814     // }
    00815 // };
    00816
    00817 // class PyAxisTags
    00818 // : public AxisTags<python::object, PyGetFunctor>
    00819 // {
    00820     // typedef AxisTags<python::object, PyGetFunctor> BaseType;
    00821   // public:
    00822     // PyAxisTags()
    00823     // {}
    00824
    00825     // PyAxisTags(python::object i1, python::object i2,
    00826              // python::object i3, python::object i4, python::object i5)
    00827     // {
    00828         // if(PySequence_Check(i1.ptr()))
    00829         // {
    00830             // int size = len(i1);
    00831             // for(int k=0; k<size; ++k)
    00832                 // if(python::extract<AxisInfo const &>(i1[k]).check())
    00833                     // push_back(i1[k]);
    00834         // }
    00835         // else if(PyInt_Check(i1.ptr()))
    00836         // {
    00837             // int size = python::extract<int>(i1)();
    00838             // for(int k=0; k<size; ++k)
    00839                 // push_back(python::object(AxisInfo()));
    00840         // }
    00841         // else
    00842         // {
    00843             // if(python::extract<AxisInfo const &>(i1).check())
    00844                 // push_back(i1);
    00845             // if(python::extract<AxisInfo const &>(i2).check())
    00846                 // push_back(i2);
    00847             // if(python::extract<AxisInfo const &>(i3).check())
    00848                 // push_back(i3);
    00849             // if(python::extract<AxisInfo const &>(i4).check())
    00850                 // push_back(i4);
    00851             // if(python::extract<AxisInfo const &>(i5).check())
    00852                 // push_back(i5);
    00853         // }
    00854     // }
    00855
    00856     // python::object getitem(int k)
    00857     // {
    00858         // if(!checkIndex(k))
    00859         // {
    00860             // PyErr_SetString(PyExc_IndexError, "AxisInfo::getitem(): Invalid index or key.");
    00861             // python::throw_error_already_set();
    00862         // }
    00863         // if(k < 0)
    00864             // k += this->size();
    00865         // return this->axes_[k];
    00866     // }
    00867
    00868     // python::object getitem(std::string const & key)
    00869     // {
    00870         // return getitem(this->findKey(key));
    00871     // }
    00872
    00873     // void setitem(int k, python::object i)
    00874     // {
    00875         // if(!this->checkIndex(k))
    00876         // {
    00877             // PyErr_SetString(PyExc_IndexError, "AxisInfo::setitem(): Invalid index or key.");
    00878             // python::throw_error_already_set();
    00879         // }
    00880         // if(!python::extract<AxisInfo const &>(i).check())
    00881         // {
    00882             // PyErr_SetString(PyExc_TypeError, "AxisInfo::setitem(): Item type must be AxisInfo.");
    00883             // python::throw_error_already_set();
    00884         // }
    00885
    00886         // if(k < 0)
    00887             // k += this->size();
    00888         // this->axes_[k] = i;
    00889     // }
    00890
    00891     // void setitem(std::string const & key, python::object i)
    00892     // {
    00893         // setitem(this->findKey(key), i);
    00894     // }
    00895
    00896     // void append(python::object i)
    00897     // {
    00898         // insert(size(), i);
    00899     // }
    00900
    00901     // void insert(int k, python::object i)
    00902     // {
    00903         // if(k < 0)
    00904             // k += this->size();
    00905         // if(k < 0)
    00906             // k = 0;
    00907         // if(k > (int)this->size())
    00908             // k = this->size();
    00909         // if(!python::extract<AxisInfo const &>(i).check())
    00910         // {
    00911             // PyErr_SetString(PyExc_TypeError, "AxisInfo::insert(): Item type must be AxisInfo.");
    00912             // python::throw_error_already_set();
    00913         // }
    00914         // this->axes_.insert(this->axes_.begin()+k, i);
    00915     // }
    00916
    00917     // void insert(std::string const & key, python::object i)
    00918     // {
    00919         // insert(this->findKey(key), i);
    00920     // }
    00921
    00922     // python::list axesByFlag(AxisType typeFlags) const
    00923     // {
    00924         // python::list res;
    00925         // for(unsigned int k=0; k<this->size(); ++k)
    00926             // if(this->get(k).typeFlags() == typeFlags)
    00927                 // res.append(k);
    00928         // return res;
    00929     // }
    00930
    00931     // python::list spatialAxes() const
    00932     // {
    00933         // python::list res;
    00934         // for(unsigned int k=0; k<this->size(); ++k)
    00935             // if(this->get(k).isSpatial())
    00936                 // res.append(k);
    00937         // return res;
    00938     // }
    00939
    00940     // python::list temporalAxes() const
    00941     // {
    00942         // python::list res;
    00943         // for(unsigned int k=0; k<this->size(); ++k)
    00944             // if(this->get(k).isTemporal())
    00945                 // res.append(k);
    00946         // return res;
    00947     // }
    00948
    00949     // python::list channelAxes() const
    00950     // {
    00951         // python::list res;
    00952         // for(unsigned int k=0; k<this->size(); ++k)
    00953             // if(this->get(k).isChannel())
    00954                 // res.append(k);
    00955         // return res;
    00956     // }
    00957
    00958     // python::list frequencyAxes() const
    00959     // {
    00960         // python::list res;
    00961         // for(unsigned int k=0; k<this->size(); ++k)
    00962             // if(this->get(k).isFrequency())
    00963                 // res.append(k);
    00964         // return res;
    00965     // }
    00966
    00967     // python::list angularAxes() const
    00968     // {
    00969         // python::list res;
    00970         // for(unsigned int k=0; k<this->size(); ++k)
    00971             // if(this->get(k).isAngular())
    00972                 // res.append(k);
    00973         // return res;
    00974     // }
    00975
    00976     // python::list untaggedAxes() const
    00977     // {
    00978         // python::list res;
    00979         // for(unsigned int k=0; k<this->size(); ++k)
    00980             // if(this->get(k).isUnknown())
    00981                 // res.append(k);
    00982         // return res;
    00983     // }
    00984
    00985     // template <class U>
    00986     // python::list vectorToPython(ArrayVector<U> const & v) const
    00987     // {
    00988         // python::list res;
    00989         // for(unsigned int k=0; k<v.size(); ++k)
    00990             // res.append(v[k]);
    00991         // return res;
    00992     // }
    00993
    00994     // python::list canonicalOrdering()
    00995     // {
    00996         // return vectorToPython(BaseType::canonicalOrdering());
    00997     // }
    00998
    00999     // python::list matchOrdering(PyAxisTags const & other)
    01000     // {
    01001         // return vectorToPython(BaseType::matchOrdering(other));
    01002     // }
    01003
    01004     // void transpose(python::object const & o)
    01005     // {
    01006         // unsigned int osize = len(o);
    01007         // ArrayVector<UInt32> permutation(osize);
    01008
    01009         // for(unsigned int k=0; k<this->size(); ++k)
    01010             // permutation[k] = python::extract<UInt32>(o[k])();
    01011
    01012         // BaseType::transpose(permutation);
    01013     // }
    01014
    01015     // void transpose()
    01016     // {
    01017         // BaseType::transpose();
    01018     // }
    01019 // };
    01020
    01021 // class TaggedShape
    01022 // {
    01023   // public:
    01024
    01025     // ArrayVector<npy_intp> shape;
    01026     // python_ptr axistags;
    01027     // npy_intp channelCount;
    01028     // std::string channelDescription;
    01029
    01030     // TaggedShape(MultiArrayIndex size)
    01031     // : shape(size)
    01032     // {}
    01033
    01034     // template <int N>
    01035     // TaggedShape(typename MultiArrayShape<N>::type const & sh)
    01036     // : shape(sh.begin(), sh.end())
    01037     // {}
    01038
    01039     // npy_intp & operator[](int i)
    01040     // {
    01041         // // rotate indices so that channels are located at index 0
    01042         // return shape[(i+1) % shape.size()];
    01043     // }
    01044
    01045     // npy_intp operator[](int i) const
    01046     // {
    01047         // return shape[(i+1) % shape.size()];
    01048     // }
    01049
    01050     // unsigned int size() const
    01051     // {
    01052         // return shape.size();
    01053     // }
    01054
    01055     // // void setChannelDescription(std::string const & description)
    01056     // // {
    01057         // // if(axistags)
    01058         // // {
    01059             // // python_ptr func(PyString_FromString("setChannelDescription"),
    01060                                          // // python_ptr::keep_count);
    01061             // // pythonToCppException(res);
    01062
    01063             // // python_ptr d(PyString_FromString(d.c_str()), python_ptr::keep_count);
    01064             // // pythonToCppException(d);
    01065
    01066             // // python_ptr res(PyObject_CallMethodObjArgs(axistags, func, d.get(), NULL),
    01067                            // // python_ptr::keep_count);
    01068             // // pythonToCppException(res);
    01069         // // }
    01070     // // }
    01071
    01072     // // void setChannelCount(int channelCount)
    01073     // // {
    01074         // // shape[0] = channelCount;
    01075     // // }
    01076
    01077     // void setChannelDescription(std::string const & description)
    01078     // {
    01079         // channelDescription = description;
    01080     // }
    01081
    01082     // void setChannelCount(int count)
    01083     // {
    01084         // channelCount = count;
    01085     // }
    01086
    01087     // void setChannelConfig(int channelCount, std::string const & description)
    01088     // {
    01089         // setChannelCount(channelCount);
    01090         // setChannelDescription(description);
    01091     // }
    01092 // };
    01093 // #endif
    01094
    01095 } // namespace vigra
    01096
    01097 #endif /* VIGRA_AXISTAGS_HXX */

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.9.0 (Tue Nov 6 2012)