[ 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
48namespace vigra {
49
50class 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
310class 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(std::string::size_type 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 bool contains(std::string const & key) const
459 {
460 return index(key) < (int)size();
461 }
462
463 AxisInfo & get(int k)
464 {
465 checkIndex(k);
466 if(k < 0)
467 k += size();
468 return axes_[k];
469 }
470
471 AxisInfo & get(std::string const & key)
472 {
473 return get(index(key));
474 }
475
476 AxisInfo const & get(int k) const
477 {
478 checkIndex(k);
479 if(k < 0)
480 k += size();
481 return axes_[k];
482 }
483
484 AxisInfo const & get(std::string const & key) const
485 {
486 return get(index(key));
487 }
488
489 void set(int k, AxisInfo const & info)
490 {
491 checkIndex(k);
492 if(k < 0)
493 k += size();
494 checkDuplicates(k, info);
495 axes_[k] = info;
496 }
497
498 void set(std::string const & key, AxisInfo const & info)
499 {
500 set(index(key), info);
501 }
502
503 void insert(int k, AxisInfo const & i)
504 {
505 if(k == (int)size())
506 {
507 push_back(i);
508 }
509 else
510 {
511 checkIndex(k);
512 if(k < 0)
513 k += size();
514 checkDuplicates(size(), i);
515 axes_.insert(axes_.begin()+k, i);
516 }
517 }
518
519 void push_back(AxisInfo const & i)
520 {
521 checkDuplicates(size(), i);
522 axes_.push_back(i);
523 }
524
525 void dropAxis(int k)
526 {
527 checkIndex(k);
528 ArrayVector<AxisInfo>::iterator i = k < 0
529 ? axes_.end() + k
530 : axes_.begin() + k;
531 axes_.erase(i, i+1);
532 }
533
534 void dropAxis(std::string const & key)
535 {
536 dropAxis(index(key));
537 }
538
539 void dropChannelAxis()
540 {
541 int k = channelIndex();
542 if(k < (int)size())
543 axes_.erase(axes_.begin() + k, axes_.begin() + k + 1);
544 }
545
546 int index(std::string const & key) const
547 {
548 for(unsigned int k=0; k<size(); ++k)
549 if(axes_[k].key() == key)
550 return k;
551 return (int)size();
552 }
553
554 double resolution(int k) const
555 {
556 return get(k).resolution_;
557 }
558
559 double resolution(std::string const & key) const
560 {
561 return resolution(index(key));
562 }
563
564 void setResolution(int k, double r)
565 {
566 get(k).resolution_ = r;
567 }
568
569 void setResolution(std::string const & key, double r)
570 {
571 setResolution(index(key), r);
572 }
573
574 void scaleResolution(int k, double factor)
575 {
576 get(k).resolution_ *= factor;
577 }
578
579 void scaleResolution(std::string const & key, double factor)
580 {
581 get(key).resolution_ *= factor;
582 }
583
584 std::string description(int k) const
585 {
586 return get(k).description_;
587 }
588
589 std::string description(std::string const & key) const
590 {
591 return description(index(key));
592 }
593
594 void setDescription(int k, std::string const & d)
595 {
596 get(k).setDescription(d);
597 }
598
599 void setDescription(std::string const & key, std::string const & d)
600 {
601 setDescription(index(key), d);
602 }
603
604 void setChannelDescription(std::string const & description)
605 {
606 int k = channelIndex();
607 if(k < (int)size())
608 axes_[k].setDescription(description);
609 }
610
611 void toFrequencyDomain(int k, int size = 0, int sign = 1)
612 {
613 get(k) = get(k).toFrequencyDomain(size, sign);
614 }
615
616 void toFrequencyDomain(std::string const & key, int size = 0, int sign = 1)
617 {
618 toFrequencyDomain(index(key), size, sign);
619 }
620
621 void fromFrequencyDomain(int k, int size = 0)
622 {
623 toFrequencyDomain(k, size, -1);
624 }
625
626 void fromFrequencyDomain(std::string const & key, int size = 0)
627 {
628 toFrequencyDomain(key, size, -1);
629 }
630
631 bool hasChannelAxis() const
632 {
633 return channelIndex() != (int)size();
634 }
635
636 // FIXME: cache the results of these functions?
637 int channelIndex() const
638 {
639 for(unsigned int k=0; k<size(); ++k)
640 if(axes_[k].isChannel())
641 return k;
642 return (int)size();
643 }
644
645 int innerNonchannelIndex() const
646 {
647 int k = 0;
648 for(; k<(int)size(); ++k)
649 if(!axes_[k].isChannel())
650 break;
651 for(int i=k+1; i<(int)size(); ++i)
652 {
653 if(axes_[i].isChannel())
654 continue;
655 if(axes_[i] < axes_[k])
656 k = i;
657 }
658 return k;
659 }
660
661 void swapaxes(int i1, int i2)
662 {
663 checkIndex(i1);
664 checkIndex(i2);
665 if(i1 < 0)
666 i1 += size();
667 if(i2 < 0)
668 i2 += size();
669 std::swap(axes_[i1], axes_[i2]);
670 }
671
672 template <class T>
673 void transpose(ArrayVector<T> const & permutation)
674 {
675 if(permutation.size() == 0)
676 {
677 transpose();
678 }
679 else
680 {
681 vigra_precondition(permutation.size() == size(),
682 "AxisTags::transpose(): Permutation has wrong size.");
683 ArrayVector<AxisInfo> newAxes(size());
684 applyPermutation(permutation.begin(), permutation.end(), axes_.begin(), newAxes.begin());
685 axes_.swap(newAxes);
686 }
687 }
688
689 void transpose()
690 {
691 std::reverse(axes_.begin(), axes_.end());
692 }
693
694 template <class T>
695 void
696 permutationToNormalOrder(ArrayVector<T> & permutation) const
697 {
698 permutation.resize(size());
699 indexSort(axes_.begin(), axes_.end(), permutation.begin());
700 }
701
702 template <class T>
703 void
704 permutationToNormalOrder(ArrayVector<T> & permutation, AxisInfo::AxisType types) const
705 {
706 ArrayVector<AxisInfo> matchingAxes;
707 for(int k=0; k<(int)size(); ++k)
708 if(axes_[k].isType(types))
709 matchingAxes.push_back(axes_[k]);
710 permutation.resize(matchingAxes.size());
711 indexSort(matchingAxes.begin(), matchingAxes.end(), permutation.begin());
712 }
713
714 template <class T>
715 void
716 permutationFromNormalOrder(ArrayVector<T> & inverse_permutation) const
717 {
718 ArrayVector<T> permutation;
719 permutationToNormalOrder(permutation);
720 inverse_permutation.resize(permutation.size());
721 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
722 }
723
724 template <class T>
725 void
726 permutationFromNormalOrder(ArrayVector<T> & inverse_permutation, AxisInfo::AxisType types) const
727 {
728 ArrayVector<T> permutation;
729 permutationToNormalOrder(permutation, types);
730 inverse_permutation.resize(permutation.size());
731 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
732 }
733
734 template <class T>
735 void permutationToNumpyOrder(ArrayVector<T> & permutation) const
736 {
737 permutationToNormalOrder(permutation);
738 std::reverse(permutation.begin(), permutation.end());
739 }
740
741 template <class T>
742 void permutationFromNumpyOrder(ArrayVector<T> & inverse_permutation) const
743 {
744 ArrayVector<T> permutation;
745 permutationToNumpyOrder(permutation);
746 inverse_permutation.resize(permutation.size());
747 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
748 }
749
750 template <class T>
751 void permutationToVigraOrder(ArrayVector<T> & permutation) const
752 {
753 permutation.resize(size());
754 indexSort(axes_.begin(), axes_.end(), permutation.begin());
755 int channel = channelIndex();
756 if(channel < (int)size())
757 {
758 for(int k=1; k<(int)size(); ++k)
759 permutation[k-1] = permutation[k];
760 permutation.back() = channel;
761 }
762 }
763
764 template <class T>
765 void permutationFromVigraOrder(ArrayVector<T> & inverse_permutation) const
766 {
767 ArrayVector<T> permutation;
768 permutationToVigraOrder(permutation);
769 inverse_permutation.resize(permutation.size());
770 indexSort(permutation.begin(), permutation.end(), inverse_permutation.begin());
771 }
772
773 template <class T>
774 void permutationToOrder(ArrayVector<T> & permutation, std::string const & order) const
775 {
776 if(order == "A")
777 {
778 permutation.resize(size());
779 linearSequence(permutation.begin(), permutation.end());
780 }
781 else if(order == "C")
782 {
783 permutationToNumpyOrder(permutation);
784 }
785 else if(order == "F")
786 {
787 permutationToNormalOrder(permutation);
788 }
789 else if(order == "V")
790 {
791 permutationToVigraOrder(permutation);
792 }
793 else
794 {
795 vigra_precondition(false,
796 "AxisTags::permutationToOrder(): unknown order '" + order + "'.");
797 }
798 }
799
800#if 0
801 ArrayVector<UInt32> matchOrdering(AxisTags const & other)
802 {
803 vigra_precondition(size() == other.size(),
804 "AxisTags::matchOrdering(): size mismatch.");
805
806 ArrayVector<UInt32> permutation(size());
807 for(unsigned int k = 0; k<size(); ++k)
808 {
809 std::string key = other.get(k).key();
810 unsigned int l=0;
811 for(; l<size(); ++l)
812 {
813 if(key == get(l).key())
814 break;
815 }
816 vigra_precondition(l < size(),
817 "AxisTags::matchOrdering(): key mismatch.");
818 permutation[k] = l;
819 }
820 return permutation;
821 }
822#endif
823
824 bool compatible(AxisTags const & other) const
825 {
826 if(size() == 0 || other.size() == 0)
827 return true;
828 if(size() != other.size())
829 return false;
830 for(unsigned int k=0; k<size(); ++k)
831 if(!axes_[k].compatible(other.axes_[k]))
832 return false;
833 return true;
834 }
835
836 bool operator==(AxisTags const & other) const
837 {
838 if(size() != other.size())
839 return false;
840 return std::equal(axes_.begin(), axes_.end(), other.axes_.begin());
841 }
842
843 bool operator!=(AxisTags const & other) const
844 {
845 return !operator==(other);
846 }
847
848 protected:
849
850 void checkIndex(int k) const
851 {
852 vigra_precondition(k < (int)size() && k >= -(int)size(),
853 "AxisTags::checkIndex(): index out of range.");
854 }
855
856 void checkDuplicates(int i, AxisInfo const & info)
857 {
858 if(info.isChannel())
859 {
860 for(int k=0; k<(int)size(); ++k)
861 {
862 vigra_precondition(k == i || !axes_[k].isChannel(),
863 "AxisTags::checkDuplicates(): can only have one channel axis.");
864 }
865 }
866 else if(!info.isUnknown())
867 {
868 for(int k=0; k<(int)size(); ++k)
869 {
870 vigra_precondition(k == i || axes_[k].key() != info.key(),
871 std::string("AxisTags::checkDuplicates(): axis key '" +
872 info.key() + "' already exists."));
873 }
874 }
875 }
876
877 ArrayVector<AxisInfo> axes_;
878};
879
880// #if 0
881// struct PyGetFunctor
882// {
883 // AxisInfo const & operator()(python::object const & o) const
884 // {
885 // return python::extract<AxisInfo const &>(o)();
886 // }
887// };
888
889// class PyAxisTags
890// : public AxisTags<python::object, PyGetFunctor>
891// {
892 // typedef AxisTags<python::object, PyGetFunctor> BaseType;
893 // public:
894 // PyAxisTags()
895 // {}
896
897 // PyAxisTags(python::object i1, python::object i2,
898 // python::object i3, python::object i4, python::object i5)
899 // {
900 // if(PySequence_Check(i1.ptr()))
901 // {
902 // int size = len(i1);
903 // for(int k=0; k<size; ++k)
904 // if(python::extract<AxisInfo const &>(i1[k]).check())
905 // push_back(i1[k]);
906 // }
907 // else if(PyInt_Check(i1.ptr()))
908 // {
909 // int size = python::extract<int>(i1)();
910 // for(int k=0; k<size; ++k)
911 // push_back(python::object(AxisInfo()));
912 // }
913 // else
914 // {
915 // if(python::extract<AxisInfo const &>(i1).check())
916 // push_back(i1);
917 // if(python::extract<AxisInfo const &>(i2).check())
918 // push_back(i2);
919 // if(python::extract<AxisInfo const &>(i3).check())
920 // push_back(i3);
921 // if(python::extract<AxisInfo const &>(i4).check())
922 // push_back(i4);
923 // if(python::extract<AxisInfo const &>(i5).check())
924 // push_back(i5);
925 // }
926 // }
927
928 // python::object getitem(int k)
929 // {
930 // if(!checkIndex(k))
931 // {
932 // PyErr_SetString(PyExc_IndexError, "AxisInfo::getitem(): Invalid index or key.");
933 // python::throw_error_already_set();
934 // }
935 // if(k < 0)
936 // k += this->size();
937 // return this->axes_[k];
938 // }
939
940 // python::object getitem(std::string const & key)
941 // {
942 // return getitem(this->findKey(key));
943 // }
944
945 // void setitem(int k, python::object i)
946 // {
947 // if(!this->checkIndex(k))
948 // {
949 // PyErr_SetString(PyExc_IndexError, "AxisInfo::setitem(): Invalid index or key.");
950 // python::throw_error_already_set();
951 // }
952 // if(!python::extract<AxisInfo const &>(i).check())
953 // {
954 // PyErr_SetString(PyExc_TypeError, "AxisInfo::setitem(): Item type must be AxisInfo.");
955 // python::throw_error_already_set();
956 // }
957
958 // if(k < 0)
959 // k += this->size();
960 // this->axes_[k] = i;
961 // }
962
963 // void setitem(std::string const & key, python::object i)
964 // {
965 // setitem(this->findKey(key), i);
966 // }
967
968 // void append(python::object i)
969 // {
970 // insert(size(), i);
971 // }
972
973 // void insert(int k, python::object i)
974 // {
975 // if(k < 0)
976 // k += this->size();
977 // if(k < 0)
978 // k = 0;
979 // if(k > (int)this->size())
980 // k = this->size();
981 // if(!python::extract<AxisInfo const &>(i).check())
982 // {
983 // PyErr_SetString(PyExc_TypeError, "AxisInfo::insert(): Item type must be AxisInfo.");
984 // python::throw_error_already_set();
985 // }
986 // this->axes_.insert(this->axes_.begin()+k, i);
987 // }
988
989 // void insert(std::string const & key, python::object i)
990 // {
991 // insert(this->findKey(key), i);
992 // }
993
994 // python::list axesByFlag(AxisType typeFlags) const
995 // {
996 // python::list res;
997 // for(unsigned int k=0; k<this->size(); ++k)
998 // if(this->get(k).typeFlags() == typeFlags)
999 // res.append(k);
1000 // return res;
1001 // }
1002
1003 // python::list spatialAxes() const
1004 // {
1005 // python::list res;
1006 // for(unsigned int k=0; k<this->size(); ++k)
1007 // if(this->get(k).isSpatial())
1008 // res.append(k);
1009 // return res;
1010 // }
1011
1012 // python::list temporalAxes() const
1013 // {
1014 // python::list res;
1015 // for(unsigned int k=0; k<this->size(); ++k)
1016 // if(this->get(k).isTemporal())
1017 // res.append(k);
1018 // return res;
1019 // }
1020
1021 // python::list channelAxes() const
1022 // {
1023 // python::list res;
1024 // for(unsigned int k=0; k<this->size(); ++k)
1025 // if(this->get(k).isChannel())
1026 // res.append(k);
1027 // return res;
1028 // }
1029
1030 // python::list frequencyAxes() const
1031 // {
1032 // python::list res;
1033 // for(unsigned int k=0; k<this->size(); ++k)
1034 // if(this->get(k).isFrequency())
1035 // res.append(k);
1036 // return res;
1037 // }
1038
1039 // python::list angularAxes() const
1040 // {
1041 // python::list res;
1042 // for(unsigned int k=0; k<this->size(); ++k)
1043 // if(this->get(k).isAngular())
1044 // res.append(k);
1045 // return res;
1046 // }
1047
1048 // python::list untaggedAxes() const
1049 // {
1050 // python::list res;
1051 // for(unsigned int k=0; k<this->size(); ++k)
1052 // if(this->get(k).isUnknown())
1053 // res.append(k);
1054 // return res;
1055 // }
1056
1057 // template <class U>
1058 // python::list vectorToPython(ArrayVector<U> const & v) const
1059 // {
1060 // python::list res;
1061 // for(unsigned int k=0; k<v.size(); ++k)
1062 // res.append(v[k]);
1063 // return res;
1064 // }
1065
1066 // python::list canonicalOrdering()
1067 // {
1068 // return vectorToPython(BaseType::canonicalOrdering());
1069 // }
1070
1071 // python::list matchOrdering(PyAxisTags const & other)
1072 // {
1073 // return vectorToPython(BaseType::matchOrdering(other));
1074 // }
1075
1076 // void transpose(python::object const & o)
1077 // {
1078 // unsigned int osize = len(o);
1079 // ArrayVector<UInt32> permutation(osize);
1080
1081 // for(unsigned int k=0; k<this->size(); ++k)
1082 // permutation[k] = python::extract<UInt32>(o[k])();
1083
1084 // BaseType::transpose(permutation);
1085 // }
1086
1087 // void transpose()
1088 // {
1089 // BaseType::transpose();
1090 // }
1091// };
1092
1093// class TaggedShape
1094// {
1095 // public:
1096
1097 // ArrayVector<npy_intp> shape;
1098 // python_ptr axistags;
1099 // npy_intp channelCount;
1100 // std::string channelDescription;
1101
1102 // TaggedShape(MultiArrayIndex size)
1103 // : shape(size)
1104 // {}
1105
1106 // template <int N>
1107 // TaggedShape(typename MultiArrayShape<N>::type const & sh)
1108 // : shape(sh.begin(), sh.end())
1109 // {}
1110
1111 // npy_intp & operator[](int i)
1112 // {
1113 // // rotate indices so that channels are located at index 0
1114 // return shape[(i+1) % shape.size()];
1115 // }
1116
1117 // npy_intp operator[](int i) const
1118 // {
1119 // return shape[(i+1) % shape.size()];
1120 // }
1121
1122 // unsigned int size() const
1123 // {
1124 // return shape.size();
1125 // }
1126
1127 // // void setChannelDescription(std::string const & description)
1128 // // {
1129 // // if(axistags)
1130 // // {
1131 // // python_ptr func(PyString_FromString("setChannelDescription"),
1132 // // python_ptr::keep_count);
1133 // // pythonToCppException(res);
1134
1135 // // python_ptr d(PyString_FromString(d.c_str()), python_ptr::keep_count);
1136 // // pythonToCppException(d);
1137
1138 // // python_ptr res(PyObject_CallMethodObjArgs(axistags, func, d.get(), NULL),
1139 // // python_ptr::keep_count);
1140 // // pythonToCppException(res);
1141 // // }
1142 // // }
1143
1144 // // void setChannelCount(int channelCount)
1145 // // {
1146 // // shape[0] = channelCount;
1147 // // }
1148
1149 // void setChannelDescription(std::string const & description)
1150 // {
1151 // channelDescription = description;
1152 // }
1153
1154 // void setChannelCount(int count)
1155 // {
1156 // channelCount = count;
1157 // }
1158
1159 // void setChannelConfig(int channelCount, std::string const & description)
1160 // {
1161 // setChannelCount(channelCount);
1162 // setChannelDescription(description);
1163 // }
1164// };
1165// #endif
1166
1167} // namespace vigra
1168
1169#endif /* VIGRA_AXISTAGS_HXX */
void linearSequence(Iterator first, Iterator last, Value start, Value step)
Fill an array with a sequence of numbers.
Definition algorithm.hxx:208
void indexSort(Iterator first, Iterator last, IndexIterator index_first, Compare c)
Return the index permutation that would sort the input array.
Definition algorithm.hxx:414
T sign(T t)
The sign function.
Definition mathutil.hxx:591
void applyPermutation(IndexIterator index_first, IndexIterator index_last, InIterator in, OutIterator out)
Sort an array according to the given index permutation.
Definition algorithm.hxx:456
std::string asString(T t)(...)

© 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.12.2 (Mon Apr 14 2025)