CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxPipeline.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 "cxPipeline.h"
12 #include "cxTypeConversions.h"
13 
14 #include <QtCore>
15 #include "boost/bind.hpp"
16 #include "libQtSignalAdapters/Qt2Func.h"
17 #include "libQtSignalAdapters/ConnectionFactories.h"
18 
19 
20 #include "cxLogger.h"
21 #include "cxBoolPropertyBase.h"
22 #include "cxDoublePropertyBase.h"
23 #include "cxColorPropertyBase.h"
24 #include "cxStringPropertyBase.h"
26 #include "cxFilterTimedAlgorithm.h"
27 
28 namespace cx
29 {
30 
31 
35 {
37  return retval;
38 }
39 
43  SelectDataStringPropertyBase(patientModelService)
44 {
45  mBase = base;
46  mInput = input;
47  connect(mInput.get(), SIGNAL(changed()), this, SLOT(inputDataChangedSlot()));
48  // connect(mInput.get(), SIGNAL(dataChanged(QString)), this, SLOT(inputDataChangedSlot()));
49  connect(mBase.get(), SIGNAL(dataChanged(QString)), this, SIGNAL(dataChanged(QString)));
50  connect(mBase.get(), SIGNAL(changed()), this, SLOT(changedSlot()));
51  connect(mBase.get(), SIGNAL(changed()), this, SIGNAL(changed()));
52 }
53 
54 
56 {
57  return mBase->setValue(value);
58 }
59 
61 {
62  return mBase->getValue();
63 }
64 
66 {
67  if (mValueName.isEmpty())
68  return mBase->getDisplayName();
69  return mValueName;
70 }
71 
73 {
74  return mBase->getValueRange();
75 }
76 
78 {
79  return mBase->convertInternal2Display(internal);
80 }
81 
83 {
84 // return mBase->getHelp();
85  return QString("<html>"
86  "<h4>%1</h4> <p>%2</p>"
87  "<h4>%3</h4> <p>%4</p>"
88  "</html>")
89  .arg("Input").arg(mInput->getHelp())
90  .arg("Output").arg(mBase->getHelp());
91 }
92 
94 {
95  return mBase->getData();
96 }
97 
99 {
100  if (name==mValueName)
101  return;
102  // mBase->setValueName(name);
103  mValueName = name;
104  emit changed();
105 }
106 
108 {
109  mBase->setHelp(text);
110 }
111 
113 {
114  // this sync helps the pipeline behaving when the output is changed.
115  this->blockSignals(true);
116  mInput->setValue(mBase->getValue());
117  this->blockSignals(false);
118 }
119 
121 {
122  // the entire point of the class: update mBase when mInput is changed:
123  mBase->setValue(mInput->getValue());
124 }
125 
126 
127 
131 
132 
133 Pipeline::Pipeline(PatientModelServicePtr patientModelService, QObject *parent) :
134  QObject(parent),
135  mPatientModelService(patientModelService)
136 {
137  mCompositeTimedAlgorithm.reset(new CompositeSerialTimedAlgorithm("Pipeline"));
138 }
139 
141 {
142  mFilters = filters;
143 
144  for (unsigned i=0; i<mFilters->size(); ++i)
145  {
146  FilterPtr filter = mFilters->get(i);
147  filter->getInputTypes();
148  filter->getOutputTypes();
149  filter->getOptions();
150  }
151 
152  this->getNodes();
153 
154  for (unsigned i=0; i<mFilters->size(); ++i)
155  {
156  FilterPtr current = mFilters->get(i);
157  mTimedAlgorithm[current->getUid()].reset(new FilterTimedAlgorithm(current));
158  }
159 }
161 {
162  return mFilters;
163 }
164 
170 void Pipeline::setOption(QString valueName, QVariant value)
171 {
172  for (unsigned i=0; i<mFilters->size(); ++i)
173  {
174  FilterPtr filter = mFilters->get(i);
175  std::vector<PropertyPtr> options = filter->getOptions();
176 
177  for (unsigned j=0; j<options.size(); ++j)
178  {
179  if (options[j]->getDisplayName()==valueName)
180  this->setOption(options[j], value);
181  }
182  }
183 }
184 
185 void Pipeline::setOption(PropertyPtr adapter, QVariant value)
186 {
187  if (value.canConvert<bool>())
188  {
189  BoolPropertyBasePtr specific = boost::dynamic_pointer_cast<BoolPropertyBase>(adapter);
190  if (specific)
191  specific->setValue(qvariant_cast<bool>(value));
192  }
193  else if (value.canConvert<double>())
194  {
195  DoublePropertyBasePtr specific = boost::dynamic_pointer_cast<DoublePropertyBase>(adapter);
196  if (specific)
197  specific->setValue(qvariant_cast<double>(value));
198  }
199  else if (value.canConvert<QColor>())
200  {
201  ColorPropertyBasePtr specific = boost::dynamic_pointer_cast<ColorPropertyBase>(adapter);
202  if (specific)
203  specific->setValue(qvariant_cast<QColor>(value));
204  }
205  else if (value.canConvert<QString>())
206  {
207  StringPropertyBasePtr specific = boost::dynamic_pointer_cast<StringPropertyBase>(adapter);
208  if (specific)
209  specific->setValue(qvariant_cast<QString>(value));
210  }
211  else
212  {
213  reportWarning(QString("Attempt to set option of type %2 is not supported").arg(value.typeName()));
214  }
215 }
216 
217 
218 std::vector<SelectDataStringPropertyBasePtr> Pipeline::getNodes()
219 {
220  // TODO: create getMainXXType() in filters instead of using zero.
221 
222  if (mNodes.empty())
223  mNodes = this->createNodes();
224  return mNodes;
225 }
226 
227 std::vector<SelectDataStringPropertyBasePtr> Pipeline::createNodes()
228 {
229  // TODO: create fused nodes: input+output
230  // TODO: create getMainXXType() in filters instead of using zero.
231 
232  std::vector<SelectDataStringPropertyBasePtr> retval;
233 
234  if (mFilters->empty())
235  return retval;
236 
237  // first node is the input of the first algo
238  retval.push_back(mFilters->get(0)->getInputTypes()[0]);
239 
240  // intermediate nodes are fusions between output and input
241  for (unsigned i=1; i<mFilters->size(); ++i)
242  {
243  SelectDataStringPropertyBasePtr output = mFilters->get(i-1)->getOutputTypes()[0];
244  SelectDataStringPropertyBasePtr base = mFilters->get(i)->getInputTypes()[0];
246  node = StringPropertyFusedInputOutputSelectData::create(mPatientModelService, base, output);
247  node->setValueName(QString("Node %1").arg(i));
248  retval.push_back(node);
249  }
250 
251  // last node is the output of the last algo
252  retval.push_back(mFilters->get(mFilters->size()-1)->getOutputTypes()[0]);
253 
254  for (unsigned i=0; i<retval.size(); ++i)
255  QtSignalAdapters::connect1<void(QString)>(retval[i].get(), SIGNAL(dataChanged(QString)),
256  boost::bind(&Pipeline::nodeValueChanged, this, _1, i));
257 
258  return retval;
259 }
260 
261 
262 void Pipeline::nodeValueChanged(QString uid, int index)
263 {
264  // std::cout << "Pipeline::nodeValueChanged(QString uid, int index) " << uid << " " << index << std::endl;
265 
266  // clear all nodes beyond the input:
267  for (unsigned i=index+1; i<mNodes.size(); ++i)
268  mNodes[i]->setValue("");
269 }
270 
272 {
273  return mTimedAlgorithm[uid];
274 }
275 
277 {
278  return mCompositeTimedAlgorithm;
279 }
280 
281 void Pipeline::execute(QString uid)
282 {
283  // generate |startIndex, endIndex>, pointing to the filters to be executed
284 
285  int endIndex = -1;
286  int startIndex = endIndex;
287 
288  if (uid.isEmpty()) // execute entire pipeline, if necessary
289  {
290  endIndex = mFilters->size();
291  startIndex = endIndex;
292  }
293  else // execute at least one given filter, more if necessary
294  {
295  for (unsigned i=0; i<mFilters->size(); ++i)
296  if (mFilters->get(i)->getUid()==uid)
297  endIndex = i+1; // set end index to after filter to execute;
298  startIndex = endIndex-1;
299  }
300 
301  if (endIndex<0) // input filter not found: ignore
302  return;
303 
304 // // filter i require node i as input
305 
306  // int startIndex = endIndex;
307 
308  // index now counts filters <0...N-1>
309  // nodes are <0...N>
310 
311  for ( ; startIndex>=-1; --startIndex)
312  {
313  if (startIndex<0)
314  break;
315  if (mNodes[startIndex]->getData()) // index output node for filter[startIndex]
316  break; // found node with data: stop here
317  }
318 
319  std::cout << "Pipeline::execute filter range s=|" << startIndex << "," << endIndex << ">" << std::endl;
320 
321  if (startIndex<0)
322  {
323  reportWarning(QString("Cannot execute filter %1: No input data set").arg(uid));
324  return;
325  }
326 
327  mCompositeTimedAlgorithm->clear();
328  for (unsigned i=startIndex; i<endIndex; ++i)
329  mCompositeTimedAlgorithm->append(mTimedAlgorithm[mFilters->get(i)->getUid()]);
330 
331  // run all filters
332  mCompositeTimedAlgorithm->execute();
333 }
334 
335 //void Pipeline::execute(QString uid)
336 //{
337 // // no input uid: execute entire pipeline
338 // if (uid.isEmpty())
339 // uid = mFilters->get(mFilters->size()-1)->getUid();
340 
341 // int endIndex = -1;
342 
343 // for (unsigned i=0; i<mFilters->size(); ++i)
344 // if (mFilters->get(i)->getUid()==uid)
345 // endIndex = i;
346 // if (endIndex<0)
347 // return;
348 
349 // // filter i require node i as input
350 // int startIndex = endIndex;
351 
352 // // index now counts filters <0...N-1>
353 // // nodes are <0...N>
354 
355 // for ( ; startIndex>=-1; --startIndex)
356 // {
357 // if (startIndex<0)
358 // break;
359 // if (mNodes[startIndex+1]->getData()) // index output node for filter[startIndex]
360 // break; // found node with data: stop here
361 // }
362 
363 // std::cout << "Pipeline::execute3 s=" << startIndex << ", e=" << endIndex << std::endl;
364 
365 // if (startIndex<0)
366 // {
367 // reportWarning(QString("Cannot execute filter %1: No input data set").arg(uid));
368 // return;
369 // }
370 
371 // mCompositeTimedAlgorithm->clear();
372 // for (unsigned i=startIndex; i<=endIndex; ++i)
373 // mCompositeTimedAlgorithm->append(mTimedAlgorithm[mFilters->get(i)->getUid()]);
374 
375 // // run all filters
376 // mCompositeTimedAlgorithm->execute();
377 //}
378 
379 
380 } // namespace cx
virtual bool setValue(bool value)=0
set the data value.
void nodeValueChanged(QString uid, int index)
Definition: cxPipeline.cpp:262
Pipeline(PatientModelServicePtr patientModelService, QObject *parent=0)
Definition: cxPipeline.cpp:133
FilterGroupPtr getFilters() const
Definition: cxPipeline.cpp:160
static StringPropertyFusedInputOutputSelectDataPtr create(PatientModelServicePtr patientModelService, SelectDataStringPropertyBasePtr base, SelectDataStringPropertyBasePtr input)
Definition: cxPipeline.cpp:32
SelectDataStringPropertyBasePtr mInput
Definition: cxPipeline.h:64
void execute(QString uid="")
Definition: cxPipeline.cpp:281
virtual QStringList getValueRange() const
Definition: cxPipeline.cpp:72
virtual QString getValue() const
get the data value.
Definition: cxPipeline.cpp:60
virtual QString convertInternal2Display(QString internal)
range of value. Use if data is constrained to a set.
Definition: cxPipeline.cpp:77
virtual QString getHelp() const
return a descriptive help string for the data, used for example as a tool tip.
Definition: cxPipeline.cpp:82
virtual QString getDisplayName() const
name of data entity. Used for display to user.
Definition: cxPipeline.cpp:65
virtual void setValueName(const QString name)
Definition: cxPipeline.cpp:98
void initialize(FilterGroupPtr filter)
Definition: cxPipeline.cpp:140
StringPropertyFusedInputOutputSelectData(PatientModelServicePtr patientModelService, SelectDataStringPropertyBasePtr base, SelectDataStringPropertyBasePtr input)
Definition: cxPipeline.cpp:40
Abstract interface for interaction with internal string-valued data.
virtual bool setValue(const QString &value)
set the data value.
Definition: cxPipeline.cpp:55
boost::shared_ptr< class Data > DataPtr
virtual bool setValue(double value)=0
set the data value.
boost::shared_ptr< class Filter > FilterPtr
boost::shared_ptr< class SelectDataStringPropertyBase > SelectDataStringPropertyBasePtr
boost::shared_ptr< class TimedBaseAlgorithm > TimedAlgorithmPtr
boost::shared_ptr< class StringPropertyBase > StringPropertyBasePtr
void setOption(QString valueName, QVariant value)
Definition: cxPipeline.cpp:170
boost::shared_ptr< class Property > PropertyPtr
void reportWarning(QString msg)
Definition: cxLogger.cpp:70
boost::shared_ptr< class StringPropertyFusedInputOutputSelectData > StringPropertyFusedInputOutputSelectDataPtr
Definition: cxPipeline.h:26
boost::shared_ptr< class BoolPropertyBase > BoolPropertyBasePtr
virtual bool setValue(QColor value)=0
set the data value.
boost::shared_ptr< class PatientModelService > PatientModelServicePtr
boost::shared_ptr< FilterGroup > FilterGroupPtr
Definition: cxFilterGroup.h:65
boost::shared_ptr< class DoublePropertyBase > DoublePropertyBasePtr
void changed()
emit when the underlying data value is changed: The user interface will be updated.
TimedAlgorithmPtr getTimedAlgorithm(QString uid)
Definition: cxPipeline.cpp:271
boost::shared_ptr< class ColorPropertyBase > ColorPropertyBasePtr
SelectDataStringPropertyBasePtr mBase
Definition: cxPipeline.h:65
std::vector< SelectDataStringPropertyBasePtr > getNodes()
Definition: cxPipeline.cpp:218
TimedAlgorithmPtr getPipelineTimedAlgorithm()
Definition: cxPipeline.cpp:276
virtual bool setValue(const QString &value)=0
set the data value.
Namespace for all CustusX production code.