void ManualImage2ImageRegistrationWidget::updateAverageAccuracyLabel() { QString fixedName; QString movingName; DataPtr fixedData = boost::dynamic_pointer_cast<Data>(mServices->registration()->getFixedData()); DataPtr movingData = boost::dynamic_pointer_cast<Data>(mServices->registration()->getMovingData()); if (fixedData) fixedName = fixedData->getName(); if (movingData) movingName = movingData->getName(); int numberOfActiveLandmarks = 0; if(this->isAverageAccuracyValid(numberOfActiveLandmarks)) { mAvarageAccuracyLabel->setText(tr("Root mean square accuracy (Landmarks) %1 mm, calculated in %2 landmarks"). arg(this->getAverageAccuracy(numberOfActiveLandmarks), 0, 'f', 2).arg(numberOfActiveLandmarks)); mAvarageAccuracyLabel->setToolTip(QString("Root Mean Square landmark accuracy from target [%1] to fixed [%2]."). arg(movingName).arg(fixedName)); } else { mAvarageAccuracyLabel->setText(" "); mAvarageAccuracyLabel->setToolTip(""); } }
void RegistrationImplService::doPatientRegistration() { DataPtr fixedImage = this->getFixedData(); if(!fixedImage) { reportError("The fixed data is not set, cannot do patient registration!"); return; } LandmarkMap fixedLandmarks = fixedImage->getLandmarks()->getLandmarks(); LandmarkMap toolLandmarks = mPatientModelService->getPatientLandmarks()->getLandmarks(); this->writePreLandmarkRegistration(fixedImage->getName(), fixedImage->getLandmarks()->getLandmarks()); this->writePreLandmarkRegistration("physical", toolLandmarks); std::vector<QString> landmarks = this->getUsableLandmarks(fixedLandmarks, toolLandmarks); vtkPointsPtr p_ref = this->convertTovtkPoints(landmarks, fixedLandmarks, fixedImage->get_rMd()); vtkPointsPtr p_pr = this->convertTovtkPoints(landmarks, toolLandmarks, Transform3D::Identity()); // ignore if too few data. if (p_ref->GetNumberOfPoints() < 3) return; bool ok = false; Transform3D rMpr = this->performLandmarkRegistration(p_pr, p_ref, &ok); if (!ok) { reportError("P-I Landmark registration: Failed to register: [" + qstring_cast(p_pr->GetNumberOfPoints()) + "p]"); return; } this->applyPatientRegistration(rMpr, "Patient Landmark"); }
QString ImageLandmarksWidget::getTargetName() const { DataPtr image = this->getCurrentData(); if (!image) return "None"; return image->getName(); }
void ImageLandmarksWidget::enableButtons() { bool selected = !mLandmarkTableWidget->selectedItems().isEmpty(); bool loaded = this->getCurrentData() != 0; mEditLandmarkButton->setEnabled(selected); mRemoveLandmarkButton->setEnabled(selected); mDeleteLandmarksButton->setEnabled(loaded); mAddLandmarkButton->setEnabled(loaded); mImportLandmarksFromPointMetricsButton->setEnabled(loaded); DataPtr image = this->getCurrentData(); if (image) { mAddLandmarkButton->setToolTip(QString("Add landmark to image %1").arg(image->getName())); mEditLandmarkButton->setToolTip(QString("Resample landmark in image %1").arg(image->getName())); } }
/** Apply the transform from the parent frame to the imported data. * */ void ImportDataDialog::importParentTransform() { if (!mTransformFromParentFrameCheckBox->isChecked()) return; if(!mData) return; DataPtr parent = mPatientModelService->getData(mData->getParentSpace()); if (!parent) return; mData->get_rMd_History()->setRegistration(parent->get_rMd()); report("Assigned rMd from data [" + parent->getName() + "] to data [" + mData->getName() + "]"); }
void FrameTreeWidget::fill(QTreeWidgetItem* parent, QDomNode node) { for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) { QString frameName = child.toElement().tagName(); // if frame refers to a data, use its name instead. DataPtr data = mPatientService->getData(frameName); if (data) frameName = data->getName(); QTreeWidgetItem* item = new QTreeWidgetItem(parent, QStringList() << frameName); this->fill(item, child); } }
/**\brief Identical to doFastRegistration_Orientation(), except data does not move. * * When applying a new transform to the patient orientation, all data is moved * the the inverse of that value, thus giving a net zero change along the path * pr...d_i. * */ void RegistrationImplService::applyPatientOrientation(const Transform3D& tMtm, const Transform3D& prMt) { Transform3D rMpr = mPatientModelService->get_rMpr(); //create a marked(m) space tm, which is related to tool space (t) as follows: //the tool is defined in DICOM space such that //the tool points toward the patients feet and the spheres faces the same //direction as the nose Transform3D tMpr = prMt.inv(); // this is the new patient registration: Transform3D tmMpr = tMtm * tMpr; // the change in pat reg becomes: Transform3D F = tmMpr * rMpr.inv(); QString description("Patient Orientation"); QDateTime oldTime = this->getLastRegistrationTime(); // time of previous reg this->applyPatientRegistration(tmMpr, description); // now apply the inverse of F to all data, // thus ensuring the total path from pr to d_i is unchanged: Transform3D delta_pre_rMd = F; // use the same registration time as generated in the applyPatientRegistration() above: RegistrationTransform regTrans(delta_pre_rMd, this->getLastRegistrationTime(), description); std::map<QString,DataPtr> data = mPatientModelService->getData(); // update the transform on all target data: for (std::map<QString,DataPtr>::iterator iter = data.begin(); iter!=data.end(); ++iter) { DataPtr current = iter->second; RegistrationTransform newTransform = regTrans; newTransform.mValue = regTrans.mValue * current->get_rMd(); current->get_rMd_History()->updateRegistration(oldTime, newTransform); report("Updated registration of data " + current->getName()); std::cout << "rMd_new\n" << newTransform.mValue << std::endl; } this->setLastRegistrationTime(regTrans.mTimestamp); reportSuccess("Patient Orientation has been performed"); }
void LandmarkRegistrationWidget::updateAverageAccuracyLabel() { QString fixedName; DataPtr fixedData = boost::dynamic_pointer_cast<Data>(mServices->registration()->getFixedData()); if (fixedData) fixedName = fixedData->getName(); if(this->isAverageAccuracyValid()) { mAvarageAccuracyLabel->setText(tr("Mean accuracy %1 mm").arg(this->getAverageAccuracy(), 0, 'f', 2)); mAvarageAccuracyLabel->setToolTip(QString("Average landmark accuracy from target [%1] to fixed [%2].").arg(this->getTargetName()).arg(fixedName)); } else { mAvarageAccuracyLabel->setText(" "); mAvarageAccuracyLabel->setToolTip(""); } }
void DataManagerImpl::loadData(DataPtr data) { if (data->getUid().contains('%')) { QString uid = data->getUid(); QString name = data->getName(); this->generateUidAndName(&uid, &name); data->setName(name); data->setUid(uid); } if (data) { if (mData.count(data->getUid()) && mData[data->getUid()]!=data) reportError(QString("Overwriting Data with uid=%1 with new object into PasM").arg(data->getUid())); // this->verifyParentFrame(data); mData[data->getUid()] = data; emit dataAddedOrRemoved(); } }
void ClipperWidget::createNewCheckboxesBasedOnData() { std::map<QString, DataPtr> datas = this->getDatas(); std::map<QString, DataPtr>::iterator iter = datas.begin(); int row = 0; for(; iter != datas.end(); ++iter) { DataPtr data = iter->second; QCheckBox *checkbox = new QCheckBox(); checkbox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); mDataTableWidget->setCellWidget(row, 0, checkbox); QTableWidgetItem *descriptionItem = new QTableWidgetItem(data->getName()); mDataTableWidget->setItem(row++, 1, descriptionItem); boost::function<void()> func = boost::bind(&ClipperWidget::dataSelectorClicked, this, checkbox, data); connect(checkbox, &QCheckBox::clicked, this, func); this->updateCheckBoxFromClipper(checkbox, data); } }
void RegistrationImplService::doFastRegistration_Translation() { DataPtr fixedImage = this->getFixedData(); if(!fixedImage) { reportError("The fixed data is not set, cannot do image registration!"); return; } LandmarkMap fixedLandmarks = fixedImage->getLandmarks()->getLandmarks(); LandmarkMap toolLandmarks = mPatientModelService->getPatientLandmarks()->getLandmarks(); this->writePreLandmarkRegistration(fixedImage->getName(), fixedImage->getLandmarks()->getLandmarks()); this->writePreLandmarkRegistration("physical", toolLandmarks); std::vector<QString> landmarks = this->getUsableLandmarks(fixedLandmarks, toolLandmarks); Transform3D rMd = fixedImage->get_rMd(); Transform3D rMpr_old = mPatientModelService->get_rMpr(); std::vector<Vector3D> p_pr_old = this->convertAndTransformToPoints(landmarks, fixedLandmarks, rMpr_old.inv()*rMd); std::vector<Vector3D> p_pr_new = this->convertAndTransformToPoints(landmarks, toolLandmarks, Transform3D::Identity()); // ignore if too few data. if (p_pr_old.size() < 1) return; LandmarkTranslationRegistration landmarkTransReg; bool ok = false; Transform3D pr_oldMpr_new = landmarkTransReg.registerPoints(p_pr_old, p_pr_new, &ok); if (!ok) { reportError("Fast translation registration: Failed to register: [" + qstring_cast(p_pr_old.size()) + "points]"); return; } this->applyPatientRegistration(rMpr_old*pr_oldMpr_new, "Fast Translation"); }
void RegistrationImplService::doImageRegistration(bool translationOnly) { //check that the fixed data is set DataPtr fixedImage = this->getFixedData(); if(!fixedImage) { reportError("The fixed data is not set, cannot do landmark image registration!"); return; } //check that the moving data is set DataPtr movingImage = this->getMovingData(); if(!movingImage) { reportError("The moving data is not set, cannot do landmark image registration!"); return; } // ignore self-registration, this gives no effect bestcase, buggy behaviour worstcase (has been observed) if(movingImage==fixedImage) { reportError("The moving and fixed are equal, ignoring landmark image registration!"); return; } LandmarkMap fixedLandmarks = fixedImage->getLandmarks()->getLandmarks(); LandmarkMap imageLandmarks = movingImage->getLandmarks()->getLandmarks(); this->writePreLandmarkRegistration(fixedImage->getName(), fixedImage->getLandmarks()->getLandmarks()); this->writePreLandmarkRegistration(movingImage->getName(), movingImage->getLandmarks()->getLandmarks()); std::vector<QString> landmarks = getUsableLandmarks(fixedLandmarks, imageLandmarks); vtkPointsPtr p_fixed_r = convertTovtkPoints(landmarks, fixedLandmarks, fixedImage->get_rMd()); vtkPointsPtr p_moving_r = convertTovtkPoints(landmarks, imageLandmarks, movingImage->get_rMd()); int minNumberOfPoints = 3; if (translationOnly) minNumberOfPoints = 1; // ignore if too few data. if (p_fixed_r->GetNumberOfPoints() < minNumberOfPoints) { reportError( QString("Found %1 corresponding landmarks, need %2, cannot do landmark image registration!") .arg(p_fixed_r->GetNumberOfPoints()) .arg(minNumberOfPoints) ); return; } bool ok = false; QString idString; Transform3D delta; if (translationOnly) { LandmarkTranslationRegistration landmarkTransReg; delta = landmarkTransReg.registerPoints(convertVtkPointsToPoints(p_fixed_r), convertVtkPointsToPoints(p_moving_r), &ok); idString = QString("Image to Image Landmark Translation"); } else { Transform3D rMd; delta = this->performLandmarkRegistration(p_moving_r, p_fixed_r, &ok); idString = QString("Image to Image Landmark"); } if (!ok) { reportError("I-I Landmark registration: Failed to register: [" + qstring_cast(p_moving_r->GetNumberOfPoints()) + "p], "+ movingImage->getName()); return; } this->applyImage2ImageRegistration(delta, idString); }
void LandmarkRegistrationWidget::prePaintEvent() { mLandmarkTableWidget->blockSignals(true); mLandmarkTableWidget->clear(); QString fixedName; DataPtr fixedData = boost::dynamic_pointer_cast<Data>(mServices->registration()->getFixedData()); if (fixedData) fixedName = fixedData->getName(); std::vector<Landmark> landmarks = this->getAllLandmarks(); LandmarkMap targetData = this->getTargetLandmarks(); Transform3D rMtarget = this->getTargetTransform(); //ready the table widget mLandmarkTableWidget->setRowCount((int)landmarks.size()); mLandmarkTableWidget->setColumnCount(4); QStringList headerItems(QStringList() << "Name" << "Status" << "Coordinates" << "Accuracy (mm)"); mLandmarkTableWidget->setHorizontalHeaderLabels(headerItems); mLandmarkTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); mLandmarkTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); for (unsigned i = 0; i < landmarks.size(); ++i) { std::vector<QTableWidgetItem*> items(4); // name, status, coordinates, accuracy LandmarkProperty prop = mServices->patient()->getLandmarkProperties()[landmarks[i].getUid()]; Vector3D coord = landmarks[i].getCoord(); coord = rMtarget.coord(coord); // display coordinates in space r (in principle, this means all coords should be equal) items[0] = new QTableWidgetItem(qstring_cast(prop.getName())); items[0]->setToolTip(QString("Landmark name. Double-click to rename.")); items[1] = new QTableWidgetItem; if (prop.getActive()) items[1]->setCheckState(Qt::Checked); else items[1]->setCheckState(Qt::Unchecked); items[1]->setToolTip(QString("Check to use landmark in current registration.")); QString coordText = "Not sampled"; if (targetData.count(prop.getUid())) { int width = 5; int prec = 1; coordText = tr("(%1, %2, %3)").arg(coord[0], width, 'f', prec).arg(coord[1], width, 'f', prec).arg( coord[2], width, 'f', prec); } items[2] = new QTableWidgetItem(coordText); items[2]->setToolTip(QString("Landmark coordinates of target [%1] in reference space.").arg(this->getTargetName())); items[3] = new QTableWidgetItem(tr("%1").arg(this->getAccuracy(landmarks[i].getUid()))); items[3]->setToolTip(QString("Distance from target [%1] to fixed [%2].").arg(this->getTargetName()).arg(fixedName)); for (unsigned j = 0; j < items.size(); ++j) { items[j]->setData(Qt::UserRole, qstring_cast(prop.getUid())); mLandmarkTableWidget->setItem(i, j, items[j]); } //highlight selected row if (prop.getUid() == mActiveLandmark) { mLandmarkTableWidget->setCurrentItem(items[2]); } } this->updateAverageAccuracyLabel(); mLandmarkTableWidget->blockSignals(false); }