SIRF  3.5.0
gadgetron_client.h
Go to the documentation of this file.
1 /*
2 SyneRBI Synergistic Image Reconstruction Framework (SIRF)
3 Copyright 2015 - 2019 Rutherford Appleton Laboratory STFC
4 
5 This is software developed for the Collaborative Computational
6 Project in Synergistic Reconstruction for Biomedical Imaging (formerly CCP PETMR)
7 (http://www.ccpsynerbi.ac.uk/).
8 
9 Licensed under the Apache License, Version 2.0 (the "License");
10 you may not use this file except in compliance with the License.
11 You may obtain a copy of the License at
12 http://www.apache.org/licenses/LICENSE-2.0
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18 
19 This file contains code snippets from
20 Gadgetron/apps/clients/gadgetron_ismrmrd_client/gadgetron_ismrmrd_client.cpp
21 by Michael S. Hansen
22 
23 GADGETRON SOFTWARE LICENSE V1.0, NOVEMBER 2011
24 
25 PERMISSION IS HEREBY GRANTED, FREE OF CHARGE, TO ANY PERSON OBTAINING
26 A COPY OF THIS SOFTWARE AND ASSOCIATED DOCUMENTATION FILES (THE
27 "SOFTWARE"), TO DEAL IN THE SOFTWARE WITHOUT RESTRICTION, INCLUDING
28 WITHOUT LIMITATION THE RIGHTS TO USE, COPY, MODIFY, MERGE, PUBLISH,
29 DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THE SOFTWARE, AND TO
30 PERMIT PERSONS TO WHOM THE SOFTWARE IS FURNISHED TO DO SO, SUBJECT TO
31 THE FOLLOWING CONDITIONS:
32 
33 THE ABOVE COPYRIGHT NOTICE, THIS PERMISSION NOTICE, AND THE LIMITATION
34 OF LIABILITY BELOW SHALL BE INCLUDED IN ALL COPIES OR REDISTRIBUTIONS
35 OF SUBSTANTIAL PORTIONS OF THE SOFTWARE.
36 
37 SOFTWARE IS BEING DEVELOPED IN PART AT THE NATIONAL HEART, LUNG, AND BLOOD
38 INSTITUTE, NATIONAL INSTITUTES OF HEALTH BY AN EMPLOYEE OF THE FEDERAL
39 GOVERNMENT IN THE COURSE OF HIS OFFICIAL DUTIES. PURSUANT TO TITLE 17,
40 SECTION 105 OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO
41 COPYRIGHT PROTECTION AND IS IN THE PUBLIC DOMAIN. EXCEPT AS CONTAINED IN
42 THIS NOTICE, THE NAME OF THE AUTHORS, THE NATIONAL HEART, LUNG, AND BLOOD
43 INSTITUTE (NHLBI), OR THE NATIONAL INSTITUTES OF HEALTH (NIH) MAY NOT
44 BE USED TO ENDORSE OR PROMOTE PRODUCTS DERIVED FROM THIS SOFTWARE WITHOUT
45 SPECIFIC PRIOR WRITTEN PERMISSION FROM THE NHLBI OR THE NIH.THE SOFTWARE IS
46 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
47 INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
48 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
49 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
50 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
51 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
52 */
53 
63 #ifndef GADGETRON_CLIENT
64 #define GADGETRON_CLIENT
65 
66 #ifndef WIN32_LEAN_AND_MEAN
67 #define WIN32_LEAN_AND_MEAN
68 #endif
69 
70 #include <chrono>
71 #include <condition_variable>
72 #include <exception>
73 #include <fstream>
74 #include <iomanip>
75 #include <iostream>
76 #include <map>
77 #include <memory>
78 #include <thread>
79 
80 #include <boost/asio.hpp>
81 #include <boost/thread/thread.hpp>
82 
83 #include <ismrmrd/dataset.h>
84 #include <ismrmrd/ismrmrd.h>
85 #include <ismrmrd/meta.h>
86 
87 #include "sirf/Gadgetron/cgadgetron_shared_ptr.h"
89 
90 enum GadgetronMessageID {
91  GADGET_MESSAGE_INT_ID_MIN = 0,
92  GADGET_MESSAGE_CONFIG_FILE = 1,
93  GADGET_MESSAGE_CONFIG_SCRIPT = 2,
94  GADGET_MESSAGE_PARAMETER_SCRIPT = 3,
95  GADGET_MESSAGE_CLOSE = 4,
96  GADGET_MESSAGE_TEXT = 5,
97  GADGET_MESSAGE_INT_ID_MAX = 999,
98  GADGET_MESSAGE_EXT_ID_MIN = 1000,
99  GADGET_MESSAGE_ISMRMRD_ACQUISITION = 1008,
100  GADGET_MESSAGE_CLOUD_JOB = 1013,
101  GADGET_MESSAGE_GADGETCLOUD_JOB = 1014,
102  GADGET_MESSAGE_DICOM_WITHNAME = 1018,
103  GADGET_MESSAGE_DEPENDENCY_QUERY = 1019,
104  GADGET_MESSAGE_ISMRMRD_IMAGE = 1022,
105  GADGET_MESSAGE_RECONDATA = 1023,
106  GADGET_MESSAGE_EXT_ID_MAX = 4096
107 };
108 
109 #define MAX_BLOBS_LOG_10 6
110 
111 namespace sirf {
112 
114  uint16_t id;
115  };
116 
118  char configuration_file[1024];
119  };
120 
122  uint32_t script_length;
123  };
124 
125  class GadgetronClientException : public std::exception {
126  public:
127  GadgetronClientException(std::string msg) : msg_(msg) {}
128  virtual ~GadgetronClientException() throw() {}
129  virtual const char* what() const throw()
130  {
131  return msg_.c_str();
132  }
133  protected:
134  std::string msg_;
135  };
136 
141  public:
142  virtual ~GadgetronClientMessageReader() {}
146  virtual void read(boost::asio::ip::tcp::socket* s) = 0;
147  };
148 
154  public:
156  (gadgetron::shared_ptr<MRAcquisitionData> ptr_acqs) : ptr_acqs_(ptr_acqs) {}
158 
159  virtual void read(boost::asio::ip::tcp::socket* stream);
160 
161  private:
162  gadgetron::shared_ptr<MRAcquisitionData> ptr_acqs_;
163  };
164 
170  public:
172  (gadgetron::shared_ptr<GadgetronImageData> ptr_images) : ptr_images_(ptr_images) {}
174 
175  template <typename T>
176  void read_data_attributes
177  (ISMRMRD::Image<T>* ptr, const ISMRMRD::ImageHeader& h, void** ptr_ptr,
178  boost::asio::ip::tcp::socket* stream)
179  {
180  ISMRMRD::Image < T >* ptr_im = new ISMRMRD::Image < T > ;
181  *ptr_ptr = (void*)ptr_im;
182  ISMRMRD::Image<T>& im = *ptr_im;
183  im.setHead(h);
184  //im.setImageType(ISMRMRD::ISMRMRD_IMTYPE_MAGNITUDE);
185 
186  //Read meta attributes
187  typedef unsigned long long size_t_type;
188  size_t_type meta_attrib_length;
189  boost::asio::read
190  (*stream, boost::asio::buffer(&meta_attrib_length, sizeof(size_t_type)));
191  if (meta_attrib_length > 0) {
192  std::string meta_attrib(meta_attrib_length, 0);
193  boost::asio::read(*stream, boost::asio::buffer(const_cast < char* >
194  (meta_attrib.c_str()), meta_attrib_length));
195  im.setAttributeString(meta_attrib);
196  }
197  //Read image data
198  boost::asio::read
199  (*stream, boost::asio::buffer(im.getDataPtr(), im.getDataSize()));
200  }
201 
202  virtual void read(boost::asio::ip::tcp::socket* stream);
203 
204  private:
205  gadgetron::shared_ptr<GadgetronImageData> ptr_images_;
206  };
207 
210  public:
211  GadgetronClientBlobMessageReader(std::string fileprefix, std::string filesuffix)
212  : number_of_calls_(0)
213  , file_prefix(fileprefix)
214  , file_suffix(filesuffix)
215  {
216  //std::cout << fileprefix << '.' << filesuffix << '\n';
217  }
218 
220 
221  virtual void read(boost::asio::ip::tcp::socket* socket)
222  {
223  //std::cout << "in GadgetronClientBlobMessageReader::read...\n";
224  // MUST READ 32-bits
225  uint32_t nbytes;
226  boost::asio::read(*socket, boost::asio::buffer(&nbytes, sizeof(uint32_t)));
227 
228  std::vector<char> data(nbytes, 0);
229  boost::asio::read(*socket, boost::asio::buffer(&data[0], nbytes));
230 
231  unsigned long long fileNameLen;
232  boost::asio::read(*socket, boost::asio::buffer(&fileNameLen, sizeof(unsigned long long)));
233 
234  std::string filenameBuf(fileNameLen, 0);
235  boost::asio::read(*socket, boost::asio::buffer(const_cast<char*>
236  (filenameBuf.c_str()), fileNameLen));
237 
238  typedef unsigned long long size_t_type;
239 
240  size_t_type meta_attrib_length;
241  boost::asio::read(*socket, boost::asio::buffer(&meta_attrib_length, sizeof(size_t_type)));
242 
243  std::string meta_attrib;
244  if (meta_attrib_length > 0) {
245  std::string meta_attrib_socket(meta_attrib_length, 0);
246  boost::asio::read(*socket, boost::asio::buffer(const_cast<char*>(meta_attrib_socket.c_str()), meta_attrib_length));
247  meta_attrib = meta_attrib_socket;
248  }
249 
250  std::stringstream filename;
251  std::string filename_attrib;
252 
253  // Create the filename: (prefix_%06.suffix)
254  filename << file_prefix << "_";
255  filename << std::setfill('0') << std::setw(MAX_BLOBS_LOG_10) << number_of_calls_;
256  filename_attrib = filename.str();
257  filename << "." << file_suffix;
258  filename_attrib.append("_attrib.xml");
259 
260  //std::cout << "Writing image " << filename.str() << std::endl;
261 
262  std::ofstream outfile;
263  outfile.open(filename.str().c_str(), std::ios::out | std::ios::binary);
264 
265  std::ofstream outfile_attrib;
266  if (meta_attrib_length > 0) {
267  outfile_attrib.open(filename_attrib.c_str(), std::ios::out | std::ios::binary);
268  }
269 
270  if (outfile.good()) {
271  /* write 'size' bytes starting at 'data's pointer */
272  outfile.write(&data[0], nbytes);
273  outfile.close();
274  if (meta_attrib_length > 0) {
275  outfile_attrib.write(meta_attrib.c_str(), meta_attrib.length());
276  outfile_attrib.close();
277  }
278  number_of_calls_++;
279  }
280  else {
281  throw GadgetronClientException("Unable to write blob to output file\n");
282  }
283  }
284 
285  protected:
286  size_t number_of_calls_;
287  std::string file_prefix;
288  std::string file_suffix;
289  };
290 
295  public:
296  GadgetronClientConnector() : socket_(0), timeout_ms_(2000)
297  {}
298  virtual ~GadgetronClientConnector()
299  {
300  if (socket_) {
301  socket_->close();
302  delete socket_;
303  }
304  }
305 
306  void set_timeout(unsigned int t)
307  {
308  timeout_ms_ = t;
309  }
310 
311  void read_task();
312 
313  void wait()
314  {
315  reader_thread_.join();
316  }
317 
318  void connect(std::string hostname, std::string port);
319 
320  void send_gadgetron_close();
321 
322  void send_gadgetron_configuration_file(std::string config_xml_name);
323 
324  void send_gadgetron_configuration_script(std::string xml_string);
325 
326  void send_gadgetron_parameters(std::string xml_string);
327 
328  void send_ismrmrd_acquisition(ISMRMRD::Acquisition& acq);
329 
330  template<typename T>
331  void send_ismrmrd_image(ISMRMRD::Image<T>* ptr_im)
332  {
333  ISMRMRD::Image<T>& im = *ptr_im;
334  if (!socket_)
335  throw GadgetronClientException("Invalid socket.");
336 
338  id.id = GADGET_MESSAGE_ISMRMRD_IMAGE;
339 
340  boost::asio::write
341  (*socket_, boost::asio::buffer(&id, sizeof(GadgetMessageIdentifier)));
342  boost::asio::write
343  (*socket_,
344  boost::asio::buffer(&im.getHead(), sizeof(ISMRMRD::ImageHeader)));
345 
346  size_t meta_attrib_length = im.getAttributeStringLength();
347  std::string meta_attrib(meta_attrib_length + 1, 0);
348  im.getAttributeString(meta_attrib);
349 
350  boost::asio::write
351  (*socket_, boost::asio::buffer(&meta_attrib_length, sizeof(size_t)));
352  boost::asio::write
353  (*socket_, boost::asio::buffer(meta_attrib.c_str(), meta_attrib_length));
354 
355  boost::asio::write
356  (*socket_, boost::asio::buffer(im.getDataPtr(), im.getDataSize()));
357  }
358 
359  void send_wrapped_image(const ImageWrap& iw)
360  {
361  IMAGE_PROCESSING_SWITCH(iw.type(), send_ismrmrd_image, iw.ptr_image());
362  }
363 
364  void register_reader
365  (unsigned short slot, gadgetron::shared_ptr<GadgetronClientMessageReader> r)
366  {
367  readers_[slot] = r;
368  }
369 
370  protected:
371  typedef
372  std::map < unsigned short, gadgetron::shared_ptr<GadgetronClientMessageReader> >
373  maptype;
374 
375  GadgetronClientMessageReader* find_reader(unsigned short r);
376 
377  boost::asio::io_service io_service;
378  boost::asio::ip::tcp::socket* socket_;
379  boost::thread reader_thread_;
380  maptype readers_;
381  unsigned int timeout_ms_;
382  };
383 
384 }
385 
386 #endif
Class for accumulating acquisitions sent by Gadgetron server.
Definition: gadgetron_client.h:153
virtual void read(boost::asio::ip::tcp::socket *stream)
Definition: gadgetron_client.cpp:72
Definition: gadgetron_client.h:209
virtual void read(boost::asio::ip::tcp::socket *socket)
Definition: gadgetron_client.h:221
Class for communicating with Gadgetron server.
Definition: gadgetron_client.h:294
Definition: gadgetron_client.h:125
Class for accumulating ISMRMRD images sent by Gadgetron server.
Definition: gadgetron_client.h:169
virtual void read(boost::asio::ip::tcp::socket *stream)
Definition: gadgetron_client.cpp:100
Abstract base class for receiving messages from Gadgetron server.
Definition: gadgetron_client.h:140
virtual void read(boost::asio::ip::tcp::socket *s)=0
Wrapper for ISMRMRD::Image.
Definition: gadgetron_image_wrap.h:106
Specification file for data container classes for Gadgetron data.
Abstract data container.
Definition: GeometricalInfo.cpp:141
Definition: gadgetron_client.h:117
Definition: gadgetron_client.h:113
Definition: gadgetron_client.h:121