NorMIT-nav  2023.01.05-dev+develop.0da12
An IGT application
cxCustomMetaImage.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 #include "cxCustomMetaImage.h"
12 
13 #include <QFile>
14 #include <QTextStream>
15 #include <QStringList>
16 #include "cxLogger.h"
17 #include "cxData.h"
18 
19 #include "cxTypeConversions.h"
20 #include "cxEnumConversion.h"
21 
22 namespace cx
23 {
24 
25 
26 IMAGE_MODALITY convertToModality(QString modalityString)
27 {
28  IMAGE_MODALITY retval = imUNKNOWN;
29 
30  if(modalityString.contains(enum2string<IMAGE_MODALITY>(imUNKNOWN), Qt::CaseInsensitive))
31  retval = imUNKNOWN;
32  else if(modalityString.contains(enum2string<IMAGE_MODALITY>(imCT), Qt::CaseInsensitive))
33  retval = imCT;
34  else if(modalityString.contains(enum2string<IMAGE_MODALITY>(imMR), Qt::CaseInsensitive))
35  retval = imMR;
36  else if(modalityString.contains(enum2string<IMAGE_MODALITY>(imUS), Qt::CaseInsensitive))
37  retval = imUS;
38  else if(modalityString.contains(enum2string<IMAGE_MODALITY>(imPET), Qt::CaseInsensitive))
39  retval = imPET;
40  else if(modalityString == "PT")
41  retval = imPET;
42  else if(modalityString.contains(enum2string<IMAGE_MODALITY>(imSC), Qt::CaseInsensitive))
43  retval = imSC;
44  else
45  CX_LOG_WARNING() << "convertToModality - Cannot convert the string \"" << modalityString << "\" to a known image modality";
46 
47  return retval;
48 }
49 
50 
51 IMAGE_SUBTYPE convertToImageSubType(QString imageTypeSubString)
52 {
53  IMAGE_SUBTYPE retval = istUNKNOWN;
54 
55  if (imageTypeSubString.isEmpty() || imageTypeSubString == " ")
56  retval = istEMPTY;
57  else if(imageTypeSubString.contains(enum2string<IMAGE_SUBTYPE>(istUNKNOWN), Qt::CaseInsensitive))
58  retval = istUNKNOWN;
59  else if(imageTypeSubString.contains(enum2string<IMAGE_SUBTYPE>(istMRT1), Qt::CaseInsensitive))
60  retval = istMRT1;
61  else if(imageTypeSubString.contains(enum2string<IMAGE_SUBTYPE>(istMRT2), Qt::CaseInsensitive))
62  retval = istMRT2;
63  else if(imageTypeSubString.contains(enum2string<IMAGE_SUBTYPE>(istMRFLAIR), Qt::CaseInsensitive))
64  retval = istMRFLAIR;
65  else if(imageTypeSubString.contains(enum2string<IMAGE_SUBTYPE>(istANGIO), Qt::CaseInsensitive))
66  retval = istANGIO;
67  else if(imageTypeSubString.contains(enum2string<IMAGE_SUBTYPE>(istUSBMODE), Qt::CaseInsensitive))
68  retval = istUSBMODE;
69  else if(imageTypeSubString.contains("bmode", Qt::CaseInsensitive))
70  retval = istUSBMODE;
71  else if(imageTypeSubString.contains("b_mode", Qt::CaseInsensitive))
72  retval = istUSBMODE;
73  else if(imageTypeSubString.contains("b mode", Qt::CaseInsensitive))
74  retval = istUSBMODE;
75  else if(imageTypeSubString.contains("seg", Qt::CaseInsensitive))
76  retval = istSEGMENTATION;
77  else if(imageTypeSubString.contains("label", Qt::CaseInsensitive))
78  retval = istSEGMENTATION;
79  else
80  CX_LOG_WARNING() << "convertToImageSubType - Cannot convert the string \"" << imageTypeSubString << "\" to a known image subtype";
81 
82  return retval;
83 }
84 
85 
87  mFilename(filename)
88 {}
89 
90 QString CustomMetaImage::readKey(QString key)
91 {
92  QFile file(mFilename);
93 
94  QString line;
95  if (file.open(QIODevice::ReadOnly))
96  {
97  QTextStream t(&file);
98  while (!t.atEnd())
99  {
100  line.clear();
101  line = t.readLine();
102  // do something with the line
103  if (line.startsWith(key, Qt::CaseInsensitive))
104  {
105  QStringList list = line.split("=", QString::SkipEmptyParts);
106  if (list.size() >= 2)
107  {
108  list = list.mid(1);
109  return list.join("=");
110  }
111  }
112  }
113  file.close();
114  }
115 
116  return "";
117 }
118 
120 {
121  QString modalityString = this->readKey("Modality");
122  return convertToModality(modalityString);
123 }
124 
126 {
127  QString imageTypeString = this->readKey("ImageType3");
128  return convertToImageSubType(imageTypeString);
129 }
130 
134 void CustomMetaImage::remove(QStringList* data, QStringList keys)
135 {
136  QRegExp regexp(QString("(^%1)").arg(keys.join("|^")));
137  QStringList removeThese = data->filter(regexp);
138  for (int i=0; i<removeThese.size(); ++i)
139  data->removeAll(removeThese[i]);
140 }
141 
147 void CustomMetaImage::append(QStringList* data, QString key, QString value)
148 {
149  // find index of ElementDataFile - this is the last element according to MHD standard (but we might have appended something else after it).
150  int last = data->lastIndexOf(QRegExp("^ElementDataFile.*"));
151  data->insert(last, QString("%1 = %2").arg(key).arg(value));
152 }
153 
154 void CustomMetaImage::setKey(QString key, QString value)
155 {
156  QFile file(mFilename);
157 
158  if (!file.open(QIODevice::ReadWrite))
159  {
160  reportError("Failed to open file " + mFilename + ".");
161  return;
162  }
163 
164  QStringList data = QTextStream(&file).readAll().split("\n");
165 
166  this->remove(&data, QStringList()<<key);
167  this->append(&data, key, value);
168 
169  file.resize(0);
170  file.write(data.join("\n").toLatin1());
171 }
172 
173 void CustomMetaImage::setModality(IMAGE_MODALITY value)
174 {
175  this->setKey("Modality", enum2string(value));
176 }
177 
178 void CustomMetaImage::setImageType(IMAGE_SUBTYPE value)
179 {
180  this->setKey("ImageType3", enum2string(value));
181 }
182 
183 
185 {
186  //read the specific TransformMatrix-tag from the header
187  Vector3D p_r(0, 0, 0);
188  Vector3D e_x(1, 0, 0);
189  Vector3D e_y(0, 1, 0);
190  Vector3D e_z(0, 0, 1);
191 
192  QFile file(mFilename);
193 
194  QString line;
195  if (file.open(QIODevice::ReadOnly))
196  {
197  QTextStream t(&file);
198  while (!t.atEnd())
199  {
200  line.clear();
201  line = t.readLine();
202  // do something with the line
203  if (line.startsWith("Position", Qt::CaseInsensitive) || line.startsWith("Offset", Qt::CaseInsensitive))
204  {
205  QStringList list = line.split(" ", QString::SkipEmptyParts);
206  if (list.size()>=5)
207  p_r = Vector3D(list[2].toDouble(), list[3].toDouble(), list[4].toDouble());
208  }
209  else if (line.startsWith("TransformMatrix", Qt::CaseInsensitive) || line.startsWith("Orientation",
210  Qt::CaseInsensitive))
211  {
212  QStringList list = line.split(" ", QString::SkipEmptyParts);
213 
214  if (list.size()>=8)
215  {
216  e_x = Vector3D(list[2].toDouble(), list[3].toDouble(), list[4].toDouble());
217  e_y = Vector3D(list[5].toDouble(), list[6].toDouble(), list[7].toDouble());
218  e_z = cross(e_x, e_y);
219  }
220  }
221  }
222  file.close();
223  }
224 
225  Transform3D rMd = Transform3D::Identity();
226 
227  // add rotational part
228  for (unsigned i = 0; i < 3; ++i)
229  {
230  rMd(i,0) = e_x[i];
231  rMd(i,1) = e_y[i];
232  rMd(i,2) = e_z[i];
233  }
234 
235 
236  // add translational part
237  rMd(0,3) = p_r[0];
238  rMd(1,3) = p_r[1];
239  rMd(2,3) = p_r[2];
240  return rMd;
241 }
242 
244 {
245  QFile file(mFilename);
246 
247  if (!file.open(QIODevice::ReadWrite))
248  {
249  reportWarning("Could not save transform because: Failed to open file " + mFilename);
250  return;
251  }
252 
253  QStringList data = QTextStream(&file).readAll().split("\n");
254 
255  this->remove(&data, QStringList()<<"TransformMatrix"<<"Offset"<<"Position"<<"Orientation");
256 
257  int dim = 3; // hardcoded - will fail for 2d images
258  std::stringstream tmList;
259  for (int c=0; c<dim; ++c)
260  for (int r=0; r<dim; ++r)
261  tmList << " " << M(r,c);
262  this->append(&data, "TransformMatrix", qstring_cast(tmList.str()));
263 
264  std::stringstream posList;
265  for (int r=0; r<dim; ++r)
266  posList << " " << M(r,3);
267  this->append(&data, "Offset", qstring_cast(posList.str()));
268 
269  file.resize(0);
270  file.write(data.join("\n").toLatin1());
271 }
272 
273 }
cx::CustomMetaImage::readKey
QString readKey(QString key)
Definition: cxCustomMetaImage.cpp:90
cxLogger.h
istEMPTY
istEMPTY
Definition: cxDefinitions.h:162
qstring_cast
QString qstring_cast(const T &val)
Definition: cxTypeConversions.h:46
imMR
imMR
Definition: cxDefinitions.h:153
cx::CustomMetaImage::readImageType
IMAGE_SUBTYPE readImageType()
Definition: cxCustomMetaImage.cpp:125
cx::CustomMetaImage::CustomMetaImage
CustomMetaImage(QString filename)
Definition: cxCustomMetaImage.cpp:86
cx
Namespace for all CustusX production code.
Definition: cx_dev_group_definitions.h:13
cx::CustomMetaImage::setImageType
void setImageType(IMAGE_SUBTYPE value)
Definition: cxCustomMetaImage.cpp:178
cx::convertToImageSubType
IMAGE_SUBTYPE convertToImageSubType(QString imageTypeSubString)
Definition: cxCustomMetaImage.cpp:51
imUNKNOWN
imUNKNOWN
Definition: cxDefinitions.h:151
cx::CustomMetaImage::setModality
void setModality(IMAGE_MODALITY value)
Definition: cxCustomMetaImage.cpp:173
cxData.h
istUNKNOWN
istUNKNOWN
Definition: cxDefinitions.h:161
cx::cross
Vector3D cross(const Vector3D &a, const Vector3D &b)
compute cross product of a and b.
Definition: cxVector3D.cpp:41
istMRT2
istMRT2
Definition: cxDefinitions.h:164
cx::CustomMetaImage::readTransform
Transform3D readTransform()
Definition: cxCustomMetaImage.cpp:184
imUS
imUS
Definition: cxDefinitions.h:154
imPET
imPET
Definition: cxDefinitions.h:155
cx::Transform3D
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
Definition: cxLandmarkPatientRegistrationWidget.h:33
cxCustomMetaImage.h
cxTypeConversions.h
imSC
imSC
Definition: cxDefinitions.h:156
cx::CustomMetaImage::readModality
IMAGE_MODALITY readModality()
Definition: cxCustomMetaImage.cpp:119
imCT
imCT
Definition: cxDefinitions.h:152
istMRFLAIR
istMRFLAIR
Definition: cxDefinitions.h:165
istANGIO
istANGIO
Definition: cxDefinitions.h:167
enum2string
QString enum2string(const ENUM &val)
CX_LOG_WARNING
#define CX_LOG_WARNING
Definition: cxLogger.h:98
cxEnumConversion.h
cx::CustomMetaImage::setKey
void setKey(QString key, QString value)
Definition: cxCustomMetaImage.cpp:154
istMRT1
istMRT1
Definition: cxDefinitions.h:163
cx::reportError
void reportError(QString msg)
Definition: cxLogger.cpp:71
istSEGMENTATION
istSEGMENTATION
Definition: cxDefinitions.h:168
cx::Vector3D
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
cx::CustomMetaImage::setTransform
void setTransform(const Transform3D M)
Definition: cxCustomMetaImage.cpp:243
cx::reportWarning
void reportWarning(QString msg)
Definition: cxLogger.cpp:70
cx::convertToModality
IMAGE_MODALITY convertToModality(QString modalityString)
Definition: cxCustomMetaImage.cpp:26
istUSBMODE
istUSBMODE
Definition: cxDefinitions.h:166