CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxUsReconstructionImplService.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 
13 
14 
15 #include <boost/bind.hpp>
16 #include <ctkPluginContext.h>
17 #include "cxLogger.h"
18 #include "cxStringProperty.h"
19 #include "cxDoubleProperty.h"
20 #include "cxBoolProperty.h"
22 #include "cxReconstructThreads.h"
23 #include "cxUSFrameData.h"
26 #include "cxReconstructParams.h"
30 #include "cxPatientModelService.h"
31 #include "cxFileManagerService.h"
32 
33 //Windows fix
34 #ifndef M_PI
35 #define M_PI 3.14159265358979323846
36 #endif
37 
38 namespace cx
39 {
40 
41 
42 UsReconstructionImplService::UsReconstructionImplService(ctkPluginContext *pluginContext, PatientModelServicePtr patientModelService, ViewServicePtr viewService, FileManagerServicePtr filemanagerservice, XmlOptionFile settings) :
43  mPatientModelService(patientModelService),
44  mViewService(viewService),
45  mFileManagerService(filemanagerservice)
46 {
47  mSettings = settings;
48  mSettings.getElement("algorithms");
49 
50  mParams.reset(new ReconstructParams(patientModelService, settings));
51  connect(mParams.get(), SIGNAL(changedInputSettings()), this, SLOT(setSettings()));
52  connect(patientModelService.get(), &PatientModelService::patientChanged, this, &UsReconstructionImplService::patientChangedSlot);
53 
54  mServiceListener = boost::shared_ptr<ServiceTrackerListener<ReconstructionMethodService> >(new ServiceTrackerListener<ReconstructionMethodService>(
55  pluginContext,
56  boost::bind(&UsReconstructionImplService::onServiceAdded, this, _1),
57  boost::bind(&UsReconstructionImplService::onServiceModified, this, _1),
58  boost::bind(&UsReconstructionImplService::onServiceRemoved, this, _1)
59  ));
60 
61  mServiceListener->open();
62 }
63 
65 {
66 }
67 
69 {
70  return false;
71 }
72 
73 void UsReconstructionImplService::patientChangedSlot()
74 {
75  this->selectData(mPatientModelService->getActivePatientFolder() + "/US_Acq/");
76  emit newInputDataPath(this->getSelectedFileData().mFilename);
77 }
78 
80 {
81  QString name = mParams->getParameter("Algorithm")->getValueAsVariant().toString();
82  if(name.isEmpty())
83  return NULL;
84  return mServiceListener->getServiceFromName(name);
85 }
86 
87 void UsReconstructionImplService::setSettings()
88 {
89  mAlgoOptions.clear();
90  this->updateFromOriginalFileData();
91  emit paramsChanged();
92  emit algorithmChanged();
93 }
94 
96 {
97  if(!mOutputVolumeParams.isValid())
98  {
99  reportError("Cannot reconstruct from invalid ultrasound data");
100  return;
101  }
104  USReconstructInputData fileData = mOriginalFileData;
105  fileData.mUsRaw = mOriginalFileData.mUsRaw->copy();
106 
107  ReconstructionExecuterPtr executer(new ReconstructionExecuter(mPatientModelService, mViewService));
108  connect(executer.get(), SIGNAL(reconstructAboutToStart()), this, SIGNAL(reconstructAboutToStart()));
109  connect(executer.get(), SIGNAL(reconstructStarted()), this, SIGNAL(reconstructStarted()));
110  connect(executer.get(), SIGNAL(reconstructFinished()), this, SIGNAL(reconstructFinished()));
111  connect(executer.get(), SIGNAL(reconstructFinished()), this, SLOT(reconstructFinishedSlot()));
112  mExecuters.push_back(executer);
113 
114  bool success = executer->startReconstruction(algo, par, fileData, mParams->getCreateBModeWhenAngio()->getValue());
115  if(!success)
116  CX_LOG_WARNING() << "US reconstruction failed. Probably an error with input data.";
117 }
118 
120 {
121  std::set<cx::TimedAlgorithmPtr> retval;
122  for (unsigned i=0; i<mExecuters.size(); ++i)
123  retval.insert(mExecuters[i]->getThread());
124  return retval;
125 }
126 
127 void UsReconstructionImplService::reconstructFinishedSlot()
128 {
129  mOriginalFileData.mUsRaw->purgeAll();
130 
131  for (unsigned i=0; i<mExecuters.size(); ++i)
132  {
133  if (mExecuters[i]->getThread()->isFinished())
134  {
135  ReconstructionExecuterPtr executer = mExecuters[i];
136  disconnect(executer.get(), SIGNAL(reconstructAboutToStart()), this, SIGNAL(reconstructAboutToStart()));
137  disconnect(executer.get(), SIGNAL(reconstructStarted()), this, SIGNAL(reconstructStarted()));
138  disconnect(executer.get(), SIGNAL(reconstructFinished()), this, SIGNAL(reconstructFinished()));
139  disconnect(executer.get(), SIGNAL(reconstructFinished()), this, SLOT(reconstructFinishedSlot()));
140 
141  mExecuters.erase(mExecuters.begin()+i);
142  i=0;
143  }
144  }
145 }
146 
147 void UsReconstructionImplService::clearAll()
148 {
149  mOriginalFileData = USReconstructInputData();
150  mOutputVolumeParams = OutputVolumeParams();
151 }
152 
154 {
155  return mOutputVolumeParams;
156 }
157 
159 {
160  mOutputVolumeParams = par;
161  this->setSettings();
162 }
163 
165 {
166  if (mAlgoOptions.empty())
167  {
169  if (algo)
170  {
171  QDomElement element = mSettings.getElement("algorithms", algo->getName());
172  mAlgoOptions = algo->getSettings(element);
173  }
174  }
175 
176  return mAlgoOptions;
177 }
178 
180 {
181  return mSettings;
182 }
183 
185 {
186  return mOriginalFileData.mFilename;
187 }
188 
190 {
191  return mOriginalFileData;
192 }
193 
195 {
196  return mParams->getParameter(uid);
197 }
198 
199 void UsReconstructionImplService::selectData(QString filename, QString calFilesPath)
200 {
201  if (filename.isEmpty())
202  {
203  reportWarning("no file selected");
204  return;
205  }
206 
207  cx::UsReconstructionFileReaderPtr fileReader(new cx::UsReconstructionFileReader(mFileManagerService));
208  USReconstructInputData fileData = fileReader->readAllFiles(filename, calFilesPath);
209  fileData.mFilename = filename;
210  if(!fileData.isValid())
211  {
212  CX_LOG_WARNING() << "UsReconstructionImplService::selectData: Invalid input data";
213  return;
214  }
215  this->selectData(fileData);
216 }
217 
219 {
220  this->clearAll();
221  mOriginalFileData = fileData;
222  this->updateFromOriginalFileData();
223  emit inputDataSelected(fileData.mFilename);
224 }
225 
226 void UsReconstructionImplService::updateFromOriginalFileData()
227 {
228  if (mFileManagerService->isNull() || !mOriginalFileData.isValid())
229  return;
230 
231  ReconstructPreprocessorPtr preprocessor(new ReconstructPreprocessor(mPatientModelService));
232  preprocessor->initialize(this->createCoreParameters(), mOriginalFileData);
233 
234  if (preprocessor->getOutputVolumeParams().isValid())
235  mOutputVolumeParams = preprocessor->getOutputVolumeParams();
236  else
237  {
238  reportError("Input ultrasound data not valid for reconstruction");
239  return;
240  }
241 
242  emit paramsChanged();
243 }
244 
246 {
248  par.mAlgorithmUid = mParams->getAlgorithmAdapter()->getValue();
249  par.mAlgoSettings = mSettings.getElement("algorithms", par.mAlgorithmUid).cloneNode(true).toElement();
250  par.mShaderPath = mShaderPath;
251  par.mAngio = mParams->getAngioAdapter()->getValue();
252  par.mTransferFunctionPreset = mParams->getPresetTFAdapter()->getValue();
253  par.mMaxOutputVolumeSize = mParams->getMaxVolumeSize()->getValue();
254  par.mExtraTimeCalibration = mParams->getTimeCalibration()->getValue();
255  par.mAlignTimestamps = mParams->getAlignTimestamps()->getValue();
256  par.mPositionThinning = mParams->getPositionThinning()->getValue();
257  par.mPosFilterStrength = mParams->getPosFilterStrength()->getValue().toDouble();;
258  par.mMaskReduce = mParams->getMaskReduce()->getValue().toDouble();
259  par.mOrientation = mParams->getOrientationAdapter()->getValue();
260  return par;
261 }
262 
263 void UsReconstructionImplService::onServiceAdded(ReconstructionMethodService* service)
264 {
265  QStringList range = mParams->getAlgorithmAdapter()->getValueRange();
266  range << service->getName();
267  mParams->getAlgorithmAdapter()->setValueRange(range);
268 
269  // select algo if none selected
270  PropertyPtr algoName = mParams->getParameter("Algorithm");
271  if (algoName->getValueAsVariant().value<QString>().isEmpty())
272  algoName->setValueFromVariant(service->getName());
273 }
274 
275 void UsReconstructionImplService::onServiceModified(ReconstructionMethodService* service)
276 {
277  reportWarning("ReconstructionMethodService modified... Do not know what to do. Contact developer.");
278 }
279 
280 void UsReconstructionImplService::onServiceRemoved(ReconstructionMethodService* service)
281 {
282  QStringList range = mParams->getAlgorithmAdapter()->getValueRange();
283  range.removeAll(service->getName());
284  mParams->getAlgorithmAdapter()->setValueRange(range);
285 
286  QString algoname = mParams->getParameter("Algorithm")->getValueAsVariant().toString();
287  if (algoname==service->getName())
288  this->setSettings();
289 }
290 
292 {
293  emit newInputDataAvailable(mhdFilename);
294 }
295 
296 } //cx
void newInputDataAvailable(QString mhdFileName)
boost::shared_ptr< class FileManagerService > FileManagerServicePtr
Reader class for the US Acquisition files.
void inputDataSelected(QString mhdFileName)
boost::shared_ptr< class ReconstructionExecuter > ReconstructionExecuterPtr
UsReconstructionImplService(ctkPluginContext *pluginContext, PatientModelServicePtr patientModelService, ViewServicePtr viewService, FileManagerServicePtr filemanagerservice, XmlOptionFile settings)
void reportError(QString msg)
Definition: cxLogger.cpp:71
virtual PropertyPtr getParam(QString uid)
Return one of the standard parameters.
Abstract interface for reconstruction algorithm.
virtual QString getSelectedFilename() const
Get the currently selected filename.
virtual std::set< cx::TimedAlgorithmPtr > getThreadedReconstruction()
Return the currently reconstructing thread object(s).
virtual void selectData(QString filename, QString calFilesPath="")
Set input data for reconstruction.
QString mShaderPath
name of shader folder
virtual void newDataOnDisk(QString mhdFilename)
boost::shared_ptr< class ViewService > ViewServicePtr
Helper struct for sending and controlling output volume properties.
QDomElement getElement()
return the current element
virtual std::vector< PropertyPtr > getSettings(QDomElement root)=0
virtual std::vector< PropertyPtr > getAlgoOptions()
Return control parameters for the currently selected algorithm, adjustable like getParams() ...
boost::shared_ptr< class UsReconstructionFileReader > UsReconstructionFileReaderPtr
boost::shared_ptr< class Property > PropertyPtr
void reportWarning(QString msg)
Definition: cxLogger.cpp:70
Collection of reconstruction parameters.
boost::shared_ptr< class ReconstructPreprocessor > ReconstructPreprocessorPtr
virtual QString getName() const =0
boost::shared_ptr< class PatientModelService > PatientModelServicePtr
Settings * settings()
Shortcut for accessing the settings instance.
Definition: cxSettings.cpp:21
Algorithm part of reconstruction - no dependencies on parameter classes.
virtual void setOutputVolumeParams(const OutputVolumeParams &par)
Control the output volume.
Helper class for listening to services being added, modified and removed.
virtual OutputVolumeParams getOutputVolumeParams() const
Return params controlling the output data. These are data-dependent.
virtual XmlOptionFile getSettings()
Return the settings xml file where parameters are stored.
virtual USReconstructInputData getSelectedFileData()
Return the currently selected input data.
#define CX_LOG_WARNING
Definition: cxLogger.h:98
void newInputDataPath(QString path)
bool mAngio
true for angio data, false is B-mode.
QString mFilename
filename used for current data read
virtual ReconstructionMethodService * createAlgorithm()
USFrameDataPtr mUsRaw
All imported US data frames with pointers to each frame.
virtual ReconstructCore::InputParams createCoreParameters()
Helper class for xml files used to store ssc/cx data.
Namespace for all CustusX production code.