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

vigra/axistags.hxx VIGRA

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)