8 #include "PlusConfigure.h" 10 #include "StealthLink/StealthLink.h" 12 #include "vtkDICOMImageReader.h" 13 #include "vtkDirectory.h" 14 #include "vtkImageData.h" 15 #include "vtkImageFlip.h" 17 #include "vtkMatrix4x4.h" 20 #include "vtkIGSIOTransformRepository.h" 27 class vtkPlusStealthLinkTracker::vtkInternalShared
31 : StealthLinkServer(NULL)
33 this->ExamIjkToRpiTransform = vtkSmartPointer<vtkMatrix4x4>::New();
34 this->ExamIjkToRasTransform = vtkSmartPointer<vtkMatrix4x4>::New();
36 this->StealthLinkServerMutex = vtkSmartPointer<vtkIGSIORecursiveCriticalSection>::New();
37 this->ExamIjkToRpiMutex = vtkSmartPointer<vtkIGSIORecursiveCriticalSection>::New();
38 this->ExamIjkToRasMutex = vtkSmartPointer<vtkIGSIORecursiveCriticalSection>::New();
39 this->ExamValidMutex = vtkSmartPointer<vtkIGSIORecursiveCriticalSection>::New();
40 this->CurrentExamMutex = vtkSmartPointer<vtkIGSIORecursiveCriticalSection>::New();
41 this->CurrentRegistrationMutex = vtkSmartPointer<vtkIGSIORecursiveCriticalSection>::New();
47 delete this->StealthLinkServer;
48 this->StealthLinkServer = NULL;
49 this->External = NULL;
53 void SetExamIjkToRpiTransformMatrix(vtkMatrix4x4* examIjkToRpiTransform)
55 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->ExamIjkToRpiMutex);
56 this->ExamIjkToRpiTransform = examIjkToRpiTransform;
59 void GetExamIjkToRpiTransformMatrix(vtkMatrix4x4* examIjkToRpiTransform)
61 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->ExamIjkToRpiMutex);
62 examIjkToRpiTransform->DeepCopy(this->ExamIjkToRpiTransform);
66 void SetExamIjkToRasTransformMatrix(vtkMatrix4x4* examIjkToRasTransform)
68 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->ExamIjkToRasMutex);
69 this->ExamIjkToRasTransform = examIjkToRasTransform;
72 void GetExamIjkToRasTransformMatrix(vtkMatrix4x4* examIjkToRasTransform)
74 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->ExamIjkToRasMutex);
75 examIjkToRasTransform->DeepCopy(this->ExamIjkToRasTransform);
79 void SetExamValid(
bool examValid)
81 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->ExamValidMutex);
82 this->ExamValid = examValid;
87 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->ExamValidMutex);
88 return this->ExamValid;
93 PlusStatus GetCurrentNavigationData(MNavStealthLink::NavData& navData)
95 MNavStealthLink::Error err;
96 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->StealthLinkServerMutex);
97 MNavStealthLink::DateTime myDateTime = this->StealthLinkServer->getServerTime();
98 if (!this->StealthLinkServer->get(navData, myDateTime, err))
100 LOG_ERROR(
" Failed to acquire the navigation data from StealthLink Server: " << err.reason() <<
" " << err.what() <<
"\n");
108 PlusStatus GetInstrumentData(MNavStealthLink::Instrument& instrument,
const std::string toolname)
110 MNavStealthLink::Error err;
111 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->StealthLinkServerMutex);
112 MNavStealthLink::DateTime myDateTime = this->StealthLinkServer->getServerTime();
113 if (!this->StealthLinkServer->get(toolname, instrument, myDateTime, err))
115 LOG_ERROR(
" Failed to acquire the instrument data from StealthLink Server: " << err.reason() <<
" " << err.what() <<
"\n");
122 void GetCurrentExam(MNavStealthLink::Exam& exam)
124 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->CurrentExamMutex);
125 exam = this->CurrentExam;
129 void GetCurrentRegistration(MNavStealthLink::Registration& registration)
131 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->CurrentRegistrationMutex);
132 registration = this->CurrentRegistration;
137 PlusStatus GetValidToolPortNames(std::vector<std::string>& validToolPortNames)
139 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->StealthLinkServerMutex);
140 MNavStealthLink::Error err;
141 MNavStealthLink::InstrumentNameList instrumentNameList;
143 if (!this->StealthLinkServer->get(instrumentNameList, err))
145 LOG_ERROR(
" Could not retrieve the instument name list: " << err.reason() << std::endl);
148 MNavStealthLink::FrameNameList frameNameList;
150 if (!this->StealthLinkServer->get(frameNameList, err))
152 LOG_ERROR(
" Could not retrieve the instument name list: " << err.reason() << std::endl);
155 for (MNavStealthLink::InstrumentNameList::iterator instrumentNameIterator = instrumentNameList.begin(); instrumentNameIterator != instrumentNameList.end(); instrumentNameIterator++)
157 validToolPortNames.push_back(*instrumentNameIterator);
159 for (MNavStealthLink::FrameNameList::iterator frameNameIterator = frameNameList.begin(); frameNameIterator != frameNameList.end(); frameNameIterator++)
161 validToolPortNames.push_back(*frameNameIterator);
163 validToolPortNames.push_back(vtkInternalShared::GetRasRegistrationToolName());
172 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->CurrentExamMutex);
173 MNavStealthLink::Error err;
175 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->StealthLinkServerMutex);
176 MNavStealthLink::DateTime myDateTime = this->StealthLinkServer->getServerTime();
177 if (!this->StealthLinkServer->get(this->CurrentExam, myDateTime, err))
179 LOG_ERROR(
" Failed to acquire the current exam: " << err.what() <<
"\n");
189 PlusStatus UpdateCurrentRegistration(
bool imageTransferRequiresPatientRegistration)
191 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->CurrentRegistrationMutex);
192 MNavStealthLink::Error err;
194 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->StealthLinkServerMutex);
195 MNavStealthLink::DateTime myDateTime = this->StealthLinkServer->getServerTime();
196 if (!this->StealthLinkServer->get(this->CurrentRegistration, myDateTime, err))
198 if (imageTransferRequiresPatientRegistration)
200 LOG_ERROR(
" Failed to acquire the current registration: " << err.what() <<
"\n");
205 LOG_WARNING(
" Failed to acquire the current registration: " << err.what() <<
"\n Using default registration");
213 bool IsStealthServerConnected()
215 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->StealthLinkServerMutex);
216 if (this->StealthLinkServer == NULL)
226 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->StealthLinkServerMutex);
227 MNavStealthLink::Version serverVersion;
228 MNavStealthLink::Error err;
230 MNavStealthLink::DateTime myDateTime = this->StealthLinkServer->getServerTime();
231 if (!this->StealthLinkServer->get(serverVersion, myDateTime, err))
233 LOG_ERROR(
"Failed to acquire the version of the StealthLinkServer " << err.reason() <<
"\n");
237 version = (unsigned) serverVersion.major + (
unsigned) serverVersion.minor;
242 PlusStatus GetExamNameList(MNavStealthLink::ExamNameList& examNameList)
244 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->StealthLinkServerMutex);
245 MNavStealthLink::Error err;
246 MNavStealthLink::DateTime myDateTime = this->StealthLinkServer->getServerTime();
247 if (!this->StealthLinkServer->get(examNameList, myDateTime, err))
249 LOG_ERROR(
"Failed to acquire the version of the StealthLinkServer " << err.reason() <<
"\n");
256 PlusStatus ConnectToStealthStation(std::string serverAddress, std::string serverPort)
258 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->StealthLinkServerMutex);
259 delete this->StealthLinkServer;
260 this->StealthLinkServer = NULL;
261 this->StealthLinkServer =
new MNavStealthLink::StealthServer(serverAddress, serverPort);
263 MNavStealthLink::Error error;
264 if (!this->StealthLinkServer->connect(error))
266 LOG_ERROR(
" Failed to connect to Stealth server application on host: " << error.what() <<
"\n");
275 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->StealthLinkServerMutex);
276 MNavStealthLink::LocalizerInfo localizerInfo;
277 MNavStealthLink::Error err;
278 if (!this->StealthLinkServer->get(localizerInfo, err))
280 LOG_ERROR(
"Cannot retrieve the localizer info " << err.reason() <<
"\n");
284 if (localizerInfo.isConnected)
294 PlusStatus GetStealthStationServerTime(
double& serverTime)
296 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->StealthLinkServerMutex);
299 serverTime = (double) this->StealthLinkServer->getServerTime();
301 catch (MNavStealthLink::Error err)
303 LOG_ERROR(
"Cannot get server time " << err.reason());
310 void DisconnectFromStealthStation()
312 this->StealthLinkServer->disconnect();
313 delete this->StealthLinkServer;
314 this->StealthLinkServer = NULL;
318 PlusStatus GetExamData(MNavStealthLink::Exam exam, std::string examImageDirectory)
320 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->StealthLinkServerMutex);
323 exam.getExamData(*(this->StealthLinkServer), examImageDirectory);
325 catch (MNavStealthLink::Error error)
327 LOG_ERROR(
"Error getting images from StealthLink: " << error.what() <<
"\n");
334 static std::string GetRasRegistrationToolName() {
return "RasRegistration"; }
337 MNavStealthLink::StealthServer* StealthLinkServer;
338 MNavStealthLink::Registration CurrentRegistration;
339 MNavStealthLink::Exam CurrentExam;
343 vtkSmartPointer<vtkMatrix4x4> ExamIjkToRpiTransform;
346 vtkSmartPointer<vtkMatrix4x4> ExamIjkToRasTransform;
349 vtkSmartPointer<vtkIGSIORecursiveCriticalSection> StealthLinkServerMutex;
350 vtkSmartPointer<vtkIGSIORecursiveCriticalSection> ExamIjkToRpiMutex;
351 vtkSmartPointer<vtkIGSIORecursiveCriticalSection> ExamIjkToRasMutex;
352 vtkSmartPointer<vtkIGSIORecursiveCriticalSection> ExamValidMutex;
353 vtkSmartPointer<vtkIGSIORecursiveCriticalSection> CurrentExamMutex;
354 vtkSmartPointer<vtkIGSIORecursiveCriticalSection> CurrentRegistrationMutex;
363 class vtkPlusStealthLinkTracker::vtkInternalUpdatePrivate
373 double ServerInitialTimeInMicroSeconds;
374 double TrackerTimeToSystemTimeSec;
381 class vtkPlusStealthLinkTracker::vtkInternal
391 vtkSmartPointer<vtkIGSIOTransformRepository> TransformRepository;
393 std::pair<std::string, std::string> PairImageIdAndName;
394 std::string ServerAddress;
395 std::string ServerPort;
396 std::string DicomImagesOutputDirectory;
399 int ImageMetaDatasetsCount;
400 bool KeepReceivedDicomFiles;
407 this->TransformRepository = vtkSmartPointer<vtkIGSIOTransformRepository>::New();
409 this->ServerAddress.clear();
410 this->ServerPort.clear();
411 this->DicomImagesOutputDirectory.clear();
418 std::string GetExamAndPatientInformationAsString(MNavStealthLink::Exam exam)
420 std::string examAndPatientInformation;
421 examAndPatientInformation = exam.name + exam.description + exam.modality + exam.hospitalName + exam.examNumber + exam.patientId + exam.patientName + exam.patientDOB;
422 return examAndPatientInformation;
426 static void GetInstrumentInformation(MNavStealthLink::Instrument instrument, ToolStatus& instrumentStatus, vtkMatrix4x4* insToTrackerTransform)
428 if (!(instrument.visibility == MNavStealthLink::Instrument::VISIBLE) && !(instrument.visibility == MNavStealthLink::Instrument::ALMOST_BLOCKED))
430 instrumentStatus = TOOL_OUT_OF_VIEW;
435 instrumentStatus = TOOL_OK;
437 for (
int col = 0; col < 4; col++)
439 for (
int row = 0; row < 4; row++)
441 insToTrackerTransform->SetElement(row, col, instrument.localizer_T_instrument [row][col]);
446 static void GetInstrumentInformation(MNavStealthLink::NavData navData, ToolStatus& instrumentStatus, vtkMatrix4x4* insToTrackerTransform)
448 if (!(navData.instVisibility == MNavStealthLink::Instrument::VISIBLE) && !(navData.instVisibility == MNavStealthLink::Instrument::ALMOST_BLOCKED))
450 instrumentStatus = TOOL_OUT_OF_VIEW;
455 instrumentStatus = TOOL_OK;
457 for (
int col = 0; col < 4; col++)
459 for (
int row = 0; row < 4; row++)
461 insToTrackerTransform->SetElement(row, col, navData.localizer_T_instrument [row][col]);
466 static void GetFrameInformation(MNavStealthLink::NavData navData,
bool& frameOutOfView, vtkMatrix4x4* frameToTrackerTransform)
468 if (!(navData.frameVisibility == MNavStealthLink::Frame::VISIBLE) && !(navData.frameVisibility == MNavStealthLink::Frame::ALMOST_BLOCKED))
470 frameOutOfView =
true;
475 frameOutOfView =
false;
477 vtkSmartPointer<vtkMatrix4x4> trackerToFrameTransform = vtkSmartPointer<vtkMatrix4x4>::New();
478 for (
int col = 0; col < 4; col++)
480 for (
int row = 0; row < 4; row++)
482 trackerToFrameTransform->SetElement(row, col, navData.frame_T_localizer [row][col]);
486 vtkMatrix4x4::Invert(trackerToFrameTransform, frameToTrackerTransform);
489 void GetRasToTrackerTransform(vtkMatrix4x4* frameToTrackerTransform, vtkMatrix4x4* rasToTrackerTransform)
492 vtkSmartPointer<vtkMatrix4x4> frameToRegExamTransform = vtkSmartPointer<vtkMatrix4x4>::New();
493 vtkSmartPointer<vtkMatrix4x4> regExamToExamRpiTransform = vtkSmartPointer<vtkMatrix4x4>::New();
494 MNavStealthLink::Registration registration;
495 MNavStealthLink::Exam exam;
496 this->External->
InternalShared->GetCurrentRegistration(registration);
498 for (
int col = 0; col < 4; col++)
500 for (
int row = 0; row < 4; row++)
502 frameToRegExamTransform->SetElement(row, col, registration.regExamMM_T_frame [row][col]);
503 regExamToExamRpiTransform->SetElement(row, col, exam.examMM_T_regExamMM[row][col]);
507 vtkSmartPointer<vtkMatrix4x4> regExamToFrameTransform = vtkSmartPointer<vtkMatrix4x4>::New();
508 vtkMatrix4x4::Invert(frameToRegExamTransform, regExamToFrameTransform);
509 vtkSmartPointer<vtkMatrix4x4> examRpiToRegExamTransform = vtkSmartPointer<vtkMatrix4x4>::New();
510 vtkMatrix4x4::Invert(regExamToExamRpiTransform, examRpiToRegExamTransform);
513 vtkSmartPointer<vtkMatrix4x4> examRpiToFrameTransform = vtkSmartPointer<vtkMatrix4x4>::New();
514 vtkMatrix4x4::Multiply4x4(regExamToFrameTransform, examRpiToRegExamTransform, examRpiToFrameTransform);
523 vtkSmartPointer<vtkMatrix4x4> rasToIjkTransform = vtkSmartPointer<vtkMatrix4x4>::New();
524 vtkSmartPointer<vtkMatrix4x4> examIjkToRasTransform = vtkSmartPointer<vtkMatrix4x4>::New();
525 this->External->
InternalShared->GetExamIjkToRasTransformMatrix(examIjkToRasTransform);
526 vtkMatrix4x4::Invert(examIjkToRasTransform, rasToIjkTransform);
530 vtkSmartPointer<vtkMatrix4x4> ijkToFrameTransform = vtkSmartPointer<vtkMatrix4x4>::New();
531 vtkSmartPointer<vtkMatrix4x4> examIjkToRpiTransform = vtkSmartPointer<vtkMatrix4x4>::New();
532 this->External->
InternalShared->GetExamIjkToRpiTransformMatrix(examIjkToRpiTransform);
533 vtkMatrix4x4::Multiply4x4(examRpiToFrameTransform, examIjkToRpiTransform, ijkToFrameTransform);
536 vtkSmartPointer<vtkMatrix4x4> rasToFrameTransform = vtkSmartPointer<vtkMatrix4x4>::New();
537 vtkMatrix4x4::Multiply4x4(ijkToFrameTransform, rasToIjkTransform, rasToFrameTransform);
540 vtkSmartPointer<vtkMatrix4x4> lpsToTrackerTransform = vtkSmartPointer<vtkMatrix4x4>::New();
541 vtkMatrix4x4::Multiply4x4(frameToTrackerTransform, rasToFrameTransform, rasToTrackerTransform);
552 this->
Internal =
new vtkInternal(
this);
589 if (sharedTransformRepository == NULL)
591 LOG_ERROR(
"vtkPlusVirtualVolumeReconstructor::UpdateTransformRepository: shared transform repository is invalid");
595 this->
Internal->TransformRepository->DeepCopy(sharedTransformRepository,
true);
606 LOG_INFO(
"Acquiring the image meta data from the device with DeviceId: " << this->
GetDeviceId());
607 igsioCommon::ImageMetaDataItem imageMetaDataItem;
608 MNavStealthLink::Exam exam;
612 imageMetaDataItem.Description = exam.description;
613 imageMetaDataItem.Modality = exam.modality;
614 imageMetaDataItem.PatientId = exam.patientId;
615 imageMetaDataItem.PatientName = exam.patientName ;
616 imageMetaDataItem.ScalarType = 3;
617 imageMetaDataItem.Size[0] = exam.size[0];
618 imageMetaDataItem.Size[1] = exam.size[1];
619 imageMetaDataItem.Size[2] = exam.size[2];
620 imageMetaDataItem.TimeStampUtc = vtkIGSIOAccurateTimer::GetUniversalTime();
621 imageMetaData.push_back(imageMetaDataItem);
622 this->
Internal->PairImageIdAndName.first = imageMetaDataItem.Id;
623 this->
Internal->PairImageIdAndName.second = this->
Internal->GetExamAndPatientInformationAsString(exam);
629 std::string examImageDirectoryToDelete;
635 if (!this->
InternalShared->UpdateCurrentRegistration(this->ImageTransferRequiresPatientRegistration))
639 if (!requestedImageId.empty())
641 if (STRCASECMP(this->
Internal->PairImageIdAndName.first.c_str(), requestedImageId.c_str()) != 0)
643 LOG_ERROR(
"The image requested does not belong to " << this->
GetDeviceId());
646 MNavStealthLink::Exam exam;
648 std::string examAndPatientInformation = this->
Internal->GetExamAndPatientInformationAsString(exam);
649 if (STRCASECMP(this->
Internal->PairImageIdAndName.second.c_str(), examAndPatientInformation.c_str()) != 0)
651 LOG_INFO(
"Current exam on the server does not match the exam you have requested. Please either update image meta data or select the exam you request on the server");
654 assignedImageId = requestedImageId;
660 std::string examImageDirectory;
665 examImageDirectoryToDelete = examImageDirectory;
667 vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
670 reader->SetDirectoryName(examImageDirectory.c_str());
671 reader->ReleaseDataFlagOn();
674 vtkSmartPointer<vtkImageFlip> flipYFilter = vtkSmartPointer<vtkImageFlip>::New();
675 flipYFilter->SetFilteredAxis(1);
676 flipYFilter->ReleaseDataFlagOn();
677 flipYFilter->SetInputConnection(reader->GetOutputPort());
679 vtkSmartPointer<vtkImageFlip> flipZFilter = vtkSmartPointer<vtkImageFlip>::New();
680 flipZFilter->SetFilteredAxis(2);
681 flipZFilter->ReleaseDataFlagOn();
682 flipZFilter->SetInputConnection(flipYFilter->GetOutputPort());
683 flipZFilter->Update();
684 imageData->DeepCopy(flipZFilter->GetOutput());
686 catch (
const std::bad_alloc& e)
688 LOG_ERROR(
"Error when downloading image from StealthLink: " << e.what() <<
". Image may be too large");
692 float* ijkOrigin_LPS = reader->GetImagePositionPatient();
693 double* ijkVectorMagnitude_LPS = reader->GetPixelSpacing();
695 float* iDirectionVector_LPS = reader->GetImageOrientationPatient();
696 float* jDirectionVector_LPS = reader->GetImageOrientationPatient() + 3;
697 float kDirectionVector_LPS[3] = {0};
698 vtkMath::Cross(iDirectionVector_LPS, jDirectionVector_LPS, kDirectionVector_LPS);
700 vtkSmartPointer<vtkMatrix4x4> examIjkToRpiTransform = vtkSmartPointer<vtkMatrix4x4>::New();
701 examIjkToRpiTransform->SetElement(0, 0, -1);
702 examIjkToRpiTransform->SetElement(2, 2, -1);
703 int xMin, xMax, yMin, yMax, zMin, zMax;
704 reader->GetDataExtent(xMin, xMax, yMin, yMax, zMin, zMax);
706 double newOrigin_ExamRpi[3];
707 newOrigin_ExamRpi[0] = (xMax - xMin + 1) * ijkVectorMagnitude_LPS[0];
708 newOrigin_ExamRpi[1] = 0;
709 newOrigin_ExamRpi[2] = (zMax - zMin + 1) * ijkVectorMagnitude_LPS[2];
710 examIjkToRpiTransform->SetElement(0, 3, newOrigin_ExamRpi[0]);
711 examIjkToRpiTransform->SetElement(1, 3, newOrigin_ExamRpi[1]);
712 examIjkToRpiTransform->SetElement(2, 3, newOrigin_ExamRpi[2]);
714 vtkSmartPointer<vtkMatrix4x4> examIjkToRasTransform = vtkSmartPointer<vtkMatrix4x4>::New();
715 for (
int i = 0;
i < 3;
i++)
718 if (
i == 0 ||
i == 1)
720 examIjkToRasTransform->SetElement(
i, 0, -iDirectionVector_LPS[
i]);
721 examIjkToRasTransform->SetElement(
i, 1, -jDirectionVector_LPS[
i]);
722 examIjkToRasTransform->SetElement(
i, 2, -kDirectionVector_LPS[
i]);
726 examIjkToRasTransform->SetElement(
i, 0, iDirectionVector_LPS[
i]);
727 examIjkToRasTransform->SetElement(
i, 1, jDirectionVector_LPS[
i]);
728 examIjkToRasTransform->SetElement(
i, 2, kDirectionVector_LPS[
i]);
732 examIjkToRasTransform->SetElement(0, 3, -ijkOrigin_LPS[0]);
733 examIjkToRasTransform->SetElement(1, 3, -ijkOrigin_LPS[1]);
734 examIjkToRasTransform->SetElement(2, 3, ijkOrigin_LPS[2]);
737 this->
InternalShared->SetExamIjkToRpiTransformMatrix(examIjkToRpiTransform);
738 this->
InternalShared->SetExamIjkToRasTransformMatrix(examIjkToRasTransform);
741 if (imageReferencFrameName.compare(
"Ras") == 0)
743 for (
int i = 0;
i < 4;
i++)
745 for (
int j = 0; j < 4; j++)
747 ijkToReferenceTransform->SetElement(
i, j, examIjkToRasTransform->GetElement(
i, j));
753 MNavStealthLink::Exam exam;
755 vtkIGSIOAccurateTimer::Delay(1);
756 const igsioTransformName rasToTrackerTransformName(
"Ras",
"Tracker");
758 MNavStealthLink::NavData navData;
764 vtkSmartPointer<vtkMatrix4x4> frameToTrackerTransform = vtkSmartPointer<vtkMatrix4x4>::New();
766 this->
Internal->GetFrameInformation(navData, frameOutOfView, frameToTrackerTransform);
768 vtkSmartPointer<vtkMatrix4x4> rasToTrackerTransform = vtkSmartPointer<vtkMatrix4x4>::New();
769 if (frameOutOfView ==
true)
771 LOG_WARNING(
"The frame is out of view. If you requested the image in Stylus, Frame or Tracker coordinate system, this will give wrong results. Please make sure that the frame is visible");
775 this->
Internal->GetRasToTrackerTransform(frameToTrackerTransform, rasToTrackerTransform);
777 this->
Internal->TransformRepository->SetTransform(rasToTrackerTransformName, rasToTrackerTransform);
778 vtkSmartPointer<vtkMatrix4x4> rasToReferenceTransform = vtkSmartPointer<vtkMatrix4x4>::New();
779 const igsioTransformName rasToReferenceTransformName(
"Ras", imageReferencFrameName.c_str());
780 this->
Internal->TransformRepository->GetTransform(rasToReferenceTransformName, rasToReferenceTransform);
781 vtkMatrix4x4::Multiply4x4(rasToReferenceTransform, examIjkToRasTransform, ijkToReferenceTransform);
785 if (!this->
Internal->KeepReceivedDicomFiles)
798 LOG_ERROR(
"InternalStartRecording failed: StealthLinkServer has not been initialized");
814 XML_READ_CSTRING_ATTRIBUTE_REQUIRED(ServerAddress, deviceConfig);
815 XML_READ_CSTRING_ATTRIBUTE_REQUIRED(ServerPort, deviceConfig);
818 XML_FIND_NESTED_ELEMENT_REQUIRED(dataSourcesElement, deviceConfig,
"DataSources");
819 for (
int nestedElementIndex = 0; nestedElementIndex < dataSourcesElement->GetNumberOfNestedElements(); nestedElementIndex++)
821 vtkXMLDataElement* toolDataElement = dataSourcesElement->GetNestedElement(nestedElementIndex);
822 if (STRCASECMP(toolDataElement->GetName(),
"DataSource") != 0)
827 if (toolDataElement->GetAttribute(
"Type") != NULL && STRCASECMP(toolDataElement->GetAttribute(
"Type"),
"Tool") != 0)
833 const char* portName = toolDataElement->GetAttribute(
"PortName");
838 const char* alwaysTrackTool = toolDataElement->GetAttribute(
"AlwaysTrack");
852 LOG_WARNING(
"The device id " << this->
GetDeviceId() <<
" might be too long, as it may be used for generating identifiers for images that will be sent through OpenIGTLink. Consider choosing a shorter device Id. Example: SLD1");
868 LOG_TRACE(
"vtkPlusStealthLinkTracker::InternalConnect");
871 LOG_DEBUG(
"Already connected to StealthLink");
875 if (this->
Internal->ServerAddress.empty() || this->
Internal->ServerPort.empty())
877 LOG_ERROR(
"Cannot connect: Server Address or Server Port are not assigned\n");
880 LOG_TRACE(
"Server Address: " << this->
Internal->ServerAddress <<
" " <<
"Server Port: " << this->Internal->ServerPort <<
"\n");
882 if (!this->
InternalShared->ConnectToStealthStation(this->Internal->ServerAddress, this->Internal->ServerPort))
903 LOG_ERROR(
"Localizer(Tracker) is not connected. Please check the StealthLink Server\n")
908 double serverTimeInMicroSeconds = 0;
909 if (!this->
InternalShared->GetStealthStationServerTime(serverTimeInMicroSeconds))
918 this->
Internal->KeepReceivedDicomFiles =
false;
919 this->
Internal->ImageMetaDatasetsCount = 1;
937 LOG_ERROR(
"InternalUpdate failed: StealthLinkServer has not been initialized");
941 double serverTimeInMicroSec;
942 if (!this->
InternalShared->GetStealthStationServerTime(serverTimeInMicroSec))
946 double timeSystemSec = 0.0;
948 double unfilteredTime = vtkIGSIOAccurateTimer::GetSystemTime();
950 MNavStealthLink::NavData navData;
956 vtkSmartPointer<vtkMatrix4x4> frameToTrackerTransform = vtkSmartPointer<vtkMatrix4x4>::New();
957 bool frameOutOfView =
true;
958 vtkPlusStealthLinkTracker::vtkInternal::GetFrameInformation(navData, frameOutOfView, frameToTrackerTransform);
963 if (toolIterator->second->GetPortName() == navData.frameName)
965 if (frameOutOfView ==
false)
969 else if (frameOutOfView ==
true)
975 else if (toolIterator->second->GetPortName() == vtkInternalShared::GetRasRegistrationToolName())
979 if (frameOutOfView ==
false && examValid ==
true)
981 vtkSmartPointer<vtkMatrix4x4> rasToTrackerTransform = vtkSmartPointer<vtkMatrix4x4>::New();
982 this->
Internal->GetRasToTrackerTransform(frameToTrackerTransform, rasToTrackerTransform);
987 vtkSmartPointer<vtkMatrix4x4> rasToTrackerTransform = vtkSmartPointer<vtkMatrix4x4>::New();
993 else if (toolIterator->second->GetPortName() == navData.instrumentName)
995 vtkSmartPointer<vtkMatrix4x4> instrumentToTrackerTransform = vtkSmartPointer<vtkMatrix4x4>::New();
996 ToolStatus instrumentStatus = TOOL_OUT_OF_VIEW;
997 vtkPlusStealthLinkTracker::vtkInternal::GetInstrumentInformation(navData, instrumentStatus, instrumentToTrackerTransform);
1006 if (STRCASECMP(toolIterator->second->GetCustomProperty(
"AlwaysTrack").c_str(),
"TRUE") == 0)
1008 MNavStealthLink::Instrument instrument;
1014 vtkSmartPointer<vtkMatrix4x4> instrumentToTrackerTransform = vtkSmartPointer<vtkMatrix4x4>::New();
1015 ToolStatus instrumentStatus = TOOL_OUT_OF_VIEW;
1016 vtkPlusStealthLinkTracker::vtkInternal::GetInstrumentInformation(instrument, instrumentStatus, instrumentToTrackerTransform);
1022 vtkSmartPointer<vtkMatrix4x4> transformMatrixForNotTrackedTool = vtkSmartPointer<vtkMatrix4x4>::New();
1036 std::vector<int> spacePlaces;
1037 for (
unsigned int i = 0;
i < str.size();
i++)\
1039 int asciiCode = (
int) str[
i];
1042 spacePlaces.push_back(
i);
1044 else if (str[
i] ==
'\\' || str[
i] ==
'/')
1048 else if (asciiCode < 48 || (asciiCode > 57 && asciiCode < 65) || (asciiCode > 90 && asciiCode < 97) || asciiCode > 122)
1051 spacePlaces.push_back(
i);
1054 std::string subStrPatientName;
1056 for (std::vector<int>::iterator it = spacePlaces.begin(); it != spacePlaces.end(); it++)
1058 subStrPatientName = str.substr(*it + 1 - placement);
1059 str = str.substr(0, *it - placement);
1060 str = str + subStrPatientName;
1067 return this->
Internal->DicomImagesOutputDirectory;
1071 this->
Internal->DicomImagesOutputDirectory = dicomImagesOutputDirectory;
1076 this->
Internal->KeepReceivedDicomFiles = keepReceivedDicomFiles;
1082 vtkDirectory::MakeDirectory(dicomImagesOutputDirectory.c_str());
1084 MNavStealthLink::Exam exam;
1086 if (exam.patientName.empty())
1090 std::string description = exam.description;
1092 std::string patientName = exam.patientName;
1094 examImageDirectory = std::string(dicomImagesOutputDirectory) + std::string(
"/") + patientName + std::string(
"_") + description + std::string(
"_") + vtkIGSIOAccurateTimer::GetInstance()->GetDateAndTimeString();
1095 if (!this->
InternalShared->GetExamData(exam, examImageDirectory))
1104 std::vector<std::string> validToolPortNames;
1105 if (!this->
InternalShared->GetValidToolPortNames(validToolPortNames))
1113 for (
unsigned int i = 0;
i < validToolPortNames.size();
i++)
1115 if (validToolPortNames[
i].compare(toolIterator->second->GetPortName()) == 0)
1123 LOG_ERROR(toolIterator->second->GetPortName() <<
" instrument is not available in the connected StealthStation. Please make sure that the port name matches the instrument name in StealthStation or remove the corresponding DataSource element from DataSources and OutputChannel elements in the Plus device set configuration file\n");
1125 std::string strValidToolPortNames(
"Valid tool port names are:\n");
1126 for (
unsigned int i = 0;
i < validToolPortNames.size();
i++)
1128 strValidToolPortNames += validToolPortNames[
i] + std::string(
"\n");
1130 LOG_INFO(strValidToolPortNames);
1141 vtkSmartPointer<vtkDirectory> dicomDirectory = vtkSmartPointer<vtkDirectory>::New();
1142 if (!dicomDirectory->Open(examImageDirectory.c_str()))
1144 LOG_ERROR(
"Cannot open the folder: " << examImageDirectory);
1149 vtkDirectory::DeleteDirectory(examImageDirectory.c_str());
1152 if (!dicomDirectory->Open(this->GetDicomImagesOutputDirectory().c_str()))
1157 if (dicomDirectory->GetNumberOfFiles() == 2)
1159 std::string file0(
".");
1160 std::string file1(
"..");
1161 if ((file0.compare(dicomDirectory->GetFile(0)) == 0 && file1.compare(dicomDirectory->GetFile(1)) == 0) ||
1162 (file0.compare(dicomDirectory->GetFile(1)) == 0 && file1.compare(dicomDirectory->GetFile(0)) == 0))
1175 message << std::setw(3) << std::setfill(
'0') << this->
Internal->ImageMetaDatasetsCount << std::ends;
1176 this->
Internal->ImageMetaDatasetsCount++;
1177 return message.str();
1183 this->
Internal->ServerAddress = serverAddress ? serverAddress :
"";
1189 this->
Internal->ServerPort = serverPort ? serverPort :
"";
DataSourceContainer::const_iterator DataSourceContainerConstIterator
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
void SetDicomImagesOutputDirectory(std::string dicomImagesOutputDirectory)
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
virtual PlusStatus ToolTimeStampedUpdateWithoutFiltering(const std::string &aToolSourceId, vtkMatrix4x4 *matrix, ToolStatus status, double unfilteredtimestamp, double filteredtimestamp, const igsioFieldMapType *customFields=NULL)
vtkInternalShared * InternalShared
vtkStandardNewMacro(vtkPlusStealthLinkTracker)
PlusStatus DeleteDicomImageOutputDirectory(std::string examImageDirectory)
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *rootConfigElement)
PlusStatus AcquireDicomImage(std::string dicomImagesOutputDirectory, std::string &examImageDirectory)
virtual std::string GetDeviceId() const
void SetServerPort(const char *serverPort)
bool RequirePortNameInDeviceSetConfiguration
~vtkPlusStealthLinkTracker()
virtual std::string GetSdkVersion()
static vtkPlusConfig * GetInstance()
void PrintSelf(ostream &os, vtkIndent indent)
PlusStatus InternalUpdate()
void SetCustomProperty(const std::string &propertyName, const std::string &propertyValue)
virtual PlusStatus InternalStopRecording()
virtual PlusStatus InternalStartRecording()
PlusStatus GetToolByPortName(const char *aPortName, vtkPlusDataSource *&aSource)
std::string GetOutputDirectory()
PlusStatus AreInstrumentPortNamesValid(bool &valid)
PlusStatus UpdateTransformRepository(vtkIGSIOTransformRepository *sharedTransformRepository)
static void RemoveForbiddenCharacters(std::string &str)
PlusStatus IsLocalizerConnected(bool &)
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement)
void SetServerAddress(const char *serverAddress)
virtual PlusStatus GetImageMetaData(igsioCommon::ImageMetaDataList &imageMetaData)
vtkPlusStealthLinkTracker()
virtual PlusStatus InternalDisconnect()
std::string GetImageMetaDatasetsCountAsString()
vtkInternalUpdatePrivate * InternalUpdatePrivate
bool StartThreadForInternalUpdates
DataSourceContainerConstIterator GetToolIteratorBegin() const
static const int MAX_DEVICE_ID_LENGTH
bool ImageTransferRequiresPatientRegistration
virtual PlusStatus InternalConnect()
DataSourceContainerConstIterator GetToolIteratorEnd() const
void SetKeepReceivedDicomFiles(bool keepReceivedDicomFiles)
virtual PlusStatus GetImage(const std::string &requestedImageId, std::string &assignedImageId, const std::string &imageReferenceFrameName, vtkImageData *imageData, vtkMatrix4x4 *ijkToReferenceTransform)
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *config)
std::string GetDicomImagesOutputDirectory()
Interface to a 3D positioning tool, video source, or generalized data stream.