stafield.h
1 /*#############################################################################
2  *
3  * Copyright 2011 by Henrik Skibbe and Marco Reisert
4  *
5 *
6  * This file is part of the STA-ImageAnalysisToolbox
7  *
8  * STA-ImageAnalysisToolbox is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * STA-ImageAnalysisToolbox is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with STA-ImageAnalysisToolbox.
20  * If not, see <http://www.gnu.org/licenses/>.
21  *
22  *
23 *#############################################################################*/
24 
25 #ifdef _STA_CUDA
26 #include "stafield_cuda.h"
27 #endif
28 
29 
30 #ifndef STA_FIELD_CLASS_H
31 #define STA_FIELD_CLASS_H
32 
33 
34 
35 #include "stensor.h"
36 #include "sta_error.h"
37 #include "string.h"
38 #include "stensor_kernels.h"
39 
40 #ifdef _SUPPORT_MATLAB_
41  #include "sta_mex_helpfunc.h"
42 #endif
43 
44 #ifdef _STA_CUDA
45  #include "stensorcuda.h"
46 #endif
47 
48 #include <list>
49 #include <string>
50 
51 
52 
53 
54 
55 namespace hanalysis
56 {
57 static int classcount=0;
58 static bool do_classcount=false;
59 
61 template<typename T>
62 class _stafield
63 {
64 protected:
65  int classcount_id;
66 
67 
68  int object_is_dead_soon;
69 
70  // not fully supported by stensor.h yet
71  T element_size[3];
72 
74  std::size_t shape[3];
75  bool own_memory;
76 
82  int L;
83 
84  // only relevant for views (selected components), else==0
85  std::size_t stride;
86 
87  static void set_death(const _stafield * cfield)
88  {
89  _stafield * field=(_stafield* ) cfield;
90  field->object_is_dead_soon++;
91  }
92 
93 
94  public:
95  std::string name;
96 
97  std::size_t getNumVoxel() const {
98  return this->shape[0]*this->shape[1]*this->shape[2];
99  }
100 
101  void switchFourierFlag()
102  {
103  if (this->field_storage==STA_FIELD_STORAGE_R)
104  {
105  this->field_storage=STA_FIELD_STORAGE_RF;
106  return;
107  }
108  if (this->field_storage==STA_FIELD_STORAGE_RF)
109  {
110  this->field_storage=STA_FIELD_STORAGE_R;
111  return;
112  }
113  }
114 
115 
116 
117  static bool equalShape(const _stafield & a,const _stafield & b)
118  {
119  if ((a.shape[0]!=b.shape[0]) ||
120  (a.shape[1]!=b.shape[1]) ||
121  (a.shape[2]!=b.shape[2]) )
122  return false;
123  return true;
124  }
125 
126  /*#############################################################
127  *
128  * standard operators
129  *
130  *#############################################################*/
131 
135  bool operator==(const _stafield & field) const
136  {
137  if ((this->shape[0]!=field.shape[0]) ||
138  (this->shape[1]!=field.shape[1]) ||
139  (this->shape[2]!=field.shape[2]) ||
140  (this->field_storage!=field.field_storage)||
141  (this->field_type!=field.field_type)||
142  (this->L!=field.L)
143  )return false;
144  return true;
145  };
146 
150  bool operator!=(const _stafield & field) const
151  {
152  return (!((*this)==field));
153  };
154 
155 
156 
157  /*#############################################################
158  *
159  * constructors
160  *
161  *#############################################################*/
162 
163 
164  _stafield()
165  {
166  this->element_size[0]=T(1);
167  this->element_size[1]=T(1);
168  this->element_size[2]=T(1);
169  this->field_storage=hanalysis::STA_FIELD_STORAGE_R;
170  this->field_type=hanalysis::STA_OFIELD_SINGLE;
171  this->shape[0]=0;
172  this->shape[1]=0;
173  this->shape[2]=0;
174  //this->data=NULL;
175  this->own_memory=true;
176  this->L=-1;
177  this->stride=0;
178  classcount++;
179  this->classcount_id=classcount;
180  this->object_is_dead_soon=0;
181  }
182 
183 
187  const std::size_t * getShape() const {
188  return this->shape;
189  };
190 
194  bool ownMemory() const {
195  return this->own_memory;
196  }
197 
198  bool oneBlockMem() const {
199  return (this->stride==0);
200  }
201 
202  std::size_t getStride() const {
203  if (this->stride==0)
204  return hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
205  return this->stride;
206  };
207 
208  void setElementSize(const T element_size[])
209  {
210  this->element_size[0]=element_size[0];
211  this->element_size[1]=element_size[1];
212  this->element_size[2]=element_size[2];
213  }
214 
215  const T * getElementSize() const
216  {
217  return this->element_size;
218  }
219 
220 
221  hanalysis::STA_FIELD_STORAGE getStorage() const
222  {
223  return this->field_storage;
224  }
225 
226  hanalysis::STA_FIELD_TYPE getType() const
227  {
228  return this->field_type;
229  }
230 
231 
232 
236  int getRank() const {
237  return this->L;
238  }
239 
240 
241 };
242 
243 #ifdef _STA_CUDA
244 template <typename T>
245 class stafieldGPU;
246 #endif
247 
248 
250 template<typename T>
251 class stafield : public _stafield<T>
252 {
253 private:
254 
255  std::complex<T> * data;
256 public:
257 
258 #ifdef _STA_CUDA
259  stafield & operator=(const stafieldGPU<T> & f)
260  {
261  if ((this->L==-1)&&(f.getRank()==-1))
262  return *this;
263  if (!f.oneBlockMem())
264  throw (hanalysis::STAError("error copying host memory to device memory, the host memory must be alignd in one single block!"));
265 
266  if ((*this)!=f)
267  {
268  if (this->stride!=0)
269  throw STAError("warning: operator= (stride!=0) shared memory block but alocating new (own) memory would be nrequired \n");
270 
271  if (!this->own_memory)
272  throw STAError("warning: operator= (!own_memory): shared memory block but alocating new (own) memory would be nrequired \n");
273 
274  if (this->own_memory && (this->data!=NULL))
275  cudaFree(this->data);
276 
277  this->field_storage=f.getStorage();
278  this->field_type=f.getType();
279  this->shape[0]=f.getShape()[0];
280  this->shape[1]=f.getShape()[1];
281  this->shape[2]=f.getShape()[2];
282 
283  this->setElementSize(f.getElementSize());
284 
285  this->data=NULL;
286  this->stride=0;
287  this->own_memory=true;
288  this->L=f.getRank();
289  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
290  this->data=new std::complex<T>[numcomponents*this->getNumVoxel()];
291  //hanalysis_cuda::gpu_malloc(this->data,numcomponents*this->getNumVoxel()*sizeof(std::complex<T>));
292 
293  }
294 
295  if (this->stride==0)
296  {
297  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
298  this->setElementSize(f.getElementSize());
299  T * const src=( T* const)(f.getDataConst());
300  T * dest=( T* )(this->getData());
301  hanalysis_cuda::gpu_memcpy_d2h(src,dest,this->getNumVoxel()*numcomponents*sizeof(std::complex<T>));
302  }else
303  throw (hanalysis::STAError("error copying host memory to device memory, the (existing) device memory must be alignd in one single block!"));
304 
305  return *this;
306  }
307 
308  stafieldGPU<T> cpu2gpu() const
309  {
310  try
311  {
312  stafieldGPU<T> result;
313  this->set_death(&result);
314  result=(*this);
315  return result;
316  }
317  catch (hanalysis::STAError & error)
318  {
319  throw error;
320  }
321  }
322 
323 
324 #endif
325 
326 
327 
328  /*#############################################################
329  *
330  * standard operators
331  *
332  *#############################################################*/
333 
334 
335  template<typename S>
336  void operator=(S value)
337  {
338  if (this->getType()!=hanalysis::STA_OFIELD_SINGLE)
339  throw (hanalysis::STAError("operator= : field type must be STA_OFIELD_SINGLE",STA_RESULT_OFIELD_TYPE_MISMATCH));
340 
341  int thestride=this->getStride();
342  std::size_t jumpz=this->shape[1]*this->shape[2];
343  int strid_all=jumpz*thestride;
344  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
345  int remaining=thestride-numcomponents;
346 
347  #pragma omp parallel for num_threads(get_numCPUs())
348  for (std::size_t z=0;z<this->shape[0];z++)
349  {
350  std::complex<T> * p=this->data+z*strid_all;
351  for (std::size_t a=0;a<jumpz;a++)
352  {
353  for (int a=0;a<numcomponents;a++)
354  (*p++)=value;
355  p+=remaining;
356  }
357  }
358  }
359 
364  {
365 
366  if (this==&f)
367  return *this;
368 
369  // both objects represent empty fields : do nothin
370  if ((this->L==-1)&&(f.L==-1))
371  return *this;
372 
373 
374 // printf("%d %d\n",this->ownMemory(),f.ownMemory());
375 // printf("%d %d\n",this->L,f.L);
376 
377 // printf("0: copying from ");
378 // if (f.stride==0)
379 // printf("full mem to ");
380 // else
381 // printf("view to");
382 //
383 // if (stride==0)
384 // printf("full mem \n");
385 // else
386 // printf("view \n");
387 
388  if ((f.object_is_dead_soon==1)
389  // remove the next check if you want that a
390  // view can change its role
391  &&(this->own_memory)
392  )
393  {
394 
395 
396 
397  if (f.object_is_dead_soon>1)
398  throw STAError("error: something went wrong with the memory managemant \n");
399 
400  if (this->own_memory && (this->data!=NULL) && (this->object_is_dead_soon<2))
401  delete [] this->data;
402 
403  this->set_death(&f);
404  this->data=f.data;
405 
406  this->field_storage=f.field_storage;
407  this->field_type=f.field_type;
408 
409  this->shape[0]=f.shape[0];
410  this->shape[1]=f.shape[1];
411  this->shape[2]=f.shape[2];
412 
413  this->setElementSize(f.getElementSize());
414 
415  this->L=f.L;
416 
417  this->stride=f.stride;
418  this->own_memory=f.own_memory;
419  return *this;
420  }
421 
422 
423  int check=0;
424 
425  if ((*this)!=f)
426  {
427  if (this->stride!=0)
428  throw STAError("warning: operator= (stride!=0) shared memory block but allocation of new (own) memory would be required \n");
429 
430  if (!this->own_memory)
431  throw STAError("warning: operator= (!own_memory): shared memory block but allocation of new (own) memory would be required \n");
432 
433 
434 
435  if (this->own_memory && (this->data!=NULL))
436  delete [] this->data;
437 
438  this->field_storage=f.field_storage;
439  this->field_type=f.field_type;
440  this->shape[0]=f.shape[0];
441  this->shape[1]=f.shape[1];
442  this->shape[2]=f.shape[2];
443 
444  this->setElementSize(f.getElementSize());
445 
446  this->data=NULL;
447  this->stride=0;
448  this->own_memory=true;
449  this->L=f.L;
450  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
451  int numVoxel=this->shape[0]*this->shape[1]*this->shape[2];
452  this->data=new std::complex<T>[numcomponents*numVoxel];
453  check=1;
454  }
455 
456  if ((f.stride==0)&&(this->stride==0))
457  {
458  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
459  this->setElementSize(f.getElementSize());
460 // printf("allocating new data\n");
461 // printf("memcpy start: num components %d \n",numcomponents);
462 // printf("from: %d\n",(std::size_t)(f.data));
463 // printf("o : %d\n",(std::size_t)(this->data));
464  memcpy(this->data,f.data,this->shape[0]*this->shape[1]*this->shape[2]*numcomponents*sizeof(std::complex<T>));
465 // printf("memcpy stop\n");
466  }
467  else
468  {
469  this->setElementSize(f.getElementSize());
470  if (check==1)
471  throw STAError("BullShit");
472 
474  (this->field_type!=hanalysis::STA_OFIELD_SINGLE))
475  throw STAError("operator= this cannot happen ! the input field must be STA_OFIELD_SINGLE",STA_RESULT_OFIELD_TYPE_MISMATCH);
476  // view -> copy
477  int numcomponents_new=this->L+1;
478  if (this->field_storage==STA_FIELD_STORAGE_C)
479  numcomponents_new=2*this->L+1;
480 
481 // std::complex<T> * in=f.data;
482 // std::complex<T> * out=this->data;
483 // for (std::size_t a=0;a<shape[0]*shape[1]*shape[2];a++)
484 // {
485 // //memcpy(out,in,numcomponents_new*sizeof(std::complex<T>));
486 // for (int b=0;b<numcomponents_new;b++)
487 // out[b]=in[b];
488 // in+=f.getStride();
489 // out+=this->getStride();
490 // }
491  numcomponents_new*=2;
492 // T * in=(T*)(f.data);
493 // T * out=(T*)(this->data);
494  int strid_in=2*(f.getStride())-numcomponents_new;
495  int strid_out=2*this->getStride()-numcomponents_new;
496  std::size_t jumpz=this->shape[1]*this->shape[2];
497  int strid_in_all=jumpz*f.getStride();
498  int strid_out_all=jumpz*this->getStride();
499 
500  #pragma omp parallel for num_threads(get_numCPUs())
501  for (std::size_t z=0;z<this->shape[0];z++)
502  {
503  T * in=(T*)(f.data+z*strid_in_all);
504  T * out=(T*)(this->data+z*strid_out_all);
505  for (std::size_t a=0;a<jumpz;a++)
506  {
507  for (int b=0;b<numcomponents_new;b++)
508  (*out++)=(*in++);
509  in+=strid_in;
510  out+=strid_out;
511  }
512  }
513  }
514 
515  return *this;
516  }
517 
518 
524  {
525  if (a!=*this)
526  throw (hanalysis::STAError("+=: shapes differ!",STA_RESULT_SHAPE_MISMATCH));
527  try
528  {
529  Mult(a,*this);
530  } catch (hanalysis::STAError & error)
531  {
532  throw error;
533  }
534  return *this;
535  }
536 
542  {
543  if (a!=*this)
544  throw (hanalysis::STAError("-=: shapes differ!",STA_RESULT_SHAPE_MISMATCH));
545  try
546  {
547  Mult(a,*this,-1);
548  } catch (hanalysis::STAError & error)
549  {
550  throw error;
551  }
552  return *this;
553  }
554 
559  stafield & operator*=(std::complex<T> alpha)
560  {
561  try
562  {
563  Mult(*this,*this,alpha,false,true);
564  } catch (hanalysis::STAError & error)
565  {
566  throw error;
567  }
568  return *this;
569  }
570 
575  stafield & operator/=(std::complex<T> alpha)
576  {
577  try
578  {
579  Mult(*this,*this,T(1)/alpha,false,true);
580  } catch (hanalysis::STAError & error)
581  {
582  throw error;
583  }
584  return *this;
585  }
586 
591  const stafield operator+(const stafield & a) const
592  {
593  if (a!=*this)
594  throw (hanalysis::STAError("-=: shapes differ!",STA_RESULT_SHAPE_MISMATCH));
595 
596  try
597  {
598  stafield result(this->shape,this->L,this->field_storage,this->field_type);
599  Mult(*this,result,T(1),false,true);
600  Mult(a,result,T(1),false,false);
601  return result;
602  } catch (hanalysis::STAError & error)
603  {
604  throw error;
605  }
606  }
607 
608 
613  const stafield operator-(const stafield & a) const
614  {
615  if (a!=*this)
616  throw (hanalysis::STAError("-=: shapes differ!",STA_RESULT_SHAPE_MISMATCH));
617 
618  try
619  {
620  stafield result(this->shape,this->L,this->field_storage,this->field_type);
621  Mult(*this,result,T(-1),false,true);
622  Mult(a,result,T(-1),false,false);
623  return result;
624  } catch (hanalysis::STAError & error)
625  {
626  throw error;
627  }
628 
629  }
630 
631 
632 
633 
634 
635 
640  const stafield operator*(std::complex<T> alpha) const
641  {
642  try
643  {
644  stafield result(this->shape,this->L,this->field_storage,this->field_type);
645  Mult(*this,result,alpha,false,true);
646  return result;
647  } catch (hanalysis::STAError & error)
648  {
649  throw error;
650  }
651  }
652 
657  const stafield operator/(std::complex<T> alpha) const
658  {
659  try
660  {
661  stafield result(this->shape,this->L,this->field_storage,this->field_type);
662  Mult(*this,result,T(1)/alpha,false,true);
663  return result;
664  } catch (hanalysis::STAError & error)
665  {
666  throw error;
667  }
668 
669  }
670 
671 
672 
673  /*
674  \returns a view on the (sub) component \f$ l \f$ with the \n
675  tensor rank \f$ l \in \mathbb N \f$ of an orientation tensor field
676  */
677  /*
678  const stafield operator()(int l) const
679  {
680  try
681  {
682  return this->get(l);
683  }
684  catch (hanalysis::STAError & error)
685  {
686  throw error;
687  }
688  }
689  */
690 
695  stafield operator[](int l) const
696  {
697  try
698  {
699  return this->get(l);
700  }
701  catch (hanalysis::STAError & error)
702  {
703  throw error;
704  }
705  }
706 
707 
708  /*#############################################################
709  *
710  * constructors
711  *
712  *#############################################################*/
713 
714 
715 
716  stafield() : _stafield<T>(), data(NULL) {};
717 // {
718 // this->element_size[0]=T(1);
719 // this->element_size[1]=T(1);
720 // this->element_size[2]=T(1);
721 // this->field_storage=hanalysis::STA_FIELD_STORAGE_R;
722 // this->field_type=hanalysis::STA_OFIELD_SINGLE;
723 // this->shape[0]=0;
724 // this->shape[1]=0;
725 // this->shape[2]=0;
726 // this->data=NULL;
727 // this->own_memory=true;
728 // this->L=-1;
729 // this->stride=0;
730 // classcount++;
731 // this->classcount_id=classcount;
732 // this->object_is_dead_soon=0;
733 // }
734 
735  stafield(const stafield & field) : _stafield<T>(), data(NULL)
736  {
737 // this->element_size[0]=T(1);
738 // this->element_size[1]=T(1);
739 // this->element_size[2]=T(1);
740 // this->field_storage=hanalysis::STA_FIELD_STORAGE_R;
741 // this->field_type=hanalysis::STA_OFIELD_SINGLE;
742 // this->shape[0]=0;
743 // this->shape[1]=0;
744 // this->shape[2]=0;
745 // this->data=NULL;
746 // this->own_memory=true;
747 // this->L=-1;
748 // this->stride=0;
749 // classcount++;
750 // this->classcount_id=classcount;
751 // this->object_is_dead_soon=0;
752 
753  (*this)=field;
754  }
755 
756 
757 
758 
759 
764  stafield(const std::size_t shape[],
765  int L,
768  const T element_size[]=NULL)
769  : _stafield<T>(), data(NULL)
770  {
771 // this->element_size[0]=T(1);
772 // this->element_size[1]=T(1);
773 // this->element_size[2]=T(1);
774 // this->stride=0;
775  if (element_size!=NULL)
776  this->setElementSize(element_size);
777 
778  //printf("%f %f %f\n",element_size[0],element_size[1],element_size[2]);
779 
780  if (L<0)
781  throw STAError("L must be >= 0");
782  this->field_storage=field_storage;
783  this->field_type=field_type;
784  this->shape[0]=shape[0];
785  this->shape[1]=shape[1];
786  this->shape[2]=shape[2];
787 // this->data=NULL;
788 // this->own_memory=true;
789  this->L=L;
790  int numcomponents=hanalysis::order2numComponents(field_storage,field_type,L);
791  int numVoxel=shape[0]*shape[1]*shape[2];
792  if (hanalysis::verbose>0)
793  printf("L: %d , (%i,%i,%i) , // %i\n",L,shape[0],shape[1],shape[2],numcomponents);
794  if (hanalysis::verbose>0)
795  printf("allocating %d bytes\n",numcomponents*numVoxel*sizeof(std::complex<T>));
796  this->data=new std::complex<T>[numcomponents*numVoxel];
797 
798 
799 // classcount++;
800 // this->classcount_id=classcount;
801 // this->object_is_dead_soon=0;
802  }
803 
804 
805 
806 
807 
808 
809 
810 
818  stafield(std::string kernelname,
819  const std::size_t shape[],
820  std::vector<T> param_v,
821  bool centered=false,
822  int L=0,
824  const T element_size[]=NULL)
825  : _stafield<T>()
826  {
827 // this->element_size[0]=T(1);
828 // this->element_size[1]=T(1);
829 // this->element_size[2]=T(1);
830 
831  if (element_size!=NULL)
832  this->setElementSize(element_size);
833  this->stride=0;
834  if (L<0)
835  throw STAError("L must be >= 0");
836  this->field_storage=field_storage;
837  this->field_type=hanalysis::STA_OFIELD_SINGLE;
838  this->shape[0]=shape[0];
839  this->shape[1]=shape[1];
840  this->shape[2]=shape[2];
841  this->data=NULL;
842  this->own_memory=true;
843  this->L=L;
844  int numcomponents=hanalysis::order2numComponents(field_storage,this->field_type,L);
845  int numVoxel=shape[0]*shape[1]*shape[2];
846  if (hanalysis::verbose>0)
847  printf("L: %d , (%i,%i,%i) , // %i\n",L,shape[0],shape[1],shape[2],numcomponents);
848  if (hanalysis::verbose>0)
849  printf("allocating %d bytes\n",numcomponents*numVoxel*sizeof(std::complex<T>));
850  this->data=new std::complex<T>[numcomponents*numVoxel];
851 
852  makeKernel(kernelname,param_v,*this,centered);
853 // classcount++;
854 // this->classcount_id=classcount;
855 // this->object_is_dead_soon=0;
856  }
857 
858 
865  stafield(const std::size_t shape[],
866  int L,
867  hanalysis::STA_FIELD_STORAGE field_storage,
868  hanalysis::STA_FIELD_TYPE field_type,
869  std::complex<T> * data,
870  std::size_t stride=0,
871  const T element_size[]=NULL) : _stafield<T>()
872  {
873 // this->element_size[0]=T(1);
874 // this->element_size[1]=T(1);
875 // this->element_size[2]=T(1);
876 
877  if (element_size!=NULL)
878  this->setElementSize(element_size);
879  this->stride=stride;
880  if (L<0)
881  throw (hanalysis::STAError("L must be >= 0",STA_RESULT_INVALID_TENSOR_RANK));
882  if (data==NULL)
883  throw ( hanalysis::STAError("data is NULL-pointer"));
884  this->field_storage=field_storage;
885  this->field_type=field_type;
886  this->shape[0]=shape[0];
887  this->shape[1]=shape[1];
888  this->shape[2]=shape[2];
889  this->data=data;
890  this->own_memory=false;
891  this->L=L;
892 // classcount++;
893 // this->classcount_id=classcount;
894 // this->object_is_dead_soon=0;
895  }
896 
897 
898 
899 
900 
901 
902 #ifdef _SUPPORT_MATLAB_
903  stafield(mxArray * field,
904  hanalysis::STA_FIELD_STORAGE field_storage,
905  hanalysis::STA_FIELD_TYPE field_type,
906  const T element_size[]=NULL)
907  : _stafield<T>()
908  {
909  stafieldFromMxArray(field,field_storage,field_type,element_size);
910  }
911 
912  stafield(mxArray * field) : _stafield<T>()
913  {
914 // if (isStaField<T>(field))
915 // {
916 // mxArray *storage = mxGetPropertyPtr(field,0,(char *)"storage");
917 // mxArray *type = mxGetPropertyPtr(field,0,(char *)"type");
918 // mxArray *data = mxGetPropertyPtr(field,0,(char *)"data");
919 // stafieldFromMxArray(data,
920 // enumfromstring(mex2string(storage)),
921 // enumfromstring(mex2string(type)));
922 // return;
923 // }
924  if (mex_isStaFieldStruct<T>(field))
925  {
926 
927  mxArray *storage = mxGetField(field,0,(char *)"storage");
928  mxArray *type = mxGetField(field,0,(char *)"type");
929  mxArray *data = mxGetField(field,0,(char *)"data");
930  mxArray *element_size = mxGetField(field,0,(char *)"element_size");
931 
932 
933  T element_size_p[3];
934  element_size_p[0]=element_size_p[1]=element_size_p[2]=1;
935 
936  switch (mxGetClassID(element_size))
937  {
938 
939  case mxSINGLE_CLASS:
940  {
941  float * esize_p= (float*) mxGetData(element_size);
942  element_size_p[0]=esize_p[2];
943  element_size_p[1]=esize_p[1];
944  element_size_p[2]=esize_p[0];
945  } break;
946 
947  case mxDOUBLE_CLASS:
948  {
949  double * esize_p= (double*) mxGetData(element_size);
950  element_size_p[0]=esize_p[2];
951  element_size_p[1]=esize_p[1];
952  element_size_p[2]=esize_p[0];
953  } break;
954 
955  default:
956  mexErrMsgTxt("unsupported data type for element size!\n");
957  }
958 
959 
960  stafieldFromMxArray(data,
961  enumfromstring_storage(mex_mex2string(storage)),
962  enumfromstring_type(mex_mex2string(type)),
963  element_size_p);
964 
965  return;
966  }
967  throw ( hanalysis::STAError("mxArray contains no valid stafield class nor a valid starfield struct!"));
968  }
969 
970  private:
971  void stafieldFromMxArray(mxArray * field,
974  const T element_size[]=NULL)
975  {
976  if (mxGetClassID(field)!=mex_getClassId<T>())
977  throw ( hanalysis::STAError("data type missmatch!"));
978 
979 // this->element_size[0]=T(1);
980 // this->element_size[1]=T(1);
981 // this->element_size[2]=T(1);
982 
983  if (element_size!=NULL)
984  this->setElementSize(element_size);
985  this->stride=0;
986  this->field_storage=field_storage;
987  this->field_type=field_type;
988  this->data=NULL;
989  this->own_memory=false;
990  const mwSize *dimsFIELD = mxGetDimensions(field);
991  const int numdimFIELD = mxGetNumberOfDimensions(field);
992  if (numdimFIELD!=5)
993  throw ( hanalysis::STAError("wrong number of dimensions"));
994  if (dimsFIELD[0]!=2)
995  throw ( hanalysis::STAError("wrong number of components in first dimension (must be 2 -> real/imag)"));
996  int ncomponents=dimsFIELD[1];
997 
998  this->L=numComponents2order(field_storage,field_type,ncomponents);
999 
1000  this->data = (std::complex<T> *) (mxGetData(field));
1001  this->shape[0]=dimsFIELD[2];
1002  this->shape[1]=dimsFIELD[3];
1003  this->shape[2]=dimsFIELD[4];
1004  std::swap(this->shape[0],this->shape[2]);
1005  if (hanalysis::verbose>0)
1006  printf("L: %d , (%i,%i,%i) , // %i\n",this->L,this->shape[0],this->shape[1],this->shape[2],ncomponents);
1007 // classcount++;
1008 // this->classcount_id=classcount;
1009 // this->object_is_dead_soon=0;
1010  }
1011 
1012  public:
1013 
1014 
1015 // static stafield createFieldAndmxClass( mxArray * & newMxArray,
1016 // const std::size_t shape[],
1017 // int L,
1018 // hanalysis::STA_FIELD_PROPERTIES field_storage=hanalysis::STA_FIELD_STORAGE_R,
1019 // hanalysis::STA_FIELD_PROPERTIES field_type=hanalysis::STA_OFIELD_SINGLE)
1020 // {
1021 // int numcomponents=hanalysis::order2numComponents(field_storage,field_type,L);
1022 //
1023 // int ndims[5];
1024 // ndims[0] = 2;
1025 // ndims[1] = numcomponents;
1026 // ndims[2]=shape[2];
1027 // ndims[3]=shape[1];
1028 // ndims[4]=shape[0];
1029 //
1030 // mxArray *precision= mxCreateString(getPrecisionFlag<T>().c_str());
1031 // mxArray *in[1];
1032 // in[0] = precision;
1033 // mxArray *out[1];
1034 // mexCallMATLAB(1, out, 1, in , "stafield");
1035 // newMxArray = out[0];
1036 // int dim = 1;
1037 // mxArray *theL = mxCreateNumericArray(1,&dim,getclassid<T>(),mxREAL);
1038 // T *s = (T*) mxGetData(theL);
1039 // *s = L;
1040 // int dimsh[] = {1,3};
1041 // mxArray *theShape = mxCreateNumericArray(2,dimsh,getclassid<T>(),mxREAL);
1042 // T *theshape = (T*) mxGetData(theShape);
1043 // theshape[0] = shape[2];
1044 // theshape[1] = shape[1];
1045 // theshape[2] = shape[0];
1046 //
1047 // mxSetProperty(newMxArray,0,"shape",theShape);
1048 // mxSetProperty(newMxArray,0,"storage",mxCreateString(enumtostring(field_storage).c_str()));
1049 // mxSetProperty(newMxArray,0,"type",mxCreateString(enumtostring(field_type).c_str()));
1050 // mxSetProperty(newMxArray,0,"L",theL);
1051 // mxSetProperty(newMxArray,0,"data",mxCreateNumericArray(5,ndims,getclassid<T>(),mxREAL));
1052 // //printf("getting pointer\n");
1053 // std::complex<T> * datap=(std::complex<T> *) (mxGetData(mxGetPropertyPtr(newMxArray,0,(char*)"data")));
1054 // //printf("done\n");
1055 // stafield stOut(shape,L,field_storage,field_type,datap);
1056 // set_death(&stOut);
1057 // return stOut;
1058 // }
1059 
1060  static stafield createFieldAndmxStruct( mxArray * & newMxArray,
1061  const std::size_t shape[],
1062  int L,
1065  const T element_size[]=NULL)
1066  {
1067  int numcomponents=hanalysis::order2numComponents(field_storage,field_type,L);
1068 
1069  mwSize ndims[5];
1070  ndims[0] = 2;
1071  ndims[1] = numcomponents;
1072  ndims[2]=shape[2];
1073  ndims[3]=shape[1];
1074  ndims[4]=shape[0];
1075 
1076  const char *field_names[] = {"storage","type","L","data","shape","element_size"};
1077 
1078  mwSize dim = 1;
1079  newMxArray=mxCreateStructArray(1,&dim,6,field_names);
1080 
1081  mxArray *theL = mxCreateNumericArray(1,&dim,mxDOUBLE_CLASS,mxREAL);
1082  double *s = (double*) mxGetData(theL);
1083  *s = L;
1084 
1085  mwSize dims[2]={1,3};
1086  dim=2;
1087  mxArray *theSHAPE = mxCreateNumericArray(dim,dims,mxDOUBLE_CLASS,mxREAL);
1088  s = (double*) mxGetData(theSHAPE);
1089  s[0] = shape[2];
1090  s[1] = shape[1];
1091  s[2] = shape[0];
1092 
1093 
1094  mxArray *theELEMENT_SIZE = mxCreateNumericArray(dim,dims,mxDOUBLE_CLASS,mxREAL);
1095  s = (double*) mxGetData(theELEMENT_SIZE);
1096  s[0]=s[1]=s[2]=T(1);
1097 
1098  if (element_size!=NULL)
1099  {
1100  s[0] = element_size[2];
1101  s[1] = element_size[1];
1102  s[2] = element_size[0];
1103  }
1104 
1105 
1106 // printf("--> %f %f %f\n",s[0],s[1],s[2]);
1107 
1108  mxSetField(newMxArray,0,"storage", mxCreateString(enumtostring_storage(field_storage).c_str()));
1109  mxSetField(newMxArray,0,"type", mxCreateString(enumtostring_type(field_type).c_str()));
1110  mxSetField(newMxArray,0,"L", theL);
1111  mxSetField(newMxArray,0,"data", mxCreateNumericArray(5,ndims,mex_getClassId<T>(),mxREAL));
1112  mxSetField(newMxArray,0,"shape", theSHAPE);
1113  mxSetField(newMxArray,0,"element_size", theELEMENT_SIZE);
1114 
1115 
1116  std::complex<T> * datap=(std::complex<T> *) (mxGetData(mxGetField(newMxArray,0,(char *)"data")));
1117 
1118 // T element_size_matlaborder[3];
1119 // element_size_matlaborder[0]=element_size[];
1120 // element_size_matlaborder[1]=element_size[1];
1121 // element_size_matlaborder[2]=element_size[0];
1122  stafield stOut(shape,L,field_storage,field_type,datap,0,element_size);
1123  _stafield<T>::set_death(&stOut);
1124  return stOut;
1125  }
1126 
1127 
1128  static stafield createFieldAndmxArray( mxArray * & newMxArray,
1129  const std::size_t shape[],
1130  int L,
1133  const T element_size[]=NULL)
1134  {
1135  int numcomponents=hanalysis::order2numComponents(field_storage,field_type,L);
1136 
1137  int ndims[5];
1138  ndims[0] = 2;
1139  ndims[1] = numcomponents;
1140  ndims[2]=shape[2];
1141  ndims[3]=shape[1];
1142  ndims[4]=shape[0];
1143  newMxArray = mxCreateNumericArray(5,ndims,mex_getClassId<T>(),mxREAL);
1144 
1145  stafield stOut(shape,L,field_storage,field_type, (std::complex<T> *) (mxGetData(newMxArray)),element_size);
1146  _stafield<T>::set_death(&stOut);
1147  return stOut;
1148  }
1149 
1150 #endif
1151 
1152 
1153 
1154 
1155 
1156  ~stafield()
1157  {
1158  if (this->own_memory && (this->data!=NULL))
1159  {
1160  if (do_classcount)
1161  printf("destroying stafield %i / remaining: %i [own]",this->classcount_id,--classcount);
1162 
1163  if (this->object_is_dead_soon<2)
1164  {
1165  if (do_classcount)
1166  printf(" (deleting data)\n");
1167 
1168  if (hanalysis::verbose>0)
1169  printf("field destrucor -> deleting data\n");
1170  delete [] this->data;
1171  }
1172  else
1173  if (do_classcount)
1174  printf(" (not deleting data, still having references)\n");
1175  } else
1176  {
1177  if (do_classcount)
1178  {
1179  if (this->L==-1)
1180  printf("destroying stafield %i / remaining: %i [empty]\n",this->classcount_id,--classcount);
1181  else
1182  printf("destroying stafield %i / remaining: %i [view]\n",this->classcount_id,--classcount);
1183  }
1184  if (hanalysis::verbose>0)
1185  printf("field destrucor -> --\n");
1186  }
1187 
1188 
1189  }
1190 
1191 
1192  /*#############################################################
1193  *
1194  * methods
1195  *
1196  *#############################################################*/
1197 
1198 
1199  std::complex<T> sum() const {
1200  std::complex<T> Sum=0;
1201  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
1202  std::size_t numel=this->getNumVoxel()*numcomponents;
1203  const std::complex<T> * data=this->getDataConst();
1204  for (std::size_t i=0;i<numel;i++)
1205  Sum+=*(data++);
1206  return Sum;
1207  }
1208 
1209 
1210 
1211 
1217  {
1218  if (this->own_memory) return false;
1219 
1220 // if (this->field_type!=hanalysis::STA_OFIELD_SINGLE)
1221 // throw STAError("operator= this cannot happen ! the input field must be STA_OFIELD_SINGLE");
1222 
1223  std::complex<T> * own_mem=NULL;
1224 
1225  // copy here
1226  if (this->stride==0)
1227  {
1228  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
1229  if (hanalysis::verbose>0)
1230  printf("copying field with %i components\n",numcomponents);
1231  if (hanalysis::verbose>0)
1232  printf("copying %i bytes\n",this->shape[0]*this->shape[1]*this->shape[2]*numcomponents*sizeof(std::complex<T>));
1233  own_mem=new std::complex<T>[this->shape[0]*this->shape[1]*this->shape[2]*numcomponents];
1234  memcpy(own_mem,this->data,this->shape[0]*this->shape[1]*this->shape[2]*numcomponents*sizeof(std::complex<T>));
1235  }
1236  else
1237  {
1238  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
1239  own_mem=new std::complex<T>[this->shape[0]*this->shape[1]*this->shape[2]*numcomponents];
1240 
1241  //printf("%d %d\n",numcomponents,this->getStride());
1242  numcomponents*=2;
1243 
1244  int strid_in=2*(this->getStride())-numcomponents;
1245  std::size_t jumpz=this->shape[1]*this->shape[2];
1246  int strid_in_all=jumpz*this->getStride();
1247  int strid_out_all=jumpz*numcomponents/2;
1248 
1249  #pragma omp parallel for num_threads(get_numCPUs())
1250  for (std::size_t z=0;z<this->shape[0];z++)
1251  {
1252  T * in=(T*)(this->data+z*strid_in_all);
1253  T * out=(T*)(own_mem+z*strid_out_all);
1254  for (std::size_t a=0;a<jumpz;a++)
1255  {
1256  for (int b=0;b<numcomponents;b++)
1257  (*out++)=(*in++);
1258  in+=strid_in;
1259  }
1260  }
1261  this->stride=0;
1262  }
1263 
1264  std::swap(this->data,own_mem);
1265  this->own_memory=true;
1266  this->object_is_dead_soon=0;
1267  return true;
1268  }
1269 
1270 
1274  std::complex<T> * getData() {
1275  return this->data;
1276  };
1277 
1281  const std::complex<T> * getDataConst() const {
1282  return this->data;
1283  };
1284 
1285 
1286 
1287 
1288 
1293  stafield get(int l) const
1294  {
1295  if (l<0)
1296  throw (hanalysis::STAError("error retrieving (sub) field l, l must be >= 0",STA_RESULT_INVALID_TENSOR_RANK));
1297  if (l>this->L)
1298  throw (hanalysis::STAError("error retrieving (sub) field l, l must be <= L"));
1299 
1300  if ((this->field_type==STA_OFIELD_ODD)&&(l%2==0))
1301  throw (hanalysis::STAError("error retrieving (sub) field l, l must be odd"));
1302 
1303  if ((this->field_type==STA_OFIELD_EVEN)&&(l%2!=0))
1304  throw (hanalysis::STAError("error retrieving (sub) field l, l must be even"));
1305 
1306  if ((this->field_type==STA_OFIELD_SINGLE)&&(l!=this->L))
1307  throw (hanalysis::STAError("error retrieving (sub) field l, l must be equal to L"));
1308 
1309 
1310  std::complex<T> * component_data;
1311  int offset=hanalysis::getComponentOffset(this->field_storage,this->field_type,l);
1312  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
1313 
1314  //printf("%d %d\n",offset,numcomponents);
1315 
1316  component_data=this->data+offset;
1317 
1318  stafield view(this->shape,
1319  l,
1320  this->field_storage,
1322  component_data);
1323  this->set_death(&view);
1324  view.stride=numcomponents;
1325 
1326  view.setElementSize(this->getElementSize());
1327  return view;
1328  }
1329 
1330 
1331  stafield get(int l,int m) const
1332  {
1333  if (l<0)
1334  throw (hanalysis::STAError("error retrieving (sub) field l, l must be >= 0",STA_RESULT_INVALID_TENSOR_RANK));
1335  if (l>this->L)
1336  throw (hanalysis::STAError("error retrieving (sub) field l, l must be <= L"));
1337 
1338  if ((this->field_type==STA_OFIELD_ODD)&&(l%2==0))
1339  throw (hanalysis::STAError("error retrieving (sub) field l, l must be odd"));
1340 
1341  if ((this->field_type==STA_OFIELD_EVEN)&&(l%2!=0))
1342  throw (hanalysis::STAError("error retrieving (sub) field l, l must be even"));
1343 
1344  if ((this->field_type==STA_OFIELD_SINGLE)&&(l!=this->L))
1345  throw (hanalysis::STAError("error retrieving (sub) field l, l must be equal to L"));
1346 
1347  if (std::abs(m)>l)
1348  throw (hanalysis::STAError("error retrieving (sub) field l,m, |m|>l!"));
1349  if ((m>0)&&(this->field_storage!=hanalysis::STA_FIELD_STORAGE_C))
1350  throw (hanalysis::STAError("error retrieving (sub) field l,m, storage m>0 but not STA_FIELD_STORAGE_C"));
1351 
1352 
1353  std::complex<T> * component_data;
1354  int offset=hanalysis::getComponentOffset(this->field_storage,this->field_type,l);
1355  offset+=l+m;
1356  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
1357 
1358  component_data=this->data+offset;
1359 
1360  stafield view(this->shape,
1361  0,
1362  this->field_storage,
1364  component_data);
1365  this->set_death(&view);
1366  view.stride=numcomponents;
1367 
1368  view.setElementSize(this->getElementSize());
1369  return view;
1370  }
1371 
1372  std::complex<T> get(int l,int m,int Z,int Y,int X) const
1373  {
1374  try{
1375  stafield tmp=this->get(l,m);
1376  std::size_t stride=tmp.getStride();
1377  const std::complex<T> * datap=tmp.getDataConst();
1378  std::size_t voxel=X+(this->shape[2]*(Y+this->shape[1]*Z));
1379  if (voxel>this->getNumVoxel())
1380  throw (hanalysis::STAError("error : point out of image boundaries"));
1381 
1382  return (*(datap+voxel*stride));
1383  }
1384  catch (hanalysis::STAError & error)
1385  {
1386  throw error;
1387  }
1388  }
1389 
1390  std::complex<T> set(int l,int m,int Z,int Y,int X, std::complex<T> value)
1391  {
1392  try{
1393  stafield tmp=this->get(l,m);
1394  std::size_t stride=tmp.getStride();
1395  std::complex<T> * datap=tmp.getData();
1396  std::size_t voxel=X+(this->shape[2]*(Y+this->shape[1]*Z));
1397  if (voxel>this->getNumVoxel())
1398  throw (hanalysis::STAError("error : point out of image boundaries"));
1399 
1400  (*(datap+voxel*stride))=value;
1401  }
1402  catch (hanalysis::STAError & error)
1403  {
1404  throw error;
1405  }
1406  }
1407 
1408 
1409 
1410 
1411 
1412  /*#############################################################
1413  *
1414  * static STA operators
1415  *
1416  *#############################################################*/
1417 
1419 
1437  static void FFT(const stafield & stIn,
1438  stafield & stOut,
1439  bool forward,
1440  bool conjugate=false,
1441  std::complex<T> alpha= T( 1 ),
1442 #ifdef _STA_LINK_FFTW
1443  int flag=FFTW_ESTIMATE )
1444 #else
1445  int flag=0 )
1446 #endif
1447  {
1448  if ((!_stafield<T>::equalShape(stIn,stOut))||
1449  (stIn.field_type!=stOut.field_type)||
1450  (stIn.L!=stOut.L)||
1453  (stIn.field_storage!=stOut.field_storage)))
1454 // (!((((stIn.field_storage==hanalysis::STA_FIELD_STORAGE_R)
1455 // ||(stIn.field_storage==hanalysis::STA_FIELD_STORAGE_RF))&&
1456 // ((stOut.field_storage==hanalysis::STA_FIELD_STORAGE_R)||
1457 // (stOut.field_storage==hanalysis::STA_FIELD_STORAGE_RF)))||
1458 // (stIn.field_storage==stOut.field_storage))))
1459  throw (hanalysis::STAError("FFT: shapes differ!",STA_RESULT_SHAPE_MISMATCH));
1460 
1461  std::size_t ncomponents_in=hanalysis::order2numComponents(stIn.getStorage(),stIn.getType(),stIn.L);
1462  std::size_t ncomponents_out=hanalysis::order2numComponents(stOut.getStorage(),stOut.getType(),stOut.L);
1463  if (((stIn.stride!=0)&&(ncomponents_in!=stIn.stride))||((stOut.stride!=0)&&(ncomponents_out!=stOut.stride)))
1464  throw (hanalysis::STAError("FFT: doesn't work on this kind of views!"));
1465  if ((stIn.data==stOut.data))
1466  throw (hanalysis::STAError("FFT: inplace not supported!"));
1467 
1468 
1469  hanalysis::STA_FIELD_STORAGE new_field_storage=stIn.getStorage();
1470  if (new_field_storage==hanalysis::STA_FIELD_STORAGE_R)
1471  new_field_storage=hanalysis::STA_FIELD_STORAGE_RF;
1472  else
1473  if (new_field_storage==hanalysis::STA_FIELD_STORAGE_RF)
1474  new_field_storage=hanalysis::STA_FIELD_STORAGE_R;
1475  stOut.field_storage=new_field_storage;
1476 
1477  if ((stIn.getStorage()==STA_FIELD_STORAGE_C)&&(stOut.getStorage()!=STA_FIELD_STORAGE_C))
1478  throw (hanalysis::STAError("FFT: storage type must be the same",STA_RESULT_STORAGE_MISMATCH));
1479 
1480 
1481 
1482 
1483  int stride_in = stIn.getStride();
1484  int stride_out = stOut.getStride();
1485  int ncomponents=hanalysis::order2numComponents(stIn.getStorage(),stIn.getType(),stIn.L);
1486 
1487  if (hanalysis::verbose>0)
1488  printf("FFT: stride_in: %i stride_out %i , ncomp: %i\n",stride_in,stride_out,ncomponents);
1489  //int err=0;
1491  stIn.getDataConst(),
1492  stOut.getData(),
1493  stIn.getShape(),
1494  ncomponents,
1495  forward,
1496  conjugate,
1497  alpha,
1498  flag);
1499  if (err!=STA_RESULT_SUCCESS)
1500  throw (hanalysis::STAError("FFT: error! "+errortostring(err),err));
1501 
1502  stOut.setElementSize(stIn.getElementSize());
1503  }
1504 
1505 
1506 
1507 
1509 
1516  static void Mult(const stafield & stIn,
1517  stafield & stOut,
1518  std::complex<T> alpha= T( 1 ),
1519  bool conjugate=false,
1520  bool clear_result = false)
1521  {
1522  if (stIn!=stOut)
1523  throw (hanalysis::STAError("Mult: shapes differ!",STA_RESULT_SHAPE_MISMATCH));
1524  if (stIn.getStorage()!=stOut.getStorage())
1525  throw (hanalysis::STAError("Mult: storage type must be the same",STA_RESULT_STORAGE_MISMATCH));
1526  int stride_in = stIn.getStride();
1527  int stride_out = stOut.getStride();
1528  int ncomponents=hanalysis::order2numComponents(stIn.getStorage(),stIn.getType(),stIn.L);
1529 
1530  if (hanalysis::verbose>0)
1531  printf("Mult: stride_in: %i stride_out %i , ncomp: %i\n",stride_in,stride_out,ncomponents);
1532 
1533  STA_RESULT err=hanalysis::sta_mult<T,std::complex<T> > (
1534  stIn.getDataConst(),
1535  stOut.getData(),
1536  stIn.getShape(),
1537  ncomponents,
1538  alpha,
1539  conjugate,
1540  stride_in,
1541  stride_out,
1542  clear_result);
1543 
1544  if (err!=STA_RESULT_SUCCESS)
1545  throw (hanalysis::STAError("Mult: error! "+errortostring(err),err));
1546 
1547  stOut.setElementSize(stIn.getElementSize());
1548  }
1549 
1550 
1551  static void Fspecial(const stafield & stIn,
1552  stafield & stOut,
1553  const sta_fspecial_func<T> & fsp,
1554  bool clear_result = false)
1555  {
1556  if (stIn!=stOut)
1557  throw (hanalysis::STAError("Fspecial: shapes differ!",STA_RESULT_SHAPE_MISMATCH));
1558  if (stIn.getStorage()!=stOut.getStorage())
1559  throw (hanalysis::STAError("Fspecial: storage type must be the same",STA_RESULT_STORAGE_MISMATCH));
1560  int stride_in = stIn.getStride();
1561  int stride_out = stOut.getStride();
1562  int ncomponents=hanalysis::order2numComponents(stIn.getStorage(),stIn.getType(),stIn.L);
1563 
1564  if (hanalysis::verbose>0)
1565  printf("Fspecial: stride_in: %i stride_out %i , ncomp: %i\n",stride_in,stride_out,ncomponents);
1566 
1567  STA_RESULT err=hanalysis::sta_special (
1568  stIn.getDataConst(),
1569  stOut.getData(),
1570  stIn.getShape(),
1571  fsp,
1572  ncomponents,
1573  stride_in,
1574  stride_out,
1575  clear_result);
1576 
1577  if (err!=STA_RESULT_SUCCESS)
1578  throw (hanalysis::STAError("Fspecial: error!"+errortostring(err),err));
1579 
1580  stOut.setElementSize(stIn.getElementSize());
1581  }
1582 
1584 
1588  static void Norm(const stafield & stIn,
1589  stafield & stOut,
1590  bool clear_result = false)
1591  {
1592  if (!stafield::equalShape(stIn,stOut))
1593  throw (hanalysis::STAError("Norm: shapes differ!",STA_RESULT_SHAPE_MISMATCH));
1594  if (stOut.getRank()!=0)
1595  throw (hanalysis::STAError("Norm: stOut must be 0-order tensor field!!",STA_RESULT_INVALID_TENSOR_RANK));
1596  if (stIn.getType()!=hanalysis::STA_OFIELD_SINGLE)
1597  throw (hanalysis::STAError("Deriv: first input field type must be STA_OFIELD_SINGLE",STA_RESULT_OFIELD_TYPE_MISMATCH));
1598  if (stOut.getType()!=stIn.getType())
1599  throw (hanalysis::STAError("Deriv: stOut field type must be STA_OFIELD_SINGLE",STA_RESULT_OFIELD_TYPE_MISMATCH));
1600 
1601  if (stIn.getStorage()!=stOut.getStorage())
1602  throw (hanalysis::STAError("Norm: storage type must be the same",STA_RESULT_STORAGE_MISMATCH));
1603  int stride_in = stIn.getStride();
1604  int stride_out = stOut.getStride();
1605 
1606  if (hanalysis::verbose>0)
1607  printf("Norm: stride_in: %i stride_out %i\n",stride_in,stride_out);
1608 
1609  STA_RESULT err=hanalysis::sta_norm<T> (
1610  stIn.getDataConst(),
1611  stOut.getData(),
1612  stIn.getShape(),
1613  stIn.getRank(),
1614  stIn.getStorage(),
1615  stride_in,
1616  stride_out,
1617  clear_result);
1618 
1619  if (err!=STA_RESULT_SUCCESS)
1620  throw (hanalysis::STAError("Norm: error!"+errortostring(err),err));
1621 
1622 
1623  stOut.setElementSize(stIn.getElementSize());
1624  }
1625 
1626 
1628 
1654  static void Deriv(const stafield & stIn,
1655  stafield & stOut,
1656  int Jupdown,
1657  bool conjugate=false,
1658  std::complex<T> alpha= T( 1 ),
1659  bool clear_result = false,
1660  int accuracy=0
1661  )
1662  {
1663  if (!stafield::equalShape(stIn,stOut))
1664  throw (hanalysis::STAError("Deriv: shapes differ!",STA_RESULT_SHAPE_MISMATCH));
1665  if (stIn.getStorage()!=stOut.getStorage())
1666  throw (hanalysis::STAError("Deriv: storage type must be the same",STA_RESULT_STORAGE_MISMATCH));
1667  if (stIn.getType()!=hanalysis::STA_OFIELD_SINGLE)
1668  throw (hanalysis::STAError("Deriv: first input field type must be STA_OFIELD_SINGLE",STA_RESULT_OFIELD_TYPE_MISMATCH));
1669  if (stOut.getType()!=stIn.getType())
1670  throw (hanalysis::STAError("Deriv: stOut field type must be STA_OFIELD_SINGLE",STA_RESULT_OFIELD_TYPE_MISMATCH));
1671  if (stOut.getRank()!=stIn.getRank()+Jupdown)
1672  throw (hanalysis::STAError("Deriv: stOut rank must be input rank+Jupdown",STA_RESULT_INVALID_TENSOR_RANK));
1673 
1674  int stride_in = stIn.getStride();
1675  int stride_out = stOut.getStride();
1676 
1677  if (hanalysis::verbose>0)
1678  printf("Deriv: stride_in: %i stride_out %i\n",stride_in,stride_out);
1679 
1681  stIn.getDataConst(),
1682  stOut.getData(),
1683  stIn.getShape(),
1684  stIn.getRank(),
1685  Jupdown,
1686  conjugate,
1687  alpha,
1688  stIn.getStorage(),
1689  stIn.getElementSize(),
1690  stride_in,
1691  stride_out,
1692  clear_result,
1693  accuracy);
1694 
1695 // printf("ok? nan %d inf %d\n",
1696 // hanalysis::stafield<T>::Is_nan(stOut),
1697 // hanalysis::stafield<T>::Is_inf(stOut));
1698 
1699  if (err!=STA_RESULT_SUCCESS)
1700  throw (hanalysis::STAError("Deriv: error!"+errortostring(err),err));
1701 
1702  stOut.setElementSize(stIn.getElementSize());
1703  }
1704 
1705 
1706 
1708 
1734  static void Deriv2(const stafield & stIn,
1735  stafield & stOut,
1736  int Jupdown,
1737  bool conjugate=false,
1738  std::complex<T> alpha= T( 1 ),
1739  bool clear_result = false)
1740  {
1741  if (!stafield::equalShape(stIn,stOut))
1742  throw (hanalysis::STAError("Deriv2: shapes differ!"));
1743  if (stIn.getStorage()!=stOut.getStorage())
1744  throw (hanalysis::STAError("Deriv2: storage type must be the same"));
1745  if (stIn.getType()!=hanalysis::STA_OFIELD_SINGLE)
1746  throw (hanalysis::STAError("Deriv2: first input field type must be STA_OFIELD_SINGLE"));
1747  if (stOut.getType()!=stIn.getType())
1748  throw (hanalysis::STAError("Deriv2: stOut field type must be STA_OFIELD_SINGLE"));
1749  if (stOut.getRank()!=stIn.getRank()+Jupdown)
1750  throw (hanalysis::STAError("Deriv2: stOut rank must be input rank+Jupdown"));
1751 
1752  int stride_in = stIn.getStride();
1753  int stride_out = stOut.getStride();
1754 
1755  if (hanalysis::verbose>0)
1756  printf("Deriv2: stride_in: %i stride_out %i\n",stride_in,stride_out);
1757 
1759  stIn.getDataConst(),
1760  stOut.getData(),
1761  stIn.getShape(),
1762  stIn.getRank(),
1763  Jupdown,
1764  conjugate,
1765  alpha,
1766  stIn.getStorage(),
1767  stIn.getElementSize(),//(T * )NULL,
1768  stride_in,
1769  stride_out,
1770  clear_result);
1771 
1772  if (err!=STA_RESULT_SUCCESS)
1773  throw (hanalysis::STAError("Deriv2: error!"+errortostring(err),err));
1774 
1775  stOut.setElementSize(stIn.getElementSize());
1776  }
1777 
1778 
1779  static bool Is_nan(const stafield & stIn)
1780  {
1781 
1782  int stride_in = stIn.getStride();
1783  int ncomponents=hanalysis::order2numComponents(stIn.getStorage(),stIn.getType(),stIn.L);
1784 
1785  return hanalysis::sta_isnan (
1786  stIn.getDataConst(),
1787  stIn.getShape(),
1788  ncomponents);
1789  }
1790 
1791  static bool Is_inf(const stafield & stIn)
1792  {
1793 
1794  int stride_in = stIn.getStride();
1795  int ncomponents=hanalysis::order2numComponents(stIn.getStorage(),stIn.getType(),stIn.L);
1796 
1797  return hanalysis::sta_isinf (
1798  stIn.getDataConst(),
1799  stIn.getShape(),
1800  ncomponents);
1801  }
1802 
1803 
1804 
1806 
1816  static void Lap(const stafield & stIn,
1817  stafield & stOut,
1818  std::complex<T> alpha= T( 1 ),
1819  bool clear_result = false,
1820  int type=1)
1821  {
1822  if (stIn.getStorage()!=stOut.getStorage())
1823  throw (hanalysis::STAError("Lap: storage type must be the same",STA_RESULT_STORAGE_MISMATCH));
1824  if (stIn!=stOut)
1825  throw (hanalysis::STAError("Lap: shapes differ!",STA_RESULT_SHAPE_MISMATCH));
1826  int stride_in = stIn.getStride();
1827  int stride_out = stOut.getStride();
1828  int ncomponents=hanalysis::order2numComponents(stIn.getStorage(),stIn.getType(),stIn.L);
1829 
1830 
1831  if (hanalysis::verbose>0)
1832  printf("Lap: stride_in: %i stride_out %i , ncomp: %i\n",stride_in,stride_out,ncomponents);
1833 
1835  stIn.getDataConst(),
1836  stOut.getData(),
1837  stIn.getShape(),
1838  ncomponents,
1839  type,
1840  alpha,
1841  stIn.getStorage(),
1842  stIn.getElementSize(),//(T * )NULL,
1843  stride_in,
1844  stride_out,
1845  clear_result);
1846 
1847  if (err!=STA_RESULT_SUCCESS)
1848  throw (hanalysis::STAError("Lap: error!"+errortostring(err),err));
1849 
1850  stOut.setElementSize(stIn.getElementSize());
1851  }
1852 
1854 
1876  static void Prod(const stafield & stIn1,
1877  const stafield & stIn2,
1878  stafield & stOut,
1879  int J,
1880  bool normalize=false,
1881  std::complex<T> alpha= T( 1 ),
1882  bool clear_result = false)
1883  {
1884 // printf("storage stIn1: %s \n",enumtostring(stIn1.getStorage()).c_str());
1885 // printf("storage stIn2: %s \n",enumtostring(stIn2.getStorage()).c_str());
1886 // printf("storage stOut: %s \n",enumtostring(stOut.getStorage()).c_str());
1887 
1888  //printf("%d %d %d \n",stIn1.getRank(),stIn2.getRank(),stOut.getRank());
1889 
1890  if ( ( std::abs ( stIn1.getRank()-stIn2.getRank() ) >J ) ||
1891  ( J>std::abs ( stIn1.getRank()+stIn2.getRank() ) ) )
1892  throw (hanalysis::STAError("Prod: ensure that |l1-l2|<=J && |l1+l2|<=J",STA_RESULT_INVALID_PRODUCT));
1893  if ( ( ( stIn1.getRank()+stIn2.getRank()+J ) %2!=0 ) && ( normalize ) )
1894  throw (hanalysis::STAError("Prod: ensure that l1+l2+J even",STA_RESULT_INVALID_PRODUCT));
1895 
1896  if (stOut.getRank()!=J)
1897  throw (hanalysis::STAError("Prod: stOut has wrong Rank!",STA_RESULT_INVALID_TENSOR_RANK));
1898 
1899 
1900  if ((!stafield::equalShape(stIn1,stOut))||(!stafield::equalShape(stIn2,stOut)))
1901  throw (hanalysis::STAError("Prod: shapes differ!",STA_RESULT_SHAPE_MISMATCH));
1902  if ((stIn1.getStorage()!=stOut.getStorage())||(stIn2.getStorage()!=stOut.getStorage()))
1903  throw (hanalysis::STAError("Prod: storage type must be the same",STA_RESULT_STORAGE_MISMATCH));
1904  if (stIn1.getType()!=hanalysis::STA_OFIELD_SINGLE)
1905  throw (hanalysis::STAError("Prod: first input field type must be STA_OFIELD_SINGLE",STA_RESULT_OFIELD_TYPE_MISMATCH));
1906  if (stIn1.getType()!=stIn2.getType())
1907  throw (hanalysis::STAError("Prod: first input field type must be STA_OFIELD_SINGLE",STA_RESULT_OFIELD_TYPE_MISMATCH));
1908  if (stOut.getType()!=stIn1.getType())
1909  throw (hanalysis::STAError("Prod: stOut field type must be STA_OFIELD_SINGLE",STA_RESULT_OFIELD_TYPE_MISMATCH));
1910 
1911  int stride_in1 = stIn1.getStride();
1912  int stride_in2 = stIn2.getStride();
1913  int stride_out = stOut.getStride();
1914 
1915  if (hanalysis::verbose>0)
1916  printf("Prod: stride_in1: %i,stride_in2: %i stride_out %i\n",stride_in1,stride_in2,stride_out);
1917 
1918 
1919 
1920 
1922  stIn1.getDataConst(),
1923  stIn2.getDataConst(),
1924  stOut.getData(),
1925  stIn1.getShape(),
1926  stIn1.getRank(),
1927  stIn2.getRank(),
1928  stOut.getRank(),
1929  alpha,
1930  normalize,
1931  stIn1.getStorage(),
1932  stride_in1,
1933  stride_in2,
1934  stride_out,
1935  clear_result);
1936 
1937  if (err!=STA_RESULT_SUCCESS)
1938  {
1939  throw (hanalysis::STAError("Prod: error!"+errortostring(err),err));
1940  }
1941 
1942 
1943  stOut.setElementSize(stIn1.getElementSize());
1944  }
1945 
1946 
1947  static void Prod3(const stafield & stIn1,
1948  const stafield & stIn2,
1949  const stafield & stIn3,
1950  stafield & stOut,
1951  int Jprod1,
1952  int Jprod2,
1953  bool normalize=false,
1954  std::complex<T> alpha= T( 1 ),
1955  bool clear_result = false)
1956  {
1957  if ( ( std::abs ( stIn1.getRank()-stIn2.getRank() ) >Jprod1 ) ||
1958  ( Jprod1>std::abs ( stIn1.getRank()+stIn2.getRank() ) ) )
1959  throw (hanalysis::STAError("Prod: ensure that |l1-l2|<=J && |l1+l2|<=J",STA_RESULT_INVALID_PRODUCT));
1960  if ( ( ( stIn1.getRank()+stIn2.getRank()+Jprod1 ) %2!=0 ) && ( normalize ) )
1961  throw (hanalysis::STAError("Prod: ensure that l1+l2+J even",STA_RESULT_INVALID_PRODUCT));
1962 
1963  if ( ( std::abs ( stIn3.getRank()-Jprod1 ) >Jprod2 ) ||
1964  ( Jprod1>std::abs ( Jprod1+stIn3.getRank() ) ) )
1965  throw (hanalysis::STAError("Prod: ensure that |l1-l2|<=J && |l1+l2|<=J",STA_RESULT_INVALID_PRODUCT));
1966  if ( ( ( stIn3.getRank()+Jprod2+Jprod1 ) %2!=0 ) && ( normalize ) )
1967  throw (hanalysis::STAError("Prod: ensure that l1+l2+J even",STA_RESULT_INVALID_PRODUCT));
1968 
1969  if (stOut.getRank()!=Jprod2)
1970  throw (hanalysis::STAError("Prod: stOut has wrong Rank!",STA_RESULT_INVALID_TENSOR_RANK));
1971 
1972 
1973  if ((!stafield::equalShape(stIn1,stOut))||(!stafield::equalShape(stIn2,stOut))||(!stafield::equalShape(stIn3,stOut)))
1974  throw (hanalysis::STAError("Prod: shapes differ!",STA_RESULT_SHAPE_MISMATCH));
1975  if ((stIn1.getStorage()!=stOut.getStorage())||(stIn2.getStorage()!=stOut.getStorage())||(stIn3.getStorage()!=stOut.getStorage()))
1976  throw (hanalysis::STAError("Prod: storage type must be the same",STA_RESULT_STORAGE_MISMATCH));
1977  if (stIn1.getType()!=hanalysis::STA_OFIELD_SINGLE)
1978  throw (hanalysis::STAError("Prod: first input field type must be STA_OFIELD_SINGLE",STA_RESULT_OFIELD_TYPE_MISMATCH));
1979  if (stIn1.getType()!=stIn2.getType())
1980  throw (hanalysis::STAError("Prod: first input field type must be STA_OFIELD_SINGLE",STA_RESULT_OFIELD_TYPE_MISMATCH));
1981  if (stOut.getType()!=stIn1.getType())
1982  throw (hanalysis::STAError("Prod: stOut field type must be STA_OFIELD_SINGLE",STA_RESULT_OFIELD_TYPE_MISMATCH));
1983  if (stOut.getType()!=stIn3.getType())
1984  throw (hanalysis::STAError("Prod: stOut field type must be STA_OFIELD_SINGLE",STA_RESULT_OFIELD_TYPE_MISMATCH));
1985 
1986  int stride_in1 = stIn1.getStride();
1987  int stride_in2 = stIn2.getStride();
1988  int stride_in3 = stIn3.getStride();
1989  int stride_out = stOut.getStride();
1990 
1991  if (hanalysis::verbose>0)
1992  printf("Prod: stride_in1: %i,stride_in2: %i stride_out %i\n",stride_in1,stride_in2,stride_out);
1993 
1994 
1995 
1996 
1997  STA_RESULT err=hanalysis::sta_3product(
1998  stIn1.getDataConst(),
1999  stIn2.getDataConst(),
2000  stIn3.getDataConst(),
2001  stOut.getData(),
2002  stIn1.getShape(),
2003  stIn1.getRank(),
2004  stIn2.getRank(),
2005  stIn3.getRank(),
2006  Jprod1,
2007  stOut.getRank(),
2008  alpha,
2009  normalize,
2010  stIn1.getStorage(),
2011  stride_in1,
2012  stride_in2,
2013  stride_in3,
2014  stride_out,
2015  clear_result);
2016 
2017  if (err!=STA_RESULT_SUCCESS)
2018  {
2019  throw (hanalysis::STAError("Prod: error!"+errortostring(err),err));
2020  }
2021 
2022 
2023  stOut.setElementSize(stIn1.getElementSize());
2024  }
2025 
2026 
2027 
2028  static std::vector<T> kernel_param(std::string params)
2029  {
2030  for (std::size_t a=0;a<params.length();a++)
2031  if (params[a]==',')
2032  params[a]=' ';
2033  std::vector<T> param_v;
2034  std::stringstream param_s;
2035  param_s<<params;
2036  int eexit=0;
2037  while (!param_s.eof() && param_s.good())
2038  {
2039  T tmp;
2040  param_s>>tmp;
2041  param_v.push_back(tmp);
2042  eexit++;
2043  if (eexit>42)
2044  throw STAError("ahhh, something went completely wrong while parsing parameters! ");
2045  }
2046  return param_v;
2047  }
2048 
2049 
2050  static void makeKernel(std::string kernelname,
2051  std::vector<T> param_v,
2052  stafield & stIn,
2053  bool centered=false)
2054  {
2055  if (stIn.getType()!=hanalysis::STA_OFIELD_SINGLE)
2056  throw (hanalysis::STAError("makeKernel: first input field type must be STA_OFIELD_SINGLE"));
2057 
2058  hanalysis::Kernel<T> * currentKernel=NULL;
2059  hanalysis::STA_CONVOLUTION_KERNELS kernel=hanalysis::STA_CONV_KERNEL_UNKNOWN;
2060 
2061  if (kernelname=="gauss")
2062  kernel=hanalysis::STA_CONV_KERNEL_GAUSS;
2063  if (kernelname=="gaussLaguerre")
2064  kernel=hanalysis::STA_CONV_KERNEL_GAUSS_LAGUERRE;
2065  if (kernelname=="gaussBessel")
2066  kernel=hanalysis::STA_CONV_KERNEL_GAUSS_BESSEL;
2067  if (kernelname=="sh")
2068  kernel=hanalysis::STA_CONV_KERNEL_SH;
2069  if (kernelname=="fourier")
2070  kernel=hanalysis::STA_CONV_KERNEL_FOURIER;
2071 
2072  switch (kernel)
2073  {
2074  case hanalysis::STA_CONV_KERNEL_FOURIER:
2075  {
2076  if (!(param_v.size()==2))
2077  throw STAError("error: wrong numger of parameters \n");
2078 
2079  currentKernel=new hanalysis::Fourier<T>();
2080  ((hanalysis::Fourier<T> *)currentKernel)->setRadius(param_v[0]);
2081  ((hanalysis::Fourier<T> *)currentKernel)->setRadFunc(param_v[1]);
2082  }break;
2083  case hanalysis::STA_CONV_KERNEL_SH:
2084  {
2085  if (!(param_v.size()==2))
2086  throw STAError("error: wrong numger of parameters \n");
2087 
2088  currentKernel=new hanalysis::SH<T>();
2089  ((hanalysis::SH<T> *)currentKernel)->setRadius(param_v[0]);
2090  ((hanalysis::SH<T> *)currentKernel)->setSmooth(param_v[1]);
2091  }break;
2092  case hanalysis::STA_CONV_KERNEL_GAUSS:
2093  {
2094  if (!(param_v.size()==1))
2095  throw STAError("error: wrong numger of parameters");
2096 
2097  currentKernel=new hanalysis::Gauss<T>();
2098  ((hanalysis::Gauss<T> *)currentKernel)->setSigma(param_v[0]);
2099  }break;
2100  case hanalysis::STA_CONV_KERNEL_GAUSS_LAGUERRE:
2101  {
2102  if (!(param_v.size()==2))
2103  throw STAError("error: wrong numger of parameters");
2104  currentKernel=new hanalysis::GaussLaguerre<T>();
2105  ((hanalysis::GaussLaguerre<T> *)currentKernel)->setSigma(param_v[0]);
2106  ((hanalysis::GaussLaguerre<T> *)currentKernel)->setDegree(std::floor(param_v[1]));
2107 
2108  }break;
2109  case hanalysis::STA_CONV_KERNEL_GAUSS_BESSEL:
2110  {
2111  if (!(param_v.size()==3))
2112  throw STAError("error: wrong numger of parameters");
2113  currentKernel=new hanalysis::GaussBessel<T>();
2114  ((hanalysis::GaussBessel<T> *)currentKernel)->setSigma(param_v[0]);
2115  ((hanalysis::GaussBessel<T> *)currentKernel)->setFreq(param_v[1]);
2116  ((hanalysis::GaussBessel<T> *)currentKernel)->setGauss(param_v[2]);
2117 
2118  }break;
2119  default :
2120  throw STAError("error: unsupported kernel \n");
2121  }
2122 
2123  int range=0;
2124  if (stIn.getStorage()==hanalysis::STA_FIELD_STORAGE_C)
2125  range=stIn.getRank();
2126 
2127  //T * v_size=NULL;
2128 
2129  for (int m=-stIn.getRank();m<=range;m++)
2130  {
2131  hanalysis::renderKernel(
2132  stIn.getData(),
2133  stIn.getShape(),
2134  currentKernel,
2135  stIn.getRank(),
2136  m,
2137  centered,
2138  stIn.getStorage(),
2139  stIn.getElementSize(),//v_size,
2140  stIn.getStride());
2141  }
2142 
2143  //printf("%f %f %f\n",stIn.getElementSize()[0],stIn.getElementSize()[1],stIn.getElementSize()[2]);
2144 
2145  delete currentKernel;
2146  }
2147 
2148  /*#############################################################
2149  *
2150  * STA operators
2151  *
2152  *#############################################################*/
2153 
2154 
2156  stafield fft(bool forward,
2157  bool conjugate=false,
2158  std::complex<T> alpha= T( 1 ),
2159 #ifdef _STA_LINK_FFTW
2160  int flag=FFTW_ESTIMATE )
2161 #else
2162  int flag=0 ) const
2163 #endif
2164  {
2165  try
2166  {
2167  stafield result(this->shape,this->L,this->field_storage,this->field_type);
2168  this->set_death(&result);
2169  FFT(*this,result,forward,conjugate,alpha,flag);
2170  return result;
2171  }
2172  catch (hanalysis::STAError & error)
2173  {
2174  throw error;
2175  }
2176  }
2177 
2180  int J=0,
2181 #ifdef _STA_LINK_FFTW
2182  int flag=FFTW_ESTIMATE )
2183 #else
2184  int flag=0 )
2185 #endif
2186  {
2187  try
2188  {
2189  return (*this).fft(true,false,T(1),flag).prod(b.fft(true,true,T(1),flag),J,true).fft(false,false,T(1)/T(b.getNumVoxel()),flag);;
2190  }
2191  catch (hanalysis::STAError & error)
2192  {
2193  throw error;
2194  }
2195  }
2196 
2197 
2198 
2200  stafield mult(std::complex<T> alpha= T( 1 ),
2201  bool conjugate=false) const
2202  {
2203 
2204  try
2205  {
2206  stafield result(this->shape,this->L,this->field_storage,this->field_type);
2207  this->set_death(&result);
2208  Mult(*this,result,alpha,conjugate,true);
2209  return result;
2210  }
2211  catch (hanalysis::STAError & error)
2212  {
2213  throw error;
2214  }
2215  }
2216 
2217 
2218 
2219  stafield fspecial(const sta_fspecial_func<T> & fsp) const
2220  {
2221 
2222  try
2223  {
2224  stafield result(this->shape,this->L,this->field_storage,this->field_type);
2225  this->set_death(&result);
2226  Fspecial(*this,result,fsp,true);
2227  return result;
2228  }
2229  catch (hanalysis::STAError & error)
2230  {
2231  throw error;
2232  }
2233  }
2234 
2235 
2237  stafield norm() const
2238  {
2239 
2240  try
2241  {
2242  stafield result(this->shape,0,this->field_storage,this->field_type);
2243 
2244  this->set_death(&result);
2245  Norm(*this,result,true);
2246  return result;
2247  }
2248  catch (hanalysis::STAError & error)
2249  {
2250  throw error;
2251  }
2252  }
2253 
2254 
2257  bool conjugate=false,
2258  std::complex<T> alpha= T( 1 ),
2259  int accuracy=0
2260  ) const
2261  {
2262 
2263 
2264  try
2265  {
2266  stafield result(this->shape,this->L+J,this->field_storage,this->field_type);
2267 
2268  this->set_death(&result);
2269 
2270  Deriv(*this,result,J,conjugate,alpha,true,accuracy);
2271 
2272  return result;
2273  }
2274  catch (hanalysis::STAError & error)
2275  {
2276  throw error;
2277  }
2278 
2279 
2280  }
2281 
2282 
2285  bool conjugate=false,
2286  std::complex<T> alpha= T( 1 ),
2287  int accuracy=0
2288  ) const
2289  {
2290 
2291  try
2292  {
2293  stafield result(this->shape,this->L+J,this->field_storage,this->field_type);
2294  this->set_death(&result);
2295  Deriv2(*this,result,J,conjugate,alpha,true);
2296  return result;
2297  }
2298  catch (hanalysis::STAError & error)
2299  {
2300  throw error;
2301  }
2302  }
2303 
2305  stafield lap(std::complex<T> alpha= T( 1 ),
2306  int type=1) const
2307  {
2308 
2309  try
2310  {
2311  stafield result(this->shape,this->L,this->field_storage,this->field_type);
2312  this->set_death(&result);
2313  Lap(*this,result,alpha,true,type);
2314  return result;
2315  }
2316  catch (hanalysis::STAError & error)
2317  {
2318  throw error;
2319  }
2320  }
2321 
2322 
2323 
2324 
2327  int J,
2328  bool normalize=false,
2329  std::complex<T> alpha= T( 1 )) const
2330  {
2331  try
2332  {
2333  stafield result(this->shape,J,this->field_storage,this->field_type);
2334  this->set_death(&result);
2335  //printf("prod prod\n");
2336  //printf("%d %d %d \n",this->getRank(),b.getRank(),result.getRank());
2337  Prod(*this,b,result,J,normalize,alpha,true);
2338  return result;
2339  }
2340  catch (hanalysis::STAError & error)
2341  {
2342  throw error;
2343  }
2344  }
2345 
2346  /*#############################################################
2347  *
2348  * STA special operators
2349  *
2350  *#############################################################*/
2351 
2352 private:
2354  {
2355  private:
2356  std::complex<T> v;
2357  public:
2358  fspecial_Exp() {
2359  v=T(1);
2360  };
2361  fspecial_Exp(std::complex<T> v) {
2362  this->v=v;
2363  };
2364  std::complex<T> fspecial(const std::complex<T> & value) const
2365  {
2366  return std::exp(v*value);
2367  }
2368  };
2369 
2371  {
2372  public:
2373  std::complex<T> fspecial(const std::complex<T> & value) const
2374  {
2375  return std::sqrt(value);
2376  }
2377  };
2378 
2379 
2381  {
2382  private:
2383  T v;
2384  public:
2385  fspecial_Pow() {
2386  v=T(1);
2387  };
2388  fspecial_Pow(T v) {
2389  this->v=v;
2390  };
2391  std::complex<T> fspecial(const std::complex<T> & value) const
2392  {
2393  return std::pow(value,v);
2394  }
2395  };
2396 
2397 
2399  {
2400  private:
2401  std::complex<T> v;
2402  public:
2403  fspecial_Invert() {
2404  v=std::numeric_limits<T>::epsilon();
2405  };
2406  fspecial_Invert(std::complex<T> v) {
2407  this->v=v;
2408  };
2409  std::complex<T> fspecial(const std::complex<T> & value) const
2410  {
2411  return T(1)/(value+v);
2412  }
2413  };
2414 
2415 public:
2416 
2418  stafield exp(std::complex<T> value=T( 1 )) const
2419  {
2420  fspecial_Exp Exp(value);
2421  try
2422  {
2423  stafield result(this->shape,this->L,this->field_storage,this->field_type);
2424  this->set_death(&result);
2425  Fspecial(*this,result,Exp,true);
2426  return result;
2427  }
2428  catch (hanalysis::STAError & error)
2429  {
2430  throw error;
2431  }
2432 
2433 
2434  }
2435 
2437  stafield sqrt() const
2438  {
2439  fspecial_Sqrt Sqrt;
2440  try
2441  {
2442  stafield result(this->shape,this->L,this->field_storage,this->field_type);
2443  this->set_death(&result);
2444  Fspecial(*this,result,Sqrt,true);
2445  return result;
2446  }
2447  catch (hanalysis::STAError & error)
2448  {
2449  throw error;
2450  }
2451  }
2452 
2454  stafield pow(T v=T (1) ) const
2455  {
2456  fspecial_Pow Pow(v);
2457  try
2458  {
2459  stafield result(this->shape,this->L,this->field_storage,this->field_type);
2460  this->set_death(&result);
2461  Fspecial(*this,result,Pow,true);
2462  return result;
2463  }
2464  catch (hanalysis::STAError & error)
2465  {
2466  throw error;
2467  }
2468  }
2469 
2471  stafield invert(T v=std::numeric_limits<T>::epsilon()) const
2472  {
2473  fspecial_Invert Inv(v);
2474  try
2475  {
2476  stafield result(this->shape,this->L,this->field_storage,this->field_type);
2477  this->set_death(&result);
2478  Fspecial(*this,result,Inv,true);
2479  return result;
2480  }
2481  catch (hanalysis::STAError & error)
2482  {
2483  throw error;
2484  }
2485  }
2486 };
2487 
2488 
2489 
2490 
2491 //typedef stafield<float> stafield_float;
2492 
2493 
2494 }
2495 
2496 
2497 #ifdef _STA_CUDA
2498  #define STA_FIELD hanalysis::stafieldGPU
2499 #else
2500  #define STA_FIELD hanalysis::stafield
2501 #endif
2502 
2503 
2504 //template class hanalysis::stafield<float>;
2505 //template class hanalysis::stafield<double>;
2506 #endif
2507 
2508 
2509 
STA_FIELD_STORAGE
tensor field data storage
Definition: stensor.h:5163
tensor field has all components of even ranks :
Definition: stensor.h:5184
stafield exp(std::complex< T > value=T(1)) const
exp, component by component
Definition: stafield.h:2418
stafield deriv(int J, bool conjugate=false, std::complex< T > alpha=T(1), int accuracy=0) const
see Deriv
Definition: stafield.h:2256
stafield(const std::size_t shape[], int L, hanalysis::STA_FIELD_STORAGE field_storage, hanalysis::STA_FIELD_TYPE field_type, std::complex< T > *data, std::size_t stride=0, const T element_size[]=NULL)
Definition: stafield.h:865
STA_RESULT sta_derivatives(const std::complex< T > *stIn, std::complex< T > *stOut, const std::size_t shape[], int J, int Jupdown, bool conjugate=false, std::complex< T > alpha=(T) 1.0, STA_FIELD_STORAGE field_storage=STA_FIELD_STORAGE_C, const T v_size[]=NULL, int stride_in=-1, int stride_out=-1, bool clear_field=false, int accuracy=0)
spherical tensor derivative:
Definition: stensor.h:5864
Definition: stafield.h:2353
bool operator!=(const _stafield &field) const
Definition: stafield.h:150
Definition: stensor_kernels.h:70
represents spherical tensor fields (CPU version)
Definition: stafield.h:251
stafield lap(std::complex< T > alpha=T(1), int type=1) const
see Lap
Definition: stafield.h:2305
hanalysis::STA_FIELD_STORAGE field_storage
must be either STA_FIELD_STORAGE_C, STA_FIELD_STORAGE_R or STA_FIELD_STORAGE_RF
Definition: stafield.h:78
const stafield operator-(const stafield &a) const
Definition: stafield.h:613
static void Deriv(const stafield &stIn, stafield &stOut, int Jupdown, bool conjugate=false, std::complex< T > alpha=T(1), bool clear_result=false, int accuracy=0)
spherical tensor derivative:
Definition: stafield.h:1654
static void Prod(const stafield &stIn1, const stafield &stIn2, stafield &stOut, int J, bool normalize=false, std::complex< T > alpha=T(1), bool clear_result=false)
spherical tensor product: and , respectively
Definition: stafield.h:1876
the STA error class
Definition: sta_error.h:68
stafield pow(T v=T(1)) const
pow, component by component
Definition: stafield.h:2454
Definition: stensor_kernels.h:69
static void Lap(const stafield &stIn, stafield &stOut, std::complex< T > alpha=T(1), bool clear_result=false, int type=1)
Laplacian: .
Definition: stafield.h:1816
const stafield operator*(std::complex< T > alpha) const
Definition: stafield.h:640
stafield(std::string kernelname, const std::size_t shape[], std::vector< T > param_v, bool centered=false, int L=0, hanalysis::STA_FIELD_STORAGE field_storage=hanalysis::STA_FIELD_STORAGE_R, const T element_size[]=NULL)
Definition: stafield.h:818
represents spherical tensor fields (GPU version)
Definition: stafield_cuda.h:44
stafield operator[](int l) const
Definition: stafield.h:695
const std::size_t * getShape() const
Definition: stafield.h:187
tensor field has one single component of rank :
Definition: stensor.h:5180
STA_FIELD_TYPE
tensor field data interpretations according to certain symmetries
Definition: stensor.h:5177
int L
tensor rank
Definition: stafield.h:82
STA_RESULT
function return value
Definition: stensor.h:124
const std::complex< T > * getDataConst() const
Definition: stafield.h:1281
std::size_t shape[3]
image shape
Definition: stafield.h:74
Definition: stensor.h:6190
stafield mult(std::complex< T > alpha=T(1), bool conjugate=false) const
see Mult
Definition: stafield.h:2200
stafield & operator+=(const stafield &a)
Definition: stafield.h:523
static void Deriv2(const stafield &stIn, stafield &stOut, int Jupdown, bool conjugate=false, std::complex< T > alpha=T(1), bool clear_result=false)
spherical tensor double-derivative:
Definition: stafield.h:1734
stafield & operator*=(std::complex< T > alpha)
Definition: stafield.h:559
Definition: stafield.h:2370
stafield fft(bool forward, bool conjugate=false, std::complex< T > alpha=T(1), int flag=0) const
see FFT
Definition: stafield.h:2156
static void Mult(const stafield &stIn, stafield &stOut, std::complex< T > alpha=T(1), bool conjugate=false, bool clear_result=false)
computes
Definition: stafield.h:1516
Definition: stensor_kernels.h:67
Definition: stensor.h:5173
Definition: stensor_kernels.h:68
hanalysis::STA_FIELD_TYPE field_type
must be either STA_OFIELD_SINGLE, STA_OFIELD_FULL, STA_OFIELD_EVEN or STA_OFIELD_ODD ...
Definition: stafield.h:80
Definition: stafield.h:2380
Definition: stafield.h:2398
STA_RESULT sta_product(const std::complex< T > *stIn1, const std::complex< T > *stIn2, std::complex< T > *stOut, const std::size_t shape[], int J1, int J2, int J, std::complex< T > alpha=T(1), bool normalize=false, STA_FIELD_STORAGE field_storage=STA_FIELD_STORAGE_C, int stride_in1=-1, int stride_in2=-1, int stride_out=-1, bool clear_field=false)
spherical tensor product: and , respectively
Definition: stensor.h:5528
bool ownMemory() const
Definition: stafield.h:194
Definition: stensor.h:5167
STA_RESULT sta_fft(const std::complex< T > *stIn, std::complex< T > *stOut, const std::size_t shape[], int components, bool forward, bool conjugate=false, S alpha=(S) 1, int flag=0)
tensor fft component by component
Definition: stensor.h:6140
stafield deriv2(int J, bool conjugate=false, std::complex< T > alpha=T(1), int accuracy=0) const
see Deriv2
Definition: stafield.h:2284
stafield(const std::size_t shape[], int L, hanalysis::STA_FIELD_STORAGE field_storage=hanalysis::STA_FIELD_STORAGE_R, hanalysis::STA_FIELD_TYPE field_type=hanalysis::STA_OFIELD_SINGLE, const T element_size[]=NULL)
Definition: stafield.h:764
stafield & operator/=(std::complex< T > alpha)
Definition: stafield.h:575
const T * getDataConst() const
Definition: stafield_cuda.h:62
Definition: stensor_kernels.h:71
int getRank() const
Definition: stafield.h:236
The STA-ImageAnalysisToolkit namespace.
Definition: stafield.h:55
stafield sqrt() const
sqrt, component by component
Definition: stafield.h:2437
tensor field has all components of odd ranks :
Definition: stensor.h:5186
stafield norm() const
see Norm
Definition: stafield.h:2237
Definition: stensor_kernels.h:49
stafield & operator=(const stafield &f)
Definition: stafield.h:363
STA_RESULT sta_derivatives2(const std::complex< T > *stIn, std::complex< T > *stOut, const std::size_t shape[], int J, int Jupdown, bool conjugate=false, std::complex< T > alpha=(T) 1.0, STA_FIELD_STORAGE field_storage=STA_FIELD_STORAGE_C, const T v_size[]=NULL, int stride_in=-1, int stride_out=-1, bool clear_field=false)
spherical tensor double-derivative:
Definition: stensor.h:5991
bool createMemCopy()
Definition: stafield.h:1216
stafield & operator-=(const stafield &a)
Definition: stafield.h:541
std::complex< T > * getData()
Definition: stafield.h:1274
stafield prod(const stafield &b, int J, bool normalize=false, std::complex< T > alpha=T(1)) const
see Prod
Definition: stafield.h:2326
static void FFT(const stafield &stIn, stafield &stOut, bool forward, bool conjugate=false, std::complex< T > alpha=T(1), int flag=0)
tensor fft component by component
Definition: stafield.h:1437
static void Norm(const stafield &stIn, stafield &stOut, bool clear_result=false)
returns lengths of vectors component by compnent
Definition: stafield.h:1588
const stafield operator/(std::complex< T > alpha) const
Definition: stafield.h:657
stafield convolve(stafield &b, int J=0, int flag=0)
see FFT
Definition: stafield.h:2179
STA_RESULT sta_laplace(const std::complex< T > *stIn, std::complex< T > *stOut, const std::size_t shape[], int components=1, int type=1, std::complex< T > alpha=1, STA_FIELD_STORAGE field_storage=STA_FIELD_STORAGE_C, const T v_size[]=NULL, int stride_in=-1, int stride_out=-1, bool clear_field=false)
Laplacian: .
Definition: stensor.h:6078
const stafield operator+(const stafield &a) const
Definition: stafield.h:591
represents spherical tensor fields
Definition: stafield.h:62
bool operator==(const _stafield &field) const
Definition: stafield.h:135
stafield invert(T v=std::numeric_limits< T >::epsilon()) const
invert, component by component
Definition: stafield.h:2471
Definition: stensor.h:5170