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

axistags.hxx VIGRA

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(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 applyPermutation(IndexIterator index_first, IndexIterator index_last, InIterator in, OutIterator out)
Sort an array according to the given index permutation.
Definition: algorithm.hxx:456
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
void transpose(const MultiArrayView< 2, T, C1 > &v, MultiArrayView< 2, T, C2 > &r)
Definition: matrix.hxx:965
void linearSequence(Iterator first, Iterator last, Value start, Value step)
Fill an array with a sequence of numbers.
Definition: algorithm.hxx:208
bool operator<=(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
less or equal
Definition: fixedpoint.hxx:521
bool operator!=(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
not equal
Definition: fftw3.hxx:841
std::string asString(T t)(...)
bool operator==(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
equal
Definition: fftw3.hxx:825
bool operator<(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
less than
Definition: fixedpoint.hxx:512
bool operator>=(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
greater or equal
Definition: fixedpoint.hxx:539
bool operator>(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
greater
Definition: fixedpoint.hxx:530
T sign(T t)
The sign function.
Definition: mathutil.hxx:591

© 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.11.1 (Fri May 19 2017)