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