CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxMNIReaderWriter.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 
12 #include "cxMNIReaderWriter.h"
13 
14 #include <QDialog>
15 #include <QColor>
16 #include <QVBoxLayout>
17 #include <QLabel>
18 #include <QPushButton>
19 #include "vtkMNITagPointReader.h"
20 #include "vtkStringArray.h"
21 #include <ctkPluginContext.h>
23 #include "cxErrorObserver.h"
24 #include "cxLogger.h"
25 #include "cxFileHelpers.h"
27 #include "cxPointMetric.h"
29 #include "cxViewServiceProxy.h"
30 #include "cxHelperWidgets.h"
31 #include "cxSpaceProviderImpl.h"
32 #include "cxTrackingServiceProxy.h"
33 #include "cxTime.h"
34 
35 namespace cx
36 {
37 
38 
40  FileReaderWriterImplService("MNIReaderWriter", PointMetric::getTypeName(), "", "tag", patientModelService),
41  mPatientModelServicePrivate(patientModelService),
42  mViewService(viewService)
43 {
44  std::vector<QString> uids;
45  uids.push_back("dummyParent1");
46  uids.push_back("dummyParent2");
48 }
49 
51 {
52  return false;
53 }
54 
56 {
57  return PointMetric::getTypeName();
58 }
59 
60 bool MNIReaderWriter::canRead(const QString &type, const QString &filename)
61 {
62  return this->canReadInternal(type, filename);
63 }
64 
65 //TODO change retval for this function signature?
66 DataPtr MNIReaderWriter::read(const QString &uid, const QString &filename)
67 {
68  PointMetricPtr pointMetric;
69  this->readInto(pointMetric, filename);
70  return pointMetric;
71 }
72 
73 std::vector<DataPtr> MNIReaderWriter::read(const QString &filename)
74 {
75  std::vector<DataPtr> retval;
76 
77  //--- HACK to be able to read *.tag files with missing newline before eof
78  forceNewlineBeforeEof(filename);
79 
80 
81  //--- Reader for MNI Tag Point files
82  vtkMNITagPointReaderPtr reader = vtkMNITagPointReader::New();
83  reader->SetFileName(filename.toStdString().c_str());
84  reader->Update();
85  if (!ErrorObserver::checkedRead(reader, filename))
86  CX_LOG_ERROR() << "Error reading MNI Tag Point file.";
87 
88  int number_of_volumes = reader->GetNumberOfVolumes();
89  QString description(reader->GetComments());
90 
91  //--- Create the point metrics
92  QString type = PointMetric::getTypeName();
93  //QString uid = "";
94  QString name = "";
95  vtkStringArray *labels = reader->GetLabelText();
96 
97  for(int i=0; i< number_of_volumes; ++i)
98  {
99  QColor color = getRandomColor();
100 
101  vtkPoints *points = reader->GetPoints(i);
102  if(points != NULL)
103  {
104  unsigned int number_of_points = points->GetNumberOfPoints();
105  //CX_LOG_DEBUG() << "Number of points: " << number_of_points;
106 
107  for(int j=0; j < number_of_points; ++j)
108  {
109  vtkStdString label = labels->GetValue(j);
110  name = QString::fromStdString(label);
111  if(name.isEmpty() || (name == QString(" ")) ) // if no name label is given in .tag file, metric name is set to continous numbering
112  name = QString::number(j+1);
113 
114  double *point = points->GetPoint(j);
115  DataPtr data_point_metric = this->createData(type, filename, name);
116  PointMetricPtr point_metric = boost::static_pointer_cast<PointMetric>(data_point_metric);
117 
118  // TODO: Should probably be a GUI selecter for type of coordinate system (REFERENCE/DATA...)
119  CoordinateSystem space(csREF, mVolumeUids[i]);
120  Vector3D vector_lps(point[0], point[1], point[2]);
121  //CX_LOG_DEBUG() << "POINTS: " << vector_ras;
122 
123  point_metric->setCoordinate(vector_lps);
124  point_metric->setSpace(space);
125  point_metric->setColor(color);
126 
127  retval.push_back(data_point_metric);
128  }
129  }
130  }
131  mVolumeUids.clear();
132 
133  return retval;
134 }
135 
136 bool MNIReaderWriter::readInto(DataPtr data, QString path)
137 {
138  CX_LOG_ERROR() << "Do not use readInto...";
139  return false;
140 
141  /*
142 
143  //--- HACK to be able to read *.tag files with missing newline before eof
144  forceNewlineBeforeEof(path);
145 
146  //TODO
147  //std::vector<DataPtr> retval;
148  //DataPtr retval;
149 
150 
151  //--- Reader for MNI Tag Point files
152  vtkMNITagPointReaderPtr reader = vtkMNITagPointReader::New();
153  reader->SetFileName(path.toStdString().c_str());
154  reader->Update();
155  if (!ErrorObserver::checkedRead(reader, path))
156  CX_LOG_ERROR() << "Error reading MNI Tag Point file.";
157 
158 
159  //--- Prompt user to select the volume(s) that is(are) related to the points in the file
160  int number_of_volumes = reader->GetNumberOfVolumes();
161  QString description(reader->GetComments());
162  bool knownUidAreValid = this->validateKnownVolumeUids(number_of_volumes);
163  if(!knownUidAreValid)
164  {
165  mVolumeUids = dialogForSelectingVolumesForImportedMNITagFile(number_of_volumes, description);
166  }
167 
168  //--- Create the point metrics
169  QString type = PointMetric::getTypeName();
170  //QString uid = "";
171  QString name = "";
172  vtkStringArray *labels = reader->GetLabelText();
173 
174  for(int i=0; i< number_of_volumes; ++i)
175  {
176  QColor color = getRandomColor();
177 
178  vtkPoints *points = reader->GetPoints(i);
179  if(points != NULL)
180  {
181  unsigned int number_of_points = points->GetNumberOfPoints();
182  //CX_LOG_DEBUG() << "Number of points: " << number_of_points;
183 
184  for(int j=0; j < number_of_points; ++j)
185  {
186  vtkStdString label = labels->GetValue(j);
187  name = QString(*label); //NB: name never used, using j+1 as name to be able to correlate two sets of points from MNI import
188  //TODO is this still needed?
189  QString uid = QDateTime::currentDateTime().toString(timestampMilliSecondsFormat()) + "_" + QString::number(i)+ QString::number(j);
190 
191  double *point = points->GetPoint(j);
192  //DataPtr data = this->createData(type, uid, QString::number(j+1));
193  data = this->createData(type, path, QString::number(j+1));
194  PointMetricPtr point_metric = boost::static_pointer_cast<PointMetric>(data);
195 
196  CoordinateSystem space(csDATA, mVolumeUids[i]);
197  Vector3D vector_ras(point[0], point[1], point[2]);
198  //CX_LOG_DEBUG() << "POINTS: " << vector_ras;
199 
200  //Convert from RAS (MINC) to LPS (CX)
201  Transform3D sMr = createTransformFromReferenceToExternal(pcsRAS);
202  Vector3D vector_lps = sMr.inv() * vector_ras;
203 
204  point_metric->setCoordinate(vector_lps);
205  point_metric->setSpace(space);
206  point_metric->setColor(color);
207 
208  //TODO make vector
209  //retval = point_metric;
210  }
211  }
212  }
213 
214  mVolumeUids.clear();
215 
216  return data != DataPtr();
217  */
218 }
219 
221 {
222  return "";
223 }
224 
225 bool MNIReaderWriter::canWrite(const QString &type, const QString &filename) const
226 {
227  return false;
228 }
229 
230 void MNIReaderWriter::write(DataPtr data, const QString &filename)
231 {
232 
233 }
234 
236 {
237  mVolumeUids = volumeUids;
238 }
239 
240 QColor MNIReaderWriter::getRandomColor()
241 {
242  QStringList colorNames = QColor::colorNames();
243  int random_int = rand() % colorNames.size();
244  QColor color(colorNames[random_int]);
245  if(color == QColor("black"))
246  color = getRandomColor();
247 
248  return color;
249 }
250 
251 std::vector<QString> MNIReaderWriter::dialogForSelectingVolumesForImportedMNITagFile( int number_of_volumes, QString description)
252 {
253  std::vector<QString> data_uid;
254 
255  QDialog selectVolumeDialog;
256  selectVolumeDialog.setWindowTitle("Select volume(s) related to points in MNI Tag Point file.");
257 
258  QVBoxLayout *layout = new QVBoxLayout();
259  QLabel *description_label = new QLabel(description);
260  layout->addWidget(description_label);
261 
262  std::map<int, StringPropertySelectImagePtr> selectedImageProperties;
263  for(int i=0; i < number_of_volumes; ++i)
264  {
265  StringPropertySelectImagePtr image_property = StringPropertySelectImage::New(mPatientModelServicePrivate);
266  QWidget *widget = createDataWidget(mViewService, mPatientModelServicePrivate, NULL, image_property);
267  layout->addWidget(widget);
268  selectedImageProperties[i] = image_property;
269  }
270 
271  QPushButton *okButton = new QPushButton(tr("Ok"));
272  layout->addWidget(okButton);
273  connect(okButton, &QAbstractButton::clicked, &selectVolumeDialog, &QWidget::close);
274  selectVolumeDialog.setLayout(layout);
275  selectVolumeDialog.exec();
276  for(int i=0; i < number_of_volumes; ++i)
277  {
278  StringPropertySelectImagePtr image_property = selectedImageProperties[i];
279  data_uid.push_back(image_property->getValue());
280  }
281  return data_uid;
282 }
283 
284 bool MNIReaderWriter::validateKnownVolumeUids(int numberOfVolumesInFile) const
285 {
286  bool retval = true;
287  retval &= numberOfVolumesInFile == mVolumeUids.size();
288  for(int i=0; i<mVolumeUids.size(); ++i)
289  {
290  DataPtr data = mPatientModelServicePrivate->getData(mVolumeUids[i]);
291  if(data)
292  retval &= true;
293  }
294  return retval;
295 }
296 
297 
298 }
DataPtr createData(QString type, QString filename, QString name="") const
void setVolumeUidsRelatedToPointsInMNIPointFile(std::vector< QString > volumeUids)
bool canReadInternal(const QString &type, const QString &filename) const
DataPtr read(const QString &uid, const QString &filename)
csREF
the data reference space (r) using LPS (left-posterior-superior) coordinates.
Definition: cxDefinitions.h:90
boost::shared_ptr< class ViewService > ViewServicePtr
QWidget * createDataWidget(ViewServicePtr viewService, PatientModelServicePtr patientModelService, QWidget *parent, PropertyPtr data, QGridLayout *gridLayout, int row)
Create a widget capable of displaying the input data.
bool canRead(const QString &type, const QString &filename)
boost::shared_ptr< class Data > DataPtr
#define CX_LOG_ERROR
Definition: cxLogger.h:99
boost::shared_ptr< class PatientModelService > PatientModelServicePtr
Identification of a Coordinate system.
void write(DataPtr data, const QString &filename)
boost::shared_ptr< class StringPropertySelectImage > StringPropertySelectImagePtr
Data class that represents a single point.
Definition: cxPointMetric.h:42
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
void forceNewlineBeforeEof(QString path)
MNIReaderWriter(PatientModelServicePtr patientModelService, ViewServicePtr viewService)
QString canWriteDataType() const
static QString getTypeName()
Definition: cxPointMetric.h:58
bool readInto(DataPtr data, QString path)
static bool checkedRead(vtkSmartPointer< vtkAlgorithm > reader, QString filename)
static StringPropertySelectImagePtr New(PatientModelServicePtr patientModelService)
bool canWrite(const QString &type, const QString &filename) const
QString canReadDataType() const
vtkSmartPointer< class vtkMNITagPointReader > vtkMNITagPointReaderPtr
Namespace for all CustusX production code.
boost::shared_ptr< class PointMetric > PointMetricPtr