PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusStealthLinkCommand.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2 Program: Plus
3 Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4 See License.txt for details.
5 =========================================================Plus=header=end*/
6 
7 #include "PlusConfigure.h"
8 #include "vtkPlusDataCollector.h"
11 
12 #include "vtkImageData.h"
13 #include "vtkDICOMImageReader.h"
14 #include "vtkObjectFactory.h"
15 #include "vtkPlusChannel.h"
17 #include "vtkIGSIOTrackedFrameList.h"
20 #include <vtkImageFlip.h>
21 #include <vtkPointData.h>
22 #include <vtkDirectory.h>
23 
24 static const std::string GET_STEALTHLINK_EXAM_DATA_CMD = "ExamData";
25 
27 
28 //----------------------------------------------------------------------------
30  : KeepReceivedDicomFiles(false)
31 {
32 }
33 
34 //----------------------------------------------------------------------------
36 {
37 }
38 
39 //----------------------------------------------------------------------------
40 void vtkPlusStealthLinkCommand::PrintSelf(ostream& os, vtkIndent indent)
41 {
42  this->Superclass::PrintSelf(os, indent);
43 }
44 
45 //----------------------------------------------------------------------------
46 void vtkPlusStealthLinkCommand::GetCommandNames(std::list<std::string>& cmdNames)
47 {
48  cmdNames.clear();
49  cmdNames.push_back(GET_STEALTHLINK_EXAM_DATA_CMD);
50 }
51 
52 //----------------------------------------------------------------------------
53 std::string vtkPlusStealthLinkCommand::GetDescription(const std::string& commandName)
54 {
55  std::string desc;
56  if (commandName.empty() || igsioCommon::IsEqualInsensitive(commandName, GET_STEALTHLINK_EXAM_DATA_CMD))
57  {
59  desc += ": Acquire the exam data from the StealthLink Server. The exam data contains the image being displayed on the StealthLink Server. The 3D volume will be constructed using these images";
60  }
61  return desc;
62 }
63 
64 //----------------------------------------------------------------------------
66 {
67  this->SetName(GET_STEALTHLINK_EXAM_DATA_CMD);
68 }
69 
70 //----------------------------------------------------------------------------
72 {
74  {
75  return PLUS_FAIL;
76  }
77 
78  if (aConfig->GetAttribute("DicomImagesOutputDirectory"))
79  {
80  this->SetDicomImagesOutputDirectory(aConfig->GetAttribute("DicomImagesOutputDirectory"));
81  }
82  else
83  {
84  LOG_INFO("The dicom images from stealthlink will be saved into the: " << vtkPlusConfig::GetInstance()->GetOutputDirectory() << "/StealthLinkDicomOutput");
85  std::string dicomImagesDefaultOutputDirectory = vtkPlusConfig::GetInstance()->GetOutputDirectory() + std::string("/StealthLinkDicomOutput");
86  this->SetDicomImagesOutputDirectory(dicomImagesDefaultOutputDirectory.c_str());
87  }
88 
89  XML_READ_STRING_ATTRIBUTE_OPTIONAL(StealthLinkDeviceId, aConfig);
90 
91  if (aConfig->GetAttribute("VolumeEmbeddedTransformToFrame"))
92  {
93  this->SetVolumeEmbeddedTransformToFrame(aConfig->GetAttribute("VolumeEmbeddedTransformToFrame"));
94  }
95  else
96  {
97  LOG_INFO("The dicom images from stealthlink will be represented in Ras coordinate system");
98  this->SetVolumeEmbeddedTransformToFrame("Ras");
99  }
100 
101  XML_READ_BOOL_ATTRIBUTE_OPTIONAL(KeepReceivedDicomFiles, aConfig);
102 
103  return PLUS_SUCCESS;
104 }
105 
106 //----------------------------------------------------------------------------
108 {
110  {
111  return PLUS_FAIL;
112  }
113  XML_WRITE_STRING_ATTRIBUTE_IF_NOT_EMPTY(StealthLinkDeviceId, aConfig);
114  XML_WRITE_STRING_ATTRIBUTE_IF_NOT_EMPTY(DicomImagesOutputDirectory, aConfig);
115  XML_WRITE_STRING_ATTRIBUTE_IF_NOT_EMPTY(VolumeEmbeddedTransformToFrame, aConfig);
116  XML_WRITE_BOOL_ATTRIBUTE(KeepReceivedDicomFiles, aConfig);
117  return PLUS_SUCCESS;
118 }
119 
120 //----------------------------------------------------------------------------
122 {
123  LOG_DEBUG("vtkPlusStealthLinkCommand::Execute: " << (!this->Name.empty() ? this->Name : "(undefined)")
124  << ", device: " << (this->StealthLinkDeviceId.empty() ? "(undefined)" : this->StealthLinkDeviceId));
125 
126  if (this->Name.empty())
127  {
128  this->QueueCommandResponse(PLUS_FAIL, "StealthLink command failed, no command name specified");
129  return PLUS_FAIL;
130  }
131 
132  vtkPlusStealthLinkTracker* stealthLinkDevice = GetStealthLinkDevice();
133  if (stealthLinkDevice == NULL)
134  {
135  this->QueueCommandResponse(PLUS_FAIL, std::string("StealthLink command failed: device ")
136  + (this->StealthLinkDeviceId.empty() ? "(undefined)" : this->StealthLinkDeviceId) + " is not found");
137  return PLUS_FAIL;
138  }
139 
140  if (igsioCommon::IsEqualInsensitive(this->Name, GET_STEALTHLINK_EXAM_DATA_CMD))
141  {
142  LOG_INFO("Acquiring the exam data from StealthLink Server: Device ID: " << GetStealthLinkDeviceId());
143 
144  stealthLinkDevice->SetDicomImagesOutputDirectory(this->GetDicomImagesOutputDirectory());
145  stealthLinkDevice->SetKeepReceivedDicomFiles(this->GetKeepReceivedDicomFiles());
146  std::string requestedImageId;
147  std::string assignedImageId;
148  vtkSmartPointer<vtkImageData> imageData = vtkSmartPointer<vtkImageData>::New();
149  vtkSmartPointer<vtkMatrix4x4> ijkToReferenceTransform = vtkSmartPointer<vtkMatrix4x4>::New();
150  // make available all transforms to the device so that it can compute ijkToReferenceTransform (Reference = VolumeEmbeddedTransformToFrame)
151  stealthLinkDevice->UpdateTransformRepository(this->CommandProcessor->GetPlusServer()->GetTransformRepository());
152  if (stealthLinkDevice->GetImage(requestedImageId, assignedImageId, std::string(this->GetVolumeEmbeddedTransformToFrame()), imageData, ijkToReferenceTransform) != PLUS_SUCCESS)
153  {
154  this->QueueCommandResponse(PLUS_FAIL, "vtkPlusStealthLinkCommand::Execute: failed, failed to receive image");
155  return PLUS_FAIL;
156  }
157  std::string resultMessage;
158  PlusStatus status = ProcessImageReply(assignedImageId, imageData, ijkToReferenceTransform, resultMessage);
159  this->QueueCommandResponse(status, "Volume sending completed: " + resultMessage);
160  return PLUS_SUCCESS;
161  }
162  this->QueueCommandResponse(PLUS_FAIL, "vtkPlusStealthLinkCommand::Execute: failed, unknown command name: " + this->Name);
163  return PLUS_FAIL;
164 }
165 
166 //----------------------------------------------------------------------------
167 PlusStatus vtkPlusStealthLinkCommand::ProcessImageReply(const std::string& imageId, vtkImageData* volumeToSend, vtkMatrix4x4* imageToReferenceOrientationMatrix, std::string& resultMessage)
168 {
169  LOG_DEBUG("Send image to client through OpenIGTLink");
170  vtkSmartPointer<vtkPlusCommandImageResponse> imageResponse = vtkSmartPointer<vtkPlusCommandImageResponse>::New();
171  this->CommandResponseQueue.push_back(imageResponse);
172  imageResponse->SetClientId(this->ClientId);
173  imageResponse->SetImageName(imageId);
174  imageResponse->SetImageData(volumeToSend);
175  imageResponse->SetImageToReferenceTransform(imageToReferenceOrientationMatrix);
176  LOG_INFO("Send reconstructed volume to client through OpenIGTLink");
177  resultMessage.clear();
178  resultMessage = std::string(", volume sent as: ") + imageResponse->GetImageName();
179  return PLUS_SUCCESS;
180 }
181 
182 //----------------------------------------------------------------------------
184 {
185  vtkPlusDataCollector* dataCollector = GetDataCollector();
186  if (dataCollector == NULL)
187  {
188  LOG_ERROR("Data collector is invalid");
189  return NULL;
190  }
191  if (!GetStealthLinkDeviceId().empty())
192  {
193  // Reconstructor device ID is specified
194  vtkPlusDevice* device = NULL;
195  if (dataCollector->GetDevice(device, GetStealthLinkDeviceId()) != PLUS_SUCCESS)
196  {
197  LOG_ERROR("No StealthLink device has been found by the name " << this->GetStealthLinkDeviceId());
198  return NULL;
199  }
200  // device found
202  if (stealthLinkDevice == NULL)
203  {
204  // wrong type
205  LOG_ERROR("The specified device " << GetStealthLinkDeviceId() << " is not StealthLink Device");
206  return NULL;
207  }
208  return stealthLinkDevice;
209  }
210  else
211  {
212  // No stealthlink device id is specified, auto-detect the first one and use that
213  for (DeviceCollectionConstIterator it = dataCollector->GetDeviceConstIteratorBegin(); it != dataCollector->GetDeviceConstIteratorEnd(); ++it)
214  {
216  if (stealthLinkDevice != NULL)
217  {
218  // found a recording device
219  SetStealthLinkDeviceId(stealthLinkDevice->GetDeviceId());
220  return stealthLinkDevice;
221  }
222  }
223  LOG_ERROR("No StealthLink Device has been found");
224  return NULL;
225  }
226 }
void SetDicomImagesOutputDirectory(std::string dicomImagesOutputDirectory)
static const std::string GET_STEALTHLINK_EXAM_DATA_CMD
virtual void PrintSelf(ostream &os, vtkIndent indent)
Abstract interface for tracker and video devices.
Definition: vtkPlusDevice.h:60
std::vector< vtkPlusDevice * >::const_iterator DeviceCollectionConstIterator
Definition: vtkPlusDevice.h:48
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *aConfig)
PlusStatus GetDevice(vtkPlusDevice *&aDevice, const std::string &aDeviceId) const
std::string Name
igsioStatus PlusStatus
Definition: PlusCommon.h:40
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *aConfig)
virtual std::string GetDeviceId() const
PlusStatus ProcessImageReply(const std::string &imageId, vtkImageData *volumeToSend, vtkMatrix4x4 *imageToReferenceOrientationMatrixWithSpacing, std::string &resultMessage)
virtual vtkPlusOpenIGTLinkServer * GetPlusServer()
#define PLUS_FAIL
Definition: PlusCommon.h:43
virtual std::string GetDescription(const std::string &commandName)
static vtkPlusConfig * GetInstance()
DeviceCollectionConstIterator GetDeviceConstIteratorBegin() const
vtkPlusCommandProcessor * CommandProcessor
vtkPlusStealthLinkTracker * GetStealthLinkDevice()
DeviceCollectionConstIterator GetDeviceConstIteratorEnd() const
Manages devices that record image or positional data.
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
std::string GetOutputDirectory()
PlusStatus UpdateTransformRepository(vtkIGSIOTransformRepository *sharedTransformRepository)
virtual void GetCommandNames(std::list< std::string > &cmdNames)
static vtkPlusStealthLinkTracker * SafeDownCast(vtkObject *o)
virtual bool GetKeepReceivedDicomFiles()
void QueueCommandResponse(PlusStatus status, const std::string &message, const std::string &error="", const igtl::MessageBase::MetaDataMap *metaData=nullptr)
virtual vtkPlusDataCollector * GetDataCollector()
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *aConfig)
vtkStandardNewMacro(vtkPlusStealthLinkCommand)
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *aConfig)
virtual void PrintSelf(ostream &os, vtkIndent indent)
PlusCommandResponseList CommandResponseQueue
void SetKeepReceivedDicomFiles(bool keepReceivedDicomFiles)
virtual PlusStatus GetImage(const std::string &requestedImageId, std::string &assignedImageId, const std::string &imageReferenceFrameName, vtkImageData *imageData, vtkMatrix4x4 *ijkToReferenceTransform)
This command reconstructs a volume from an image sequence and saves it to disk or sends it to the cli...