SIRF  3.4.0
gadgetron_data_containers.h
Go to the documentation of this file.
1 /*
2 SyneRBI Synergistic Image Reconstruction Framework (SIRF)
3 Copyright 2015 - 2020 Rutherford Appleton Laboratory STFC
4 Copyright 2020 University College London
5 Copyright 2020 - 2021 Physikalisch-Technische Bundesanstalt (PTB)
6 
7 This is software developed for the Collaborative Computational
8 Project in Synergistic Reconstruction for Biomedical Imaging (formerly CCP PETMR)
9 (http://www.ccpsynerbi.ac.uk/).
10 
11 Licensed under the Apache License, Version 2.0 (the "License");
12 you may not use this file except in compliance with the License.
13 You may obtain a copy of the License at
14 http://www.apache.org/licenses/LICENSE-2.0
15 Unless required by applicable law or agreed to in writing, software
16 distributed under the License is distributed on an "AS IS" BASIS,
17 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 See the License for the specific language governing permissions and
19 limitations under the License.
20 
21 */
22 
33 #ifndef GADGETRON_DATA_CONTAINERS
34 #define GADGETRON_DATA_CONTAINERS
35 
36 #include <string>
37 #include <vector>
38 
39 //#include <boost/algorithm/string.hpp>
40 
41 #include <ismrmrd/ismrmrd.h>
42 #include <ismrmrd/dataset.h>
43 
44 #include "sirf/common/DataContainer.h"
45 #include "sirf/common/ImageData.h"
46 #include "sirf/common/multisort.h"
47 #include "sirf/Gadgetron/cgadgetron_shared_ptr.h"
49 
50 #include "sirf/iUtilities/LocalisedException.h"
51 
52 //#define SIRF_DYNAMIC_CAST(T, X, Y) T& X = (T&)Y
53 #define SIRF_DYNAMIC_CAST(T, X, Y) T& X = dynamic_cast<T&>(Y)
54 
62 #define TO_BE_IGNORED(acq) \
63  (!(acq).isFlagSet(ISMRMRD::ISMRMRD_ACQ_IS_PARALLEL_CALIBRATION) && \
64  !(acq).isFlagSet(ISMRMRD::ISMRMRD_ACQ_IS_PARALLEL_CALIBRATION_AND_IMAGING) && \
65  !(acq).isFlagSet(ISMRMRD::ISMRMRD_ACQ_LAST_IN_MEASUREMENT) && \
66  !(acq).isFlagSet(ISMRMRD::ISMRMRD_ACQ_IS_REVERSE) && \
67  (acq).flags() >= (1 << (ISMRMRD::ISMRMRD_ACQ_IS_NOISE_MEASUREMENT - 1)))
68 
75 namespace sirf {
76 
77  class FourierEncoding;
78  class CartesianFourierEncoding;
79 #if GADGETRON_TOOLBOXES_AVAILABLE
80  class RPEFourierEncoding;
81 #endif
82 
84  public:
85  AcquisitionsInfo(std::string data = "") : data_(data)
86  {
87  if (data.empty())
88  have_header_ = false;
89  else {
90  deserialize();
91  have_header_ = true;
92  }
93  }
94  AcquisitionsInfo& operator=(std::string data)
95  {
96  data_ = data;
97  if (data.empty())
98  have_header_ = false;
99  else {
100  deserialize();
101  have_header_ = true;
102  }
103 
104  return *this;
105  }
106  const char* c_str() const { return data_.c_str(); }
107  operator std::string&() { return data_; }
108  operator const std::string&() const { return data_; }
109  bool empty() const { return data_.empty(); }
110  const ISMRMRD::IsmrmrdHeader& get_IsmrmrdHeader() const
111  {
112  if (!have_header_)
113  deserialize();
114  return header_;
115  }
116 
117  private:
118  void deserialize() const
119  {
120  if (!this->empty())
121  { header_ = ISMRMRD::IsmrmrdHeader();
122  ISMRMRD::deserialize(data_.c_str(), header_);
123  }
124  have_header_ = true;
125  }
126  std::string data_;
127  mutable ISMRMRD::IsmrmrdHeader header_;
128  mutable bool have_header_;
129  };
130 
143  {
144  static int const num_kspace_dims_ = 7 + ISMRMRD::ISMRMRD_Constants::ISMRMRD_USER_INTS;
145 
146  public:
147 
148  typedef std::array<int, num_kspace_dims_> TagType;
149  typedef std::vector<int> SetType;
150 
151  KSpaceSubset(){
152  for(int i=0; i<num_kspace_dims_; ++i)
153  this->tag_[i] = -1;
154  }
155 
156  KSpaceSubset(TagType tag){
157  this->tag_ = tag;
158  this->idx_set_ = {};
159  }
160 
161  KSpaceSubset(TagType tag, SetType idx_set){
162  this->tag_ = tag;
163  this->idx_set_ = idx_set;
164  }
165 
166  TagType get_tag(void) const {return tag_;}
167  SetType get_idx_set(void) const {return idx_set_;}
168  void add_idx_to_set(size_t const idx){this->idx_set_.push_back(idx);}
169 
170  bool is_first_set() const {
171  bool is_first= (tag_[0] == 0);
172  if(is_first)
173  {
174  for(int dim=2; dim<num_kspace_dims_; ++dim)
175  is_first *= (tag_[dim] == 0);
176  }
177  return is_first;
178  }
179 
180  static void print_tag(const TagType& tag);
181  static void print_acquisition_tag(ISMRMRD::Acquisition acq);
182 
184 
187  static TagType get_tag_from_acquisition(ISMRMRD::Acquisition acq);
188 
190 
193  static TagType get_tag_from_img(const CFImage& img);
194 
195  private:
197 
201  TagType tag_;
202 
204 
208  SetType idx_set_;
209  };
210 
217  public:
218  // static methods
219 
220  // ISMRMRD acquisitions algebra: acquisitions viewed as vectors of
221  // acquisition data
222  // y := a x + b y
223  static void axpby
224  (complex_float_t a, const ISMRMRD::Acquisition& acq_x,
225  complex_float_t b, ISMRMRD::Acquisition& acq_y);
226  static void xapyb
227  (const ISMRMRD::Acquisition& acq_x, complex_float_t a,
228  ISMRMRD::Acquisition& acq_y, complex_float_t b);
229  static void xapyb
230  (const ISMRMRD::Acquisition& acq_x, const ISMRMRD::Acquisition& acq_a,
231  ISMRMRD::Acquisition& acq_y, const ISMRMRD::Acquisition& acq_b);
232 
233  // the inner (l2) product of x and y
234  static complex_float_t dot
235  (const ISMRMRD::Acquisition& acq_x, const ISMRMRD::Acquisition& acq_y);
236  // elementwise multiplication
237  // y := x .* y
238  static void multiply
239  (const ISMRMRD::Acquisition& acq_x, ISMRMRD::Acquisition& acq_y);
240  // elementwise division
241  // y := x ./ y
242  static void divide
243  (const ISMRMRD::Acquisition& acq_x, ISMRMRD::Acquisition& acq_y);
244  // l2 norm of x
245  static float norm(const ISMRMRD::Acquisition& acq_x);
246 
247  // type and dimension of an ISMRMRD::Acquisition parameter
248  static void ismrmrd_par_info(const char* par, int* output)
249  {
250  // default type: int, dimension: 1
251  output[0] = 0;
252  output[1] = 1;
253 
254  // check parameter type
255  if (sirf::iequals(par, "sample_time_us") ||
256  sirf::iequals(par, "position") ||
257  sirf::iequals(par, "read_dir") ||
258  sirf::iequals(par, "phase_dir") ||
259  sirf::iequals(par, "slice_dir") ||
260  sirf::iequals(par, "patient_table_position") ||
261  sirf::iequals(par, "user_float"))
262  output[0] = 1; // float
263 
264  // check parameter dimension
265  if (sirf::iequals(par, "physiology_time_stamp"))
266  output[1] = ISMRMRD::ISMRMRD_Constants::ISMRMRD_PHYS_STAMPS;
267  else if (sirf::iequals(par, "channel_mask"))
268  output[1] = ISMRMRD::ISMRMRD_Constants::ISMRMRD_CHANNEL_MASKS;
269  else if (sirf::iequals(par, "position") ||
270  sirf::iequals(par, "read_dir") ||
271  sirf::iequals(par, "phase_dir") ||
272  sirf::iequals(par, "slice_dir") ||
273  sirf::iequals(par, "patient_table_position"))
274  output[1] = 3;
275  else if (sirf::iequals(par, "user_int") ||
276  sirf::iequals(par, "idx_user"))
277  output[1] = ISMRMRD::ISMRMRD_Constants::ISMRMRD_USER_INTS;
278  else if (sirf::iequals(par, "user_float"))
279  output[1] = ISMRMRD::ISMRMRD_Constants::ISMRMRD_USER_FLOATS;
280  }
281  // value of an ISMRMRD::Acquisition int parameter
282  static void ismrmrd_par_value(ISMRMRD::Acquisition& acq,
283  const char* name, unsigned long long int* v)
284  {
285  if (sirf::iequals(name, "version"))
286  *v = ((unsigned int)acq.version());
287  else if (sirf::iequals(name, "flags"))
288  *v = ((unsigned long long int)acq.flags());
289  else if (sirf::iequals(name, "measurement_uid"))
290  *v = ((unsigned int)acq.measurement_uid());
291  else if (sirf::iequals(name, "scan_counter"))
292  *v = ((unsigned int)acq.scan_counter());
293  else if (sirf::iequals(name, "acquisition_time_stamp"))
294  *v = ((unsigned int)acq.acquisition_time_stamp());
295  else if (sirf::iequals(name, "number_of_samples"))
296  *v = ((unsigned int)acq.number_of_samples());
297  else if (sirf::iequals(name, "available_channels"))
298  *v = ((unsigned int)acq.available_channels());
299  else if (sirf::iequals(name, "active_channels"))
300  *v = ((unsigned int)acq.active_channels());
301  else if (sirf::iequals(name, "discard_pre"))
302  *v = ((unsigned int)acq.discard_pre());
303  else if (sirf::iequals(name, "discard_post"))
304  *v = ((unsigned int)acq.discard_post());
305  else if (sirf::iequals(name, "center_sample"))
306  *v = ((unsigned int)acq.center_sample());
307  else if (sirf::iequals(name, "encoding_space_ref"))
308  *v = ((unsigned int)acq.encoding_space_ref());
309  else if (sirf::iequals(name, "trajectory_dimensions"))
310  *v = ((unsigned int)acq.trajectory_dimensions());
311  else if (sirf::iequals(name, "kspace_encode_step_1"))
312  *v = ((unsigned int)acq.idx().kspace_encode_step_1);
313  else if (sirf::iequals(name, "kspace_encode_step_2"))
314  *v = ((unsigned int)acq.idx().kspace_encode_step_2);
315  else if (sirf::iequals(name, "average"))
316  *v = ((unsigned int)acq.idx().average);
317  else if (sirf::iequals(name, "slice"))
318  *v = ((unsigned int)acq.idx().slice);
319  else if (sirf::iequals(name, "contrast"))
320  *v = ((unsigned int)acq.idx().contrast);
321  else if (sirf::iequals(name, "phase"))
322  *v = ((unsigned int)acq.idx().phase);
323  else if (sirf::iequals(name, "repetition"))
324  *v = ((unsigned int)acq.idx().repetition);
325  else if (sirf::iequals(name, "set"))
326  *v = ((unsigned int)acq.idx().set);
327  else if (sirf::iequals(name, "segment"))
328  *v = ((unsigned int)acq.idx().segment);
329  else if (sirf::iequals(name, "physiology_time_stamp")) {
330  int n = ISMRMRD::ISMRMRD_Constants::ISMRMRD_PHYS_STAMPS;
331  const uint32_t* pts = acq.physiology_time_stamp();
332  for (int i = 0; i < n; i++)
333  v[i] = (unsigned int)pts[i];
334  }
335  else if (sirf::iequals(name, "channel_mask")) {
336  int n = ISMRMRD::ISMRMRD_Constants::ISMRMRD_CHANNEL_MASKS;
337  const uint64_t* pts = acq.channel_mask();
338  for (int i = 0; i < n; i++)
339  v[i] = (unsigned long long int)pts[i];
340  }
341  }
342  // value of an ISMRMRD::Acquisition float parameter
343  static void ismrmrd_par_value(ISMRMRD::Acquisition& acq,
344  const char* name, float* v)
345  {
346  if (sirf::iequals(name, "sample_time_us"))
347  *v = acq.sample_time_us();
348  else if (sirf::iequals(name, "position")) {
349  float* u = acq.position();
350  for (int i = 0; i < 3; i++)
351  v[i] = u[i];
352  }
353  else if (sirf::iequals(name, "read_dir")) {
354  float* u = acq.read_dir();
355  for (int i = 0; i < 3; i++)
356  v[i] = u[i];
357  }
358  else if (sirf::iequals(name, "phase_dir")) {
359  float* u = acq.phase_dir();
360  for (int i = 0; i < 3; i++)
361  v[i] = u[i];
362  }
363  else if (sirf::iequals(name, "slice_dir")) {
364  float* u = acq.slice_dir();
365  for (int i = 0; i < 3; i++)
366  v[i] = u[i];
367  }
368  else if (sirf::iequals(name, "patient_table_position")) {
369  float* u = acq.patient_table_position();
370  for (int i = 0; i < 3; i++)
371  v[i] = u[i];
372  }
373  }
374 
375  // abstract methods
376 
377  virtual void empty() = 0;
378  virtual void take_over(MRAcquisitionData&) = 0;
379 
380  // the number of acquisitions in the container
381  virtual unsigned int number() const = 0;
382 
383  virtual gadgetron::shared_ptr<ISMRMRD::Acquisition>
384  get_acquisition_sptr(unsigned int num) = 0;
385  virtual void get_acquisition(unsigned int num, ISMRMRD::Acquisition& acq) const = 0;
386  virtual void set_acquisition(unsigned int num, ISMRMRD::Acquisition& acq) = 0;
387  virtual void append_acquisition(ISMRMRD::Acquisition& acq) = 0;
388 
389  virtual void copy_acquisitions_info(const MRAcquisitionData& ac) = 0;
390  virtual void copy_acquisitions_data(const MRAcquisitionData& ac) = 0;
391 
392  // 'export' constructors: workaround for creating 'ABC' objects
393  virtual gadgetron::unique_ptr<MRAcquisitionData> new_acquisitions_container() = 0;
394  virtual MRAcquisitionData*
395  same_acquisitions_container(const AcquisitionsInfo& info) const = 0;
396 
397  virtual void set_data(const complex_float_t* z, int all = 1) = 0;
398  virtual void get_data(complex_float_t* z, int all = 1);
399 
400  virtual void set_user_floats(float const * const z, int const idx);
401 
402  virtual bool is_complex() const
403  {
404  return true;
405  }
406 
407  // acquisition data algebra
408  virtual void dot(const DataContainer& dc, void* ptr) const;
409  complex_float_t dot(const DataContainer& a_x)
410  {
411  complex_float_t z;
412  dot(a_x, &z);
413  return z;
414  }
415  virtual void axpby(
416  const void* ptr_a, const DataContainer& a_x,
417  const void* ptr_b, const DataContainer& a_y);
418  virtual void xapyb(
419  const DataContainer& a_x, const DataContainer& a_a,
420  const DataContainer& a_y, const DataContainer& a_b);
421  virtual void xapyb(
422  const DataContainer& a_x, const void* ptr_a,
423  const DataContainer& a_y, const void* ptr_b);
424  //{
425  // axpby(ptr_a, a_x, ptr_b, a_y);
426  //}
427  virtual void multiply(const DataContainer& x, const DataContainer& y);
428  virtual void divide(const DataContainer& x, const DataContainer& y);
429  virtual void maximum(const DataContainer& x, const DataContainer& y)
430  {
431  THROW("maximum not defined for MRAcquisitionData");
432  }
433  virtual void minimum(const DataContainer& x, const DataContainer& y)
434  {
435  THROW("minimum not defined for MRAcquisitionData");
436  }
437  virtual float norm() const;
438 
439  virtual void write(const std::string &filename) const;
440 
441  // regular methods
442 
443  AcquisitionsInfo acquisitions_info() const { return acqs_info_; }
444  void set_acquisitions_info(std::string info) { acqs_info_ = info; }
445  void set_acquisitions_info(const AcquisitionsInfo info) { acqs_info_ = info;}
446 
447  ISMRMRD::TrajectoryType get_trajectory_type() const;
448 
449  void set_trajectory_type(const ISMRMRD::TrajectoryType type);
450 
451  void set_trajectory(const uint16_t traj_dim, float* traj)
452  {
453  ISMRMRD::Acquisition acq;
454  for(int i=0; i<number(); ++i)
455  {
456  get_acquisition(i, acq);
457  const uint16_t num_samples = acq.number_of_samples();
458  const uint16_t num_channels = acq.active_channels();
459  acq.resize(num_samples,num_channels,traj_dim);
460  int const offset = i*traj_dim*num_samples;
461  acq.setTraj(traj + offset);
462  set_acquisition(i, acq);
463  }
464  }
465 
466  gadgetron::unique_ptr<MRAcquisitionData> clone() const
467  {
468  return gadgetron::unique_ptr<MRAcquisitionData>(this->clone_impl());
469  }
470 
471  bool undersampled() const;
472  int get_acquisitions_dimensions(size_t ptr_dim) const;
473  void get_kspace_dimensions(std::vector<size_t>& dims) const;
474  uint16_t get_trajectory_dimensions(void) const;
475 
476  void sort();
477  void sort_by_time();
478  bool sorted() const { return sorted_; }
479  void set_sorted(bool sorted) { sorted_ = sorted; }
480 
482 
486  std::vector<KSpaceSubset::SetType > get_kspace_order() const;
487 
489  std::vector<KSpaceSubset> get_kspace_sorting() const { return this->sorting_; }
490 
492 
498  void organise_kspace();
499 
500  virtual std::vector<int> get_flagged_acquisitions_index(const std::vector<ISMRMRD::ISMRMRD_AcquisitionFlags> flags) const;
501  virtual std::vector<int> get_slice_encoding_index(const unsigned kspace_encode_step_2) const;
502 
503 
504  virtual void get_subset(MRAcquisitionData& subset, const std::vector<int> subset_idx) const;
505  virtual void set_subset(const MRAcquisitionData &subset, const std::vector<int> subset_idx);
506 
507  std::vector<int> index() { return index_; }
508  const std::vector<int>& index() const { return index_; }
509 
510  int index(int i) const
511  {
512  const std::size_t ni = index_.size();
513  if (i < 0 || (ni > 0 && static_cast<std::size_t>(i) >= ni) || static_cast<unsigned>(i) >= number())
514  THROW("Aquisition number is out of range");
515  if (ni > 0)
516  return index_[i];
517  else
518  return i;
519  }
520 
530  void read( const std::string& filename_ismrmrd_with_ext );
531 
532  protected:
533  bool sorted_ = false;
534  std::vector<int> index_;
535  std::vector<KSpaceSubset> sorting_;
536  AcquisitionsInfo acqs_info_;
537 
538  // new MRAcquisitionData objects will be created from this template
539  // using same_acquisitions_container()
540  static gadgetron::shared_ptr<MRAcquisitionData> acqs_templ_;
541 
542  virtual MRAcquisitionData* clone_impl() const = 0;
543 
544  private:
545  void binary_op_(int op,
546  const MRAcquisitionData& a_x, const MRAcquisitionData& a_y,
547  const void* ptr_a = 0, const void* ptr_b = 0);
548 
549  };
550 
560  public:
561  AcquisitionsVector(const std::string& filename_with_ext)
562  {
563  this->read(filename_with_ext);
564  }
565 
567  {
568  acqs_info_ = info;
569  }
570  virtual void empty();
571  virtual void take_over(MRAcquisitionData& ad) {}
572  virtual unsigned int number() const { return (unsigned int)acqs_.size(); }
573  virtual unsigned int items() const { return (unsigned int)acqs_.size(); }
574  virtual void append_acquisition(ISMRMRD::Acquisition& acq)
575  {
576  acqs_.push_back(gadgetron::shared_ptr<ISMRMRD::Acquisition>
577  (new ISMRMRD::Acquisition(acq)));
578  }
579  virtual gadgetron::shared_ptr<ISMRMRD::Acquisition>
580  get_acquisition_sptr(unsigned int num)
581  {
582  int ind = index(num);
583  return acqs_[ind];
584  }
585  virtual void get_acquisition(unsigned int num, ISMRMRD::Acquisition& acq) const
586  {
587  int ind = index(num);
588  acq = *acqs_[ind];
589  }
590  virtual void set_acquisition(unsigned int num, ISMRMRD::Acquisition& acq)
591  {
592  int ind = index(num);
593  *acqs_[ind] = acq;
594  }
595  virtual void copy_acquisitions_info(const MRAcquisitionData& ac)
596  {
597  acqs_info_ = ac.acquisitions_info();
598  }
599  virtual void copy_acquisitions_data(const MRAcquisitionData& ac);
600  virtual void set_data(const complex_float_t* z, int all = 1);
601 
602  virtual AcquisitionsVector* same_acquisitions_container
603  (const AcquisitionsInfo& info) const
604  {
605  return new AcquisitionsVector(info);
606  }
607  virtual ObjectHandle<DataContainer>* new_data_container_handle() const
608  {
609  DataContainer* ptr = new AcquisitionsVector(acqs_info_);
610  return new ObjectHandle<DataContainer>
611  (gadgetron::shared_ptr<DataContainer>(ptr));
612  }
613  virtual gadgetron::unique_ptr<MRAcquisitionData>
614  new_acquisitions_container()
615  {
616  return gadgetron::unique_ptr<MRAcquisitionData>
617  (new AcquisitionsVector(acqs_info_));
618  }
619 
620  private:
621  std::vector<gadgetron::shared_ptr<ISMRMRD::Acquisition> > acqs_;
622  virtual AcquisitionsVector* clone_impl() const;
623  virtual void conjugate_impl();
624  };
625 
632  class ISMRMRDImageData : public ImageData {
633  public:
634  //ISMRMRDImageData(ISMRMRDImageData& id, const char* attr,
635  //const char* target); //does not build, have to be in the derived class
636 
637  virtual void empty() = 0;
638  virtual unsigned int number() const = 0;
639  virtual gadgetron::shared_ptr<ImageWrap> sptr_image_wrap
640  (unsigned int im_num) = 0;
641  virtual gadgetron::shared_ptr<const ImageWrap> sptr_image_wrap
642  (unsigned int im_num) const = 0;
643 // virtual ImageWrap& image_wrap(unsigned int im_num) = 0;
644 // virtual const ImageWrap& image_wrap(unsigned int im_num) const = 0;
645  virtual void append(int image_data_type, void* ptr_image) = 0;
646  virtual void append(const ImageWrap& iw) = 0;
647  virtual void append(gadgetron::shared_ptr<ImageWrap> sptr_iw) = 0;
648  virtual gadgetron::shared_ptr<ISMRMRDImageData> abs() const = 0;
649  virtual gadgetron::shared_ptr<ISMRMRDImageData> real() const = 0;
650  virtual void clear_data() = 0;
651  virtual void set_image_type(int imtype) = 0;
652  virtual void get_data(complex_float_t* data) const;
653  virtual void set_data(const complex_float_t* data);
654  virtual void get_real_data(float* data) const;
655  virtual void set_real_data(const float* data);
656  virtual int read(std::string filename, std::string variable = "", int iv = -1);
657  virtual void write(const std::string &filename, const std::string &groupname, const bool dicom) const;
658  virtual void write(const std::string &filename) const
659  {
660  size_t size = filename.size();
661  std::string suff = filename.substr(size - 4, 4);
662  if (suff == std::string(".dcm")) {
663  std::string prefix = filename.substr(0, size - 4);
664  this->write(prefix, "", true);
665  }
666  else {
667  auto found = filename.find_last_of("/\\");
668  auto slash_found = found;
669  if (found == std::string::npos)
670  found = filename.find_last_of(".");
671  else
672  found = filename.substr(found + 1).find_last_of(".");
673  if (found == std::string::npos)
674  this->write(filename + ".h5", "", false);
675  else {
676  std::string ext = filename.substr(slash_found + found + 1);
677  if (ext == std::string(".h5"))
678  this->write(filename, "", false);
679  else
680  std::cerr << "WARNING: writing ISMRMRD images to "
681  << ext << "-files not implemented, "
682  << "please convert to Nifti images\n";
683  }
684  }
685  }
686  virtual Dimensions dimensions() const
687  {
688  Dimensions dim;
689  const ImageWrap& iw = image_wrap(0);
690  int d[5];
691  iw.get_dim(d);
692  dim["x"] = d[0];
693  dim["y"] = d[1];
694  dim["z"] = d[2];
695  dim["c"] = d[3];
696  dim["n"] = number();
697  return dim;
698  }
699  virtual void get_image_dimensions(unsigned int im_num, int* dim) const
700  {
701  if (im_num >= number())
702  dim[0] = dim[1] = dim[2] = dim[3] = 0;
703  const ImageWrap& iw = image_wrap(im_num);
704  iw.get_dim(dim);
705  }
706  bool check_dimension_consistency() const
707  {
708  size_t const num_dims = 4;
709  std::vector<int> first_img_dims(num_dims), temp_img_dims(num_dims);
710 
711  this->get_image_dimensions(0, &first_img_dims[0]);
712 
713  bool dims_match = true;
714  for(int i=1; i<number(); ++i)
715  {
716  this->get_image_dimensions(0, &temp_img_dims[0]);
717  dims_match *= (first_img_dims == temp_img_dims);
718  }
719  return dims_match;
720  }
721  virtual gadgetron::shared_ptr<ISMRMRDImageData>
722  new_images_container() const = 0;
723  virtual gadgetron::shared_ptr<ISMRMRDImageData>
724  clone(const char* attr, const char* target) = 0;
725  virtual int image_data_type(unsigned int im_num) const
726  {
727  return image_wrap(im_num).type();
728  }
729 
730  virtual float norm() const;
731  virtual void dot(const DataContainer& dc, void* ptr) const;
732  virtual void axpby(
733  const void* ptr_a, const DataContainer& a_x,
734  const void* ptr_b, const DataContainer& a_y);
735  virtual void xapyb(
736  const DataContainer& a_x, const void* ptr_a,
737  const DataContainer& a_y, const void* ptr_b)
738  {
739  ComplexFloat_ a(*(complex_float_t*)ptr_a);
740  ComplexFloat_ b(*(complex_float_t*)ptr_b);
741  xapyb_(a_x, a, a_y, b);
742  }
743  virtual void xapyb(
744  const DataContainer& a_x, const void* ptr_a,
745  const DataContainer& a_y, const DataContainer& a_b)
746  {
747  ComplexFloat_ a(*(complex_float_t*)ptr_a);
748  SIRF_DYNAMIC_CAST(const ISMRMRDImageData, b, a_b);
749  xapyb_(a_x, a, a_y, b);
750  }
751  virtual void xapyb(
752  const DataContainer& a_x, const DataContainer& a_a,
753  const DataContainer& a_y, const void* ptr_b)
754  {
755  SIRF_DYNAMIC_CAST(const ISMRMRDImageData, a, a_a);
756  ComplexFloat_ b(*(complex_float_t*)ptr_b);
757  xapyb_(a_x, a, a_y, b);
758  }
759  virtual void xapyb(
760  const DataContainer& a_x, const DataContainer& a_a,
761  const DataContainer& a_y, const DataContainer& a_b)
762  {
763  SIRF_DYNAMIC_CAST(const ISMRMRDImageData, a, a_a);
764  SIRF_DYNAMIC_CAST(const ISMRMRDImageData, b, a_b);
765  xapyb_(a_x, a, a_y, b);
766  }
767  virtual void multiply(const DataContainer& x, const DataContainer& y);
768  virtual void divide(const DataContainer& x, const DataContainer& y);
769  virtual void maximum(const DataContainer& x, const DataContainer& y)
770  {
771  THROW("maximum not defined for ISMRMRDImageData");
772  }
773  virtual void minimum(const DataContainer& x, const DataContainer& y)
774  {
775  THROW("minimum not defined for ISMRMRDImageData");
776  }
777 
778  void fill(float s);
779  void scale(float s);
780  complex_float_t dot(const DataContainer& a_x)
781  {
782  complex_float_t z;
783  dot(a_x, &z);
784  return z;
785  }
786  void axpby(
787  complex_float_t a, const DataContainer& a_x,
788  complex_float_t b, const DataContainer& a_y)
789  {
790  axpby(&a, a_x, &b, a_y);
791  }
792  void xapyb(
793  const DataContainer& a_x, complex_float_t a,
794  const DataContainer& a_y, complex_float_t b)
795  {
796  xapyb(a_x, &a, a_y, &b);
797  }
798  gadgetron::unique_ptr<ISMRMRDImageData> clone() const
799  {
800  return gadgetron::unique_ptr<ISMRMRDImageData>(this->clone_impl());
801  }
802 
803  virtual void sort() = 0;
804  bool sorted() const { return sorted_; }
805  void set_sorted(bool sorted) { sorted_ = sorted; }
806  std::vector<int> index() { return index_; }
807  const std::vector<int>& index() const { return index_; }
808  int index(int i) const
809  {
810  const std::size_t ni = index_.size();
811  if (i < 0 || (ni > 0 && static_cast<std::size_t>(i) >= ni) || static_cast<unsigned>(i) >= number())
812  THROW("Image number is out of range. You tried to look up an image number that is not inside the container.");
813  if (ni > 0)
814  return index_[i];
815  else
816  return i;
817  }
818  ImageWrap& image_wrap(unsigned int im_num)
819  {
820  gadgetron::shared_ptr<ImageWrap> sptr_iw = sptr_image_wrap(im_num);
821  return *sptr_iw;
822  }
823  const ImageWrap& image_wrap(unsigned int im_num) const
824  {
825  const gadgetron::shared_ptr<const ImageWrap>& sptr_iw =
826  sptr_image_wrap(im_num);
827  return *sptr_iw;
828  }
830  void set_meta_data(const AcquisitionsInfo &acqs_info);
832  const AcquisitionsInfo &get_meta_data() const { return acqs_info_; }
833 
834  protected:
835  bool sorted_=false;
836  std::vector<int> index_;
837  AcquisitionsInfo acqs_info_;
839  virtual ISMRMRDImageData* clone_impl() const = 0;
840  virtual void conjugate_impl();
841 
842  private:
843  class ComplexFloat_ {
844  public:
845  ComplexFloat_(complex_float_t v) : v_(v) {}
846  unsigned int number() const
847  {
848  return 0;
849  }
850  complex_float_t image_wrap(unsigned int i)
851  {
852  return v_;
853  }
854  private:
855  complex_float_t v_;
856  };
857 
858  template<class A, class B>
859  void xapyb_(const DataContainer& a_x, A& a, const DataContainer& a_y, B& b)
860  {
861  SIRF_DYNAMIC_CAST(const ISMRMRDImageData, x, a_x);
862  SIRF_DYNAMIC_CAST(const ISMRMRDImageData, y, a_y);
863  unsigned int nx = x.number();
864  unsigned int na = a.number();
865  unsigned int ny = y.number();
866  unsigned int nb = b.number();
867  //std::cout << nx << ' ' << ny << '\n';
868  if (nx != ny)
869  THROW("ImageData sizes mismatch in axpby");
870  if (na > 0 && na != nx)
871  THROW("ImageData sizes mismatch in axpby");
872  if (nb > 0 && nb != nx)
873  THROW("ImageData sizes mismatch in axpby");
874  unsigned int n = number();
875  if (n > 0) {
876  if (n != nx)
877  THROW("ImageData sizes mismatch in axpby");
878  for (unsigned int i = 0; i < nx; i++)
879  image_wrap(i).xapyb(x.image_wrap(i), a.image_wrap(i),
880  y.image_wrap(i), b.image_wrap(i));
881  }
882  else {
883  for (unsigned int i = 0; i < nx; i++) {
884  const ImageWrap& u = x.image_wrap(i);
885  const ImageWrap& v = y.image_wrap(i);
886  ImageWrap w(u);
887  w.xapyb(u, a.image_wrap(i), v, b.image_wrap(i));
888  append(w);
889  }
890  }
891  this->set_meta_data(x.get_meta_data());
892  }
893 
894  };
895 
897 
906  class GadgetronImagesVector : public GadgetronImageData {
907  public:
910  typedef std::vector<gadgetron::shared_ptr<ImageWrap> >::iterator
911  ImageWrapIter;
912  typedef std::vector<gadgetron::shared_ptr<ImageWrap> >::const_iterator
913  ImageWrapIter_const;
914  class Iterator : public ImageData::Iterator {
915  public:
916  Iterator(ImageWrapIter iw, int n, int i, const ImageWrap::Iterator& it) :
917  iw_(iw), n_(n), i_(i), iter_(it), end_((**iw).end())
918  {}
919  Iterator(const Iterator& iter) : iw_(iter.iw_), n_(iter.n_), i_(iter.i_),
920  iter_(iter.iter_), end_(iter.end_), sptr_iter_(iter.sptr_iter_)
921  {}
922  Iterator& operator=(const Iterator& iter)
923  {
924  iw_ = iter.iw_;
925  n_ = iter.n_;
926  i_ = iter.i_;
927  iter_ = iter.iter_;
928  end_ = iter.end_;
929  sptr_iter_ = iter.sptr_iter_;
930  return *this;
931  }
932  virtual bool operator==(const BaseIter& ai) const
933  {
934  SIRF_DYNAMIC_CAST(const Iterator, i, ai);
935  return iter_ == i.iter_;
936  }
937  virtual bool operator!=(const BaseIter& ai) const
938  {
939  SIRF_DYNAMIC_CAST(const Iterator, i, ai);
940  return iter_ != i.iter_;
941  }
942  Iterator& operator++()
943  {
944  if (i_ >= n_ || (i_ == n_ - 1 && iter_ == end_))
945  throw std::out_of_range("cannot advance out-of-range iterator");
946  ++iter_;
947  if (iter_ == end_ && i_ < n_ - 1) {
948  ++i_;
949  ++iw_;
950  iter_ = (**iw_).begin();
951  end_ = (**iw_).end();
952  }
953  return *this;
954  }
955  Iterator& operator++(int)
956  {
957  sptr_iter_.reset(new Iterator(*this));
958  if (i_ >= n_ || (i_ == n_ - 1 && iter_ == end_))
959  throw std::out_of_range("cannot advance out-of-range iterator");
960  ++iter_;
961  if (iter_ == end_ && i_ < n_ - 1) {
962  ++i_;
963  ++iw_;
964  iter_ = (**iw_).begin();
965  end_ = (**iw_).end();
966  }
967  return *sptr_iter_;
968  }
969  NumRef& operator*()
970  {
971  if (i_ >= n_ || (i_ == n_ - 1 && iter_ == end_))
972  throw std::out_of_range
973  ("cannot dereference out-of-range iterator");
974  return *iter_;
975  }
976  private:
977  //std::vector<gadgetron::shared_ptr<ImageWrap> >::iterator iw_;
978  ImageWrapIter iw_;
979  int n_;
980  int i_;
981  ImageWrap::Iterator iter_;
982  ImageWrap::Iterator end_;
983  gadgetron::shared_ptr<Iterator> sptr_iter_;
984  };
985 
987  public:
988  Iterator_const(ImageWrapIter_const iw, int n, int i,
989  const ImageWrap::Iterator_const& it) :
990  iw_(iw), n_(n), i_(i), iter_(it), end_((**iw).end_const())
991  {}
992  Iterator_const(const Iterator_const& iter) : iw_(iter.iw_),
993  n_(iter.n_), i_(iter.i_),
994  iter_(iter.iter_), end_(iter.end_), sptr_iter_(iter.sptr_iter_)
995  {}
996  Iterator_const& operator=(const Iterator_const& iter)
997  {
998  iw_ = iter.iw_;
999  n_ = iter.n_;
1000  i_ = iter.i_;
1001  iter_ = iter.iter_;
1002  end_ = iter.end_;
1003  sptr_iter_ = iter.sptr_iter_;
1004  return *this;
1005  }
1006  bool operator==(const BaseIter_const& ai) const
1007  {
1008  SIRF_DYNAMIC_CAST(const Iterator_const, i, ai);
1009  return iter_ == i.iter_;
1010  }
1011  bool operator!=(const BaseIter_const& ai) const
1012  {
1013  SIRF_DYNAMIC_CAST(const Iterator_const, i, ai);
1014  return iter_ != i.iter_;
1015  }
1016  Iterator_const& operator++()
1017  {
1018  if (i_ >= n_ || (i_ == n_ - 1 && iter_ == end_))
1019  throw std::out_of_range("cannot advance out-of-range iterator");
1020  ++iter_;
1021  if (iter_ == end_ && i_ < n_ - 1) {
1022  ++i_;
1023  ++iw_;
1024  iter_ = (**iw_).begin_const();
1025  end_ = (**iw_).end_const();
1026  }
1027  return *this;
1028  }
1029  // causes crashes and very inefficient anyway
1030  //Iterator_const& operator++(int)
1031  //{
1032  // sptr_iter_.reset(new Iterator_const(*this));
1033  // if (i_ >= n_ || (i_ == n_ - 1 && iter_ == end_))
1034  // throw std::out_of_range("cannot advance out-of-range iterator");
1035  // ++iter_;
1036  // if (iter_ == end_ && i_ < n_ - 1) {
1037  // ++i_;
1038  // ++iw_;
1039  // iter_ = (**iw_).begin_const();
1040  // end_ = (**iw_).end_const();
1041  // }
1042  // return *sptr_iter_;
1043  //}
1044  const NumRef& operator*() const
1045  {
1046  if (i_ >= n_ || (i_ == n_ - 1 && iter_ == end_))
1047  throw std::out_of_range
1048  ("cannot dereference out-of-range iterator");
1049  ref_.copy(*iter_);
1050  return ref_;
1051  //return *iter_;
1052  }
1053  private:
1054  //std::vector<gadgetron::shared_ptr<ImageWrap> >::const_iterator iw_;
1055  ImageWrapIter_const iw_;
1056  int n_;
1057  int i_;
1060  mutable NumRef ref_;
1061  gadgetron::shared_ptr<Iterator_const> sptr_iter_;
1062  };
1063 
1064  GadgetronImagesVector() : images_()
1065  {}
1066 
1077  GadgetronImagesVector(const MRAcquisitionData& ad, const bool coil_resolved=false);
1079  GadgetronImagesVector(GadgetronImagesVector& images, const char* attr,
1080  const char* target);
1081  virtual void empty()
1082  {
1083  images_.clear();
1084  }
1085  virtual unsigned int items() const
1086  {
1087  return (unsigned int)images_.size();
1088  }
1089  virtual unsigned int number() const
1090  {
1091  return (unsigned int)images_.size();
1092  }
1093  virtual void append(int image_data_type, void* ptr_image)
1094  {
1095  images_.push_back(gadgetron::shared_ptr<ImageWrap>
1096  (new ImageWrap(image_data_type, ptr_image)));
1097  }
1098  virtual void append(CFImage& img)
1099  {
1100  void* vptr_img = new CFImage(img);
1101  this->append(7, vptr_img);
1102  }
1103  virtual void append(const ImageWrap& iw)
1104  {
1105  images_.push_back(gadgetron::shared_ptr<ImageWrap>(new ImageWrap(iw)));
1106  }
1107  virtual void append(gadgetron::shared_ptr<ImageWrap> sptr_iw)
1108  {
1109  images_.push_back(sptr_iw);
1110  }
1111  virtual gadgetron::shared_ptr<GadgetronImageData> abs() const;
1112  virtual gadgetron::shared_ptr<GadgetronImageData> real() const;
1113  virtual void clear_data()
1114  {
1115  std::vector<gadgetron::shared_ptr<ImageWrap> > empty_data;
1116  images_.swap(empty_data);
1117  }
1118  virtual void sort();
1119  virtual gadgetron::shared_ptr<ImageWrap> sptr_image_wrap
1120  (unsigned int im_num)
1121  {
1122  int i = index(im_num);
1123  return images_.at(i);
1124  }
1125  virtual gadgetron::shared_ptr<const ImageWrap> sptr_image_wrap
1126  (unsigned int im_num) const
1127  {
1128  int i = index(im_num);
1129  return images_.at(i);
1130  }
1131 /* virtual ImageWrap& image_wrap(unsigned int im_num)
1132  {
1133  gadgetron::shared_ptr<ImageWrap> sptr_iw = sptr_image_wrap(im_num);
1134  return *sptr_iw;
1135  }
1136  virtual const ImageWrap& image_wrap(unsigned int im_num) const
1137  {
1138  const gadgetron::shared_ptr<const ImageWrap>& sptr_iw =
1139  sptr_image_wrap(im_num);
1140  return *sptr_iw;
1141  }
1142 */
1143  virtual ObjectHandle<DataContainer>* new_data_container_handle() const
1144  {
1145  return new ObjectHandle<DataContainer>
1146  (gadgetron::shared_ptr<DataContainer>(new_images_container()));
1147  }
1148  virtual gadgetron::shared_ptr<GadgetronImageData> new_images_container() const
1149  {
1150  gadgetron::shared_ptr<GadgetronImageData> sptr_img
1151  ((GadgetronImageData*)new GadgetronImagesVector());
1152  sptr_img->set_meta_data(get_meta_data());
1153  return sptr_img;
1154  }
1155  virtual gadgetron::shared_ptr<GadgetronImageData>
1156  clone(const char* attr, const char* target)
1157  {
1158  return gadgetron::shared_ptr<GadgetronImageData>
1159  (new GadgetronImagesVector(*this, attr, target));
1160  }
1161 
1162  virtual Iterator& begin()
1163  {
1164  ImageWrapIter iw = images_.begin();
1165  begin_.reset(new Iterator(iw, images_.size(), 0, (**iw).begin()));
1166  return *begin_;
1167  }
1168  virtual Iterator& end()
1169  {
1170  ImageWrapIter iw = images_.begin();
1171  int n = images_.size();
1172  for (int i = 0; i < n - 1; i++)
1173  ++iw;
1174  end_.reset(new Iterator(iw, n, n - 1, (**iw).end()));
1175  return *end_;
1176  }
1177  virtual Iterator_const& begin() const
1178  {
1179  ImageWrapIter_const iw = images_.begin();
1180  begin_const_.reset
1181  (new Iterator_const(iw, images_.size(), 0, (**iw).begin_const()));
1182  return *begin_const_;
1183  }
1184  virtual Iterator_const& end() const
1185  {
1186  ImageWrapIter_const iw = images_.begin();
1187  int n = images_.size();
1188  for (int i = 0; i < n - 1; i++)
1189  ++iw;
1190  end_const_.reset
1191  (new Iterator_const(iw, n, n - 1, (**iw).end_const()));
1192  return *end_const_;
1193  }
1194  virtual void set_image_type(int image_type);
1195  virtual void get_data(complex_float_t* data) const;
1196  virtual void set_data(const complex_float_t* data);
1197  virtual void get_real_data(float* data) const;
1198  virtual void set_real_data(const float* data);
1199 
1201  std::unique_ptr<GadgetronImagesVector> clone() const
1202  {
1203  return std::unique_ptr<GadgetronImagesVector>(this->clone_impl());
1204  }
1205 
1207  void print_header(const unsigned im_num);
1208 
1210  virtual bool is_complex() const;
1211 
1213  virtual void reorient(const VoxelisedGeometricalInfo3D &geom_info_out);
1214 
1216  virtual void set_up_geom_info();
1217 
1218  private:
1220  virtual GadgetronImagesVector* clone_impl() const
1221  {
1222  return new GadgetronImagesVector(*this);
1223  }
1224 
1225  std::vector<gadgetron::shared_ptr<ImageWrap> > images_;
1226  mutable gadgetron::shared_ptr<Iterator> begin_;
1227  mutable gadgetron::shared_ptr<Iterator> end_;
1228  mutable gadgetron::shared_ptr<Iterator_const> begin_const_;
1229  mutable gadgetron::shared_ptr<Iterator_const> end_const_;
1230  };
1231 
1238  {
1239  public:
1241  void calculate(const MRAcquisitionData& ad);
1242  protected:
1243  std::unique_ptr<MRAcquisitionData> extract_calibration_data(const MRAcquisitionData& ad) const;
1244  gadgetron::shared_ptr<FourierEncoding> sptr_enc_;
1245  };
1246 
1262  {
1263 
1264  public:
1265 
1268  GadgetronImagesVector(ad, true){}
1269  CoilSensitivitiesVector(const char * file)
1270  {
1271  throw std::runtime_error("This has not been implemented yet.");
1272  }
1273 
1274  void set_csm_smoothness(int s){csm_smoothness_ = s;}
1275 
1276  void calculate(CoilImagesVector& iv);
1277  void calculate(const MRAcquisitionData& acq)
1278  {
1279  CoilImagesVector ci;
1280  ci.calculate(acq);
1281  calculate(ci);
1282  }
1283 
1284  CFImage get_csm_as_cfimage(size_t const i) const;
1285  CFImage get_csm_as_cfimage(const KSpaceSubset::TagType tag, const int offset) const;
1286 
1287 
1288  void get_dim(size_t const num_csm, int* dim) const
1289  {
1290  GadgetronImagesVector::get_image_dimensions(num_csm, dim);
1291  }
1292 
1293  void forward(GadgetronImageData& img, GadgetronImageData& combined_img)const;
1294  void backward(GadgetronImageData& combined_img, const GadgetronImageData& img)const;
1295 
1296  protected:
1297 
1298  void coilchannels_from_combined_image(GadgetronImageData& img, GadgetronImageData& combined_img) const;
1299  void combine_images_with_coilmaps(GadgetronImageData& combined_img, const GadgetronImageData& img) const;
1300 
1301  void calculate_csm(ISMRMRD::NDArray<complex_float_t>& cm, ISMRMRD::NDArray<float>& img, ISMRMRD::NDArray<complex_float_t>& csm);
1302 
1303  private:
1304  int csm_smoothness_ = 0;
1305  void smoothen_(int nx, int ny, int nz, int nc, complex_float_t* u, complex_float_t* v, int* obj_mask, int w);
1306  void mask_noise_(int nx, int ny, int nz, float* u, float noise, int* mask);
1307  float max_diff_(int nx, int ny, int nz, int nc, float small_grad, complex_float_t* u, complex_float_t* v);
1308  float max_(int nx, int ny, int nz, float* u);
1309 
1310  };
1311 
1312 void match_img_header_to_acquisition(CFImage& img, const ISMRMRD::Acquisition& acq);
1313 
1314 }
1315 
1316 #endif
Definition: ImageData.h:37
Definition: GeometricalInfo.h:49
bool iequals(const std::string &a, const std::string &b)
Case insensitive string comparison, replaces boost::iequals.
Definition: iequals.cpp:7
Definition: gadgetron_data_containers.h:986
virtual void xapyb(const DataContainer &a_x, const void *ptr_a, const DataContainer &a_y, const void *ptr_b)
alternative interface to the above
Definition: gadgetron_data_containers.h:735
virtual void maximum(const DataContainer &x, const DataContainer &y)
*this = the elementwise max(x, y)
Definition: gadgetron_data_containers.h:769
A coil sensitivities container based on the GadgetronImagesVector class.
Definition: gadgetron_data_containers.h:1261
Definition: ImageData.h:52
std::vector< KSpaceSubset > get_kspace_sorting() const
Function to get the all KSpaceSubset&#39;s of the MRAcquisitionData.
Definition: gadgetron_data_containers.h:489
A vector implementation of the abstract MR acquisition data container class.
Definition: gadgetron_data_containers.h:559
Definition: ANumRef.h:140
Definition: ImageData.h:44
Class to keep track of order in k-space.
Definition: gadgetron_data_containers.h:142
virtual void minimum(const DataContainer &x, const DataContainer &y)
*this = the elementwise min(x, y)
Definition: gadgetron_data_containers.h:773
Abstract data container.
Definition: GeometricalInfo.cpp:141
virtual void xapyb(const DataContainer &a_x, const DataContainer &a_a, const DataContainer &a_y, const DataContainer &a_b)
*this = elementwise sum of two elementwise products x*a and y*b
Definition: gadgetron_data_containers.h:759
Definition: DataHandle.h:159
Definition: gadgetron_image_wrap.h:108
Definition: gadgetron_data_containers.h:83
virtual void minimum(const DataContainer &x, const DataContainer &y)
*this = the elementwise min(x, y)
Definition: gadgetron_data_containers.h:433
const AcquisitionsInfo & get_meta_data() const
Get the meta data.
Definition: gadgetron_data_containers.h:832
virtual void maximum(const DataContainer &x, const DataContainer &y)
*this = the elementwise max(x, y)
Definition: gadgetron_data_containers.h:429
Definition: DataContainer.h:41
Definition: gadgetron_data_containers.h:914
A vector implementation of the abstract Gadgetron image data container class.
Definition: gadgetron_data_containers.h:906
std::unique_ptr< GadgetronImagesVector > clone() const
Clone and return as unique pointer.
Definition: gadgetron_data_containers.h:1201
Specification file for a wrapper class for ISMRMRD::Image.
Definition: gadgetron_image_wrap.h:179
Abstract Gadgetron image data container class.
Definition: gadgetron_data_containers.h:632
Abstract MR acquisition data container class.
Definition: gadgetron_data_containers.h:216
A coil images container based on the GadgetronImagesVector class.
Definition: gadgetron_data_containers.h:1237
Wrapper for ISMRMRD::Image.
Definition: gadgetron_image_wrap.h:106