vigra - vigra/axistags.hxx Source File

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