CustusX  15.4.0-beta
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->getProbeData("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 (mProbeData.count(uid))
90  retval = mProbeData.find(uid)->second;
91  else if (mProbeData.count("default"))
92  retval = mProbeData.find("default")->second;
93  else
94  retval = mProbeData.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->getProbeData(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->getProbeData().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=mProbeData.begin(); iter!=mProbeData.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=mProbeData.begin(); iter!=mProbeData.end(); ++iter)
189  iter->second.applySoundSpeedCompensationFactor(mSoundSpeedCompensationFactor);
190  emit sectorChanged();
191 }
192 
194 {
195  if (probeSector.getUid().isEmpty())
196  probeSector.setUid(mActiveUid);
197 
198  mProbeData[probeSector.getUid()] = probeSector;
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  mProbeData.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 = createConfigurationFromProbeData(config, this->getProbeData("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  if (this->getProbeData().getUseDigitalVideo())
286  return QString("Digital");
287 
288  return this->findRtSource(configId);
289 }
290 
291 QString ProbeImpl::findRtSource(QString configId) const
292 {
293  QStringList rtSourceList = mXml->getRtSourceList(this->getInstrumentScannerId(), this->getInstrumentId());
294 
295  //Use first RT source if no config id
296  if(configId.isEmpty() && !rtSourceList.empty())
297  return rtSourceList.at(0);
298 
299  QString retval;
300 
301  for (int i = 0; i < rtSourceList.size(); ++i)
302  {
303  QStringList configIdList;
304  configIdList << mXml->getConfigIdList(this->getInstrumentScannerId(), this->getInstrumentId(), rtSourceList[i]);
305  if(configIdList.contains(configId))
306  {
307  if(!retval.isEmpty())
308  reportWarning(QString("Config id is not unique: %1. Scanner %2, probe: %3. Occurring in RT source: %4 and %5").
309  arg(configId).arg(this->getInstrumentScannerId()).arg(this->getInstrumentId()).arg(rtSourceList[i]).arg(retval));
310  retval = rtSourceList[i];
311  }
312  }
313  return retval;
314 }
315 
316 ProbeImpl::ProbeImpl(QString instrumentUid, QString scannerUid) :
317  mInstrumentUid(instrumentUid),
318  mScannerUid(scannerUid),
319  mSoundSpeedCompensationFactor(1.0),
320  mOverrideTemporalCalibration(false),
321  mTemporalCalibration(0.0)
322 {
323  ProbeDefinition probeData;
324  mProbeData[probeData.getUid()] = probeData;
325  mActiveUid = probeData.getUid();
326 }
327 
328 void ProbeImpl::initProbeXmlConfigParser(ProbeXmlConfigParserPtr xml = ProbeXmlConfigParserPtr())
329 {
330  if (!xml)
331  {
332  QString xmlFileName = cx::DataLocations::getRootConfigPath() + QString("/tool/ProbeCalibConfigs.xml");
333  mXml.reset(new ProbeXmlConfigParserImpl(xmlFileName));
334  } else
335  mXml = xml;
336 }
337 
338 void ProbeImpl::initConfigId()
339 {
340  QStringList configs = this->getConfigIdList();
341  if (!configs.isEmpty())
342  this->applyNewConfigurationWithId(configs[0]);
343  else
344  {
345  reportWarning(QString("Found no probe configuration for:\n"
346  "scanner=[%1] instrument=[%2].\n"
347  "Check that your %3 file contains entries\n"
348  "<USScanner> <Name>%1</Name> ... <USProbe> <Name>%2</Name>").arg(mScannerUid).arg(mInstrumentUid).arg(mXml->getFileName()));
349  }
350 }
351 
353 {
354  if (mConfig.mConfigId != this->getConfigId())
355  {
356  mConfig = this->getConfiguration(this->getConfigId());
357  }
358  return mConfig;
359 }
360 
362 {
363  if (mConfig.mConfigId != uid)
364  {
366  if(this->hasRtSource())
367  config = mXml->getConfiguration(mScannerUid, mInstrumentUid, this->getRtSourceName(uid), uid);
368  return config;
369  }
370  return mConfig;
371 }
372 
373 QString ProbeImpl::getInstrumentId() const
374 {
375  return mInstrumentUid;
376 }
377 
378 QString ProbeImpl::getInstrumentScannerId() const
379 {
380  return mScannerUid;
381 }
382 
383 bool ProbeImpl::hasRtSource() const
384 {
385  return !(this->getRtSourceName().isEmpty());
386 }
387 
388 void ProbeImpl::setConfigId(QString uid)
389 {
390  mConfigurationId = uid;
391 }
392 
393 void ProbeImpl::updateProbeSector()
394 {
395  if(this->isValidConfigId() && !this->getProbeData().getUseDigitalVideo())
396  {
397  ProbeDefinition probeSector = this->createProbeSector();
398  this->setProbeSector(probeSector);
399  }
400 }
401 
402 bool ProbeImpl::isValidConfigId()
403 {
404  //May need to create ProbeXmlConfigParser::isValidConfig(...) also
405  return !this->getConfiguration().isEmpty();
406 }
407 
408 ProbeDefinition ProbeImpl::createProbeSector()
409 {
411  ProbeDefinition probeSector = createProbeDataFromConfiguration(config);
412  probeSector.setUid(mActiveUid);
413  return probeSector;
414 }
415 
416 void ProbeImpl::updateTemporalCalibration()
417 {
418  if (mOverrideTemporalCalibration)
419  this->setTemporalCalibration(mTemporalCalibration);
420 }
421 
422 
423 } //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).
ProbeXmlConfigParser::Configuration createConfigurationFromProbeData(ProbeXmlConfigParser::Configuration basis, ProbeDefinition data)
#define CX_ASSERT(statement)
Definition: cxLogger.h:128
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 setProbeSector(ProbeDefinition probeSector)
virtual void applyNewConfigurationWithId(QString uid)
TYPE getType() const
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.
Definition: cxProbeData.h:118
virtual ProbeDefinition getProbeData(QString uid="active") const
Return a ProbeData for the given uid. Use 'active' to get the default.
Definition: cxProbeImpl.cpp:83
void activeConfigChanged()
static QString getRootConfigPath()
return path to root config folder. May be replaced with getExistingConfigPath()
virtual void setSoundSpeedCompensationFactor(double val)
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
bool getUseDigitalVideo() const
virtual void addXml(QDomNode &dataNode)
Utility functions for drawing an US Probe sector.
Definition: cxProbeSector.h:59
boost::shared_ptr< class ProbeImpl > ProbeImplPtr
boost::shared_ptr< ProbeAdapterRTSource > ProbeAdapterRTSourcePtr
ProbeDefinition createProbeDataFromConfiguration(ProbeXmlConfigParser::Configuration config)
virtual void setRTSource(VideoSourcePtr source)