CustusX  15.8
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxPlaybackUSAcquisitionVideo.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 
34 #include <QStringList>
35 #include <QDir>
36 #include <QtCore>
37 #include <boost/bind.hpp>
38 #include "vtkImageImport.h"
39 #include "vtkImageData.h"
40 #include "cxTypeConversions.h"
42 #include "cxTestVideoSource.h"
43 #include "cxTrackingService.h"
44 //#include "cxProbeImpl.h"
45 #include "cxUSFrameData.h"
46 #include "cxPlaybackTime.h"
47 
48 #include "cxBasicVideoSource.h"
49 #include "cxImage.h"
50 #include "cxImageDataContainer.h"
51 #include "cxVideoServiceBackend.h"
52 #include "cxFileHelpers.h"
53 #include <QtConcurrent>
54 #include "cxTool.h"
55 
56 namespace cx
57 {
58 
60  QObject(NULL),
61  mVideoSourceUid("playback")
62 {
63  mBackend = backend;
64  mVideoSource.reset(new BasicVideoSource(mVideoSourceUid));
65  mVideoSource->setStatusString(QString("No US Acquisition"));
66 
67  connect(&mUSImageDataFutureWatcher, SIGNAL(finished()), this, SLOT(usDataLoadFinishedSlot()));
68 }
69 
71 {
72 }
73 
75 {
76  return mVideoSource;
77 }
78 
80 {
81  return mTimer ? true : false;
82 }
83 
85 {
86  if (mTimer)
87  disconnect(mTimer.get(), SIGNAL(changed()), this, SLOT(timerChangedSlot()));
88  mTimer = controller;
89  if (mTimer)
90  connect(mTimer.get(), SIGNAL(changed()), this, SLOT(timerChangedSlot()));
91 
92  if (controller)
93  {
94  mVideoSource->start();
95  }
96  else
97  {
98  mVideoSource->deconfigure();
99  }
100 }
101 
102 void USAcquisitionVideoPlayback::setRoot(const QString path)
103 {
104  mRoot = path;
105  mEvents = this->getEvents();
106 }
107 
108 std::vector<TimelineEvent> USAcquisitionVideoPlayback::getEvents()
109 {
110  std::vector<TimelineEvent> events;
111 
112  QStringList allFiles = this->getAbsolutePathToFtsFiles(mRoot);
113  for (int i=0; i<allFiles.size(); ++i)
114  {
116  std::vector<TimedPosition> timestamps = reader.readFrameTimestamps(allFiles[i]);
117 
118  if (timestamps.empty())
119  continue;
120 
121  TimelineEvent current(
122  QString("Acquisition %1").arg(QFileInfo(allFiles[i]).fileName()),
123  timestamps.front().mTime,
124  timestamps.back().mTime);
125  current.mUid = allFiles[i];
126  current.mGroup = "acquisition";
127  current.mColor = QColor::fromHsv(36, 255, 222);
128 
129  events.push_back(current);
130 
131  }
132 
133  return events;
134 }
135 
138 QStringList USAcquisitionVideoPlayback::getAbsolutePathToFtsFiles(QString folder)
139 {
140  return getAbsolutePathToFiles(folder, QStringList("*.fts"), true);
141 }
142 
143 void USAcquisitionVideoPlayback::timerChangedSlot()
144 {
145  TimelineEvent event;
146  for (unsigned i=0; i<mEvents.size(); ++i)
147  {
148  if (mEvents[i].isInside(mTimer->getTime().toMSecsSinceEpoch()))
149  {
150  event = mEvents[i];
151  break;
152  }
153  }
154 
155  this->loadFullData(event.mUid);
156  this->updateFrame(event.mUid);
157 }
158 
159 void USAcquisitionVideoPlayback::loadFullData(QString filename)
160 {
161  // if same filename, ok and return
162  if (filename == mCurrentData.mFilename)
163  return;
164 
165  mVideoSource->setInfoString(QString(""));
166  mVideoSource->setStatusString(QString("No US Acquisition"));
167  mVideoSource->deconfigure();
168 
169  // if no data: ignore but keep the already loaded data
170  if (filename.isEmpty())
171  return;
172 
173  // clear data
174  mCurrentData = USReconstructInputData();
175 
176  // if no new data, return
177  if (filename.isEmpty())
178  return;
179 
180  // load new data
181  // start an asynchronous read of data
182  if (!mUSImageDataReader)
183  {
184  mUSImageDataReader.reset(new UsReconstructionFileReader());
185  mUSImageDataFutureResult = QtConcurrent::run(boost::bind(&UsReconstructionFileReader::readAllFiles, mUSImageDataReader, filename, ""));
186  mUSImageDataFutureWatcher.setFuture(mUSImageDataFutureResult);
187  }
188 }
189 
190 void USAcquisitionVideoPlayback::usDataLoadFinishedSlot()
191 {
192  // file read operation has completed: read and clear
193  mCurrentData = mUSImageDataFutureResult.result();
194  mCurrentData.mProbeData.mData.setUid(mVideoSourceUid);
195  // clear result so we can check for it next run
196  mUSImageDataReader.reset();
197 
198  mVideoSource->start();
199 
200  // set the probe sector from file data:
201  ToolPtr tool = mBackend->getToolManager()->getFirstProbe();
202  if (tool)
203  {
204  ProbePtr probe = tool->getProbe();
205  if (probe)
206  probe->setProbeSector(mCurrentData.mProbeData.mData);
207  }
208 
209  // create a vector to allow for quick search
210  mCurrentTimestamps.clear();
211  for (unsigned i=0; i<mCurrentData.mFrames.size(); ++i)
212  mCurrentTimestamps.push_back(mCurrentData.mFrames[i].mTime);
213 
214  this->updateFrame(mCurrentData.mFilename);
215 }
216 
217 void USAcquisitionVideoPlayback::updateFrame(QString filename)
218 {
219  if (mUSImageDataReader)
220  {
221  mVideoSource->setInfoString(QString("Loading US Data..."));
222  mVideoSource->setStatusString(QString("Loading US Data..."));
223  mVideoSource->setInput(ImagePtr());
224  return;
225  }
226 
227  if (mCurrentData.mFilename.isEmpty() || !mCurrentData.mUsRaw || filename!=mCurrentData.mFilename)
228  {
229  mVideoSource->setInfoString(QString(""));
230  mVideoSource->setStatusString(QString("No US Acquisition"));
231  mVideoSource->setInput(ImagePtr());
232  return;
233  }
234 
235  // if not already started:
236  mVideoSource->start();
237 
238  double timestamp = mTimer->getTime().toMSecsSinceEpoch();
239 
240  // find index of current frame: Use the last frame _before_ the current timestamp.
241  std::vector<double>::iterator iter = std::lower_bound(mCurrentTimestamps.begin(), mCurrentTimestamps.end(), timestamp);
242  if (iter==mCurrentTimestamps.begin())
243  return;
244  --iter; // use the frame before, not after.
245  int index = std::distance(mCurrentTimestamps.begin(), iter);
246 
247  int timeout = 1000; // invalidate data if timestamp differ from time too much
248  mVideoSource->overrideTimeout(fabs(timestamp-*iter)>timeout);
249 
250  ImagePtr image(new Image(mVideoSourceUid, mCurrentData.mUsRaw->getImageContainer()->get(index)));
251  image->setAcquisitionTime(QDateTime::fromMSecsSinceEpoch(timestamp));
252 
253  mVideoSource->setInfoString(QString("%1 - Frame %2").arg(mCurrentData.mUsRaw->getName()).arg(index));
254  if (mVideoSource->validData())
255  mVideoSource->setStatusString(QString(""));
256  else
257  mVideoSource->setStatusString(QString("Timeout"));
258 
259  mVideoSource->setInput(image);
260 }
261 
262 
263 
264 } // cx
265 
Reader class for the US Acquisition files.
void setTime(PlaybackTimePtr controller)
Description of one event in time.
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:48
std::vector< TimedPosition > readFrameTimestamps(QString fileName)
std::vector< TimedPosition > mFrames
boost::shared_ptr< class VideoServiceBackend > VideoServiceBackendPtr
boost::shared_ptr< Probe > ProbePtr
Definition: cxProbe.h:93
USAcquisitionVideoPlayback(VideoServiceBackendPtr backend)
USReconstructInputData readAllFiles(QString fileName, QString calFilesPath="")
void setUid(QString uid)
boost::shared_ptr< class VideoSource > VideoSourcePtr
VideoSource controlled by a vtkImageData.
ProbeDefinition mData
Definition: cxProbeSector.h:75
std::vector< TimelineEvent > getEvents()
QStringList getAbsolutePathToFiles(QString path, QStringList nameFilters, bool includeSubDirs)
QString mFilename
filename used for current data read
USFrameDataPtr mUsRaw
All imported US data frames with pointers to each frame.
boost::shared_ptr< class PlaybackTime > PlaybackTimePtr
boost::shared_ptr< class Tool > ToolPtr