UsTK : Ultrasound ToolKit  version 2.0.1 under development (2023-12-07)
usImageSettingsXmlParser.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ustk software.
4  * Copyright (C) 2016 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ustk with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * This software was developed at:
17  * Inria Rennes - Bretagne Atlantique
18  * Campus Universitaire de Beaulieu
19  * 35042 Rennes Cedex
20  * France
21  *
22  * If you have questions regarding the use of this file, please contact
23  * Inria at ustk@inria.fr
24  *
25  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27  *
28  * Authors:
29  * Marc Pouliquen
30  *
31  *****************************************************************************/
32 
38 #include <visp3/ustk_core/usImageSettingsXmlParser.h>
39 #ifdef VISP_HAVE_XML2
40 
45  : m_transducerSettings(usTransducerSettings()), m_spacingX(0.0), m_spacingY(0.0), m_spacingZ(0.0),
46  m_motorSettings(usMotorSettings()), m_imageFileName(std::string("")), m_image_type(us::UNKNOWN), m_is_3D(false),
47  m_is_sequence(false)
48 {
49  nodeMap["settings"] = CODE_XML_SETTINGS;
50  nodeMap["image_type"] = CODE_XML_IMAGE_TYPE;
51  nodeMap["scanline_pitch"] = CODE_XML_SCANLINE_PITCH;
52  nodeMap["probe_radius"] = CODE_XML_TRANSDUCER_RADIUS;
53  nodeMap["is_probe_convex"] = CODE_XML_IS_TRANSDUCER_CONVEX;
54  nodeMap["frame_pitch"] = CODE_XML_FRAME_PITCH;
55  nodeMap["motor_radius"] = CODE_XML_MOTOR_RADIUS;
56  nodeMap["motor_type"] = CODE_XML_MOTOR_TYPE;
57  nodeMap["axial_resolution"] = CODE_XML_AXIAL_RESOLUTION;
58  nodeMap["height_resolution"] = CODE_XML_HEIGHT_RESOLUTION;
59  nodeMap["sampling_frequency"] = CODE_XML_SAMPLING_FREQUENCY;
60  nodeMap["transmit_frequency"] = CODE_XML_TRANSMIT_FREQUENCY;
61  nodeMap["width_resolution"] = CODE_XML_WIDTH_RESOLUTION;
62  nodeMap["scanline_number"] = CODE_XML_SCANLINE_NUMBER;
63  nodeMap["frame_number"] = CODE_XML_FRAME_NUMBER;
64  nodeMap["spacing_x"] = CODE_XML_SPACING_X;
65  nodeMap["spacing_y"] = CODE_XML_SPACING_Y;
66  nodeMap["spacing_z"] = CODE_XML_SPACING_Z;
67  nodeMap["image_file_name"] = CODE_XML_ASSOCIATED_IMAGE_FILE_NAME;
68  nodeMap["sequence_frame_rate"] = CODE_XML_SEQUENCE_FRAME_RATE;
69  nodeMap["sequence_start_number"] = CODE_XML_SEQUENCE_FIRST_IMAGE_NUMBER;
70  nodeMap["sequence_stop_number"] = CODE_XML_SEQUENCE_LAST_IMAGE_NUMBER;
71 }
72 
77  : vpXmlParser()
78 {
79  *this = twinparser;
80 }
81 
87 {
88  m_transducerSettings = twinparser.getTransducerSettings();
89  m_imageFileName = twinparser.getImageFileName();
90  m_motorSettings = twinparser.getMotorSettings();
91  m_image_type = twinparser.getImageType();
92  m_is_3D = twinparser.isImage3D();
93  m_widthResolution = twinparser.getWidthResolution();
94  m_heightResolution = twinparser.getHeightResolution();
95  m_axialResolution = twinparser.getAxialResolution();
96  m_spacingX = twinparser.getSpacingX();
97  m_spacingY = twinparser.getSpacingY();
98  m_spacingZ = twinparser.getSpacingZ();
99 
100  return *this;
101 }
102 
107 
113 void usImageSettingsXmlParser::readMainClass(xmlDocPtr doc, xmlNodePtr node)
114 {
115  std::string value;
116  for (xmlNodePtr dataNode = node->xmlChildrenNode; dataNode != NULL; dataNode = dataNode->next) {
117  if (dataNode->type == XML_ELEMENT_NODE) {
118  std::map<std::string, int>::iterator iter_data = this->nodeMap.find((char *)dataNode->name);
119  if (iter_data != nodeMap.end()) {
120  switch (iter_data->second) {
121  case CODE_XML_IMAGE_TYPE:
122  value = xmlReadStringChild(doc, dataNode);
123  if (strcmp(value.c_str(), "postscan") == 0) {
124  this->m_image_type = us::POSTSCAN_2D;
125  } else if (strcmp(value.c_str(), "prescan") == 0) {
126  this->m_image_type = us::PRESCAN_2D;
127  } else if (strcmp(value.c_str(), "rf") == 0) {
128  this->m_image_type = us::RF_2D;
129  } else
130  throw(vpException(vpException::fatalError, std::string("unknown image type in xml file")));
131  break;
133  if (this->m_image_type == us::PRESCAN_2D || this->m_image_type == us::RF_2D) {
134  this->m_axialResolution = xmlReadDoubleChild(doc, dataNode);
135  } else
136  throw(vpException(vpException::fatalError,
137  std::string("Trying to assign an axial resolution to a post-scan image !")));
138  break;
140  if (this->m_image_type == us::RF_2D || this->m_image_type == us::PRESCAN_2D) {
141  throw(vpException(vpException::fatalError,
142  std::string("Trying to assign an height resolution to a pre-scan image !")));
143  } else if (this->m_is_3D) {
144  throw(vpException(
145  vpException::fatalError,
146  std::string("Trying to assign an height resolution to a 3D image ! Use spacing_y instead.")));
147  } else
148  this->m_heightResolution = xmlReadDoubleChild(doc, dataNode);
149  break;
151  if (this->m_image_type == us::RF_2D || this->m_image_type == us::PRESCAN_2D) {
152  throw(vpException(vpException::fatalError,
153  std::string("Trying to assign an width resolution to a pre-scan image !")));
154  } else if (this->m_is_3D) {
155  throw(vpException(
156  vpException::fatalError,
157  std::string("Trying to assign an height resolution to a 3D image ! Use spacing_x instead.")));
158  } else
159  this->m_widthResolution = xmlReadDoubleChild(doc, dataNode);
160  break;
161  case CODE_XML_SPACING_X:
162  if (this->m_image_type == us::RF_2D || this->m_image_type == us::PRESCAN_2D) {
163  throw(
164  vpException(vpException::fatalError, std::string("Trying to assign a spacing to a pre-scan image !")));
165  } else if (!this->m_is_3D) {
166  throw(vpException(
167  vpException::fatalError,
168  std::string("Trying to assign a spacing to a 2D image ! Use height/width resolutions instead.")));
169  } else
170  this->m_widthResolution = xmlReadDoubleChild(doc, dataNode);
171  break;
172  case CODE_XML_SPACING_Y:
173  if (this->m_image_type == us::RF_2D || this->m_image_type == us::PRESCAN_2D) {
174  throw(
175  vpException(vpException::fatalError, std::string("Trying to assign a spacing to a pre-scan image !")));
176  } else if (!this->m_is_3D) {
177  throw(vpException(
178  vpException::fatalError,
179  std::string("Trying to assign an spacing to a 2D image ! Use height/width resolutions instead.")));
180  } else
181  this->m_widthResolution = xmlReadDoubleChild(doc, dataNode);
182  break;
183  case CODE_XML_SPACING_Z:
184  if (this->m_image_type == us::RF_2D || this->m_image_type == us::PRESCAN_2D) {
185  throw(
186  vpException(vpException::fatalError, std::string("Trying to assign a spacing to a pre-scan image !")));
187  } else if (!this->m_is_3D) {
188  throw(vpException(
189  vpException::fatalError,
190  std::string("Trying to assign an spacing to a 2D image ! Use height/width resolutions instead.")));
191  } else
192  this->m_widthResolution = xmlReadDoubleChild(doc, dataNode);
193  break;
195  if (this->m_image_type == us::RF_2D || this->m_image_type == us::PRESCAN_2D) {
196  throw(vpException(vpException::fatalError,
197  std::string("Trying to assign a scan line number to a pre-scan image (for pre-scan "
198  "images scan line number is the image width) !")));
199  } else
200  this->m_transducerSettings.setScanLineNumber(xmlReadIntChild(doc, dataNode));
201  break;
203  this->m_transducerSettings.setScanLinePitch(xmlReadDoubleChild(doc, dataNode));
204  this->m_transducerSettings.setScanLinePitch(xmlReadDoubleChild(doc, dataNode));
205  break;
207  this->m_transducerSettings.setTransducerRadius(xmlReadDoubleChild(doc, dataNode));
208  this->m_transducerSettings.setTransducerRadius(xmlReadDoubleChild(doc, dataNode));
209  break;
211  this->m_transducerSettings.setTransducerConvexity(xmlReadBoolChild(doc, dataNode));
212  this->m_transducerSettings.setTransducerConvexity(xmlReadBoolChild(doc, dataNode));
213  break;
215  this->m_transducerSettings.setSamplingFrequency(xmlReadIntChild(doc, dataNode));
216  break;
218  this->m_transducerSettings.setTransmitFrequency(xmlReadIntChild(doc, dataNode));
219  break;
221  this->m_motorSettings.setFramePitch(xmlReadDoubleChild(doc, dataNode));
222  break;
224  this->m_motorSettings.setMotorRadius(xmlReadDoubleChild(doc, dataNode));
225  break;
226  case CODE_XML_MOTOR_TYPE:
227  value = xmlReadStringChild(doc, dataNode);
228  if (strcmp(value.c_str(), "linear_motor") == 0) {
229  this->m_motorSettings.setMotorType(usMotorSettings::LinearMotor);
230  } else if (strcmp(value.c_str(), "tilting_motor") == 0) {
231  this->m_motorSettings.setMotorType(usMotorSettings::TiltingMotor);
232  } else if (strcmp(value.c_str(), "rotational_motor") == 0) {
233  this->m_motorSettings.setMotorType(usMotorSettings::RotationalMotor);
234  } else
235  throw(vpException(vpException::fatalError, std::string("unknown image type in xml file")));
236  value = "";
237  break;
239  this->m_imageFileName = xmlReadStringChild(doc, dataNode);
240  break;
242  this->m_sequence_frame_rate = xmlReadDoubleChild(doc, dataNode);
243  this->m_is_sequence = true;
244  break;
246  this->m_sequence_start = xmlReadIntChild(doc, dataNode);
247  this->m_is_sequence = true;
248  break;
250  this->m_sequence_stop = xmlReadIntChild(doc, dataNode);
251  this->m_is_sequence = true;
252  break;
253  default:
254  vpTRACE("unknown tag in readConfigNode : %d, %s", iter_data->second, (iter_data->first).c_str());
255  break;
256  }
257  }
258  }
259  }
260 }
261 
267 {
268  std::string imageFileName = m_imageFileName;
269  xmlWriteStringChild(node, "image_file_name", imageFileName);
270  if (this->m_image_type == us::RF_2D) {
271  xmlWriteStringChild(node, "image_type", std::string("rf"));
272  xmlWriteDoubleChild(node, "scanline_pitch", m_transducerSettings.getScanLinePitch());
273  xmlWriteDoubleChild(node, "probe_radius", m_transducerSettings.getTransducerRadius());
274  xmlWriteBoolChild(node, "is_probe_convex", m_transducerSettings.isTransducerConvex());
275  xmlWriteDoubleChild(node, "axial_resolution", m_axialResolution);
276  xmlWriteDoubleChild(node, "transmit_frequency", m_transducerSettings.getTransmitFrequency());
277  xmlWriteDoubleChild(node, "sampling_frequency", m_transducerSettings.getSamplingFrequency());
278  }
279  if (this->m_image_type == us::PRESCAN_2D) {
280  xmlWriteStringChild(node, "image_type", std::string("prescan"));
281  xmlWriteDoubleChild(node, "scanline_pitch", m_transducerSettings.getScanLinePitch());
282  xmlWriteDoubleChild(node, "probe_radius", m_transducerSettings.getTransducerRadius());
283  xmlWriteBoolChild(node, "is_probe_convex", m_transducerSettings.isTransducerConvex());
284  xmlWriteDoubleChild(node, "axial_resolution", m_axialResolution);
285  xmlWriteDoubleChild(node, "transmit_frequency", m_transducerSettings.getTransmitFrequency());
286  xmlWriteDoubleChild(node, "sampling_frequency", m_transducerSettings.getSamplingFrequency());
287  } else if (this->m_image_type == us::POSTSCAN_2D) {
288  xmlWriteStringChild(node, "image_type", std::string("postscan"));
289  xmlWriteDoubleChild(node, "scanline_pitch", m_transducerSettings.getScanLinePitch());
290  xmlWriteDoubleChild(node, "probe_radius", m_transducerSettings.getTransducerRadius());
291  xmlWriteBoolChild(node, "is_probe_convex", m_transducerSettings.isTransducerConvex());
292  xmlWriteIntChild(node, "scanline_number", m_transducerSettings.getScanLineNumber());
293  xmlWriteDoubleChild(node, "transmit_frequency", m_transducerSettings.getTransmitFrequency());
294  xmlWriteDoubleChild(node, "sampling_frequency", m_transducerSettings.getSamplingFrequency());
295  if (m_is_3D) {
296  xmlWriteIntChild(node, "frame_number", m_motorSettings.getFrameNumber());
297  xmlWriteDoubleChild(node, "spacing_x", m_spacingX);
298  xmlWriteDoubleChild(node, "spacing_y", m_spacingY);
299  xmlWriteDoubleChild(node, "spacing_z", m_spacingZ);
300  } else {
301  xmlWriteDoubleChild(node, "height_resolution", m_heightResolution);
302  xmlWriteDoubleChild(node, "width_resolution", m_widthResolution);
303  }
304  }
305  if (m_is_3D) {
306  xmlWriteDoubleChild(node, "frame_pitch", m_motorSettings.getFramePitch());
307  xmlWriteDoubleChild(node, "motor_radius", m_motorSettings.getMotorRadius());
308  if (m_motorSettings.getMotorType() == usMotorSettings::LinearMotor) {
309  xmlWriteStringChild(node, "motor_type", std::string("linear_motor"));
310  } else if (m_motorSettings.getMotorType() == usMotorSettings::TiltingMotor) {
311  xmlWriteStringChild(node, "motor_type", std::string("tilting_motor"));
312  } else if (m_motorSettings.getMotorType() == usMotorSettings::RotationalMotor) {
313  xmlWriteStringChild(node, "motor_type", std::string("rotational_motor"));
314  }
315  }
316  if (m_is_sequence) {
317  std::cout << "writing sequence parameters" << std::endl;
318  // xmlWriteStringChild(node, "sequence_name", this->m_sequence_name);
319  xmlWriteDoubleChild(node, "sequence_frame_rate", this->m_sequence_frame_rate);
320  xmlWriteIntChild(node, "sequence_start_number", this->m_sequence_start);
321  xmlWriteIntChild(node, "sequence_stop_number", this->m_sequence_stop);
322  }
323 }
324 
335 void usImageSettingsXmlParser::setImageSettings(double transducerRadius, double scanLinePitch, bool isTransducerConvex,
336  double axialResolution, us::ImageType image_type, int samplingFrequency,
337  int transmitFrequency)
338 {
339  if (image_type == us::PRESCAN_2D || image_type == us::RF_2D) {
340  m_transducerSettings.setTransducerConvexity(isTransducerConvex);
341  m_transducerSettings.setTransducerRadius(transducerRadius);
342  m_transducerSettings.setScanLinePitch(scanLinePitch);
343  m_transducerSettings.setSamplingFrequency(samplingFrequency);
344  m_transducerSettings.setTransmitFrequency(transmitFrequency);
345  m_axialResolution = axialResolution;
346  m_image_type = image_type;
347  } else {
348  throw(vpException(vpException::fatalError, "trying to write axial resolution in a image not rf nor pre-scan !"));
349  }
350 }
351 
363 void usImageSettingsXmlParser::setImageSettings(double transducerRadius, double scanLinePitch, bool isTransducerConvex,
364  unsigned int scanLineNumber, double widthResolution,
365  double heightResolution, int samplingFrequency, int transmitFrequency)
366 {
367  m_transducerSettings.setTransducerConvexity(isTransducerConvex);
368  m_transducerSettings.setTransducerRadius(transducerRadius);
369  m_transducerSettings.setScanLinePitch(scanLinePitch);
370  m_transducerSettings.setScanLineNumber(scanLineNumber);
371  m_transducerSettings.setSamplingFrequency(samplingFrequency);
372  m_transducerSettings.setTransmitFrequency(transmitFrequency);
373  m_heightResolution = widthResolution;
374  m_widthResolution = heightResolution;
375  m_image_type = us::POSTSCAN_2D;
376 }
377 
383 {
384  m_is_3D = true;
385  m_motorSettings = motorSettings;
386 }
387 
392 void usImageSettingsXmlParser::setImageFileName(const std::string &imageFileName) { m_imageFileName = imageFileName; }
393 #endif // VISP_HAVE_XML2
Input/output operations between ultrasound image settings and the assiciated xml files.
void setMotorSettings(const usMotorSettings &motorSettings)
usImageSettingsXmlParser & operator=(const usImageSettingsXmlParser &twinparser)
usMotorSettings getMotorSettings() const
void setImageFileName(const std::string &imageFileName)
us::ImageType getImageType() const
usTransducerSettings getTransducerSettings() const
void setImageSettings(double transducerRadius, double scanLinePitch, bool isTransducerConvex, double axialResolution, us::ImageType image_type, int samplingFrequency, int transmitFrequency)
std::string getImageFileName() const
void writeMainClass(xmlNodePtr node)
void readMainClass(xmlDocPtr doc, xmlNodePtr node)
Generic class for 3D ultrasound motor settings associated to the 3D probe used during acquisition.
unsigned int getFrameNumber() const
double getMotorRadius() const
void setMotorType(const usMotorType &motorType)
void setMotorRadius(double motorRadius)
double getFramePitch() const
usMotorType getMotorType() const
void setFramePitch(double framePitch)
Generic class for 2D ultrasound data common settings associated to the type of probe transducer used ...
void setTransducerConvexity(const bool isTransducerConvex)
void setScanLinePitch(const double scanLinePitch)
void setTransmitFrequency(const int transmitFrequency)
void setSamplingFrequency(const int samplingFrequency)
void setTransducerRadius(const double transducerRadius)
double getTransducerRadius() const
unsigned int getScanLineNumber() const
void setScanLineNumber(unsigned int scanLineNumber)
General tools.
ImageType
Definition: us.h:65
@ PRESCAN_2D
Definition: us.h:70
@ POSTSCAN_2D
Definition: us.h:72
@ RF_2D
Definition: us.h:68