]> Creatis software - clitk.git/blobdiff - vv/vvMainWindow.cxx
Remove debug
[clitk.git] / vv / vvMainWindow.cxx
index 56aa5b1bc6d8b587ed72b3877dae53ecb1901286..409919f8019a8bca8105a8beac2ff7fce97fc859 100644 (file)
@@ -88,6 +88,7 @@ It is distributed under dual licence
 
 // Standard includes
 #include <iostream>
+#include <fstream>
 #include <sstream>
 #include <iomanip>
 
@@ -101,7 +102,7 @@ It is distributed under dual licence
 #define COLUMN_IMAGE_NAME 7
 
 #ifdef CLITK_PRIVATE_FEATURES
-#define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.refscan *.nii.gz *.usf)"
+#define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.refscan *.nii.gz *.usf *.svl)"
 #else
 #define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.refscan *.nii.gz)"
 #endif
@@ -181,8 +182,10 @@ vvMainWindow::vvMainWindow():vvMainWindowBase()
   contextMenu.addAction(actionAdd_fusion_image);
   contextActions.push_back(actionAdd_fusion_image);
 
+#ifdef CLITK_EXPERIMENTAL
   contextMenu.addAction(actionAdd_USSequence_toCT);
   contextActions.push_back(actionAdd_USSequence_toCT);
+#endif
 
 
   contextMenu.addSeparator();
@@ -292,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()));
 
 
   ///////////////////////////////////////////////
@@ -334,6 +337,7 @@ vvMainWindow::vvMainWindow():vvMainWindowBase()
   connect(overlayPanel,SIGNAL(FusionPropertyUpdated(int,int,int,double,double, bool)),
     this,SLOT(SetFusionProperty(int,int,int,double,double, bool)));
   connect(landmarksPanel,SIGNAL(UpdateRenderWindows()),this,SLOT(UpdateRenderWindows()));
+  connect(landmarksPanel,SIGNAL(SelectedPointChanged()),this,SLOT(GoToLandmark()));
 
   connect(overlayPanel,SIGNAL(FusionSequencePropertyUpdated(int, bool, unsigned int, bool)),
     this,SLOT(SetFusionSequenceProperty(int, bool,unsigned int, bool)));
@@ -735,7 +739,7 @@ void vvMainWindow::OpenDicom()
 {
   std::vector<std::string> files;
 
-  std::cout << "dicomSeriesSelector " << std::endl;
+  //std::cout << "dicomSeriesSelector " << std::endl;
   if (dicomSeriesSelector->exec() == QDialog::Accepted) {
     files = *(dicomSeriesSelector->GetFilenames());
     LoadImages(files, vvImageReader::DICOM);
@@ -955,7 +959,7 @@ void vvMainWindow::LoadImages(std::vector<std::string> files, vvImageReader::Loa
     double range[2];
     mSlicerManagers.back()->GetImage()->GetFirstVTKImageData()->GetScalarRange(range);
     if ((range[0] == 0) && (range[1] == 1)) {
-      presetComboBox->setCurrentIndex(5);// binary
+      presetComboBox->setCurrentIndex(WL_BINARY);// binary
     } else {
       // TODO
     }
@@ -995,6 +999,12 @@ void vvMainWindow::CurrentImageChanged(std::string id)
   }
   DataTree->topLevelItem(selected)->setSelected(1);
   mCurrentSelectedImageId = id;
+
+  landmarksPanel->SetCurrentLandmarks(mSlicerManagers[selected]->GetLandmarks(),
+                                      mSlicerManagers[selected]->GetTSlice());
+  landmarksPanel->SetCurrentPath(mInputPathName.toStdString());
+  landmarksPanel->SetCurrentImage(mSlicerManagers[selected]->GetFileName().c_str());
+  
   emit SelectedImageHasChanged(mSlicerManagers[selected]);
 }
 //------------------------------------------------------------------------------
@@ -1124,6 +1134,9 @@ void vvMainWindow::ImageInfoChanged()
     dim += pixelType + ")";
 
     infoPanel->setFileName(image);
+    std::string creationImageTimeValue("No creation time");
+    itk::ExposeMetaData< std::string > (*imageSelected->GetFirstMetaDataDictionary(), "creationImageTime", creationImageTimeValue);
+    infoPanel->setImageCreationTime(QString(creationImageTimeValue.c_str()));
     infoPanel->setDimension(dim);
     infoPanel->setSizePixel(GetVectorIntAsString(inputSize));
     infoPanel->setSizeMM(GetVectorDoubleAsString(sizeMM));
@@ -1135,7 +1148,7 @@ void vvMainWindow::ImageInfoChanged()
     infoPanel->setTransformation(Get4x4MatrixDoubleAsString(transformation));
 
     landmarksPanel->SetCurrentLandmarks(mSlicerManagers[index]->GetLandmarks(),
-      mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetVTKImages().size());
+                                        mSlicerManagers[index]->GetTSlice());
     landmarksPanel->SetCurrentPath(mInputPathName.toStdString());
     landmarksPanel->SetCurrentImage(mSlicerManagers[index]->GetFileName().c_str());
 
@@ -1147,26 +1160,26 @@ void vvMainWindow::ImageInfoChanged()
       }
     }
 
-    infoPanel->setFileName(image);
-    infoPanel->setDimension(dim);
-    infoPanel->setSizePixel(GetVectorIntAsString(inputSize));
-    infoPanel->setSizeMM(GetVectorDoubleAsString(sizeMM));
-    infoPanel->setOrigin(GetVectorDoubleAsString(origin));
-    infoPanel->setSpacing(GetVectorDoubleAsString(inputSpacing));
-    infoPanel->setNPixel(QString::number(NPixel)+" ("+inputSizeInBytes+")");
-
-    landmarksPanel->SetCurrentLandmarks(mSlicerManagers[index]->GetLandmarks(),
-      mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetVTKImages().size());
-    landmarksPanel->SetCurrentPath(mInputPathName.toStdString());
-    landmarksPanel->SetCurrentImage(mSlicerManagers[index]->GetFileName().c_str());
-
-    overlayPanel->getCurrentImageName(mSlicerManagers[index]->GetFileName().c_str());
-    for (int i = 0; i < 4; i++) {
-      if (DataTree->selectedItems()[0]->data(i+1,Qt::CheckStateRole).toInt() > 0 || i == 3) {
-        mSlicerManagers[index]->UpdateInfoOnCursorPosition(i);
-        break;
-      }
-    }
+//     infoPanel->setFileName(image);
+//     infoPanel->setDimension(dim);
+//     infoPanel->setSizePixel(GetVectorIntAsString(inputSize));
+//     infoPanel->setSizeMM(GetVectorDoubleAsString(sizeMM));
+//     infoPanel->setOrigin(GetVectorDoubleAsString(origin));
+//     infoPanel->setSpacing(GetVectorDoubleAsString(inputSpacing));
+//     infoPanel->setNPixel(QString::number(NPixel)+" ("+inputSizeInBytes+")");
+// 
+//     landmarksPanel->SetCurrentLandmarks(mSlicerManagers[index]->GetLandmarks(),
+//                                         mSlicerManagers[index]->GetTSlice());
+//     landmarksPanel->SetCurrentPath(mInputPathName.toStdString());
+//     landmarksPanel->SetCurrentImage(mSlicerManagers[index]->GetFileName().c_str());
+// 
+//     overlayPanel->getCurrentImageName(mSlicerManagers[index]->GetFileName().c_str());
+//     for (int i = 0; i < 4; i++) {
+//       if (DataTree->selectedItems()[0]->data(i+1,Qt::CheckStateRole).toInt() > 0 || i == 3) {
+//         mSlicerManagers[index]->UpdateInfoOnCursorPosition(i);
+//         break;
+//       }
+//     }
     WindowLevelChanged();
 
     slicingPresetComboBox->setCurrentIndex(mSlicerManagers[index]->GetSlicingPreset());
@@ -1581,12 +1594,17 @@ void vvMainWindow::CloseImage(QTreeWidgetItem* item, int column)
       }
       if (overlay_type=="fusionSequence") {
         //removing the overlay sequence in a fusion sequence visualization mode 
-        //TODO: remove the synchronization (transform matrices, etc...)
+        //reset the transforms
+        overlayPanel->getFusionSequenceProperty(-1, false, 0, false);
 
-        //=> unlink and untie the slicer managers
+        //unlink and untie the slicer managers
         RemoveLink(mSlicerManagers[index]->GetId().c_str(), mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->GetId().c_str());
         mSlicerManagers[index]->SetFusionSequenceInvolvmentCode(-1);
         mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->SetFusionSequenceInvolvmentCode(-1);
+        for (unsigned i=0 ; i<4 ; i++) {
+            mSlicerManagers[index]->GetSlicer(i)->SetFusionSequenceCode(-1);
+            mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->GetSlicer(i)->SetFusionSequenceCode(-1);
+        }
 
       }
       mSlicerManagers[index]->RemoveActor(overlay_type, overlay_index-1);
@@ -1622,18 +1640,43 @@ void vvMainWindow::CloseImage(QTreeWidgetItem* item, int column)
       for (int i = 0; i < index; i++) {
         Manageriter++;
       }
-      linkPanel->removeImage(index);
-      mSlicerManagers[index]->RemoveActors();
-
       //if the slicer manager was involved in a fusion sequence visualization...
-      if ( item->data(1,Qt::UserRole).toString().toStdString() == "fusionSequence" ) {
-        //TODO
-        //make sure both SlicerManager exit the FusionSequence visualization mode
-        //disable the temporal and spatial sync? make sure we reset the spatial transforms to their initial states...
+      if ( mSlicerManagers[index]->IsInvolvedInFusionSequence() ) {
+        //in both cases, close the overlay: find it... and close it
+        //ideally, I should duplicate the code, and avoid calling CloseImage, since this pops up another interactive box
+        QTreeWidgetItem* overlayItem;
+        if (mSlicerManagers[index]->IsMainSequenceOfFusionSequence()) {
+          for (unsigned i=0 ; i<item->childCount() ; i++) {
+            overlayItem = item->child(i);
+            this->CloseImage( overlayItem, 0 );
+          }
+        }
+        else {
+          QTreeWidgetItem* linkedItem = this->GetItemFromSlicerManager( mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()] );
+          for (unsigned i=0 ; i<linkedItem->childCount() ; i++) {
+            overlayItem = linkedItem->child(i);
+            this->CloseImage( overlayItem, 0 );
+          }
+        }
+
+        /* -- this is normally already done when closing the overlay.
+        //reset the transforms
+        overlayPanel->getFusionSequenceProperty(-1, false, 0, false);
+
+        //unlink and untie the slicer managers
+        RemoveLink(mSlicerManagers[index]->GetId().c_str(), mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->GetId().c_str());
         mSlicerManagers[index]->SetFusionSequenceInvolvmentCode(-1);
         mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->SetFusionSequenceInvolvmentCode(-1);
+        for (unsigned i=0 ; i<4 ; i++) {
+            mSlicerManagers[index]->GetSlicer(i)->SetFusionSequenceCode(-1);
+            mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->GetSlicer(i)->SetFusionSequenceCode(-1);
+        }
+        */
       }
 
+      linkPanel->removeImage(index);
+      mSlicerManagers[index]->RemoveActors();
+
       //remove the slicer manager
       delete mSlicerManagers[index];
       mSlicerManagers.erase(Manageriter);
@@ -1775,7 +1818,7 @@ void vvMainWindow::WindowLevelChanged()
 //------------------------------------------------------------------------------
 void vvMainWindow::WindowLevelEdited()
 {
-  presetComboBox->setCurrentIndex(6);
+  presetComboBox->setCurrentIndex(WL_USER);
   UpdateWindowLevel();
 }
 //------------------------------------------------------------------------------
@@ -1785,7 +1828,7 @@ void vvMainWindow::SetWindowLevel(double w, double l)
 {
   windowSpinBox->setValue(w);
   levelSpinBox->setValue(l);
-  presetComboBox->setCurrentIndex(6);
+  presetComboBox->setCurrentIndex(WL_USER);
   colorMapComboBox->setCurrentIndex(0);
   UpdateWindowLevel();
 }
@@ -1795,7 +1838,7 @@ void vvMainWindow::SetWindowLevel(double w, double l)
 void vvMainWindow::UpdateWindowLevel()
 {
   if (DataTree->selectedItems().size()) {
-    if (presetComboBox->currentIndex() == 7) //For ventilation
+    if (presetComboBox->currentIndex() == WL_VENTILATION) //For ventilation
       colorMapComboBox->setCurrentIndex(5);
     int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
     mSlicerManagers[index]->SetColorWindow(windowSpinBox->value());
@@ -1831,7 +1874,7 @@ void vvMainWindow::SwitchWindowLevel()
 {
   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
   int window = mSlicerManagers[index]->GetColorWindow();
-  presetComboBox->setCurrentIndex(6);
+  presetComboBox->setCurrentIndex(WL_USER);
   windowSpinBox->setValue(-window);
   UpdateWindowLevel();
 }
@@ -1850,7 +1893,7 @@ void vvMainWindow::ApplyWindowLevelToAllImages()
       continue;
     mSlicerManagers[i]->SetColorWindow(window);
     mSlicerManagers[i]->SetColorLevel(level);
-    mSlicerManagers[i]->SetPreset(6);
+    mSlicerManagers[i]->SetPreset(WL_USER);
     mSlicerManagers[i]->Render();
   }
 }
@@ -1863,7 +1906,7 @@ void vvMainWindow::ApplyWindowToSetOfImages(double window, unsigned int indexMin
     if (mSlicerManagers[i] == NULL)
       continue;
     mSlicerManagers[i]->SetColorWindow(window);
-    mSlicerManagers[i]->SetPreset(6);
+    mSlicerManagers[i]->SetPreset(WL_USER);
     mSlicerManagers[i]->Render();
   }
 }
@@ -1876,7 +1919,7 @@ void vvMainWindow::ApplyLevelToSetOfImages(double level, unsigned int indexMin,
     if (mSlicerManagers[i] == NULL)
       continue;
     mSlicerManagers[i]->SetColorLevel(level);
-    mSlicerManagers[i]->SetPreset(6);
+    mSlicerManagers[i]->SetPreset(WL_USER);
     mSlicerManagers[i]->Render();
   }
 }
@@ -2196,7 +2239,15 @@ void vvMainWindow::AddFusionImage(int index, QString file)
     QMessageBox::information(this,tr("Problem reading Fusion !"),"File doesn't exist!");
 }
 //------------------------------------------------------------------------------
-
+//------------------------------------------------------------------------------
+void vvMainWindow::AddLandmarks(int index, std::vector<std::string> files)
+{
+    if (!landmarksPanel->LoadFromFile(files))
+      QMessageBox::information(this,tr("Problem reading Landmarks !"),"File doesn't exist!");
+    
+    landmarksPanel->SetCurrentPath(mInputPathName.toStdString());
+    landmarksPanel->SetCurrentImage(mSlicerManagers[index]->GetFileName().c_str());
+}
 
 //------------------------------------------------------------------------------
 void vvMainWindow::OpenField()
@@ -2413,7 +2464,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!
@@ -2424,35 +2475,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<double> 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<double> 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::cout<<"nbFrameMain = "<<nbFrameMain<<", nbFrameSecondary= "<<nbFrameSecondary<<", signal size: "<<tmpVect.size()<<std::endl;
+  std::vector<unsigned> temporalCorrespondances;
+  if ( tmpVect.size() == nbFrameMain + nbFrameSecondary ) {
+    for (unsigned i=0 ; i<tmpVect.size() ; i++) {
+      if (i<nbFrameMain) { //first part of the file: i -> index in secondary seq.
+        if ( tmpVect(i)<nbFrameSecondary ) temporalCorrespondances.push_back(tmpVect(i));
+        else { signalOK=false; break; } //pointing outside the secondary sequence...
+      }
+      else { //first part of the file -> index in secondary seq.
+        if ( tmpVect(i)<nbFrameMain ) temporalCorrespondances.push_back(tmpVect(i));
+        else { signalOK=false; break; } //pointing outside the secondary sequence...      
+      }      
+    }
   }
-  else {//else, send a message to signal the failure...
-    QString error = "The provided signal doesn't have the same duration as the sequence\n";
+  else {signalOK=false;}
+  if (!signalOK) {//else, send a message to signal the failure...
+    QString error = "The provided temporal correspondances is invalid - check tooltip.\n";
     error += "Ignoring file: " + fileName;
-    QMessageBox::information(this,tr("Problem adding signal!"),error);
+    QMessageBox::information(this,tr("Problem adding temporal correspondances!"),error);
     return;
   }
+  else {
+    //for convenience, associate this sequence to both the current slicer manager, and to the linked one
+    mSlicerManagers[index]->SetFusionSequenceCorrespondances(temporalCorrespondances);
+    mSlicerManagers[ mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager() ]->SetFusionSequenceCorrespondances(temporalCorrespondances);
+    overlayPanel->enableFusionSequenceTemporalSync();
+  }
 
 }
 //------------------------------------------------------------------------------
@@ -2469,6 +2536,7 @@ void vvMainWindow::AddFusionSequence(int index, std::vector<std::string> fileNam
     mInputPathName = itksys::SystemTools::GetFilenamePath(file.toStdString()).c_str();
     itk::ImageIOBase::Pointer reader = itk::ImageIOFactory::CreateImageIO(
       file.toStdString().c_str(), itk::ImageIOFactory::ReadMode);
+    std::sort (fileNames.begin(), fileNames.end());//make sure the files are sorted.
     reader->SetFileName(fileNames[0].c_str());
     reader->ReadImageInformation();
     std::string component = reader->GetComponentTypeAsString(reader->GetComponentType());
@@ -2536,8 +2604,15 @@ void vvMainWindow::AddFusionSequence(int index, std::vector<std::string> fileNam
 
       //This loads the secondary sequence (US) as an independent sequence
       LoadImages(fileNames, type);
-      //reset the transforms to identiy
+      //reset the transforms to identity
+      //FIX -- and set the thickness of the US slices to a large value (necessary for visualization purposes...)
+      double sp_x, sp_y, sp_z;
+      mSlicerManagers[indexParent]->GetImage()->GetVTKImages()[0]->GetSpacing(sp_x, sp_y, sp_z);
+      sp_z = std::max(sp_x, std::max(sp_y, sp_z)) + 0.5; //
       for (unsigned i=0 ; i<mSlicerManagers.back()->GetImage()->GetTransform().size() ; i++) {
+        sp_x = mSlicerManagers.back()->GetImage()->GetVTKImages()[i]->GetSpacing()[0];
+        sp_y = mSlicerManagers.back()->GetImage()->GetVTKImages()[i]->GetSpacing()[1];
+        mSlicerManagers.back()->GetImage()->GetVTKImages()[i]->SetSpacing( sp_x, sp_y, sp_z);
         mSlicerManagers.back()->GetImage()->GetTransform()[i]->Identity();
         mSlicerManagers.back()->GetImage()->GetTransform()[i]->Update();
       }
@@ -2560,7 +2635,7 @@ void vvMainWindow::AddFusionSequence(int index, std::vector<std::string> fileNam
       error += mSlicerManagers[index]->GetLastError().c_str();
       QMessageBox::information(this,tr("Problem reading image !"),error);
     }
-    //WindowLevelChanged();
+    WindowLevelChanged();
     ImageInfoChanged(); //this internally calls WindowLevelChanged...
   }
   else {
@@ -2621,21 +2696,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... 
       }
 
 
@@ -2891,12 +2958,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);
           }
         }
       }
@@ -3374,6 +3442,23 @@ void vvMainWindow::GoToCursor()
 }
 //------------------------------------------------------------------------------
 
+//------------------------------------------------------------------------------
+void vvMainWindow::GoToLandmark()
+{
+  int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
+  for (int column = 1; column < 5; column++) {
+    if (DataTree->selectedItems()[0]->data(column,Qt::CheckStateRole).toInt() > 1) {
+      double* cursorPos = landmarksPanel->GetSelectedPoint();
+      mSlicerManagers[index]->GetSlicer(column-1)->SetCurrentPosition(
+        cursorPos[0],cursorPos[1],cursorPos[2],cursorPos[3]);
+      mSlicerManagers[index]->UpdateViews(1,column-1);
+      mSlicerManagers[index]->UpdateLinked(column-1);
+      break;
+    }
+  }
+}
+//------------------------------------------------------------------------------
+
 //------------------------------------------------------------------------------
 void vvMainWindow::PlayPause()
 {