[ 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) |
html generated using doxygen and Python
|