X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=vv%2FvvMainWindow.cxx;h=d2c732f707baee8022495499f8973304d38994ce;hb=d964acf3ee5b9c88194791613a06bee333671200;hp=bff6700b3141f1af531d45d85768876d5850c6b1;hpb=2c87c1a16f2f1656c4aeb97cccb0284a48762cf7;p=clitk.git diff --git a/vv/vvMainWindow.cxx b/vv/vvMainWindow.cxx index bff6700..d2c732f 100644 --- a/vv/vvMainWindow.cxx +++ b/vv/vvMainWindow.cxx @@ -48,6 +48,7 @@ It is distributed under dual licence #include "vvSaveState.h" #include "vvReadState.h" #include "clitkConfiguration.h" +#include "clitkMatrix.h" // ITK include #include @@ -88,6 +89,7 @@ It is distributed under dual licence // Standard includes #include +#include #include #include @@ -101,9 +103,9 @@ 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 *.dcm *.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)" +#define EXTENSIONS "Images ( *.bmp *.dcm *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.refscan *.nii.gz)" #endif @@ -276,7 +278,7 @@ vvMainWindow::vvMainWindow():vvMainWindowBase() connect(actionWarp_image_with_vector_field,SIGNAL(triggered()),this,SLOT(WarpImage())); connect(actionLoad_images,SIGNAL(triggered()),this,SLOT(OpenImages())); connect(actionOpen_Dicom,SIGNAL(triggered()),this,SLOT(OpenDicom())); - connect(actionOpen_Dicom_Struct,SIGNAL(triggered()),this,SLOT(OpenDCStructContour())); + // connect(actionOpen_Dicom_Struct,SIGNAL(triggered()),this,SLOT(OpenDCStructContour())); connect(actionOpen_VTK_contour,SIGNAL(triggered()),this,SLOT(OpenVTKContour())); connect(actionOpen_Multiple_Images_As_One,SIGNAL(triggered()),this,SLOT(MergeImages())); connect(actionSlice_Image_As_Multiple_Images,SIGNAL(triggered()),this,SLOT(SliceImages())); @@ -294,7 +296,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())); /////////////////////////////////////////////// @@ -460,7 +462,7 @@ void vvMainWindow::AddContour(int image_index, vvMesh::Pointer contour, bool pro brush.setColor(QColor(contour->r*255,contour->g*255,contour->b*255)); brush.setStyle(Qt::SolidPattern); item->setData(COLUMN_IMAGE_NAME,Qt::BackgroundRole,brush); - item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,contour->structure_name.c_str()); + // item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,contour->structure_name.c_str()); for (int j = 1; j <= 4; j++) item->setData(j,Qt::CheckStateRole,DataTree->topLevelItem(image_index)->data(j,Qt::CheckStateRole)); @@ -1003,7 +1005,7 @@ void vvMainWindow::CurrentImageChanged(std::string id) mSlicerManagers[selected]->GetTSlice()); landmarksPanel->SetCurrentPath(mInputPathName.toStdString()); landmarksPanel->SetCurrentImage(mSlicerManagers[selected]->GetFileName().c_str()); - + emit SelectedImageHasChanged(mSlicerManagers[selected]); } //------------------------------------------------------------------------------ @@ -1133,6 +1135,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)); @@ -1141,7 +1146,7 @@ void vvMainWindow::ImageInfoChanged() infoPanel->setNPixel(QString::number(NPixel)+" ("+inputSizeInBytes+")"); transformation = imageSelected->GetTransform()[tSlice]->GetMatrix(); - infoPanel->setTransformation(Get4x4MatrixDoubleAsString(transformation)); + infoPanel->setTransformation(clitk::Get4x4MatrixDoubleAsString(transformation).c_str()); landmarksPanel->SetCurrentLandmarks(mSlicerManagers[index]->GetLandmarks(), mSlicerManagers[index]->GetTSlice()); @@ -1163,12 +1168,12 @@ void vvMainWindow::ImageInfoChanged() // 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) { @@ -1339,38 +1344,6 @@ QString vvMainWindow::GetSizeInBytes(unsigned long size) } //------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -QString vvMainWindow::Get4x4MatrixDoubleAsString(vtkSmartPointer matrix, const int precision) -{ - std::ostringstream strmatrix; - - // Figure out the number of digits of the integer part of the largest absolute value - // for each column - unsigned width[4]; - for (unsigned int j = 0; j < 4; j++){ - double absmax = 0.; - for (unsigned int i = 0; i < 4; i++) - absmax = std::max(absmax, vnl_math_abs(matrix->GetElement(i, j))); - unsigned ndigits = (unsigned)std::max(0.,std::log10(absmax))+1; - width[j] = precision+ndigits+3; - } - - // Output with correct width, aligned to the right - for (unsigned int i = 0; i < 4; i++) { - for (unsigned int j = 0; j < 4; j++) { - strmatrix.setf(ios::fixed,ios::floatfield); - strmatrix.precision(precision); - strmatrix.fill(' '); - strmatrix.width(width[j]); - strmatrix << std::right << matrix->GetElement(i, j); - } - strmatrix << std::endl; - } - QString result = strmatrix.str().c_str(); - return result; -} -//------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ QString vvMainWindow::GetVectorDoubleAsString(std::vector vectorDouble) { @@ -1471,7 +1444,7 @@ void vvMainWindow::DisplayChanged(QTreeWidgetItem *clickedItem, int column) clickedParentItem->setData(column, Qt::CheckStateRole, vis?2:0); // Children - std::map actorTypeCounts; + std::map actorTypeCounts; for (int iChild = 0; iChild < clickedParentItem->childCount(); iChild++) { QTreeWidgetItem* currentChildItem = clickedParentItem->child(iChild); std::string actorType = currentChildItem->data(1,Qt::UserRole).toString().toStdString(); @@ -1589,7 +1562,7 @@ void vvMainWindow::CloseImage(QTreeWidgetItem* item, int column) if (DataTree->topLevelItem(index)->child(child) == item) break; } if (overlay_type=="fusionSequence") { - //removing the overlay sequence in a fusion sequence visualization mode + //removing the overlay sequence in a fusion sequence visualization mode //reset the transforms overlayPanel->getFusionSequenceProperty(-1, false, 0, false); @@ -1638,6 +1611,24 @@ void vvMainWindow::CloseImage(QTreeWidgetItem* item, int column) } //if the slicer manager was involved in a fusion sequence visualization... 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 ; ichildCount() ; i++) { + overlayItem = item->child(i); + this->CloseImage( overlayItem, 0 ); + } + } + else { + QTreeWidgetItem* linkedItem = this->GetItemFromSlicerManager( mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()] ); + for (unsigned i=0 ; ichildCount() ; 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); @@ -1649,8 +1640,7 @@ void vvMainWindow::CloseImage(QTreeWidgetItem* item, int column) mSlicerManagers[index]->GetSlicer(i)->SetFusionSequenceCode(-1); mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->GetSlicer(i)->SetFusionSequenceCode(-1); } - - //TODO: also remove the image overlaid with the main sequence, as it is becoming invalid... + */ } linkPanel->removeImage(index); @@ -1694,12 +1684,12 @@ void vvMainWindow::ReloadImage(QTreeWidgetItem* item, int column) else if (role == "fusionSequence") { //both versions of the secondary sequence must be updated. mSlicerManagers[index]->ReloadFusionSequence(); - mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->Reload(); + mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->Reload(); } else { mSlicerManagers[index]->Reload(); //if we update the secondary sequence, then the overlay of the main sequence should also be updated - if (mSlicerManagers[index]->IsSecondarySequenceOfFusionSequence()) mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->ReloadFusionSequence(); + if (mSlicerManagers[index]->IsSecondarySequenceOfFusionSequence()) mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->ReloadFusionSequence(); } // Update view and info ImageInfoChanged(); @@ -1768,7 +1758,7 @@ void vvMainWindow::WindowLevelChanged() mSlicerManagers[index]->GetFusionLevel()); if (mSlicerManagers[index]->IsMainSequenceOfFusionSequence()) { overlayPanel->getFusionSequenceProperty(mSlicerManagers[index]->GetFusionSequenceFrameIndex(), - mSlicerManagers[index]->GetFusionSequenceSpatialSyncFlag(), + mSlicerManagers[index]->GetFusionSequenceSpatialSyncFlag(), mSlicerManagers[index]->GetFusionSequenceNbFrames(), mSlicerManagers[index]->GetFusionSequenceTemporalSyncFlag()); } @@ -1782,7 +1772,7 @@ void vvMainWindow::WindowLevelChanged() mSlicerManagers[ind]->GetFusionWindow(), mSlicerManagers[ind]->GetFusionLevel()); overlayPanel->getFusionSequenceProperty(mSlicerManagers[ind]->GetFusionSequenceFrameIndex(), - mSlicerManagers[ind]->GetFusionSequenceSpatialSyncFlag(), + mSlicerManagers[ind]->GetFusionSequenceSpatialSyncFlag(), mSlicerManagers[ind]->GetFusionSequenceNbFrames(), mSlicerManagers[ind]->GetFusionSequenceTemporalSyncFlag()); } @@ -1867,12 +1857,22 @@ void vvMainWindow::ApplyWindowLevelToAllImages() double window = mSlicerManagers[index]->GetColorWindow(); double level = mSlicerManagers[index]->GetColorLevel(); + double fusWindow = mSlicerManagers[index]->GetFusionWindow(); + double fusLevel = mSlicerManagers[index]->GetFusionLevel(); + + double overWindow = mSlicerManagers[index]->GetOverlayColorWindow(); + double overLevel = mSlicerManagers[index]->GetOverlayColorLevel(); + for (unsigned int i = 0; i < mSlicerManagers.size(); i++) { if (mSlicerManagers[i] == NULL) continue; mSlicerManagers[i]->SetColorWindow(window); mSlicerManagers[i]->SetColorLevel(level); mSlicerManagers[i]->SetPreset(WL_USER); + mSlicerManagers[i]->SetFusionWindow(fusWindow); + mSlicerManagers[i]->SetFusionLevel(fusLevel); + mSlicerManagers[i]->SetOverlayColorWindow(overWindow); + mSlicerManagers[i]->SetOverlayColorLevel(overLevel); mSlicerManagers[i]->Render(); } } @@ -2125,9 +2125,15 @@ void vvMainWindow::SelectFusionImage() QString Extensions = EXTENSIONS; Extensions += ";;All Files (*)"; - QString file = QFileDialog::getOpenFileName(this,tr("Load Fusion image"),mInputPathName,Extensions); - if (!file.isEmpty()) - AddFusionImage(index,file); + QStringList files = QFileDialog::getOpenFileNames(this,tr("Load Fusion image"),mInputPathName,Extensions); + if (files.isEmpty()) + return; + + std::vector vecFileNames; + for (int i = 0; i < files.size(); i++) { + vecFileNames.push_back(files[i].toStdString()); + } + AddFusionImage(index,vecFileNames,vvImageReader::IMAGE); } //------------------------------------------------------------------------------ @@ -2142,77 +2148,78 @@ void vvMainWindow::ResetTransformationToIdentity() //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -void vvMainWindow::AddFusionImage(int index, QString file) +void vvMainWindow::AddFusionImage(int index, std::vector fileNames, vvImageReader::LoadedImageType type) { + QString file(fileNames[0].c_str()); if (QFile::exists(file)) { mInputPathName = itksys::SystemTools::GetFilenamePath(file.toStdString()).c_str(); itk::ImageIOBase::Pointer reader = itk::ImageIOFactory::CreateImageIO( file.toStdString().c_str(), itk::ImageIOFactory::ReadMode); - reader->SetFileName(file.toStdString().c_str()); + reader->SetFileName(fileNames[0].c_str()); reader->ReadImageInformation(); std::string component = reader->GetComponentTypeAsString(reader->GetComponentType()); - if (reader) { - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - vvProgressDialog progress("Opening fusion"); - qApp->processEvents(); + int dimension = reader->GetNumberOfDimensions(); + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + vvProgressDialog progress("Opening fusion"); + qApp->processEvents(); - std::string filename = itksys::SystemTools::GetFilenameWithoutExtension(file.toStdString()).c_str(); - if (mSlicerManagers[index]->SetFusion(file.toStdString(), - reader->GetNumberOfDimensions(), component)) { - //create an item in the tree with good settings - QTreeWidgetItem *item = new QTreeWidgetItem(); - item->setData(0,Qt::UserRole,file.toStdString().c_str()); - item->setData(1,Qt::UserRole,tr("fusion")); - QFileInfo fileinfo(filename.c_str()); //Do not show the path + std::string filename = itksys::SystemTools::GetFilenameWithoutExtension(file.toStdString()).c_str(); + if (mSlicerManagers[index]->SetFusion(fileNames,dimension, component,type)) { + //create an item in the tree with good settings + QTreeWidgetItem *item = new QTreeWidgetItem(); + item->setData(0,Qt::UserRole,file.toStdString().c_str()); + item->setData(1,Qt::UserRole,tr("fusion")); + QFileInfo fileinfo(file); //Do not show the path item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,fileinfo.fileName()); item->setToolTip(COLUMN_IMAGE_NAME, mSlicerManagers[index]->GetListOfAbsoluteFilePathInOneString("fusion").c_str()); qApp->processEvents(); - for (int j = 1; j <= 4; j++) { - item->setData(j,Qt::CheckStateRole,DataTree->topLevelItem(index)->data(j,Qt::CheckStateRole)); - } - - //Create the buttons for reload and close - qApp->processEvents(); - QTreePushButton* cButton = new QTreePushButton; - cButton->setItem(item); - cButton->setColumn(COLUMN_CLOSE_IMAGE); - cButton->setToolTip(tr("close image")); - cButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/exit.png"))); - connect(cButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)), - this,SLOT(CloseImage(QTreeWidgetItem*, int))); - - QTreePushButton* rButton = new QTreePushButton; - rButton->setItem(item); - rButton->setColumn(COLUMN_RELOAD_IMAGE); - rButton->setToolTip(tr("reload image")); - rButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/rotateright.png"))); - connect(rButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)), - this,SLOT(ReloadImage(QTreeWidgetItem*, int))); - - DataTree->topLevelItem(index)->setExpanded(1); - DataTree->topLevelItem(index)->addChild(item); - DataTree->setItemWidget(item, COLUMN_CLOSE_IMAGE, cButton); - DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton); - - //set the id of the image - QString id = DataTree->topLevelItem(index)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString(); - item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str()); - UpdateTree(); - qApp->processEvents(); - ImageInfoChanged(); - QApplication::restoreOverrideCursor(); - } else { - QApplication::restoreOverrideCursor(); - QString error = "Cannot import the new image.\n"; - error += mSlicerManagers[index]->GetLastError().c_str(); - QMessageBox::information(this,tr("Problem reading image !"),error); + for (int j = 1; j <= 4; j++) { + item->setData(j,Qt::CheckStateRole,DataTree->topLevelItem(index)->data(j,Qt::CheckStateRole)); } + + //Create the buttons for reload and close + qApp->processEvents(); + QTreePushButton* cButton = new QTreePushButton; + cButton->setItem(item); + cButton->setColumn(COLUMN_CLOSE_IMAGE); + cButton->setToolTip(tr("close image")); + cButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/exit.png"))); + connect(cButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)), + this,SLOT(CloseImage(QTreeWidgetItem*, int))); + + QTreePushButton* rButton = new QTreePushButton; + rButton->setItem(item); + rButton->setColumn(COLUMN_RELOAD_IMAGE); + rButton->setToolTip(tr("reload image")); + rButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/rotateright.png"))); + connect(rButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)), + this,SLOT(ReloadImage(QTreeWidgetItem*, int))); + + DataTree->topLevelItem(index)->setExpanded(1); + DataTree->topLevelItem(index)->addChild(item); + DataTree->setItemWidget(item, COLUMN_CLOSE_IMAGE, cButton); + DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton); + + //set the id of the image + QString id = DataTree->topLevelItem(index)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString(); + item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str()); + UpdateTree(); + qApp->processEvents(); + ImageInfoChanged(); + QApplication::restoreOverrideCursor(); + + // Update the display to update, e.g., the sliders + for(int i=0; i<4; i++) + DisplaySliders(index, i); } else { + QApplication::restoreOverrideCursor(); QString error = "Cannot import the new image.\n"; + error += mSlicerManagers[index]->GetLastError().c_str(); QMessageBox::information(this,tr("Problem reading image !"),error); } + WindowLevelChanged(); } else QMessageBox::information(this,tr("Problem reading Fusion !"),"File doesn't exist!"); @@ -2223,7 +2230,7 @@ void vvMainWindow::AddLandmarks(int index, std::vector 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()); } @@ -2242,12 +2249,12 @@ void vvMainWindow::OpenField() return; } - QString Extensions = "Images ( *.mhd)"; - Extensions += ";;Images ( *.mha)"; - Extensions += ";;VF Images ( *.vf)"; - Extensions += ";;nii Images ( *.nii)"; - Extensions += ";;nrrd Images ( *.nrrd)"; - Extensions += ";;nhdr Images ( *.nhdr)"; + QString Extensions = "Images ( *.mhd *.mha *.vf *.nii *.nrrd *.nhdr)"; + // Extensions += ";;Images ( *.mha)"; + // Extensions += ";;VF Images ( *.vf)"; + // Extensions += ";;nii Images ( *.nii)"; + // Extensions += ";;nrrd Images ( *.nrrd)"; + // Extensions += ";;nhdr Images ( *.nhdr)"; Extensions += ";;All Files (*)"; QString file = QFileDialog::getOpenFileName(this,tr("Load deformation field"),mInputPathName,Extensions); if (!file.isEmpty()) @@ -2443,7 +2450,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 +2461,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::cout<<"nbFrameMain = "< 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(); + } } //------------------------------------------------------------------------------ @@ -2499,6 +2522,7 @@ void vvMainWindow::AddFusionSequence(int index, std::vector 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()); @@ -2566,8 +2590,15 @@ void vvMainWindow::AddFusionSequence(int index, std::vector 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 ; iGetImage()->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(); } @@ -2590,7 +2621,7 @@ void vvMainWindow::AddFusionSequence(int index, std::vector fileNam error += mSlicerManagers[index]->GetLastError().c_str(); QMessageBox::information(this,tr("Problem reading image !"),error); } - //WindowLevelChanged(); + WindowLevelChanged(); ImageInfoChanged(); //this internally calls WindowLevelChanged... } else { @@ -2608,7 +2639,7 @@ void vvMainWindow::SetFusionSequenceProperty(int fusionSequenceFrameIndex, bool { int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]); - if (!mSlicerManagers[index]->IsInvolvedInFusionSequence()) return; + if (!mSlicerManagers[index]->IsInvolvedInFusionSequence()) return; //check if the focus moved to the linked sequence, and in this case, select the master sequence instead if (!mSlicerManagers[index]->IsMainSequenceOfFusionSequence()) { @@ -2616,8 +2647,8 @@ void vvMainWindow::SetFusionSequenceProperty(int fusionSequenceFrameIndex, bool } int secondaryIndex = mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager(); if (secondaryIndex==-1) return; //this should never happen - if ( (!mSlicerManagers[index]->IsMainSequenceOfFusionSequence()) || - (!mSlicerManagers[secondaryIndex]->IsSecondarySequenceOfFusionSequence()) ) + if ( (!mSlicerManagers[index]->IsMainSequenceOfFusionSequence()) || + (!mSlicerManagers[secondaryIndex]->IsSecondarySequenceOfFusionSequence()) ) {return;} //this should never happen, raise an exception? if (mSlicerManagers[index]->GetSlicer(0)->GetFusion()) { @@ -2651,21 +2682,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... } @@ -2914,19 +2937,20 @@ void vvMainWindow::HorizontalSliderMoved(int value,int column, int slicer_index) //i is the SlicerManager that is in charge of this slicer. if (mSlicerManagers[i]->IsInvolvedInFusionSequence()) { //if the slicerManager is involved in a fusionSequence as the secondary sequence, then update the slider position in the overlay panel and everything accordingly - if (mSlicerManagers[i]->IsSecondarySequenceOfFusionSequence()) { - overlayPanel->updateFusionSequenceSliderValueFromWindow(value, true); + if (mSlicerManagers[i]->IsSecondarySequenceOfFusionSequence()) { + overlayPanel->updateFusionSequenceSliderValueFromWindow(value, true); } else { //if this is the primary sequence that has been modified - if (mSlicerManagers[i]->GetFusionSequenceTemporalSyncFlag()) { + 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); } } } @@ -3221,9 +3245,9 @@ void vvMainWindow::SaveScreenshotAllSlices() // Change the slice slicer->SetSlice(i); // -> change the slice of the current slicer SM->UpdateSlice(0); // --> this one emit UpdateSlice - QCoreApplication::flush(); // -> needed to force display of contours + QCoreApplication::flush(); // -> needed to force display of contours - // Screenshot + // Screenshot vtkSmartPointer windowToImageFilter = vtkSmartPointer::New(); windowToImageFilter->SetInput(renderWindow); windowToImageFilter->SetMagnification(1); @@ -3237,7 +3261,7 @@ void vvMainWindow::SaveScreenshotAllSlices() if (i<100) num = "0"+num; if (i<1000) num = "0"+num; - fn = itksys::SystemTools::GetFilenamePath(filename.toStdString()) + "/"+ fn + fn = itksys::SystemTools::GetFilenamePath(filename.toStdString()) + "/"+ fn + "_" + num + itksys::SystemTools::GetFilenameLastExtension(filename.toStdString()); writer->SetFileName(fn.c_str()); writer->SetInput(windowToImageFilter->GetOutput()); @@ -3633,4 +3657,3 @@ void vvMainWindow::UpdateCurrentSlicer() mSlicerManagerCurrentIndex = index; } //------------------------------------------------------------------------------ -