From 82bf58777744b005f1478e6d3fd05fb05548d143 Mon Sep 17 00:00:00 2001 From: rblanc Date: Tue, 26 Feb 2013 10:40:52 +0100 Subject: [PATCH] updated experimental fusion sequence visualization mode to enable temporal linking --- vv/qt_ui/vvOverlayPanel.ui | 25 ++++++----- vv/vvMainWindow.cxx | 85 +++++++++++++++++++++----------------- vv/vvMainWindow.h | 2 +- vv/vvOverlayPanel.cxx | 2 +- vv/vvOverlayPanel.h | 2 +- vv/vvSlicerManager.h | 6 +-- 6 files changed, 68 insertions(+), 54 deletions(-) diff --git a/vv/qt_ui/vvOverlayPanel.ui b/vv/qt_ui/vvOverlayPanel.ui index 0e5a01f..05986d8 100644 --- a/vv/qt_ui/vvOverlayPanel.ui +++ b/vv/qt_ui/vvOverlayPanel.ui @@ -6,8 +6,8 @@ 0 0 - 444 - 612 + 446 + 679 @@ -65,9 +65,9 @@ p, li { white-space: pre-wrap; } - 220 + 230 60 - 80 + 91 17 @@ -78,9 +78,9 @@ p, li { white-space: pre-wrap; } - 220 + 270 10 - 61 + 81 17 @@ -115,7 +115,7 @@ p, li { white-space: pre-wrap; } 30 0 - 171 + 231 32 @@ -141,7 +141,7 @@ p, li { white-space: pre-wrap; } 130 36 - 151 + 201 20 @@ -149,17 +149,20 @@ p, li { white-space: pre-wrap; } Qt::Horizontal - + 20 60 - 131 + 171 23 + + <html><head/><body><p>Load a file indicating the correspondances between time indices between both sequences.</p><p>The format needs to be the following:</p><p>let nt1 the number of frames in sequence 1, resp. nt2 and seq. 2 </p><p>The file must contain nt1 + nt2 entries.</p><p>entry i (i&lt;=nt1) indicates for the i-th frame of sequence 1 the index to display for sequence 2.</p><p>resp. i&gt;nt1 indicate corresp from seq. 2 to seq. 1</p></body></html> + - Load Fused Seq. Signal + Load Correspondances diff --git a/vv/vvMainWindow.cxx b/vv/vvMainWindow.cxx index a7dee1f..a06870f 100644 --- a/vv/vvMainWindow.cxx +++ b/vv/vvMainWindow.cxx @@ -88,6 +88,7 @@ It is distributed under dual licence // Standard includes #include +#include #include #include @@ -294,7 +295,7 @@ vvMainWindow::vvMainWindow():vvMainWindowBase() connect(actionDocumentation,SIGNAL(triggered()),this,SLOT(ShowDocumentation())); connect(actionRegister_vv,SIGNAL(triggered()),this,SLOT(PopupRegisterForm())); - connect(overlayPanel, SIGNAL(FusionSequenceSignalButtonPressed()), this, SLOT(SelectFusionSequenceTemporalSignal())); + connect(overlayPanel, SIGNAL(FusionSequenceCorrespondancesButtonPressed()), this, SLOT(SelectFusionSequenceCorrespondances())); /////////////////////////////////////////////// @@ -1651,6 +1652,7 @@ void vvMainWindow::CloseImage(QTreeWidgetItem* item, int column) } //TODO: also remove the image overlaid with the main sequence, as it is becoming invalid... + //this shall be done by calling this->CloseImage() with the correct index;... } linkPanel->removeImage(index); @@ -2443,7 +2445,7 @@ void vvMainWindow::SelectFusionSequence() //------------------------------------------------------------------------------ -void vvMainWindow::SelectFusionSequenceTemporalSignal() { +void vvMainWindow::SelectFusionSequenceCorrespondances() { //make sure the index is right? //in the end, I should attach the temporal data to the right sequence! @@ -2454,35 +2456,51 @@ void vvMainWindow::SelectFusionSequenceTemporalSignal() { } //open a dialog box to find a file - QString Extensions = EXTENSIONS; - Extensions += ";;All Files (*)"; + //QString Extensions = EXTENSIONS; + QString Extensions = ";;All Files (*)"; QString fileName = QFileDialog::getOpenFileName(this,tr("Load respiratory signal for fused sequence"),mInputPathName,Extensions); if (fileName.isNull()) return; //read it as a vector of values - std::vector signal; - //...TODO, look for itk functions that can do that... vnl in the worst case. - signal.push_back(1);signal.push_back(2); - - //TODO: instead: if the loaded signal is longer, just crop it... - //this allows loading only the first few frames when testing. - //->maybe raise a message that this behavior may be unsafe... - - //if compatible with the fused image sequence (number of images = number of entries), enable the temporalSync - if ( signal.size() >= mSlicerManagers[index]->GetFusionSequenceNbFrames()) { - //for convenience, associate this sequence to both the current slicer manager, and to the linked one - mSlicerManagers[index]->SetFusionSequenceTemporalSignal(signal); - mSlicerManagers[ mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager() ]->SetFusionSequenceTemporalSignal(signal); - overlayPanel->enableFusionSequenceTemporalSync(); - QMessageBox::information(this,tr("Adding signal"),"would add the signal from file: "+ fileName); + vnl_vector tmpVect; + + std::ifstream file; + file.open(fileName.toStdString().c_str()); + tmpVect.read_ascii(file); + file.close(); + + //if compatible with the fused image sequence (number of entries = nb of entries in main sequence + nb of entries in joint sequence), enable the temporalSync + bool signalOK = true; + unsigned nbFrameMain = mSlicerManagers[index]->GetImage()->GetTransform().size(); + unsigned nbFrameSecondary = mSlicerManagers[index]->GetFusionSequenceNbFrames(); + + std::vector temporalCorrespondances; + if ( tmpVect.size() == nbFrameMain + nbFrameSecondary ) { + for (unsigned i=0 ; i index in secondary seq. + if ( tmpVect(i) index in secondary seq. + if ( tmpVect(i)SetFusionSequenceCorrespondances(temporalCorrespondances); + mSlicerManagers[ mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager() ]->SetFusionSequenceCorrespondances(temporalCorrespondances); + overlayPanel->enableFusionSequenceTemporalSync(); + } } //------------------------------------------------------------------------------ @@ -2651,21 +2669,13 @@ void vvMainWindow::SetFusionSequenceProperty(int fusionSequenceFrameIndex, bool if (spatialSyncFlag) { //reslice the CT if (temporalSyncFlag) { //do the temporal synchronisation - //TODO: add the temporal synchronisation stuff - //if the button is checked, get the phase of the requested US frame from the available signal - //and select the corresponding one in the CT. (check the one just before, and the one just after, and select the closest) - - //TODO: do it also the other way around, when modifying the time index related to CT, select a close frame - //this should not be done here directly, but the code should be inspired from the one here - //->find a good US frame such that when calling this function with this US frame, it produces the expected result - - - //TODO: select the right CT image to display int mainSequenceFrameIndex=0; //estimate the TSlice to set to the CT - + unsigned nbFramesMain = mSlicerManagers[index]->GetImage()->GetTransform().size(); + mainSequenceFrameIndex = mSlicerManagers[index]->GetFusionSequenceCorrespondances()[ nbFramesMain + fusionSequenceFrameIndex]; //and set it! mSlicerManagers[index]->SetTSlice(mainSequenceFrameIndex, false); + //warning, there is a loopback, and modification of the TSlice in main sequence forces an update of the TSlice in secondary, etc... } @@ -2921,12 +2931,13 @@ void vvMainWindow::HorizontalSliderMoved(int value,int column, int slicer_index) if (mSlicerManagers[i]->GetFusionSequenceTemporalSyncFlag()) { //WARNING: for some obscure reason, there are problems when accessing mSlicerManagers[mSlicerManagers[i]->GetFusionSequenceIndexOfLinkedManager()]->GetFusionSequenceFrameIndex(); - //int estimatedValue=mSlicerManagers[mSlicerManagers[i]->GetFusionSequenceIndexOfLinkedManager()]->GetFusionSequenceFrameIndex(); int estimatedValue=0; - //TODO: if temporal sync is active //estimate a corresponding time index for the secondary (US) sequence, and update it accordingly. - //estimatedValue = ... - overlayPanel->updateFusionSequenceSliderValueFromWindow(estimatedValue, true); + estimatedValue = mSlicerManagers[i]->GetFusionSequenceCorrespondances()[ value ]; + //TODO: at the moment, there is a loop in TSlice modifications + //modifying sequence 1 causes seq 2 to update, which in turns update seq1... + //I disable control on seq1 at the moment. + //overlayPanel->updateFusionSequenceSliderValueFromWindow(estimatedValue, true); } } } diff --git a/vv/vvMainWindow.h b/vv/vvMainWindow.h index 15ec687..dd95c0a 100644 --- a/vv/vvMainWindow.h +++ b/vv/vvMainWindow.h @@ -161,7 +161,7 @@ public slots: void SelectFusionImage(); //select the file(s) from the disk containing the image sequence to fuse void SelectFusionSequence(); - void SelectFusionSequenceTemporalSignal(); + void SelectFusionSequenceCorrespondances(); void ResetTransformationToIdentity(); diff --git a/vv/vvOverlayPanel.cxx b/vv/vvOverlayPanel.cxx index 649f1fd..b394bb5 100644 --- a/vv/vvOverlayPanel.cxx +++ b/vv/vvOverlayPanel.cxx @@ -65,7 +65,7 @@ vvOverlayPanel::vvOverlayPanel(QWidget * parent):QWidget(parent) connect(fCTUSSlider,SIGNAL(valueChanged(int)),this,SLOT(setFusionSequenceProperty())); connect(fCTUSActivateSpaceSyncCheckBox,SIGNAL(stateChanged(int)),this,SLOT(setFusionSequenceProperty())); connect(fCTUSActivateTimeSyncCheckBox,SIGNAL(stateChanged(int)),this,SLOT(setFusionSequenceProperty())); - connect(fCTUSLoadSignalPushButton,SIGNAL(clicked()),this,SIGNAL(FusionSequenceSignalButtonPressed())); + connect(fCTUSLoadCorrespondancesPushButton,SIGNAL(clicked()),this,SIGNAL(FusionSequenceCorrespondancesButtonPressed())); } void vvOverlayPanel::getCurrentImageName(QString name) diff --git a/vv/vvOverlayPanel.h b/vv/vvOverlayPanel.h index b0e69db..5329bf8 100644 --- a/vv/vvOverlayPanel.h +++ b/vv/vvOverlayPanel.h @@ -68,7 +68,7 @@ signals: void OverlayPropertyUpdated(int color, int linked, double window, double level); void FusionPropertyUpdated(int opacity, int thresOpacity, int colormap, double window, double level, bool showLegend); void FusionSequencePropertyUpdated(int sequenceFrameIndex, bool spatialSync, unsigned int sequenceLength, bool temporalSync); - void FusionSequenceSignalButtonPressed(); + void FusionSequenceCorrespondancesButtonPressed(); private: bool disableFusionSignals; diff --git a/vv/vvSlicerManager.h b/vv/vvSlicerManager.h index 3479dc6..60f2392 100644 --- a/vv/vvSlicerManager.h +++ b/vv/vvSlicerManager.h @@ -177,7 +177,7 @@ class vvSlicerManager : public QObject { mFusionSequenceListInitialTransformMatrices.push_back( tmpMat ); } void SetFusionSequenceIndexOfLinkedManager(int index) { mFusionSequenceIndexLinkedManager = index; } - void SetFusionSequenceTemporalSignal(std::vector s) { mFusionSequenceTemporalSignal = s; } + void SetFusionSequenceCorrespondances(std::vector s) { mFusionSequenceCorrespondances = s; } void SetFusionSequenceInvolvmentCode(int code) { mFusionSequenceInvolvementCode=code; } int GetFusionSequenceInvolvmentCode() { return mFusionSequenceInvolvementCode;} @@ -195,7 +195,7 @@ class vvSlicerManager : public QObject { const vtkSmartPointer& GetFusionSequenceInitialTransformMatrixAtFrame(unsigned i) { return mFusionSequenceListInitialTransformMatrices[i]; } - const std::vector& GetFusionSequenceTemporalSignal() {return mFusionSequenceTemporalSignal;} + const std::vector& GetFusionSequenceCorrespondances() {return mFusionSequenceCorrespondances;} double GetColorWindow() const; double GetColorLevel() const; @@ -332,7 +332,7 @@ protected: bool mFusionSequenceSpatialSyncFlag, mFusionSequenceTemporalSyncFlag; //flags indicating whether the spatial/temporal synchronization are actives vtkSmartPointer mFusionSequenceMainTransform; std::vector< vtkSmartPointer > mFusionSequenceListInitialTransformMatrices; - std::vector mFusionSequenceTemporalSignal; + std::vector mFusionSequenceCorrespondances; int mPreset; SlicingPresetType mSlicingPreset; -- 2.45.1