UsTK : Ultrasound ToolKit  version 2.0.1 under development (2025-03-12)
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 
40 #ifdef VISP_HAVE_XML2
41 
42 #include <libxml/parser.h>
43 
48  : m_transducerSettings(usTransducerSettings()), m_spacingX(0.0), m_spacingY(0.0), m_spacingZ(0.0),
49  m_motorSettings(usMotorSettings()), m_imageFileName(std::string("")), m_image_type(us::UNKNOWN), m_is_3D(false),
50  m_is_sequence(false)
51 {
52  nodeMap["settings"] = CODE_XML_SETTINGS;
53  nodeMap["image_type"] = CODE_XML_IMAGE_TYPE;
54  nodeMap["scanline_pitch"] = CODE_XML_SCANLINE_PITCH;
55  nodeMap["probe_radius"] = CODE_XML_TRANSDUCER_RADIUS;
56  nodeMap["is_probe_convex"] = CODE_XML_IS_TRANSDUCER_CONVEX;
57  nodeMap["frame_pitch"] = CODE_XML_FRAME_PITCH;
58  nodeMap["motor_radius"] = CODE_XML_MOTOR_RADIUS;
59  nodeMap["motor_type"] = CODE_XML_MOTOR_TYPE;
60  nodeMap["axial_resolution"] = CODE_XML_AXIAL_RESOLUTION;
61  nodeMap["height_resolution"] = CODE_XML_HEIGHT_RESOLUTION;
62  nodeMap["sampling_frequency"] = CODE_XML_SAMPLING_FREQUENCY;
63  nodeMap["transmit_frequency"] = CODE_XML_TRANSMIT_FREQUENCY;
64  nodeMap["width_resolution"] = CODE_XML_WIDTH_RESOLUTION;
65  nodeMap["scanline_number"] = CODE_XML_SCANLINE_NUMBER;
66  nodeMap["frame_number"] = CODE_XML_FRAME_NUMBER;
67  nodeMap["spacing_x"] = CODE_XML_SPACING_X;
68  nodeMap["spacing_y"] = CODE_XML_SPACING_Y;
69  nodeMap["spacing_z"] = CODE_XML_SPACING_Z;
70  nodeMap["image_file_name"] = CODE_XML_ASSOCIATED_IMAGE_FILE_NAME;
71  nodeMap["sequence_frame_rate"] = CODE_XML_SEQUENCE_FRAME_RATE;
72  nodeMap["sequence_start_number"] = CODE_XML_SEQUENCE_FIRST_IMAGE_NUMBER;
73  nodeMap["sequence_stop_number"] = CODE_XML_SEQUENCE_LAST_IMAGE_NUMBER;
74 }
75 
80  : vpXmlParser()
81 {
82  *this = twinparser;
83 }
84 
90 {
91  m_transducerSettings = twinparser.getTransducerSettings();
92  m_imageFileName = twinparser.getImageFileName();
93  m_motorSettings = twinparser.getMotorSettings();
94  m_image_type = twinparser.getImageType();
95  m_is_3D = twinparser.isImage3D();
96  m_widthResolution = twinparser.getWidthResolution();
97  m_heightResolution = twinparser.getHeightResolution();
98  m_axialResolution = twinparser.getAxialResolution();
99  m_spacingX = twinparser.getSpacingX();
100  m_spacingY = twinparser.getSpacingY();
101  m_spacingZ = twinparser.getSpacingZ();
102 
103  return *this;
104 }
105 
110 
116 void usImageSettingsXmlParser::readMainClass(xmlDocPtr doc, xmlNodePtr node)
117 {
118  std::string value;
119  for (xmlNodePtr dataNode = node->xmlChildrenNode; dataNode != NULL; dataNode = dataNode->next) {
120  if (dataNode->type == XML_ELEMENT_NODE) {
121  std::map<std::string, int>::iterator iter_data = this->nodeMap.find((char *)dataNode->name);
122  if (iter_data != nodeMap.end()) {
123  switch (iter_data->second) {
124  case CODE_XML_IMAGE_TYPE:
125  value = xmlReadStringChild(doc, dataNode);
126  if (strcmp(value.c_str(), "postscan") == 0) {
127  this->m_image_type = us::POSTSCAN_2D;
128  }
129  else if (strcmp(value.c_str(), "prescan") == 0) {
130  this->m_image_type = us::PRESCAN_2D;
131  }
132  else if (strcmp(value.c_str(), "rf") == 0) {
133  this->m_image_type = us::RF_2D;
134  }
135  else
136  throw(vpException(vpException::fatalError, std::string("unknown image type in xml file")));
137  break;
139  if (this->m_image_type == us::PRESCAN_2D || this->m_image_type == us::RF_2D) {
140  this->m_axialResolution = xmlReadDoubleChild(doc, dataNode);
141  }
142  else
143  throw(vpException(vpException::fatalError,
144  std::string("Trying to assign an axial resolution to a post-scan image !")));
145  break;
147  if (this->m_image_type == us::RF_2D || this->m_image_type == us::PRESCAN_2D) {
148  throw(vpException(vpException::fatalError,
149  std::string("Trying to assign an height resolution to a pre-scan image !")));
150  }
151  else if (this->m_is_3D) {
152  throw(vpException(
153  vpException::fatalError,
154  std::string("Trying to assign an height resolution to a 3D image ! Use spacing_y instead.")));
155  }
156  else
157  this->m_heightResolution = xmlReadDoubleChild(doc, dataNode);
158  break;
160  if (this->m_image_type == us::RF_2D || this->m_image_type == us::PRESCAN_2D) {
161  throw(vpException(vpException::fatalError,
162  std::string("Trying to assign an width resolution to a pre-scan image !")));
163  }
164  else if (this->m_is_3D) {
165  throw(vpException(
166  vpException::fatalError,
167  std::string("Trying to assign an height resolution to a 3D image ! Use spacing_x instead.")));
168  }
169  else
170  this->m_widthResolution = xmlReadDoubleChild(doc, dataNode);
171  break;
172  case CODE_XML_SPACING_X:
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  }
177  else if (!this->m_is_3D) {
178  throw(vpException(
179  vpException::fatalError,
180  std::string("Trying to assign a spacing to a 2D image ! Use height/width resolutions instead.")));
181  }
182  else
183  this->m_widthResolution = xmlReadDoubleChild(doc, dataNode);
184  break;
185  case CODE_XML_SPACING_Y:
186  if (this->m_image_type == us::RF_2D || this->m_image_type == us::PRESCAN_2D) {
187  throw(
188  vpException(vpException::fatalError, std::string("Trying to assign a spacing to a pre-scan image !")));
189  }
190  else if (!this->m_is_3D) {
191  throw(vpException(
192  vpException::fatalError,
193  std::string("Trying to assign an spacing to a 2D image ! Use height/width resolutions instead.")));
194  }
195  else
196  this->m_widthResolution = xmlReadDoubleChild(doc, dataNode);
197  break;
198  case CODE_XML_SPACING_Z:
199  if (this->m_image_type == us::RF_2D || this->m_image_type == us::PRESCAN_2D) {
200  throw(
201  vpException(vpException::fatalError, std::string("Trying to assign a spacing to a pre-scan image !")));
202  }
203  else if (!this->m_is_3D) {
204  throw(vpException(
205  vpException::fatalError,
206  std::string("Trying to assign an spacing to a 2D image ! Use height/width resolutions instead.")));
207  }
208  else
209  this->m_widthResolution = xmlReadDoubleChild(doc, dataNode);
210  break;
212  if (this->m_image_type == us::RF_2D || this->m_image_type == us::PRESCAN_2D) {
213  throw(vpException(vpException::fatalError,
214  std::string("Trying to assign a scan line number to a pre-scan image (for pre-scan "
215  "images scan line number is the image width) !")));
216  }
217  else
218  this->m_transducerSettings.setScanLineNumber(xmlReadIntChild(doc, dataNode));
219  break;
221  this->m_transducerSettings.setScanLinePitch(xmlReadDoubleChild(doc, dataNode));
222  this->m_transducerSettings.setScanLinePitch(xmlReadDoubleChild(doc, dataNode));
223  break;
225  this->m_transducerSettings.setTransducerRadius(xmlReadDoubleChild(doc, dataNode));
226  this->m_transducerSettings.setTransducerRadius(xmlReadDoubleChild(doc, dataNode));
227  break;
229  this->m_transducerSettings.setTransducerConvexity(xmlReadBoolChild(doc, dataNode));
230  this->m_transducerSettings.setTransducerConvexity(xmlReadBoolChild(doc, dataNode));
231  break;
233  this->m_transducerSettings.setSamplingFrequency(xmlReadIntChild(doc, dataNode));
234  break;
236  this->m_transducerSettings.setTransmitFrequency(xmlReadIntChild(doc, dataNode));
237  break;
239  this->m_motorSettings.setFramePitch(xmlReadDoubleChild(doc, dataNode));
240  break;
242  this->m_motorSettings.setMotorRadius(xmlReadDoubleChild(doc, dataNode));
243  break;
244  case CODE_XML_MOTOR_TYPE:
245  value = xmlReadStringChild(doc, dataNode);
246  if (strcmp(value.c_str(), "linear_motor") == 0) {
247  this->m_motorSettings.setMotorType(usMotorSettings::LinearMotor);
248  }
249  else if (strcmp(value.c_str(), "tilting_motor") == 0) {
250  this->m_motorSettings.setMotorType(usMotorSettings::TiltingMotor);
251  }
252  else if (strcmp(value.c_str(), "rotational_motor") == 0) {
253  this->m_motorSettings.setMotorType(usMotorSettings::RotationalMotor);
254  }
255  else
256  throw(vpException(vpException::fatalError, std::string("unknown image type in xml file")));
257  value = "";
258  break;
260  this->m_imageFileName = xmlReadStringChild(doc, dataNode);
261  break;
263  this->m_sequence_frame_rate = xmlReadDoubleChild(doc, dataNode);
264  this->m_is_sequence = true;
265  break;
267  this->m_sequence_start = xmlReadIntChild(doc, dataNode);
268  this->m_is_sequence = true;
269  break;
271  this->m_sequence_stop = xmlReadIntChild(doc, dataNode);
272  this->m_is_sequence = true;
273  break;
274  default:
275  vpTRACE("unknown tag in readConfigNode : %d, %s", iter_data->second, (iter_data->first).c_str());
276  break;
277  }
278  }
279  }
280  }
281 }
282 
288 {
289  std::string imageFileName = m_imageFileName;
290  xmlWriteStringChild(node, "image_file_name", imageFileName);
291  if (this->m_image_type == us::RF_2D) {
292  xmlWriteStringChild(node, "image_type", std::string("rf"));
293  xmlWriteDoubleChild(node, "scanline_pitch", m_transducerSettings.getScanLinePitch());
294  xmlWriteDoubleChild(node, "probe_radius", m_transducerSettings.getTransducerRadius());
295  xmlWriteBoolChild(node, "is_probe_convex", m_transducerSettings.isTransducerConvex());
296  xmlWriteDoubleChild(node, "axial_resolution", m_axialResolution);
297  xmlWriteDoubleChild(node, "transmit_frequency", m_transducerSettings.getTransmitFrequency());
298  xmlWriteDoubleChild(node, "sampling_frequency", m_transducerSettings.getSamplingFrequency());
299  }
300  if (this->m_image_type == us::PRESCAN_2D) {
301  xmlWriteStringChild(node, "image_type", std::string("prescan"));
302  xmlWriteDoubleChild(node, "scanline_pitch", m_transducerSettings.getScanLinePitch());
303  xmlWriteDoubleChild(node, "probe_radius", m_transducerSettings.getTransducerRadius());
304  xmlWriteBoolChild(node, "is_probe_convex", m_transducerSettings.isTransducerConvex());
305  xmlWriteDoubleChild(node, "axial_resolution", m_axialResolution);
306  xmlWriteDoubleChild(node, "transmit_frequency", m_transducerSettings.getTransmitFrequency());
307  xmlWriteDoubleChild(node, "sampling_frequency", m_transducerSettings.getSamplingFrequency());
308  }
309  else if (this->m_image_type == us::POSTSCAN_2D) {
310  xmlWriteStringChild(node, "image_type", std::string("postscan"));
311  xmlWriteDoubleChild(node, "scanline_pitch", m_transducerSettings.getScanLinePitch());
312  xmlWriteDoubleChild(node, "probe_radius", m_transducerSettings.getTransducerRadius());
313  xmlWriteBoolChild(node, "is_probe_convex", m_transducerSettings.isTransducerConvex());
314  xmlWriteIntChild(node, "scanline_number", m_transducerSettings.getScanLineNumber());
315  xmlWriteDoubleChild(node, "transmit_frequency", m_transducerSettings.getTransmitFrequency());
316  xmlWriteDoubleChild(node, "sampling_frequency", m_transducerSettings.getSamplingFrequency());
317  if (m_is_3D) {
318  xmlWriteIntChild(node, "frame_number", m_motorSettings.getFrameNumber());
319  xmlWriteDoubleChild(node, "spacing_x", m_spacingX);
320  xmlWriteDoubleChild(node, "spacing_y", m_spacingY);
321  xmlWriteDoubleChild(node, "spacing_z", m_spacingZ);
322  }
323  else {
324  xmlWriteDoubleChild(node, "height_resolution", m_heightResolution);
325  xmlWriteDoubleChild(node, "width_resolution", m_widthResolution);
326  }
327  }
328  if (m_is_3D) {
329  xmlWriteDoubleChild(node, "frame_pitch", m_motorSettings.getFramePitch());
330  xmlWriteDoubleChild(node, "motor_radius", m_motorSettings.getMotorRadius());
331  if (m_motorSettings.getMotorType() == usMotorSettings::LinearMotor) {
332  xmlWriteStringChild(node, "motor_type", std::string("linear_motor"));
333  }
334  else if (m_motorSettings.getMotorType() == usMotorSettings::TiltingMotor) {
335  xmlWriteStringChild(node, "motor_type", std::string("tilting_motor"));
336  }
337  else if (m_motorSettings.getMotorType() == usMotorSettings::RotationalMotor) {
338  xmlWriteStringChild(node, "motor_type", std::string("rotational_motor"));
339  }
340  }
341  if (m_is_sequence) {
342  std::cout << "writing sequence parameters" << std::endl;
343  // xmlWriteStringChild(node, "sequence_name", this->m_sequence_name);
344  xmlWriteDoubleChild(node, "sequence_frame_rate", this->m_sequence_frame_rate);
345  xmlWriteIntChild(node, "sequence_start_number", this->m_sequence_start);
346  xmlWriteIntChild(node, "sequence_stop_number", this->m_sequence_stop);
347  }
348 }
349 
360 void usImageSettingsXmlParser::setImageSettings(double transducerRadius, double scanLinePitch, bool isTransducerConvex,
361  double axialResolution, us::ImageType image_type, int samplingFrequency,
362  int transmitFrequency)
363 {
364  if (image_type == us::PRESCAN_2D || image_type == us::RF_2D) {
365  m_transducerSettings.setTransducerConvexity(isTransducerConvex);
366  m_transducerSettings.setTransducerRadius(transducerRadius);
367  m_transducerSettings.setScanLinePitch(scanLinePitch);
368  m_transducerSettings.setSamplingFrequency(samplingFrequency);
369  m_transducerSettings.setTransmitFrequency(transmitFrequency);
370  m_axialResolution = axialResolution;
371  m_image_type = image_type;
372  }
373  else {
374  throw(vpException(vpException::fatalError, "trying to write axial resolution in a image not rf nor pre-scan !"));
375  }
376 }
377 
389 void usImageSettingsXmlParser::setImageSettings(double transducerRadius, double scanLinePitch, bool isTransducerConvex,
390  unsigned int scanLineNumber, double widthResolution,
391  double heightResolution, int samplingFrequency, int transmitFrequency)
392 {
393  m_transducerSettings.setTransducerConvexity(isTransducerConvex);
394  m_transducerSettings.setTransducerRadius(transducerRadius);
395  m_transducerSettings.setScanLinePitch(scanLinePitch);
396  m_transducerSettings.setScanLineNumber(scanLineNumber);
397  m_transducerSettings.setSamplingFrequency(samplingFrequency);
398  m_transducerSettings.setTransmitFrequency(transmitFrequency);
399  m_heightResolution = widthResolution;
400  m_widthResolution = heightResolution;
401  m_image_type = us::POSTSCAN_2D;
402 }
403 
409 {
410  m_is_3D = true;
411  m_motorSettings = motorSettings;
412 }
413 
418 void usImageSettingsXmlParser::setImageFileName(const std::string &imageFileName) { m_imageFileName = imageFileName; }
419 #endif // VISP_HAVE_XML2
Input/output operations between ultrasound image settings and the associated 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