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

axistags.hxx |

1 /************************************************************************/
2 /* */
3 /* Copyright 2010-2011 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35
36 #ifndef VIGRA_AXISTAGS_HXX
37 #define VIGRA_AXISTAGS_HXX
38
39 #include "utilities.hxx"
40 #include "array_vector.hxx"
41 #include "algorithm.hxx"
42 #include "error.hxx"
43 #include "functorexpression.hxx"
44 #include <string>
45 #include <sstream>
46 #include <iomanip>
47
48 namespace vigra {
49
50 class AxisInfo
51 {
52 public:
53
54 // this particular assignment of bits to types is crucial for
55 // canonical axis ordering
56 enum AxisType { Channels = 1,
57 Space = 2,
58 Angle = 4,
59 Time = 8,
60 Frequency = 16,
61 UnknownAxisType = 32,
62 NonChannel = Space | Angle | Time | Frequency | UnknownAxisType,
63 AllAxes = 2*UnknownAxisType-1 };
64
65 AxisInfo(std::string key = "?", AxisType typeFlags = UnknownAxisType,
66 double resolution = 0.0, std::string description = "")
67 : key_(key),
68 description_(description),
69 resolution_(resolution),
70 flags_(typeFlags)
71 {}
72
73 std::string key() const
74 {
75 return key_;
76 }
77
78 std::string description() const
79 {
80 return description_;
81 }
82
83 void setDescription(std::string const & description)
84 {
85 description_ = description;
86 }
87
88 double resolution() const
89 {
90 return resolution_;
91 }
92
93 void setResolution(double resolution)
94 {
95 resolution_ = resolution;
96 }
97
98 AxisType typeFlags() const
99 {
100 return flags_ == 0
101 ? UnknownAxisType
102 : flags_;
103 }
104
105 bool isUnknown() const
106 {
107 return isType(UnknownAxisType);
108 }
109
110 bool isSpatial() const
111 {
112 return isType(Space);
113 }
114
115 bool isTemporal() const
116 {
117 return isType(Time);
118 }
119
120 bool isChannel() const
121 {
122 return isType(Channels);
123 }
124
125 bool isFrequency() const
126 {
127 return isType(Frequency);
128 }
129
130 bool isAngular() const
131 {
132 return isType(Angle);
133 }
134
135 bool isType(AxisType type) const
136 {
137 return (typeFlags() & type) != 0;
138 }
139
140 std::string repr() const
141 {
142 std::string res("AxisInfo: '");
143 res += key_ + "' (type:";
144 if(isUnknown())
145 {
146 res += " none";
147 }
148 else
149 {
150 if(isChannel())
151 res += " Channels";
152 if(isSpatial())
153 res += " Space";
154 if(isTemporal())
155 res += " Time";
156 if(isAngular())
157 res += " Angle";
158 if(isFrequency())
159 res += " Frequency";
160 }
161 if(resolution_ > 0.0)
162 {
163 res += ", resolution=";
164 res += asString(resolution_);
165 }
166 res += ")";
167 if(description_ != "")
168 {
169 res += " ";
170 res += description_;
171 }
172 return res;
173 }
174
175 AxisInfo toFrequencyDomain(unsigned int size = 0, int sign = 1) const
176 {
177 AxisType type;
178 if(sign == 1)
179 {
180 vigra_precondition(!isFrequency(),
181 "AxisInfo::toFrequencyDomain(): axis is already in the Fourier domain.");
182 type = AxisType(Frequency | flags_);
183 }
184 else
185 {
186 vigra_precondition(isFrequency(),
187 "AxisInfo::fromFrequencyDomain(): axis is not in the Fourier domain.");
188 type = AxisType(~Frequency & flags_);
189 }
190 AxisInfo res(key(), type, 0.0, description_);
191 if(resolution_ > 0.0 && size > 0u)
192 res.resolution_ = 1.0 / (resolution_ * size);
193 return res;
194 }
195
196 AxisInfo fromFrequencyDomain(unsigned int size = 0) const
197 {
198 return toFrequencyDomain(size, -1);
199 }
200
201 bool compatible(AxisInfo const & other) const
202 {
203 return isUnknown() || other.isUnknown() ||
204 ((typeFlags() & ~Frequency) == (other.typeFlags() & ~Frequency) &&
205 key() == other.key());
206 }
207
208 bool operator==(AxisInfo const & other) const
209 {
210 return typeFlags() == other.typeFlags() && key() == other.key();
211 }
212
213 bool operator!=(AxisInfo const & other) const
214 {
215 return !operator==(other);
216 }
217
218 // the primary ordering is according to axis type:
219 // Channels < Space < Angle < Time < Frequency < Unknown
220 // the secondary ordering is the lexicographic ordering of the keys
221 // "x" < "y" < "z"
222 bool operator<(AxisInfo const & other) const
223 {
224 return (typeFlags() < other.typeFlags()) ||
225 (typeFlags() == other.typeFlags() && key() < other.key());
226 }
227
228 bool operator<=(AxisInfo const & other) const
229 {
230 return !(other < *this);
231 }
232
233 bool operator>(AxisInfo const & other) const
234 {
235 return other < *this;
236 }
237
238 bool operator>=(AxisInfo const & other) const
239 {
240 return !(*this < other);
241 }
242
243 // factory functions for standard tags
244 static AxisInfo x(double resolution = 0.0, std::string const & description = "")
245 {
246 return AxisInfo("x", Space, resolution, description);
247 }
248
249 static AxisInfo y(double resolution = 0.0, std::string const & description = "")
250 {
251 return AxisInfo("y", Space, resolution, description);
252 }
253
254 static AxisInfo z(double resolution = 0.0, std::string const & description = "")
255 {
256 return AxisInfo("z", Space, resolution, description);
257 }
258
259 static AxisInfo t(double resolution = 0.0, std::string const & description = "")
260 {
261 return AxisInfo("t", Time, resolution, description);
262 }
263
264 static AxisInfo fx(double resolution = 0.0, std::string const & description = "")
265 {
266 return AxisInfo("x", AxisType(Space | Frequency), resolution, description);
267 }
268
269 static AxisInfo fy(double resolution = 0.0, std::string const & description = "")
270 {
271 return AxisInfo("y", AxisType(Space | Frequency), resolution, description);
272 }
273
274 static AxisInfo fz(double resolution = 0.0, std::string const & description = "")
275 {
276 return AxisInfo("z", AxisType(Space | Frequency), resolution, description);
277 }
278
279 static AxisInfo ft(double resolution = 0.0, std::string const & description = "")
280 {
281 return AxisInfo("t", AxisType(Time | Frequency), resolution, description);
282 }
283
284 static AxisInfo c(std::string const & description = "")
285 {
286 return AxisInfo("c", Channels, 0.0, description);
287 }
288
289 std::string key_, description_;
290 double resolution_;
291 AxisType flags_;
292 };
293
294 class AxisTags
295 {
296 public:
297
298 AxisTags()
299 {}
300
301 AxisTags(int size)
302 : axes_(size)
303 {}
304
305 AxisTags(AxisInfo const & i1)
306 {
307 push_back(i1);
308 }
309
310 AxisTags(AxisInfo const & i1, AxisInfo const & i2)
311 {
312 push_back(i1);
313 push_back(i2);
314 }
315
316 AxisTags(AxisInfo const & i1, AxisInfo const & i2, AxisInfo const & i3)
317 {
318 push_back(i1);
319 push_back(i2);
320 push_back(i3);
321 }
322
323 AxisTags(AxisInfo const & i1, AxisInfo const & i2,
324 AxisInfo const & i3, AxisInfo const & i4)
325 {
326 push_back(i1);
327 push_back(i2);
328 push_back(i3);
329 push_back(i4);
330 }
331
332 AxisTags(AxisInfo const & i1, AxisInfo const & i2,
333 AxisInfo const & i3, AxisInfo const & i4, AxisInfo const & i5)
334 {
335 push_back(i1);
336 push_back(i2);
337 push_back(i3);
338 push_back(i4);
339 push_back(i5);
340 }
341
342 // static AxisTags fromJSON(std::string const & repr);
343
344 std::string toJSON() const
345 {
346 std::stringstream s;
347 s << "{\n \"axes\": [";
348 for(unsigned int k=0; k<size(); ++k)
349 {
350 if(k > 0)
351 s << ",";
352 s << "\n";
353 s << " {\n";
354 s << " \"key\": \"" << axes_[k].key() << "\",\n";
355 s << " \"typeFlags\": " << (unsigned int)axes_[k].typeFlags() << ",\n";
356 s << " \"resolution\": " << std::setprecision(17) << axes_[k].resolution() << ",\n";
357 s << " \"description\": \"" << axes_[k].description() << "\"\n";
358 s << " }";
359 }
360 s << "\n ]\n}";
361 return s.str();
362 }
363
364 unsigned int size() const
365 {
366 return axes_.size();
367 }
368
369 int axisTypeCount(AxisInfo::AxisType type) const
370 {
371 int res = 0;
372 for(unsigned int k=0; k<size(); ++k)
373 if(axes_[k].isType(type))
374 ++res;
375 return res;
376 }
377
378 std::string repr() const
379 {
380 std::string res;
381 if(size() > 0)
382 res += axes_[0].key();
383 for(unsigned int k=1; k<size(); ++k)
384 {
385 res += " ";
386 res += axes_[k].key();
387 }
388 return res;
389 }
390
391 AxisInfo & get(int k)
392 {
393 checkIndex(k);
394 if(k < 0)
395 k += size();
396 return axes_[k];
397 }
398
399 AxisInfo & get(std::string const & key)
400 {
401 return get(index(key));
402 }
403
404 AxisInfo const & get(int k) const
405 {
406 checkIndex(k);
407 if(k < 0)
408 k += size();
409 return axes_[k];
410 }
411
412 AxisInfo const & get(std::string const & key) const
413 {
414 return get(index(key));
415 }
416
417 void set(int k, AxisInfo const & info)
418 {
419 checkIndex(k);
420 if(k < 0)
421 k += size();
422 checkDuplicates(k, info);
423 axes_[k] = info;
424 }
425
426 void set(std::string const & key, AxisInfo const & info)
427 {
428 set(index(key), info);
429 }
430
431 void insert(int k, AxisInfo const & i)
432 {
433 if(k == (int)size())
434 {
435 push_back(i);
436 }
437 else
438 {
439 checkIndex(k);
440 if(k < 0)
441 k += size();
442 checkDuplicates(size(), i);
443 axes_.insert(axes_.begin()+k, i);
444 }
445 }
446
447 void push_back(AxisInfo const & i)
448 {
449 checkDuplicates(size(), i);
450 axes_.push_back(i);
451 }
452
453 void dropAxis(int k)
454 {
455 checkIndex(k);
456 ArrayVector<AxisInfo>::iterator i = k < 0
457 ? axes_.end() + k
458 : axes_.begin() + k;
459 axes_.erase(i, i+1);
460 }
461
462 void dropAxis(std::string const & key)
463 {
464 dropAxis(index(key));
465 }
466
467 void dropChannelAxis()
468 {
469 int k = channelIndex();
470 if(k < (int)size())
471 axes_.erase(axes_.begin() + k, axes_.begin() + k + 1);
472 }
473
474 int index(std::string const & key) const
475 {
476 for(unsigned int k=0; k<size(); ++k)
477 if(axes_[k].key() == key)
478 return k;
479 return (int)size();
480 }
481
482 double resolution(int k) const
483 {
484 return get(k).resolution_;
485 }
486
487 double resolution(std::string const & key) const
488 {
489 return resolution(index(key));
490 }
491
492 void setResolution(int k, double r)
493 {
494 get(k).resolution_ = r;
495 }
496
497 void setResolution(std::string const & key, double r)
498 {
499 setResolution(index(key), r);
500 }
501
502 void scaleResolution(int k, double factor)
503 {
504 get(k).resolution_ *= factor;
505 }
506
507 void scaleResolution(std::string const & key, double factor)
508 {
509 get(key).resolution_ *= factor;
510 }
511
512 std::string description(int k) const
513 {
514 return get(k).description_;
515 }
516
517 std::string description(std::string const & key) const
518 {
519 return description(index(key));
520 }
521
522 void setDescription(int k, std::string const & d)
523 {
524 get(k).setDescription(d);
525 }
526
527 void setDescription(std::string const & key, std::string const & d)
528 {
529 setDescription(index(key), d);
530 }
531
532 void setChannelDescription(std::string const & description)
533 {
534 int k = channelIndex();
535 if(k < (int)size())
536 axes_[k].setDescription(description);
537 }
538
539 void toFrequencyDomain(int k, int size = 0, int sign = 1)
540 {
541 get(k) = get(k).toFrequencyDomain(size, sign);
542 }
543
544 void toFrequencyDomain(std::string const & key, int size = 0, int sign = 1)
545 {
546 toFrequencyDomain(index(key), size, sign);
547 }
548
549 void fromFrequencyDomain(int k, int size = 0)
550 {
551 toFrequencyDomain(k, size, -1);
552 }
553
554 void fromFrequencyDomain(std::string const & key, int size = 0)
555 {
556 toFrequencyDomain(key, size, -1);
557 }
558
559 bool hasChannelAxis() const
560 {
561 return channelIndex() != (int)size();
562 }
563
564 // FIXME: cache the results of these functions?
565 int channelIndex() const
566 {
567 for(unsigned int k=0; k<size(); ++k)
568 if(axes_[k].isChannel())
569 return k;
570 return (int)size();
571 }
572
573 int innerNonchannelIndex() const
574 {
575 int k = 0;
576 for(; k<(int)size(); ++k)
577 if(!axes_[k].isChannel())
578 break;
579 for(int i=k+1; i<(int)size(); ++i)
580 {
581 if(axes_[i].isChannel())
582 continue;
583 if(axes_[i] < axes_[k])
584 k = i;
585 }
586 return k;
587 }
588
589 void swapaxes(int i1, int i2)
590 {
591 checkIndex(i1);
592 checkIndex(i2);
593 if(i1 < 0)
594 i1 += size();
595 if(i2 < 0)
596 i2 += size();
597 std::swap(axes_[i1], axes_[i2]);
598 }
599
600 template <class T>
601 void transpose(ArrayVector<T> const & permutation)
602 {
603 if(permutation.size() == 0)
604 {
605 transpose();
606 }
607 else
608 {
609 vigra_precondition(permutation.size() == size(),
610 "AxisTags::transpose(): Permutation has wrong size.");
611 ArrayVector<AxisInfo> newAxes(size());
612 applyPermutation(permutation.begin(), permutation.end(), axes_.begin(), newAxes.begin());
613 axes_.swap(newAxes);
614 }
615 }
616
617 void transpose()
618 {
619 std::reverse(axes_.begin(), axes_.end());
620 }
621
622 template <class T>
623 void
624 permutationToNormalOrder(ArrayVector<T> & permutation) const
625 {
626 permutation.resize(size());
627 indexSort(axes_.begin(), axes_.end(), permutation.begin());
628 }
629
630 template <class T>
631 void
632 permutationToNormalOrder(ArrayVector<T> & permutation, AxisInfo::AxisType types) const
633 {
634 ArrayVector<AxisInfo> matchingAxes;
635 for(int k=0; k<(int)size(); ++k)
636 if(axes_[k].isType(types))
637 matchingAxes.push_back(axes_[k]);
638 permutation.resize(matchingAxes.size());
639 indexSort(matchingAxes.begin(), matchingAxes.end(), permutation.begin());
640 }
641
642 template <class T>
643 void
644 permutationFromNormalOrder(ArrayVector<T> & inverse_permutation) const
645 {
646 ArrayVector<T> permutation;
647 permutationToNormalOrder(permutation);
648 inverse_permutation.resize(permutation.size());
649 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
650 }
651
652 template <class T>
653 void
654 permutationFromNormalOrder(ArrayVector<T> & inverse_permutation, AxisInfo::AxisType types) const
655 {
656 ArrayVector<T> permutation;
657 permutationToNormalOrder(permutation, types);
658 inverse_permutation.resize(permutation.size());
659 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
660 }
661
662 template <class T>
663 void permutationToNumpyOrder(ArrayVector<T> & permutation) const
664 {
665 permutationToNormalOrder(permutation);
666 std::reverse(permutation.begin(), permutation.end());
667 }
668
669 template <class T>
670 void permutationFromNumpyOrder(ArrayVector<T> & inverse_permutation) const
671 {
672 ArrayVector<T> permutation;
673 permutationToNumpyOrder(permutation);
674 inverse_permutation.resize(permutation.size());
675 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
676 }
677
678 template <class T>
679 void permutationToVigraOrder(ArrayVector<T> & permutation) const
680 {
681 permutation.resize(size());
682 indexSort(axes_.begin(), axes_.end(), permutation.begin());
683 int channel = channelIndex();
684 if(channel < (int)size())
685 {
686 for(int k=1; k<(int)size(); ++k)
687 permutation[k-1] = permutation[k];
688 permutation.back() = channel;
689 }
690 }
691
692 template <class T>
693 void permutationFromVigraOrder(ArrayVector<T> & inverse_permutation) const
694 {
695 ArrayVector<T> permutation;
696 permutationToVigraOrder(permutation);
697 inverse_permutation.resize(permutation.size());
698 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
699 }
700
701 template <class T>
702 void permutationToOrder(ArrayVector<T> & permutation, std::string const & order) const
703 {
704 if(order == "A")
705 {
706 permutation.resize(size());
707 linearSequence(permutation.begin(), permutation.end());
708 }
709 else if(order == "C")
710 {
711 permutationToNumpyOrder(permutation);
712 }
713 else if(order == "F")
714 {
715 permutationToNormalOrder(permutation);
716 }
717 else if(order == "V")
718 {
719 permutationToVigraOrder(permutation);
720 }
721 else
722 {
723 vigra_precondition(false,
724 "AxisTags::permutationToOrder(): unknown order '" + order + "'.");
725 }
726 }
727
728 #if 0
729 ArrayVector<UInt32> matchOrdering(AxisTags const & other)
730 {
731 vigra_precondition(size() == other.size(),
732 "AxisTags::matchOrdering(): size mismatch.");
733
734 ArrayVector<UInt32> permutation(size());
735 for(unsigned int k = 0; k<size(); ++k)
736 {
737 std::string key = other.get(k).key();
738 unsigned int l=0;
739 for(; l<size(); ++l)
740 {
741 if(key == get(l).key())
742 break;
743 }
744 vigra_precondition(l < size(),
745 "AxisTags::matchOrdering(): key mismatch.");
746 permutation[k] = l;
747 }
748 return permutation;
749 }
750 #endif
751
752 bool compatible(AxisTags const & other) const
753 {
754 if(size() == 0 || other.size() == 0)
755 return true;
756 if(size() != other.size())
757 return false;
758 for(unsigned int k=0; k<size(); ++k)
759 if(!axes_[k].compatible(other.axes_[k]))
760 return false;
761 return true;
762 }
763
764 bool operator==(AxisTags const & other) const
765 {
766 if(size() != other.size())
767 return false;
768 return std::equal(axes_.begin(), axes_.end(), other.axes_.begin());
769 }
770
771 bool operator!=(AxisTags const & other) const
772 {
773 return !operator==(other);
774 }
775
776 protected:
777
778 void checkIndex(int k) const
779 {
780 vigra_precondition(k < (int)size() && k >= -(int)size(),
781 "AxisTags::checkIndex(): index out of range.");
782 }
783
784 void checkDuplicates(int i, AxisInfo const & info)
785 {
786 if(info.isChannel())
787 {
788 for(int k=0; k<(int)size(); ++k)
789 {
790 vigra_precondition(k == i || !axes_[k].isChannel(),
791 "AxisTags::checkDuplicates(): can only have one channel axis.");
792 }
793 }
794 else if(!info.isUnknown())
795 {
796 for(int k=0; k<(int)size(); ++k)
797 {
798 vigra_precondition(k == i || axes_[k].key() != info.key(),
799 std::string("AxisTags::checkDuplicates(): axis key '" +
800 info.key() + "' already exists."));
801 }
802 }
803 }
804
805 ArrayVector<AxisInfo> axes_;
806 };
807
808 // #if 0
809 // struct PyGetFunctor
810 // {
811 // AxisInfo const & operator()(python::object const & o) const
812 // {
813 // return python::extract<AxisInfo const &>(o)();
814 // }
815 // };
816
817 // class PyAxisTags
818 // : public AxisTags<python::object, PyGetFunctor>
819 // {
820 // typedef AxisTags<python::object, PyGetFunctor> BaseType;
821 // public:
822 // PyAxisTags()
823 // {}
824
825 // PyAxisTags(python::object i1, python::object i2,
826 // python::object i3, python::object i4, python::object i5)
827 // {
828 // if(PySequence_Check(i1.ptr()))
829 // {
830 // int size = len(i1);
831 // for(int k=0; k<size; ++k)
832 // if(python::extract<AxisInfo const &>(i1[k]).check())
833 // push_back(i1[k]);
834 // }
835 // else if(PyInt_Check(i1.ptr()))
836 // {
837 // int size = python::extract<int>(i1)();
838 // for(int k=0; k<size; ++k)
839 // push_back(python::object(AxisInfo()));
840 // }
841 // else
842 // {
843 // if(python::extract<AxisInfo const &>(i1).check())
844 // push_back(i1);
845 // if(python::extract<AxisInfo const &>(i2).check())
846 // push_back(i2);
847 // if(python::extract<AxisInfo const &>(i3).check())
848 // push_back(i3);
849 // if(python::extract<AxisInfo const &>(i4).check())
850 // push_back(i4);
851 // if(python::extract<AxisInfo const &>(i5).check())
852 // push_back(i5);
853 // }
854 // }
855
856 // python::object getitem(int k)
857 // {
858 // if(!checkIndex(k))
859 // {
860 // PyErr_SetString(PyExc_IndexError, "AxisInfo::getitem(): Invalid index or key.");
861 // python::throw_error_already_set();
862 // }
863 // if(k < 0)
864 // k += this->size();
865 // return this->axes_[k];
866 // }
867
868 // python::object getitem(std::string const & key)
869 // {
870 // return getitem(this->findKey(key));
871 // }
872
873 // void setitem(int k, python::object i)
874 // {
875 // if(!this->checkIndex(k))
876 // {
877 // PyErr_SetString(PyExc_IndexError, "AxisInfo::setitem(): Invalid index or key.");
878 // python::throw_error_already_set();
879 // }
880 // if(!python::extract<AxisInfo const &>(i).check())
881 // {
882 // PyErr_SetString(PyExc_TypeError, "AxisInfo::setitem(): Item type must be AxisInfo.");
883 // python::throw_error_already_set();
884 // }
885
886 // if(k < 0)
887 // k += this->size();
888 // this->axes_[k] = i;
889 // }
890
891 // void setitem(std::string const & key, python::object i)
892 // {
893 // setitem(this->findKey(key), i);
894 // }
895
896 // void append(python::object i)
897 // {
898 // insert(size(), i);
899 // }
900
901 // void insert(int k, python::object i)
902 // {
903 // if(k < 0)
904 // k += this->size();
905 // if(k < 0)
906 // k = 0;
907 // if(k > (int)this->size())
908 // k = this->size();
909 // if(!python::extract<AxisInfo const &>(i).check())
910 // {
911 // PyErr_SetString(PyExc_TypeError, "AxisInfo::insert(): Item type must be AxisInfo.");
912 // python::throw_error_already_set();
913 // }
914 // this->axes_.insert(this->axes_.begin()+k, i);
915 // }
916
917 // void insert(std::string const & key, python::object i)
918 // {
919 // insert(this->findKey(key), i);
920 // }
921
922 // python::list axesByFlag(AxisType typeFlags) const
923 // {
924 // python::list res;
925 // for(unsigned int k=0; k<this->size(); ++k)
926 // if(this->get(k).typeFlags() == typeFlags)
927 // res.append(k);
928 // return res;
929 // }
930
931 // python::list spatialAxes() const
932 // {
933 // python::list res;
934 // for(unsigned int k=0; k<this->size(); ++k)
935 // if(this->get(k).isSpatial())
936 // res.append(k);
937 // return res;
938 // }
939
940 // python::list temporalAxes() const
941 // {
942 // python::list res;
943 // for(unsigned int k=0; k<this->size(); ++k)
944 // if(this->get(k).isTemporal())
945 // res.append(k);
946 // return res;
947 // }
948
949 // python::list channelAxes() const
950 // {
951 // python::list res;
952 // for(unsigned int k=0; k<this->size(); ++k)
953 // if(this->get(k).isChannel())
954 // res.append(k);
955 // return res;
956 // }
957
958 // python::list frequencyAxes() const
959 // {
960 // python::list res;
961 // for(unsigned int k=0; k<this->size(); ++k)
962 // if(this->get(k).isFrequency())
963 // res.append(k);
964 // return res;
965 // }
966
967 // python::list angularAxes() const
968 // {
969 // python::list res;
970 // for(unsigned int k=0; k<this->size(); ++k)
971 // if(this->get(k).isAngular())
972 // res.append(k);
973 // return res;
974 // }
975
976 // python::list untaggedAxes() const
977 // {
978 // python::list res;
979 // for(unsigned int k=0; k<this->size(); ++k)
980 // if(this->get(k).isUnknown())
981 // res.append(k);
982 // return res;
983 // }
984
985 // template <class U>
986 // python::list vectorToPython(ArrayVector<U> const & v) const
987 // {
988 // python::list res;
989 // for(unsigned int k=0; k<v.size(); ++k)
990 // res.append(v[k]);
991 // return res;
992 // }
993
994 // python::list canonicalOrdering()
995 // {
996 // return vectorToPython(BaseType::canonicalOrdering());
997 // }
998
999 // python::list matchOrdering(PyAxisTags const & other)
1000 // {
1001 // return vectorToPython(BaseType::matchOrdering(other));
1002 // }
1003
1004 // void transpose(python::object const & o)
1005 // {
1006 // unsigned int osize = len(o);
1007 // ArrayVector<UInt32> permutation(osize);
1008
1009 // for(unsigned int k=0; k<this->size(); ++k)
1010 // permutation[k] = python::extract<UInt32>(o[k])();
1011
1012 // BaseType::transpose(permutation);
1013 // }
1014
1015 // void transpose()
1016 // {
1017 // BaseType::transpose();
1018 // }
1019 // };
1020
1021 // class TaggedShape
1022 // {
1023 // public:
1024
1025 // ArrayVector<npy_intp> shape;
1026 // python_ptr axistags;
1027 // npy_intp channelCount;
1028 // std::string channelDescription;
1029
1030 // TaggedShape(MultiArrayIndex size)
1031 // : shape(size)
1032 // {}
1033
1034 // template <int N>
1035 // TaggedShape(typename MultiArrayShape<N>::type const & sh)
1036 // : shape(sh.begin(), sh.end())
1037 // {}
1038
1039 // npy_intp & operator[](int i)
1040 // {
1041 // // rotate indices so that channels are located at index 0
1042 // return shape[(i+1) % shape.size()];
1043 // }
1044
1045 // npy_intp operator[](int i) const
1046 // {
1047 // return shape[(i+1) % shape.size()];
1048 // }
1049
1050 // unsigned int size() const
1051 // {
1052 // return shape.size();
1053 // }
1054
1055 // // void setChannelDescription(std::string const & description)
1056 // // {
1057 // // if(axistags)
1058 // // {
1059 // // python_ptr func(PyString_FromString("setChannelDescription"),
1060 // // python_ptr::keep_count);
1061 // // pythonToCppException(res);
1062
1063 // // python_ptr d(PyString_FromString(d.c_str()), python_ptr::keep_count);
1064 // // pythonToCppException(d);
1065
1066 // // python_ptr res(PyObject_CallMethodObjArgs(axistags, func, d.get(), NULL),
1067 // // python_ptr::keep_count);
1068 // // pythonToCppException(res);
1069 // // }
1070 // // }
1071
1072 // // void setChannelCount(int channelCount)
1073 // // {
1074 // // shape[0] = channelCount;
1075 // // }
1076
1077 // void setChannelDescription(std::string const & description)
1078 // {
1079 // channelDescription = description;
1080 // }
1081
1082 // void setChannelCount(int count)
1083 // {
1084 // channelCount = count;
1085 // }
1086
1087 // void setChannelConfig(int channelCount, std::string const & description)
1088 // {
1089 // setChannelCount(channelCount);
1090 // setChannelDescription(description);
1091 // }
1092 // };
1093 // #endif
1094
1095 } // namespace vigra
1096
1097 #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.10.0 (Mon Nov 18 2013)