[ 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.9.0 (Wed Feb 27 2013)