NorMIT-nav  16.5
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 #include "cxCustomMetaImage.h"
33 
34 #include <QFile>
35 #include <QTextStream>
36 #include <QStringList>
37 #include "cxLogger.h"
38 
39 #include "cxTypeConversions.h"
40 
41 namespace cx
42 {
43 
45  mFilename(filename)
46 {}
47 
48 QString CustomMetaImage::readKey(QString key)
49 {
50  QFile file(mFilename);
51 
52  QString line;
53  if (file.open(QIODevice::ReadOnly))
54  {
55  QTextStream t(&file);
56  while (!t.atEnd())
57  {
58  line.clear();
59  line = t.readLine();
60  // do something with the line
61  if (line.startsWith(key, Qt::CaseInsensitive))
62  {
63  QStringList list = line.split("=", QString::SkipEmptyParts);
64  if (list.size() >= 2)
65  {
66  list = list.mid(1);
67  return list.join("=");
68  }
69  }
70  }
71  file.close();
72  }
73 
74  return "";
75 }
76 
78 {
79  QString mod = this->readKey("Modality");
80 
81  if (mod.contains("CT", Qt::CaseInsensitive))
82  return "CT";
83  if (mod.contains("MR", Qt::CaseInsensitive))
84  return "MR";
85  if (mod.contains("US", Qt::CaseInsensitive))
86  return "US";
87  if (mod.contains("OTHER", Qt::CaseInsensitive))
88  return "OTHER";
89  mod = mod.remove("MET_MOD_");
90  return mod;
91 }
92 
94 {
95  return this->readKey("ImageType3");
96 }
97 
101 void CustomMetaImage::remove(QStringList* data, QStringList keys)
102 {
103  QRegExp regexp(QString("(^%1)").arg(keys.join("|^")));
104  QStringList removeThese = data->filter(regexp);
105  for (int i=0; i<removeThese.size(); ++i)
106  data->removeAll(removeThese[i]);
107 }
108 
114 void CustomMetaImage::append(QStringList* data, QString key, QString value)
115 {
116  // find index of ElementDataFile - this is the last element according to MHD standard (but we might have appended something else after it).
117  int last = data->lastIndexOf(QRegExp("^ElementDataFile.*"));
118  data->insert(last, QString("%1 = %2").arg(key).arg(value));
119 }
120 
121 void CustomMetaImage::setKey(QString key, QString value)
122 {
123  QFile file(mFilename);
124 
125  if (!file.open(QIODevice::ReadWrite))
126  {
127  reportError("Failed to open file " + mFilename + ".");
128  return;
129  }
130 
131  QStringList data = QTextStream(&file).readAll().split("\n");
132 
133  this->remove(&data, QStringList()<<key);
134  this->append(&data, key, value);
135 
136  file.resize(0);
137  file.write(data.join("\n").toLatin1());
138 }
139 
140 void CustomMetaImage::setModality(QString value)
141 {
142  QStringList valid_values;
143  valid_values << "CT" << "MR" << "NM" << "US" << "OTHER" << "UNKNOWN";
144  if(!valid_values.contains(value, Qt::CaseInsensitive))
145  value = "UNKNOWN";
146 
147  this->setKey("Modality", value);
148 }
149 
150 void CustomMetaImage::setImageType(QString value)
151 {
152  if (value.isEmpty())
153  return;
154  this->setKey("ImageType3", value);
155 }
156 
157 
159 {
160  //read the specific TransformMatrix-tag from the header
161  Vector3D p_r(0, 0, 0);
162  Vector3D e_x(1, 0, 0);
163  Vector3D e_y(0, 1, 0);
164  Vector3D e_z(0, 0, 1);
165 
166  QFile file(mFilename);
167 
168  QString line;
169  if (file.open(QIODevice::ReadOnly))
170  {
171  QTextStream t(&file);
172  while (!t.atEnd())
173  {
174  line.clear();
175  line = t.readLine();
176  // do something with the line
177  if (line.startsWith("Position", Qt::CaseInsensitive) || line.startsWith("Offset", Qt::CaseInsensitive))
178  {
179  QStringList list = line.split(" ", QString::SkipEmptyParts);
180  if (list.size()>=5)
181  p_r = Vector3D(list[2].toDouble(), list[3].toDouble(), list[4].toDouble());
182  }
183  else if (line.startsWith("TransformMatrix", Qt::CaseInsensitive) || line.startsWith("Orientation",
184  Qt::CaseInsensitive))
185  {
186  QStringList list = line.split(" ", QString::SkipEmptyParts);
187 
188  if (list.size()>=8)
189  {
190  e_x = Vector3D(list[2].toDouble(), list[3].toDouble(), list[4].toDouble());
191  e_y = Vector3D(list[5].toDouble(), list[6].toDouble(), list[7].toDouble());
192  e_z = cross(e_x, e_y);
193  }
194  }
195  }
196  file.close();
197  }
198 
199  Transform3D rMd = Transform3D::Identity();
200 
201  // add rotational part
202  for (unsigned i = 0; i < 3; ++i)
203  {
204  rMd(i,0) = e_x[i];
205  rMd(i,1) = e_y[i];
206  rMd(i,2) = e_z[i];
207  }
208 
209 
210  // add translational part
211  rMd(0,3) = p_r[0];
212  rMd(1,3) = p_r[1];
213  rMd(2,3) = p_r[2];
214  return rMd;
215 }
216 
218 {
219  QFile file(mFilename);
220 
221  if (!file.open(QIODevice::ReadWrite))
222  {
223  reportError("Failed to open file " + mFilename + ".");
224  return;
225  }
226 
227  QStringList data = QTextStream(&file).readAll().split("\n");
228 
229  this->remove(&data, QStringList()<<"TransformMatrix"<<"Offset"<<"Position"<<"Orientation");
230 
231  int dim = 3; // hardcoded - will fail for 2d images
232  std::stringstream tmList;
233  for (int c=0; c<dim; ++c)
234  for (int r=0; r<dim; ++r)
235  tmList << " " << M(r,c);
236  this->append(&data, "TransformMatrix", qstring_cast(tmList.str()));
237 
238  std::stringstream posList;
239  for (int r=0; r<dim; ++r)
240  posList << " " << M(r,3);
241  this->append(&data, "Offset", qstring_cast(posList.str()));
242 
243  file.resize(0);
244  file.write(data.join("\n").toLatin1());
245 }
246 
247 }
QString qstring_cast(const T &val)
void reportError(QString msg)
Definition: cxLogger.cpp:92
CustomMetaImage(QString filename)
QString readKey(QString key)
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
Vector3D cross(const Vector3D &a, const Vector3D &b)
compute cross product of a and b.
Definition: cxVector3D.cpp:62
void setImageType(QString value)
void setModality(QString value)
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:63
void setKey(QString key, QString value)
void setTransform(const Transform3D M)