CustusX  16.5.0-rc9
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxProbeImpl.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 
33 #include "cxProbeImpl.h"
34 
35 #include <QStringList>
36 #include "cxVideoSource.h"
37 #include "cxLogger.h"
38 #include "cxProbeSector.h"
39 #include "cxProbeAdapterRTSource.h"
40 #include "cxTypeConversions.h"
41 #include "cxVector3D.h"
42 
43 #include "cxDataLocations.h"
45 
46 namespace cx
47 {
48 
49 ProbeImplPtr ProbeImpl::New(QString instrumentUid, QString scannerUid, ProbeXmlConfigParserPtr xml)
50 {
51  ProbeImpl* object = new ProbeImpl(instrumentUid, scannerUid);
52  ProbeImplPtr retval(object);
53  object->mSelf = retval;
54  retval->initProbeXmlConfigParser(xml);
55  retval->initConfigId();
56  return retval;
57 }
58 
59 bool ProbeImpl::isValid() const
60 {
61  return this->getProbeDefinition("active").getType() != ProbeDefinition::tNONE;
62 }
63 
65 {
66  QStringList retval;
67  for (std::map<QString, VideoSourcePtr>::iterator iter=mSource.begin(); iter!=mSource.end(); ++iter)
68  retval << iter->first;
69  return retval;
70 }
71 
73 {
74  if (mSource.empty())
75  return VideoSourcePtr();
76  if (uid=="active")
77  uid = mActiveUid;
78  if (mSource.count(uid))
79  return mSource.find(uid)->second;
80  return mSource.begin()->second;
81 }
82 
84 {
85  ProbeDefinition retval;
86 
87  if (uid=="active")
88  uid = mActiveUid;
89  if (mProbeDefinition.count(uid))
90  retval = mProbeDefinition.find(uid)->second;
91  else if (mProbeDefinition.count("default"))
92  retval = mProbeDefinition.find("default")->second;
93  else
94  retval = mProbeDefinition.begin()->second;
95 
96  // ensure uid is matching the requested uid even if not found.
97  retval.setUid(uid);
98  return retval;
99 }
100 
102 {
103  ProbeSectorPtr retval(new ProbeSector());
104  retval->setData(this->getProbeDefinition(uid));
105  return retval;
106 }
107 
108 void ProbeImpl::addXml(QDomNode& dataNode)
109 {
110  QDomDocument doc = dataNode.ownerDocument();
111  dataNode.toElement().setAttribute("config", mConfigurationId);
112 }
113 
114 void ProbeImpl::parseXml(QDomNode& dataNode)
115 {
116  if (dataNode.isNull())
117  return;
118  QString cfg = dataNode.toElement().attribute("config");
119  if (cfg.isEmpty())
120  return;
121  this->applyNewConfigurationWithId(cfg);
122 }
123 
124 QStringList ProbeImpl::getConfigIdList() const
125 {
126  if (!this->hasRtSource())
127  return QStringList();
128 
129  // Combine config lists from all RT sources
130  QStringList configIdList;
131  QStringList rtSourceList = mXml->getRtSourceList(this->getInstrumentScannerId(), this->getInstrumentId());
132  for (int i = 0; i < rtSourceList.size(); ++i)
133  configIdList << mXml->getConfigIdList(this->getInstrumentScannerId(), this->getInstrumentId(), rtSourceList[i]);
134 
135  return configIdList;
136 }
137 
138 QString ProbeImpl::getConfigName(QString configString)
139 {
140  ProbeXmlConfigParser::Configuration config = this->getConfiguration(configString);
141  return config.mName;
142 }
143 
144 QString ProbeImpl::getConfigId() const
145 {
146  if (this->getProbeDefinition().getUseDigitalVideo())
147  return "Digital";
148  return mConfigurationId;
149 }
150 
152 {
153  if (!this->hasRtSource())
154  return "";
155  QStringList retval;
156  retval << this->getInstrumentScannerId() << this->getInstrumentId() << this->getRtSourceName() << this->getConfigId();
157  return retval.join(":");
158 }
159 
161 {
162  this->setConfigId(uid);
163  this->applyConfig();
164  emit activeConfigChanged();
165 }
166 
167 void ProbeImpl::applyConfig()
168 {
169  this->updateProbeSector();
170  this->updateTemporalCalibration();
171  this->setSoundSpeedCompensationFactor(mSoundSpeedCompensationFactor);
172  emit sectorChanged();
173 }
174 
176 {
177  mOverrideTemporalCalibration = true;
178  mTemporalCalibration = val;
179  for (std::map<QString, ProbeDefinition>::iterator iter=mProbeDefinition.begin(); iter!=mProbeDefinition.end(); ++iter)
180  iter->second.setTemporalCalibration(mTemporalCalibration);
181 }
182 
184 {
185  if(similar(mSoundSpeedCompensationFactor, factor))
186  return;
187  mSoundSpeedCompensationFactor = factor;
188  for (std::map<QString, ProbeDefinition>::iterator iter=mProbeDefinition.begin(); iter!=mProbeDefinition.end(); ++iter)
189  iter->second.applySoundSpeedCompensationFactor(mSoundSpeedCompensationFactor);
190  emit sectorChanged();
191 }
192 
194 {
195  if (probeDefinition.getUid().isEmpty())
196  probeDefinition.setUid(mActiveUid);
197 
198  mProbeDefinition[probeDefinition.getUid()] = probeDefinition;
199  emit sectorChanged();
200 }
201 
203 {
204  CX_ASSERT(source); // not handled after refactoring - add clear method??
205  if (!source)
206  return;
207 
208  // uid already exist: check if base object is the same
209  if (mSource.count(source->getUid()))
210  {
211  VideoSourcePtr old = mSource.find(source->getUid())->second;
212 
213  ProbeAdapterRTSourcePtr oldAdapter;
214  oldAdapter = boost::dynamic_pointer_cast<ProbeAdapterRTSource>(old);
215  // check for identity, ignore if no change
216  if (oldAdapter && (source==oldAdapter->getBaseSource()))
217  return;
218  }
219 
220  // must have same uid as original: the uid identifies the video source
221  mSource[source->getUid()].reset(new ProbeAdapterRTSource(source->getUid(), mSelf.lock(), source));
222  emit sectorChanged();
223 
224  emit videoSourceAdded(mSource[source->getUid()]);
225 }
226 
228 {
229  if (!source)
230  return;
231  if (!mSource.count(source->getUid()))
232  return;
233 
234  mSource.erase(source->getUid());
235  mProbeDefinition.erase(source->getUid());
236  this->applyConfig();//May need to re-create config, as the old ProbeDefinition may be deleted
237 }
238 
239 void ProbeImpl::setActiveStream(QString uid)
240 {
241  if (uid.isEmpty())
242  return;
243  mActiveUid = uid;
244  emit sectorChanged();
245 }
246 
248 {
249  return mActiveUid;
250 }
251 
253 {
255 
256  int index = this->getConfigIdList().indexOf(config.mConfigId);
257  if (index<0)
258  return;
259  if (index!=0)
260  --index;
261 
262  mXml->removeConfig(config.mUsScanner, config.mUsProbe, config.mRtSource, config.mConfigId);
263  if (index < this->getConfigIdList().size())
264  this->applyNewConfigurationWithId(this->getConfigIdList()[index]);
265  emit sectorChanged();
266 }
267 
268 void ProbeImpl::saveCurrentConfig(QString uid, QString name)
269 {
271  config.mConfigId = uid;
272  config.mName = name;
273  config = createConfigurationFromProbeDefinition(config, this->getProbeDefinition("active"));
274 
275  mXml->saveCurrentConfig(config);
276  this->applyNewConfigurationWithId(uid);
277 }
278 
279 QString ProbeImpl::getRtSourceName(QString configurationId) const
280 {
281  QString configId = configurationId;
282  if (configId.isEmpty())
283  configId = mConfigurationId;
284 
285  return this->findRtSource(configId);
286 }
287 
288 QString ProbeImpl::findRtSource(QString configId) const
289 {
290  QStringList rtSourceList = mXml->getRtSourceList(this->getInstrumentScannerId(), this->getInstrumentId());
291 
292  //Use first RT source if no config id
293  if(configId.isEmpty() && !rtSourceList.empty())
294  return rtSourceList.at(0);
295 
296  QString retval;
297 
298  for (int i = 0; i < rtSourceList.size(); ++i)
299  {
300  QStringList configIdList;
301  configIdList << mXml->getConfigIdList(this->getInstrumentScannerId(), this->getInstrumentId(), rtSourceList[i]);
302  if(configIdList.contains(configId))
303  {
304  if(!retval.isEmpty())
305  reportWarning(QString("Config id is not unique: %1. Scanner %2, probe: %3. Occurring in RT source: %4 and %5").
306  arg(configId).arg(this->getInstrumentScannerId()).arg(this->getInstrumentId()).arg(rtSourceList[i]).arg(retval));
307  retval = rtSourceList[i];
308  }
309  }
310  return retval;
311 }
312 
313 ProbeImpl::ProbeImpl(QString instrumentUid, QString scannerUid) :
314  mInstrumentUid(instrumentUid),
315  mScannerUid(scannerUid),
316  mSoundSpeedCompensationFactor(1.0),
317  mOverrideTemporalCalibration(false),
318  mTemporalCalibration(0.0)
319 {
320  ProbeDefinition probeDefinition;
321  mProbeDefinition[probeDefinition.getUid()] = probeDefinition;
322  mActiveUid = probeDefinition.getUid();
323 }
324 
325 void ProbeImpl::initProbeXmlConfigParser(ProbeXmlConfigParserPtr xml = ProbeXmlConfigParserPtr())
326 {
327  if (!xml)
328  {
329  QString xmlFileName = cx::DataLocations::getRootConfigPath() + QString("/tool/ProbeCalibConfigs.xml");
330  mXml.reset(new ProbeXmlConfigParserImpl(xmlFileName));
331  } else
332  mXml = xml;
333 }
334 
335 void ProbeImpl::initConfigId()
336 {
337  QStringList configs = this->getConfigIdList();
338  if (!configs.isEmpty())
339  this->applyNewConfigurationWithId(configs[0]);
340  else
341  {
342  reportWarning(QString("Found no probe configuration for:\n"
343  "scanner=[%1] instrument=[%2].\n"
344  "Check that your %3 file contains entries\n"
345  "<USScanner> <Name>%1</Name> ... <USProbe> <Name>%2</Name>").arg(mScannerUid).arg(mInstrumentUid).arg(mXml->getFileName()));
346  }
347 }
348 
350 {
351  if (mConfig.mConfigId != this->getConfigId())
352  {
353  mConfig = this->getConfiguration(this->getConfigId());
354  }
355  return mConfig;
356 }
357 
359 {
360  if (mConfig.mConfigId != uid)
361  {
363  if(this->hasRtSource())
364  config = mXml->getConfiguration(mScannerUid, mInstrumentUid, this->getRtSourceName(uid), uid);
365  return config;
366  }
367  return mConfig;
368 }
369 
370 QString ProbeImpl::getInstrumentId() const
371 {
372  return mInstrumentUid;
373 }
374 
375 QString ProbeImpl::getInstrumentScannerId() const
376 {
377  return mScannerUid;
378 }
379 
380 bool ProbeImpl::hasRtSource() const
381 {
382  return !(this->getRtSourceName().isEmpty());
383 }
384 
385 void ProbeImpl::setConfigId(QString uid)
386 {
387  mConfigurationId = uid;
388 }
389 
390 void ProbeImpl::updateProbeSector()
391 {
392  if(this->isValidConfigId() && !this->getProbeDefinition().getUseDigitalVideo())
393  {
394  ProbeDefinition probeSector = this->createProbeSector();
395  this->setProbeDefinition(probeSector);
396  }
397 }
398 
399 bool ProbeImpl::isValidConfigId()
400 {
401  //May need to create ProbeXmlConfigParser::isValidConfig(...) also
402  return !this->getConfiguration().isEmpty();
403 }
404 
405 ProbeDefinition ProbeImpl::createProbeSector()
406 {
408  ProbeDefinition probeSector = createProbeDefinitionFromConfiguration(config);
409  probeSector.setUid(mActiveUid);
410  return probeSector;
411 }
412 
413 void ProbeImpl::updateTemporalCalibration()
414 {
415  if (mOverrideTemporalCalibration)
416  this->setTemporalCalibration(mTemporalCalibration);
417 }
418 
419 
420 } //namespace cx
< a easy-to-work-with struct for a specific xml configuration
ProbeXmlConfigParser::Configuration getConfiguration()
virtual void saveCurrentConfig(QString uid, QString name)
save current config to disk under ids (uid,name).
virtual ProbeDefinition getProbeDefinition(QString uid="active") const
Return a ProbeDefinition for the given uid. Use 'active' to get the default.
Definition: cxProbeImpl.cpp:83
#define CX_ASSERT(statement)
Definition: cxLogger.h:131
virtual void removeCurrentConfig()
remove the current config from disk
virtual void setActiveStream(QString uid)
virtual VideoSourcePtr getRTSource(QString uid="active") const
Return a VideoSource for the given uid. Use 'active' to get the default stream.
Definition: cxProbeImpl.cpp:72
VideoSource that applies the parameters from a Probe to the VideoSource.
QString getRtSourceName(QString configurationId="") const
virtual QString getConfigName(QString uid)
QString getUid() const
virtual void setTemporalCalibration(double val)
virtual QString getActiveStream() const
virtual void parseXml(QDomNode &dataNode)
virtual QString getConfigurationPath() const
virtual ProbeSectorPtr getSector(QString uid="active")
virtual void removeRTSource(VideoSourcePtr source)
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
void videoSourceAdded(VideoSourcePtr source)
virtual void applyNewConfigurationWithId(QString uid)
void reportWarning(QString msg)
Definition: cxLogger.cpp:91
void setUid(QString uid)
Implementation of abstract interface ProbeXmlConfigParser Interface to ProbeCalibConfigs.xml.
boost::shared_ptr< class VideoSource > VideoSourcePtr
boost::shared_ptr< ProbeXmlConfigParser > ProbeXmlConfigParserPtr
void sectorChanged()
< Return a ProbeSectorPtr for the given uid. Use 'active' to get the default.
virtual QString getConfigId() const
boost::shared_ptr< class ProbeSector > ProbeSectorPtr
Definition of characteristics for an Ultrasound Probe Sector.
void activeConfigChanged()
static QString getRootConfigPath()
return path to root config folder. May be replaced with getExistingConfigPath()
virtual void setSoundSpeedCompensationFactor(double val)
boost::shared_ptr< class ProbeImpl > ProbeImplPtr
virtual QStringList getAvailableVideoSources()
Return a list of all available video source. The default is one with uid=='active'.
Definition: cxProbeImpl.cpp:64
static ProbeImplPtr New(QString instrumentUid, QString scannerUid, ProbeXmlConfigParserPtr xml=ProbeXmlConfigParserPtr())
Definition: cxProbeImpl.cpp:49
QString mName
Name of config set.
virtual QStringList getConfigIdList() const
virtual bool isValid() const
Definition: cxProbeImpl.cpp:59
virtual void addXml(QDomNode &dataNode)
Utility functions for drawing an US Probe sector.
Definition: cxProbeSector.h:59
virtual void setProbeDefinition(ProbeDefinition probeDefinition)
boost::shared_ptr< ProbeAdapterRTSource > ProbeAdapterRTSourcePtr
ProbeDefinition createProbeDefinitionFromConfiguration(ProbeXmlConfigParser::Configuration config)
ProbeXmlConfigParser::Configuration createConfigurationFromProbeDefinition(ProbeXmlConfigParser::Configuration basis, ProbeDefinition data)
virtual void setRTSource(VideoSourcePtr source)