+//------------------------------------------------------------------------------
+//when this function is called index is the slicer manager index corresponding to the main sequence (CT)
+//the files behind fileNames points to the data for the secondary sequence
+void vvMainWindow::AddFusionSequence(int index, std::vector<std::string> 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(fileNames[0].c_str());
+ reader->ReadImageInformation();
+ std::string component = reader->GetComponentTypeAsString(reader->GetComponentType());
+ int dimension = reader->GetNumberOfDimensions();
+ QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+ vvProgressDialog progress("Opening " + file.toStdString());
+ qApp->processEvents();
+
+ std::string filename = itksys::SystemTools::GetFilenameWithoutExtension(file.toStdString()).c_str();
+
+ if (mSlicerManagers[index]->SetFusionSequence(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("fusionSequence"));
+
+ 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("fusionSequence").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);
+
+ //store the original transform matrix
+ int indexParent = GetSlicerIndexFromItem( DataTree->topLevelItem(index) );
+ mSlicerManagers[indexParent]->SetFusionSequenceMainTransformMatrix( mSlicerManagers[indexParent]->GetSlicer(0)->GetImage()->GetTransform()[0]->GetMatrix() );
+
+ //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);
+
+
+ //This loads the secondary sequence (US) as an independent sequence
+ LoadImages(fileNames, type);
+ //reset the transforms to identiy
+ for (unsigned i=0 ; i<mSlicerManagers.back()->GetImage()->GetTransform().size() ; i++) {
+ mSlicerManagers.back()->GetImage()->GetTransform()[i]->Identity();
+ mSlicerManagers.back()->GetImage()->GetTransform()[i]->Update();
+ }
+
+ //automatically link both images...
+ AddLink(mSlicerManagers[indexParent]->GetId().c_str(), mSlicerManagers.back()->GetId().c_str(), false);
+
+ //tie the main and secondary sequences by raising flags and informing each another of their respective SlicerManager indices
+ mSlicerManagers[indexParent]->SetFusionSequenceIndexOfLinkedManager(mSlicerManagers.size()-1);
+ mSlicerManagers[indexParent]->SetFusionSequenceInvolvmentCode(0); //main sequence
+ mSlicerManagers.back()->SetFusionSequenceIndexOfLinkedManager(indexParent);
+ mSlicerManagers.back()->SetFusionSequenceInvolvmentCode(1); //secondary sequence
+ for (unsigned i=0 ; i<4 ; i++) {
+ mSlicerManagers.back()->GetSlicer(i)->SetFusionSequenceCode(1); //flag the slicers of the secondary sequence
+ }
+
+ } 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();
+ ImageInfoChanged(); //this internally calls WindowLevelChanged...
+ }
+ else {
+ QMessageBox::information(this,tr("Problem reading fusion sequence !"),"File doesn't exist!");
+ return;
+ }
+
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+//fusionSequenceFrameIndex and fusionSequenceNbFrames are relative to the secondary sequence (US)
+void vvMainWindow::SetFusionSequenceProperty(int fusionSequenceFrameIndex, bool spatialSyncFlag, unsigned int fusionSequenceNbFrames, bool temporalSyncFlag)
+{
+ int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
+
+ 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()) {
+ index = mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager();
+ }
+ int secondaryIndex = mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager();
+ if (secondaryIndex==-1) return; //this should never happen
+ if ( (!mSlicerManagers[index]->IsMainSequenceOfFusionSequence()) ||
+ (!mSlicerManagers[secondaryIndex]->IsSecondarySequenceOfFusionSequence()) )
+ {return;} //this should never happen, raise an exception?
+
+ if (mSlicerManagers[index]->GetSlicer(0)->GetFusion()) {
+
+ //First, if the spatialSync button is unchecked, then reposition the parent sequence (CT) in its original coordinate frame
+ if ( (!spatialSyncFlag) && (mSlicerManagers[index]->GetFusionSequenceSpatialSyncFlag()) ) {
+ for ( unsigned i=0 ; i<mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetTransform().size() ; i++ ) {
+ mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetTransform()[i]->SetMatrix( mSlicerManagers[index]->GetFusionSequenceMainTransformMatrix() );
+ mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetTransform()[i]->Update();
+ }
+
+ for (int i=0; i<mSlicerManagers[index]->GetNumberOfSlicers(); i++) {
+ mSlicerManagers[index]->GetSlicer(i)->ForceUpdateDisplayExtent();
+ mSlicerManagers[index]->GetSlicer(i)->Render();
+ }
+ }
+
+ //then, update the property values in the slicer manager
+ mSlicerManagers[index]->SetFusionSequenceLength(fusionSequenceNbFrames);
+ mSlicerManagers[index]->SetFusionSequenceSpatialSyncFlag(spatialSyncFlag);
+ mSlicerManagers[index]->SetFusionSequenceTemporalSyncFlag(temporalSyncFlag);
+ mSlicerManagers[index]->SetFusionSequenceFrameIndex(fusionSequenceFrameIndex);
+
+ //select the right frame of the US sequence
+ mSlicerManagers[index]->SetFusionSequenceTSlice(fusionSequenceFrameIndex); //here, I should only update the overlayed sequence
+ mSlicerManagers[secondaryIndex]->SetTSlice(fusionSequenceFrameIndex, false); //this should update the secondary sequence (individual version)
+
+ //update the horizontal sliders of the main window
+ overlayPanel->updateFusionSequenceSliderValueFromWindow(fusionSequenceFrameIndex, false);
+
+ 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
+
+ //and set it!
+ mSlicerManagers[index]->SetTSlice(mainSequenceFrameIndex, false);
+ }