OSCR

The University of Texas Southwestern Glioma Dataset - MRI, Molecular Markers and Segmentations.

Code ↔ Paper

4 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 4 matches
  1. [1] § Data Records ↔ src/applications/Preprocessing/src/depends/itkN3MRIBiasFieldCorrectionImageFilter.h, lines 1–76 · score 0.58 · Advanced Normalization Tools, ANTs, MRI, variables, masks, preprocessing
  2. [2] § Methods › Data and preprocessing ↔ src/view/gui/fMainWindow.cpp, lines 727–814 · score 0.55 · skull stripping, NIfTI, Initiative, DICOM, pipeline, brain
  3. [3] § Background & Summary ↔ src/view/gui/fMainWindow.cpp, lines 655–725 · score 0.54 · deep learning, brain tumor, prognosis, models, training, field
  4. [4] § Data Records ↔ src/view/gui/fMainWindow.cpp, lines 727–814 · score 0.51 · Skull stripped, NIfTI, Initiative, preprocessing, pipelines, segmentation

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

C++ · 5,535 lines · 195 KB · other · 3 matches

  1. //\*file fMainWindow.cpp
  2. //
  3. //brief Implementation of fMainWindow class
  4. //
  5. //https://www.med.upenn.edu/sbia/software/ <br>
  6. //[email hidden]
  7. //
  8. //Copyright (c) 2018 University of Pennsylvania. All rights reserved. <br>
  9. //See COPYING file or https://www.med.upenn.edu/sbia/software-agreement.html
  10. //
  11. //*/
  12. /////
  13. #include "fMainWindow.h"
  14. #include "OutputInteractorStyleNavigator.h"
  15. #include "SimpleImageManager.h"
  16. #include "fHelpDialog.h"
  17. //#include "EGFRvIIISurrogateIndex.h"
  18. //#include "TrainingModule.h"
  19. //#include "GeodesicSegmentation.h"
  20. #include "N3BiasCorrection.h"
  21. #include "SusanDenoising.h"
  22. //#include "WhiteStripe.h"
  23. //#include "PerfusionDerivatives.h"
  24. //#include "PerfusionAlignment.h"
  25. //#include "DiffusionDerivatives.h"
  26. #include "ZScoreNormalizer.h"
  27. //#include "PerfusionPCA.h"
  28. //#include "SBRT_LungField.h"
  29. //#include "SBRT_Nodule.h"
  30. //#include "SBRT_Analysis.h"
  31. #include "PreferencesDialog.h"
  32. #include "cbicaITKSafeImageIO.h"
  33. #include "itkFlipImageFilter.h"
  34. #include "lddmm_common.h"
  35. #include "lddmm_data.h"
  36. #include "GreedyAPI.h"
  37. #include <vnl/vnl_cost_function.h>
  38. #include <vnl/vnl_random.h>
  39. #include <vnl/algo/vnl_powell.h>
  40. #include <vnl/algo/vnl_svd.h>
  41. #include <vnl/vnl_trace.h>
  42. #include "cbicaCmdParser.h"
  43. #ifndef __APPLE__
  44. //#include "LibraPreprocess.h"
  45. #endif
  46. #include "Registry.h"
  47. //#include "DirectionalityEstimate.h"
  48. #include "SlicerManager.h"
  49. #include "Slicer.h"
  50. #include "InteractorStyleNavigator.h"
  51. #include "CaPTkUtils.h"
  52. #include "CaPTkGUIUtils.h"
  53. #include "vtkTransform.h"
  54. #include "vtkImageMapToWindowLevelColors.h"
  55. #include "vtkLookupTable.h"
  56. #include "ComparisonViewerCommand.h"
  57. #include "QtConcurrent/qtconcurrentrun.h"
  58. #include "itkTranslationTransform.h"
  59. #include "ApplicationPreferences.h"
  60. #include "cbicaUtilities.h"
  61. //#include "DicomSeriesReader.h"
  62. // this function calls an external application from CaPTk in the most generic way while waiting for output
  63. int fMainWindow::startExternalProcess(const QString &application, const QStringList &arguments)
  64. {
  65. m_NumberOfUnfinishedExternalProcesses++;
  66. auto fullCommand = application.toStdString() + " " + arguments.join(" ").toStdString();
  67. cbica::Logging(loggerFile, fullCommand);
  68. int returnVal = std::system(fullCommand.c_str());
  69. m_NumberOfUnfinishedExternalProcesses--;
  70. return returnVal;
  71. #ifdef _WIN32
  72. //QProcess process;
  73. //process.setStandardOutputFile((m_tempFolderLocation + "/process_" + application.toStdString() + ".log").c_str());
  74. //if (arguments.isEmpty())
  75. //{
  76. // if (QFileInfo(application).completeSuffix() == "py")
  77. // {
  78. // process.start("python.exe " + application + ".py");
  79. // }
  80. // else
  81. // {
  82. // process.start(application);
  83. // }
  84. //}
  85. //else
  86. //{
  87. // if (QFileInfo(application).completeSuffix() == "py")
  88. // {
  89. // process.start("python.exe " + application + ".py", arguments);
  90. // }
  91. // else
  92. // {
  93. // process.start(application, arguments);
  94. // }
  95. //}
  96. //process.write("exit\n\r");
  97. //process.waitForFinished(-1);
  98. //process.close();
  99. //return process.exitCode();
  100. #else
  101. //std::string args_string = ""/*arguments.join(" ")*/, app_string = application.toStdString();
  102. //for (size_t i = 0; i < arguments.size(); i++)
  103. //{
  104. // args_string += " " + arguments[i].toStdString();
  105. //}
  106. ////if (cbica::getFilenameExtension(application.toStdString()) == ".py")
  107. ////{
  108. //// app_string = "python " + application.toStdString();
  109. ////}
  110. //return std::system((app_string + args_string).c_str());
  111. #endif
  112. }
  113. int GetNumberOfDimensions(vtkImageData* input)
  114. {
  115. int dim = 0;
  116. #if VTK_MAJOR_VERSION <= 5
  117. int* extent = input->GetWholeExtent();
  118. #else
  119. int* extent = input->GetExtent();
  120. #endif
  121. if (extent[4] != extent[5])
  122. {
  123. dim = 3;
  124. }
  125. else if (extent[3] != extent[4])
  126. {
  127. dim = 2;
  128. }
  129. else if (extent[0] != extent[1])
  130. {
  131. dim = 1;
  132. }
  133. return dim;
  134. }
  135. inline std::string correctExtension(const std::string &inputFileName)
  136. {
  137. std::string returnString = inputFileName, tempPath, tempBase, tempExt;
  138. cbica::splitFileName(returnString, tempPath, tempBase, tempExt);
  139. if (tempExt.empty())
  140. {
  141. returnString += NII_GZ_EXT;
  142. }
  143. return returnString;
  144. }
  145. fMainWindow::fMainWindow()
  146. {
  147. setupUi(this);
  148. //! load preferences
  149. ApplicationPreferences::GetInstance()->DeSerializePreferences();
  150. ApplicationPreferences::GetInstance()->DisplayPreferences();
  151. //! comparison mode OFF at startup
  152. this->SetComparisonMode(false);
  153. this->bottomLayout = new QHBoxLayout();
  154. help_discussion = new QAction(this);
  155. help_forum = new QAction(this);
  156. help_bugs = new QAction(this);
  157. help_features = new QAction(this);
  158. help_download = new QAction(this);
  159. actionLoad_Recurrence_Images = new QAction(this);
  160. actionLoad_Nifti_Images = new QAction(this);
  161. actionLoad_Dicom_Images = new QAction(this);
  162. actionLoad_Nifti_ROI = new QAction(this);
  163. actionSave_Nifti_Images = new QAction(this);
  164. actionSave_Dicom_Images = new QAction(this);
  165. actionSave_ROI_Images = new QAction(this);
  166. actionSave_ROI_Dicom_Images = new QAction(this);
  167. actionExit = new QAction(this);
  168. actionAppEGFR = new QAction(this);
  169. actionAppRecurrence = new QAction(this);
  170. actionAppGeodesic = new QAction(this);
  171. actionAppGeodesicTraining = new QAction(this);
  172. actionHelp_Interactions = new QAction(this);
  173. actionAbout = new QAction(this);
  174. actionPreferences = new QAction(this);
  175. //---------------setting menu and status bar for the main window---------------
  176. this->setStatusBar(statusbar);
  177. menubar = new QMenuBar(this);
  178. menuFile = new QMenu("File");
  179. menuLoadFile = new QMenu("Load");
  180. menuSaveFile = new QMenu("Save");
  181. menuExit = new QMenu("Exit");
  182. menuLoadFileDicom = new QMenu("Dicom");
  183. menuLoadFileNifti = new QMenu("Nifti");
  184. menuFile->addMenu(menuLoadFile);
  185. menuFile->addMenu(menuSaveFile);
  186. menuApp = new QMenu("Applications");
  187. //menuDeepLearning = new QMenu("Deep Learning");
  188. menuPreprocessing = new QMenu("Preprocessing");
  189. menuHelp = new QMenu("Help");
  190. SaggitalViewWidget.reset(new QVTKOpenGLWidget(SaggitalWidget));
  191. AxialViewWidget.reset(new QVTKOpenGLWidget(AxialWidget));
  192. CoronalViewWidget.reset(new QVTKOpenGLWidget(CoronalWidget));
  193. SaggitalRenWin = vtkSmartPointer< vtkGenericOpenGLRenderWindow>::New();
  194. AxialRenWin = vtkSmartPointer< vtkGenericOpenGLRenderWindow>::New();
  195. CoronalRenWin = vtkSmartPointer< vtkGenericOpenGLRenderWindow>::New();
  196. SaggitalViewWidget->SetRenderWindow(SaggitalRenWin);
  197. AxialViewWidget->SetRenderWindow(AxialRenWin);
  198. CoronalViewWidget->SetRenderWindow(CoronalRenWin);
  199. SaggitalViewWidget->setMouseTracking(true);
  200. AxialViewWidget->setMouseTracking(true);
  201. CoronalViewWidget->setMouseTracking(true);
  202. SaggitalWidgetGridLayout->addWidget(SaggitalViewWidget.data(), 0, 0, 1, 1);
  203. AxialWidgetGridLayout->addWidget(AxialViewWidget.data(), 0, 0, 1, 1);
  204. CoronalWidgetGridLayout->addWidget(CoronalViewWidget.data(), 0, 0, 1, 1);
  205. QSizePolicy sizePolicy5(QSizePolicy::Preferred, QSizePolicy::Expanding);
  206. sizePolicy5.setHorizontalStretch(0);
  207. sizePolicy5.setVerticalStretch(0);
  208. preferenceDialog = new PreferencesDialog(nullptr);
  209. infoPanel = new fBottomImageInfoTip(centralwidget);
  210. imagesPanel = new fImagesPanel(); // New Images Panel
  211. m_tabWidget->addTab(imagesPanel, QString());
  212. //tumorPanel = new fTumorPanel();
  213. //m_tabWidget->addTab(tumorPanel, QString());
  214. drawingPanel = new fDrawingPanel();
  215. segmentationPanel = new fSegmentationPanel();
  216. trainingPanel = new fTrainingPanel();
  217. m_tabWidget->addTab(drawingPanel, QString());
  218. m_tabWidget->addTab(segmentationPanel, "Segmentation");
  219. m_tabWidget->addTab(trainingPanel, "Training");
  220. int minheight = drawingPanel->sizeHint().height() + 25;
  221. m_tabWidget->setMinimumHeight(minheight);
  222. m_tabWidget->setMaximumHeight(m_tabWidget->minimumHeight());
  223. m_toolTabdock->setWindowFlags(Qt::Window);
  224. #ifdef Q_OS_WIN
  225. m_toolTabdock->setFeatures(QDockWidget::DockWidgetFloatable);
  226. #else
  227. //TBD fix this - work around untill solved
  228. m_toolTabdock->setFeatures(QDockWidget::NoDockWidgetFeatures);
  229. #endif
  230. m_toolTabdock->setWidget(m_tabWidget);
  231. overallGridLayout->addWidget(m_toolTabdock, 0, 0, 1, 3);
  232. QFrame * frame = new QFrame(this);
  233. sizePolicy5.setHeightForWidth(frame->sizePolicy().hasHeightForWidth());
  234. frame->setSizePolicy(sizePolicy5);
  235. frame->setFrameShape(QFrame::HLine);
  236. frame->setFrameShadow(QFrame::Sunken);
  237. overallGridLayout->addWidget(frame, 3, 0, 1, 3);
  238. this->setCentralWidget(centralwidget);
  239. AxialViewWidget->raise();
  240. CoronalViewWidget->raise();
  241. SaggitalViewWidget->raise();
  242. infoPanel->raise();
  243. m_tabWidget->raise();
  244. menuHelp->addAction(actionHelp_Interactions);
  245. //menuDownload = menuHelp->addMenu("Sample Data");
  246. //auto supportMenu = menuHelp->addMenu("Support Links");
  247. //menuHelp->addAction(actionAbout);
  248. //supportMenu->addAction(help_bugs);
  249. //supportMenu->addAction(help_download);
  250. menubar->addMenu(menuFile);
  251. menubar->addMenu(menuPreprocessing);
  252. #ifndef PACKAGE_VIEWER
  253. //menubar->addMenu(menuApp);
  254. #endif
  255. //menubar->addMenu(menuDeepLearning);
  256. menubar->addMenu(menuHelp);
  257. this->setMenuBar(menubar);
  258. menubar->addAction(menuFile->menuAction());
  259. menubar->addAction(menuPreprocessing->menuAction());
  260. #ifndef PACKAGE_VIEWER
  261. //menubar->addAction(menuApp->menuAction());
  262. #endif
  263. //menubar->addAction(menuDeepLearning->menuAction());
  264. menubar->addAction(menuHelp->menuAction());
  265. menuLoadFile->addAction(actionLoad_Nifti_Images);
  266. menuLoadFile->addAction(actionLoad_Nifti_ROI);
  267. // menuLoadFile->addAction(actionLoad_Dicom_Images);
  268. menuSaveFile->addAction(actionSave_Nifti_Images);
  269. menuSaveFile->addAction(actionSave_ROI_Images);
  270. menuFile->addAction(actionPreferences);
  271. menuFile->addAction(actionExit);
  272. //menuDownload->addAction("GreedyRegistration");
  273. m_tabWidget->setCurrentIndex(0);
  274. bottomLayout->addWidget(infoPanel);
  275. bottomLayout->addStretch();
  276. bottomLayout->addWidget(preferencesGroupBox);
  277. overallGridLayout->addLayout(bottomLayout, 4, 0, 2, 3);
  278. std::string nonNativeAppPaths_wrap = std::string(CAPTK_APP_LIST_PY_GUI);
  279. if (nonNativeAppPaths_wrap[0] == ' ')
  280. {
  281. nonNativeAppPaths_wrap.erase(0, 1);
  282. }
  283. //nonNativeAppPaths_wrap = nonNativeAppPaths_wrap + " itksnap";
  284. m_pyGUIApps = cbica::stringSplit(nonNativeAppPaths_wrap, " ");
  285. nonNativeAppPaths_wrap = std::string(CAPTK_APP_LIST_PY_CLI);
  286. if (nonNativeAppPaths_wrap[0] == ' ')
  287. {
  288. nonNativeAppPaths_wrap.erase(0, 1);
  289. }
  290. m_pyCLIApps = cbica::stringSplit(nonNativeAppPaths_wrap, " ");
  291. size_t allAppCounter = 0;
  292. for (size_t i = 0; i < m_pyGUIApps.size(); i++)
  293. {
  294. if (m_pyGUIApps[i] == "confetti")
  295. {
  296. m_pyGUIApps[i] = "ConfettiGUI";
  297. }
  298. if ((m_pyGUIApps[i] == "librabatch") || (m_pyGUIApps[i] == "librasingle"))
  299. {
  300. m_pyGUIApps[i] = "libra";
  301. }
  302. if (m_pyGUIApps[i] == "SBRT_Segment")
  303. {
  304. m_pyGUIApps[i] = "SBRT_Lung_Segment";
  305. }
  306. if (m_pyGUIApps[i] == "SBRT_Analyze")
  307. {
  308. m_pyGUIApps[i] = "SBRT_Lung_Analyze";
  309. }
  310. m_allNonNativeApps[m_pyGUIApps[i]] = getApplicationPath(m_pyGUIApps[i]);
  311. allAppCounter++;
  312. }
  313. for (size_t i = 0; i < m_pyCLIApps.size(); i++)
  314. {
  315. m_allNonNativeApps[m_pyCLIApps[i]] = getApplicationPath(m_pyCLIApps[i]);
  316. }
  317. // TBD: this needs to be controlled from CMake and not hard-coded here
  318. std::string brainAppList = "";// " EGFRvIIISVMIndex EGFRvIIISurrogateIndex RecurrenceEstimator PseudoProgressionEstimator SurvivalPredictor MolecularSubtypePredictor PopulationAtlases WhiteStripe confetti";
  319. std::string breastAppList = "";
  320. #ifndef __APPLE__
  321. //breastAppList = " librasingle librabatch breastSegment texturePipeline";
  322. #endif
  323. std::string lungAppList = "";// " LungField Nodule Analysis";
  324. //std::string miscAppList = " DirectionalityEstimate DiffusionDerivatives PerfusionAlignment PerfusionDerivatives PerfusionPCA TrainingModule";
  325. std::string miscAppList = "";// " DirectionalityEstimate DiffusionDerivatives TrainingModule";
  326. std::string segAppList = "";// " itksnap GeodesicSegmentation GeodesicTrainingSegmentation deepmedic_tumor deepmedic_brain";
  327. std::string preProcessingAlgos = " BiasCorrect-N3 Denoise-SUSAN GreedyRegistration HistogramMatching ZScoringNormalizer deepmedic_brain BraTSPipeline";
  328. //#ifndef __APPLE__
  329. // preProcessingAlgos += " breastNormalize";
  330. //#endif
  331. //std::string deepLearningAlgos = " deepmedic_tumor deepmedic_brain";
  332. if (!brainAppList.empty())
  333. {
  334. vectorOfGBMApps = populateStringListInMenu(brainAppList, this, menuApp, "Glioblastoma", false);
  335. menuApp->addSeparator();
  336. }
  337. if (!breastAppList.empty())
  338. {
  339. vectorOfBreastApps = populateStringListInMenu(breastAppList, this, menuApp, "Breast Cancer", false);
  340. menuApp->addSeparator();
  341. }
  342. if (!lungAppList.empty())
  343. {
  344. vectorOfLungApps = populateStringListInMenu(lungAppList, this, menuApp, "Lung Cancer", false);
  345. menuApp->addSeparator();
  346. }
  347. if (!segAppList.empty())
  348. {
  349. vectorOfSegmentationApps = populateStringListInMenu(segAppList, this, menuApp, "Segmentation", false);
  350. }
  351. if (!miscAppList.empty())
  352. {
  353. vectorOfMiscApps = populateStringListInMenu(miscAppList, this, menuApp, "Miscellaneous", false);
  354. }
  355. if (!preProcessingAlgos.empty())
  356. {
  357. vectorOfPreprocessingActionsAndNames = populateStringListInMenu(preProcessingAlgos, this, menuPreprocessing, "", false);
  358. }
  359. //if (!deepLearningAlgos.empty())
  360. //{
  361. // vectorOfDeepLearningActionsAndNames = populateStringListInMenu(deepLearningAlgos, this, menuDeepLearning, "", false);
  362. // auto temp = populateStringListInMenu(" ", this, menuDeepLearning, "Breast", false);
  363. // temp = populateStringListInMenu(" ", this, menuDeepLearning, "Lung", false);
  364. // menuDeepLearning->addSeparator();
  365. // temp = populateStringListInMenu(" ", this, menuDeepLearning, "Training", false);
  366. //}
  367. //menuDownload->addAction("All");
  368. //for (const auto &currentActionAndName : vectorOfGBMApps)
  369. //{
  370. // if (currentActionAndName.name != "Glioblastoma")
  371. // {
  372. // if (currentActionAndName.name == "confetti")
  373. // {
  374. // menuDownload->addAction("Confetti");
  375. // }
  376. // else
  377. // {
  378. // menuDownload->addAction(currentActionAndName.name.c_str());
  379. // }
  380. // }
  381. //}
  382. bool libraCheck = false;
  383. for (const auto &currentActionAndName : vectorOfBreastApps)
  384. {
  385. if (!libraCheck)
  386. {
  387. if (currentActionAndName.name.find("libra") != std::string::npos)
  388. {
  389. libraCheck = true;
  390. //menuDownload->addAction("LIBRA");
  391. }
  392. }
  393. //if (currentActionAndName.name != "Breast Cancer")
  394. //{
  395. // if (!libraCheck)
  396. // {
  397. // if (currentActionAndName.name.find("libra") != std::string::npos)
  398. // {
  399. // libraCheck = true;
  400. // menuDownload->addAction("LIBRA");
  401. // }
  402. // }
  403. //}
  404. }
  405. bool sbrtCheck = false;
  406. for (const auto &currentActionAndName : vectorOfLungApps)
  407. {
  408. if (currentActionAndName.name != "Lung Cancer")
  409. {
  410. if (!sbrtCheck)
  411. {
  412. if ((currentActionAndName.name.find("LungField") != std::string::npos) ||
  413. (currentActionAndName.name.find("Nodule") != std::string::npos) ||
  414. (currentActionAndName.name.find("Analysis") != std::string::npos))
  415. {
  416. sbrtCheck = true;
  417. //menuDownload->addAction("LungCancer");
  418. }
  419. }
  420. }
  421. }
  422. for (const auto &currentActionAndName : vectorOfMiscApps)
  423. {
  424. if (currentActionAndName.name != "Miscellaneous")
  425. {
  426. if ((currentActionAndName.name != "itksnap") && (currentActionAndName.name != "deepmedic"))
  427. {
  428. if (!currentActionAndName.name.empty())
  429. {
  430. //menuDownload->addAction(currentActionAndName.name.c_str());
  431. }
  432. }
  433. }
  434. }
  435. m_imagesTable = imagesPanel->GetImagesTable();
  436. m_nonVisImagesTable = imagesPanel->GetNonViewingImagesTable();
  437. assert(m_imagesTable != NULL);
  438. assert(m_nonVisImagesTable != NULL);
  439. mSequenceNumber = 0;
  440. t1cePath = "";
  441. QString msg = tr(EXE_NAME);
  442. #ifdef SW_VER
  443. msg += " - v" + tr(SW_VER);
  444. #endif
  445. this->setWindowTitle(msg);
  446. #ifdef Q_OS_WIN32
  447. currentPlatform = "windows";
  448. #endif
  449. mInputPathName = "";
  450. //mMainWidget = this;
  451. mCurrentSelectedImageId = "";
  452. mCurrentPickedImageId = "";
  453. mCurrentPickedImageIndex = 0;
  454. mCurrentNearPoints = 0;
  455. mCurrentFarPoints = 0;
  456. mCurrentInitPoints = 0;
  457. mCustomImageToThreshold = itk::Image< short, 3 >::New();
  458. mProjectVariant = std::string(PROJECT_VARIANT);
  459. connect(&registrationPanel,
  460. SIGNAL(RegistrationSignal(std::string, std::vector<std::string>, std::vector<std::string>, std::vector<std::string>, std::string, bool, bool, bool, std::string, std::string)),
  461. this,
  462. SLOT(Registration(std::string, std::vector<std::string>, std::vector<std::string>, std::vector<std::string>, std::string, bool, bool, bool, std::string, std::string)));
  463. cbica::createDir(loggerFolder);
  464. m_tempFolderLocation = loggerFolder + "tmp_" + cbica::getCurrentProcessID();
  465. if (cbica::directoryExists(m_tempFolderLocation))
  466. {
  467. auto temp = cbica::stringSplit(cbica::getCurrentLocalTime(), ":");
  468. m_tempFolderLocation += temp[0] + temp[1] + temp[2] + "/";
  469. }
  470. cbica::createDir(m_tempFolderLocation);
  471. mLandmarks = new Landmarks(LANDMARK_TYPE::DEFAULT);
  472. mSeedPoints = new Landmarks(LANDMARK_TYPE::TUMOR_POINTS);
  473. mTissuePoints = new Landmarks(LANDMARK_TYPE::TISSUE_POINTS);
  474. mMask = vtkSmartPointer<vtkImageData>::New();
  475. mSlicerManagers.resize(0);
  476. image4DSlider->setEnabled(false);
  477. image4DSlider->setValue(0);
  478. connect(imagesPanel, SIGNAL(sigOverlayCheckBoxChanged(int)), this, SLOT(overlayUseStateChanged(int)));
  479. connect(imagesPanel, SIGNAL(sigOverlaySliderChanged(int)), this, SLOT(overlaySliderChanged(int)));
  480. connect(imagesPanel, SIGNAL(sigOverlayChanged()), this, SLOT(overlayChanged()));
  481. connect(imagesPanel, SIGNAL(sigTheiaClicked()), this, SLOT(ApplicationTheia()));
  482. connect(imagesPanel, SIGNAL(CompareModeToggled(bool)), this, SLOT(EnableComparisonMode(bool)));
  483. connect(imagesPanel, SIGNAL(sigImageModalityChanged(int)), this, SLOT(imageModalityChanged(int)));
  484. connect(imagesPanel, SIGNAL(helpClicked_Interaction(std::string)), this, SLOT(help_contextual(std::string)));
  485. connect(image4DSlider, SIGNAL(valueChanged(int)), this, SLOT(imageSliderChanged()));
  486. SetPresetComboBox();
  487. // init the sliders
  488. verticalSliders.push_back(AxialViewSlider);
  489. verticalSliders.push_back(CoronalViewSlider);
  490. verticalSliders.push_back(SaggitalViewSlider);
  491. for (int i = 0; i < 3; i++)
  492. {
  493. verticalSliders[i]->hide();
  494. }
  495. connect(AxialViewSlider, SIGNAL(valueChanged(int)), this, SLOT(AxialViewSliderChanged()));
  496. connect(CoronalViewSlider, SIGNAL(valueChanged(int)), this, SLOT(CoronalViewSliderChanged()));
  497. connect(SaggitalViewSlider, SIGNAL(valueChanged(int)), this, SLOT(SaggitalViewSliderChanged()));
  498. connect(actionLoad_Recurrence_Images, SIGNAL(triggered()), this, SLOT(openImages()));
  499. connect(actionLoad_Nifti_Images, SIGNAL(triggered()), this, SLOT(openImages()));
  500. //connect(actionLoad_Dicom_Images, SIGNAL(triggered()), this, SLOT(openDicomImages()));
  501. connect(actionSave_ROI_Images, SIGNAL(triggered()), this, SLOT(SaveDrawing()));
  502. connect(actionSave_ROI_Dicom_Images, SIGNAL(triggered()), this, SLOT(SaveDicomDrawing()));
  503. connect(actionSave_Nifti_Images, SIGNAL(triggered()), this, SLOT(SaveImage()));
  504. connect(actionSave_Dicom_Images, SIGNAL(triggered()), this, SLOT(SaveDicomImage()));
  505. connect(actionPreferences, SIGNAL(triggered()), this, SLOT(OnPreferencesMenuClicked()));
  506. connect(actionLoad_Nifti_ROI, SIGNAL(triggered()), this, SLOT(LoadDrawing()));
  507. connect(actionExit, SIGNAL(triggered()), this, SLOT(close()));
  508. connect(actionAbout, SIGNAL(triggered()), this, SLOT(about()));
  509. connect(actionHelp_Interactions, SIGNAL(triggered()), this, SLOT(help_Interactions()));
  510. connect(help_bugs, SIGNAL(triggered()), this, SLOT(help_BugTracker()));
  511. //connect(menuDownload, SIGNAL(triggered(QAction*)), this, SLOT(help_Download(QAction*)));
  512. connect(&mHelpTutorial, SIGNAL(skipTutorialOnNextRun(bool)), this, SLOT(skipTutorial(bool)));
  513. for (size_t i = 0; i < vectorOfGBMApps.size(); i++)
  514. {
  515. if (vectorOfGBMApps[i].name.find("EGFRvIIISurrogate") != std::string::npos)
  516. {
  517. vectorOfGBMApps[i].action->setText(" Glioblastoma EGFRvIII Surrogate Index (PHI Estimator)"); // TBD set at source
  518. connect(vectorOfGBMApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationEGFR()));
  519. }
  520. if (vectorOfGBMApps[i].name.find("EGFRvIIISVM") != std::string::npos)
  521. {
  522. vectorOfGBMApps[i].action->setText(" Glioblastoma EGFRvIII SVM Index"); // TBD set at source
  523. connect(vectorOfGBMApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationEGFRvIIISVM()));
  524. }
  525. else if (vectorOfGBMApps[i].name.find("Recurrence") != std::string::npos)
  526. {
  527. vectorOfGBMApps[i].action->setText(" Glioblastoma Infiltration Index"); // TBD set at source
  528. connect(vectorOfGBMApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationRecurrence()));
  529. }
  530. else if (vectorOfGBMApps[i].name.find("PseudoProgression") != std::string::npos)
  531. {
  532. vectorOfGBMApps[i].action->setText(" Glioblastoma PseudoProgression Infiltration Index"); // TBD set at source
  533. connect(vectorOfGBMApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationPseudoProgression()));
  534. }
  535. else if (vectorOfGBMApps[i].name.find("Survival") != std::string::npos)
  536. {
  537. vectorOfGBMApps[i].action->setText(" Glioblastoma Survival Prediction Index"); // TBD set at source
  538. connect(vectorOfGBMApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationSurvival()));
  539. }
  540. else if (vectorOfGBMApps[i].name.find("PopulationAtlases") != std::string::npos)
  541. {
  542. vectorOfGBMApps[i].action->setText(" Population Atlas"); // TBD set at source
  543. connect(vectorOfGBMApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationPopulationAtlas()));
  544. }
  545. else if (vectorOfGBMApps[i].name.find("ImagingSubtype") != std::string::npos)
  546. {
  547. vectorOfGBMApps[i].action->setText(" Glioblastoma Imaging Subtype Predictor"); // TBD set at source
  548. connect(vectorOfGBMApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationImagingSubtype()));
  549. }
  550. else if (vectorOfGBMApps[i].name.find("MolecularSubtypePredictor") != std::string::npos)
  551. {
  552. vectorOfGBMApps[i].action->setText(" Glioblastoma Molecular Subtype Predictor"); // TBD set at source
  553. connect(vectorOfGBMApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationMolecularSubtype()));
  554. }
  555. else if (vectorOfGBMApps[i].name.find("WhiteStripe") != std::string::npos)
  556. {
  557. vectorOfGBMApps[i].action->setText(" WhiteStripe Normalization"); // TBD set at source
  558. connect(vectorOfGBMApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationWhiteStripe()));
  559. }
  560. else if (vectorOfGBMApps[i].name.find("confetti") != std::string::npos)
  561. {
  562. vectorOfGBMApps[i].action->setText(" Confetti"); //TBD set at source
  563. connect(vectorOfGBMApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationConfetti()));
  564. }
  565. else if (vectorOfGBMApps[i].name.find("DirectionalityEstimate") != std::string::npos)
  566. {
  567. vectorOfGBMApps[i].action->setText(" Directionality Estimator"); //TBD set at source
  568. connect(vectorOfGBMApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationDirectionality()));
  569. }
  570. }
  571. for (size_t i = 0; i < vectorOfBreastApps.size(); i++)
  572. {
  573. if (vectorOfBreastApps[i].name.find("librasingle") != std::string::npos)
  574. {
  575. vectorOfBreastApps[i].action->setText(" Breast Density Estimator (LIBRA) SingleImage"); //TBD set at source
  576. connect(vectorOfBreastApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationLIBRASingle()));
  577. }
  578. else if (vectorOfBreastApps[i].name.find("librabatch") != std::string::npos)
  579. {
  580. vectorOfBreastApps[i].action->setText(" Breast Density Estimator (LIBRA) BatchMode"); //TBD set at source
  581. connect(vectorOfBreastApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationLIBRABatch()));
  582. }
  583. else if (vectorOfBreastApps[i].name.find("breastSegment") != std::string::npos)
  584. {
  585. vectorOfBreastApps[i].action->setText(" Breast Segmentation"); //TBD set at source
  586. connect(vectorOfBreastApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationBreastSegmentation()));
  587. }
  588. else if (vectorOfBreastApps[i].name.find("texturePipeline") != std::string::npos)
  589. {
  590. vectorOfBreastApps[i].action->setText(" Texture Feature Pipeline"); //TBD set at source
  591. connect(vectorOfBreastApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationTexturePipeline()));
  592. }
  593. }
  594. for (size_t i = 0; i < vectorOfLungApps.size(); i++)
  595. {
  596. if (vectorOfLungApps[i].name.find("LungField") != std::string::npos)
  597. {
  598. vectorOfLungApps[i].action->setText(" Lung Field Segmentation");
  599. connect(vectorOfLungApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationSBRTLungField()));
  600. }
  601. if (vectorOfLungApps[i].name.find("Nodule") != std::string::npos)
  602. {
  603. vectorOfLungApps[i].action->setText(" Lung Nodule Segmentation");
  604. connect(vectorOfLungApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationSBRTNodule()));
  605. }
  606. if (vectorOfLungApps[i].name.find("Analysis") != std::string::npos)
  607. {
  608. vectorOfLungApps[i].action->setText(" Prognostic Modeling");
  609. connect(vectorOfLungApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationSBRTAnalysis()));
  610. }
  611. }
  612. for (size_t i = 0; i < vectorOfSegmentationApps.size(); i++)
  613. {
  614. if (vectorOfSegmentationApps[i].name.find("itksnap") != std::string::npos)
  615. {
  616. vectorOfSegmentationApps[i].action->setText(" ITK-SNAP"); //TBD set at source
  617. connect(vectorOfSegmentationApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationITKSNAP()));
  618. }
  619. else if (vectorOfSegmentationApps[i].name.find("GeodesicSegmentation") != std::string::npos)
  620. {
  621. vectorOfSegmentationApps[i].action->setText(" Geodesic Segmentation"); // TBD set at source
  622. connect(vectorOfSegmentationApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationGeodesic()));
  623. }
  624. else if (vectorOfSegmentationApps[i].name.find("GeodesicTrainingSegmentation") != std::string::npos)
  625. {
  626. vectorOfSegmentationApps[i].action->setText(" Geodesic Training Segmentation"); // TBD set at source
  627. connect(vectorOfSegmentationApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationGeodesicTraining()));
  628. }
  629. else if (vectorOfSegmentationApps[i].name.find("deepmedic_tumor") != std::string::npos)
  630. {
  631. vectorOfSegmentationApps[i].action->setText(" Brain Tumor Segmentation (DeepLearning)"); // TBD set at source
  632. connect(vectorOfSegmentationApps[i].action, &QAction::triggered, this, [this] { ApplicationDeepMedicSegmentation(fDeepMedicDialog::Tumor); });
  633. }
  634. else if (vectorOfSegmentationApps[i].name.find("deepmedic_brain") != std::string::npos)
  635. {
  636. vectorOfSegmentationApps[i].action->setText(" Skull Stripping (DeepLearning)"); // TBD set at source
  637. connect(vectorOfSegmentationApps[i].action, &QAction::triggered, this, [this] { ApplicationDeepMedicSegmentation(fDeepMedicDialog::SkullStripping); });
  638. }
  639. }
  640. for (size_t i = 0; i < vectorOfMiscApps.size(); i++)
  641. {
  642. if (vectorOfMiscApps[i].name.find("DirectionalityEstimate") != std::string::npos)
  643. {
  644. vectorOfMiscApps[i].action->setText(" Directionality Estimator"); //TBD set at source
  645. connect(vectorOfMiscApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationDirectionality()));
  646. }
  647. else if (vectorOfMiscApps[i].name.find("PerfusionPCA") != std::string::npos)
  648. {
  649. vectorOfMiscApps[i].action->setText(" Perfusion PCA"); //TBD set at source
  650. connect(vectorOfMiscApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationPCA()));
  651. }
  652. else if (vectorOfMiscApps[i].name.find("PerfusionDerivatives") != std::string::npos)
  653. {
  654. vectorOfMiscApps[i].action->setText(" Perfusion Derivatives"); //TBD set at source
  655. connect(vectorOfMiscApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationPerfusionMeasuresCalculation()));
  656. }
  657. else if (vectorOfMiscApps[i].name.find("PerfusionAlignment") != std::string::npos)
  658. {
  659. vectorOfMiscApps[i].action->setText(" Perfusion Alignment"); //TBD set at source
  660. connect(vectorOfMiscApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationPerfusionAlignmentCalculation()));
  661. }
  662. else if (vectorOfMiscApps[i].name.find("DiffusionDerivatives") != std::string::npos)
  663. {
  664. vectorOfMiscApps[i].action->setText(" Diffusion Derivatives"); //TBD set at source
  665. connect(vectorOfMiscApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationDiffusionMeasuresCalculation()));
  666. }
  667. else if (vectorOfMiscApps[i].name.find("TrainingModule") != std::string::npos)
  668. {
  669. vectorOfMiscApps[i].action->setText(" Training Module"); //TBD set at source
  670. connect(vectorOfMiscApps[i].action, SIGNAL(triggered()), this, SLOT(ApplicationTrainingModule()));
  671. }
  672. }
  673. // add a single function for all preprocessing steps, this function will check for the specific names and then initiate that algorithm
  674. for (size_t i = 0; i < vectorOfPreprocessingActionsAndNames.size(); i++)
  675. {
  676. if (vectorOfPreprocessingActionsAndNames[i].name.find("Denoise") != std::string::npos)
  677. {
  678. connect(vectorOfPreprocessingActionsAndNames[i].action, SIGNAL(triggered()), this, SLOT(ImageDenoising()));
  679. }
  680. else if (vectorOfPreprocessingActionsAndNames[i].name.find("BiasCorrect") != std::string::npos)
  681. {
  682. vectorOfPreprocessingActionsAndNames[i].action->setText("BiasCorrection");//TBD set at source
  683. connect(vectorOfPreprocessingActionsAndNames[i].action, SIGNAL(triggered()), this, SLOT(ImageBiasCorrection()));
  684. }
  685. else if (vectorOfPreprocessingActionsAndNames[i].name.find("GreedyRegistration") != std::string::npos)
  686. {
  687. vectorOfPreprocessingActionsAndNames[i].action->setText("Registration");
  688. connect(vectorOfPreprocessingActionsAndNames[i].action, SIGNAL(triggered()), this, SLOT(ImageRegistration()));
  689. }
  690. else if (vectorOfPreprocessingActionsAndNames[i].name.find("HistogramMatching") != std::string::npos)
  691. {
  692. connect(vectorOfPreprocessingActionsAndNames[i].action, SIGNAL(triggered()), this, SLOT(ImageHistogramMatching()));
  693. }
  694. else if (vectorOfPreprocessingActionsAndNames[i].name.find("DeepMedicNormalizer") != std::string::npos)
  695. {
  696. vectorOfPreprocessingActionsAndNames[i].action->setText("Z-Scoring Normalizer"); // TBD set at source
  697. connect(vectorOfPreprocessingActionsAndNames[i].action, SIGNAL(triggered()), this, SLOT(ImageDeepMedicNormalizer()));
  698. }
  699. else if (vectorOfPreprocessingActionsAndNames[i].name.find("SkullStripping") != std::string::npos)
  700. {
  701. vectorOfPreprocessingActionsAndNames[i].action->setText("Skull Stripping");
  702. vectorOfPreprocessingActionsAndNames[i].action->setDisabled(true);
  703. connect(vectorOfPreprocessingActionsAndNames[i].action, SIGNAL(triggered()), this, SLOT(ImageSkullStripping()));
  704. }
  705. //else if (vectorOfPreprocessingActionsAndNames[i].name.find("DCM2NIfTI") != std::string::npos)
  706. //{
  707. // vectorOfPreprocessingActionsAndNames[i].action->setText("DICOM to NIfTI");
  708. // connect(vectorOfPreprocessingActionsAndNames[i].action, SIGNAL(triggered()), this, SLOT(DCM2NIfTIConversion()));
  709. //}
  710. else if (vectorOfPreprocessingActionsAndNames[i].name.find("deepmedic_brain") != std::string::npos)
  711. {
  712. vectorOfPreprocessingActionsAndNames[i].action->setText("Skull Stripping (DeepLearning)"); // TBD set at source
  713. connect(vectorOfPreprocessingActionsAndNames[i].action, &QAction::triggered, this, [this] { ApplicationDeepMedicSegmentation(fDeepMedicDialog::SkullStripping); });
  714. }
  715. else if (vectorOfPreprocessingActionsAndNames[i].name.find("breastNormalize") != std::string::npos)
  716. {
  717. vectorOfPreprocessingActionsAndNames[i].action->setText("Mammogram Preprocessing");
  718. connect(vectorOfPreprocessingActionsAndNames[i].action, SIGNAL(triggered()), this, SLOT(ImageMamogramPreprocess()));
  719. }
  720. else if (vectorOfPreprocessingActionsAndNames[i].name.find("BraTSPipeline") != std::string::npos)
  721. {
  722. vectorOfPreprocessingActionsAndNames[i].action->setText("BraTS Pipeline");
  723. connect(vectorOfPreprocessingActionsAndNames[i].action, SIGNAL(triggered()), this, SLOT(ImageBraTSPipeline()));
  724. }
  725. }
  726. // add a single function for all preprocessing steps, this function will check for the specific names and then initiate that algorithm
  727. for (size_t i = 0; i < vectorOfDeepLearningActionsAndNames.size(); i++)
  728. {
  729. if (vectorOfDeepLearningActionsAndNames[i].name.find("deepmedic_tumor") != std::string::npos)
  730. {
  731. vectorOfDeepLearningActionsAndNames[i].action->setText("Brain Tumor Segmentation"); // TBD set at source
  732. connect(vectorOfDeepLearningActionsAndNames[i].action, &QAction::triggered, this, [this] { ApplicationDeepMedicSegmentation(fDeepMedicDialog::Tumor); });
  733. }
  734. else if (vectorOfDeepLearningActionsAndNames[i].name.find("deepmedic_brain") != std::string::npos)
  735. {
  736. vectorOfDeepLearningActionsAndNames[i].action->setText("Skull Stripping"); // TBD set at source
  737. connect(vectorOfDeepLearningActionsAndNames[i].action, &QAction::triggered, this, [this] { ApplicationDeepMedicSegmentation(fDeepMedicDialog::SkullStripping); });
  738. }
  739. }
  740. //connect(&fetalbrainpanel, SIGNAL(skullstripfun()), this, SLOT(FetalBrain_SkullStripfunc()));
  741. //connect(&fetalbrainpanel, SIGNAL(drawlinear()), this, SLOT(FetalBrain_Predict()));
  742. //connect(&fetalbrainpanel, SIGNAL(TrainNewFetalModel(std::string, std::string)), this, SLOT(FetalBrain_TrainNewModel(const std::string &, const std::string &)));
  743. connect(m_imagesTable, SIGNAL(itemSelectionChanged()), this, SLOT(DisplayChanged()));
  744. connect(m_imagesTable, SIGNAL(itemClicked(QTableWidgetItem*)), this, SLOT(DisplayChanged(QTableWidgetItem*)));
  745. connect(imagesPanel, SIGNAL(sigImageTableSelectionChanged()), this, SLOT(DisplayChanged()));
  746. connect(windowSpinBox, SIGNAL(editingFinished()), this, SLOT(WindowLevelEdited()));
  747. connect(levelSpinBox, SIGNAL(editingFinished()), this, SLOT(WindowLevelEdited()));
  748. connect(presetComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateWindowLevel()));
  749. connect(thresholdSpinBox, SIGNAL(valueChanged(double)), this, SLOT(thresholdSpinBoxChanged()));
  750. thresholdSpinBox->setValue(20);
  751. //connect(tumorPanel, SIGNAL(UpdateRenderWindows()), this, SLOT(UpdateRenderWindows()));
  752. //connect(tumorPanel, SIGNAL(SetActiveLandmarksTypeSignal(int, int, int)), this, SLOT(SetActiveLandmarksType(int, int, int)));
  753. //connect(tumorPanel, SIGNAL(MoveSlicerCursor(double, double, double)), this, SLOT(MoveSlicerCursor(double, double, double)));
  754. //connect(tumorPanel, SIGNAL(helpClicked_Interaction(std::string)), this, SLOT(help_contextual(std::string)));
  755. connect(segmentationPanel, SIGNAL(helpClicked_SegmentationUsage(std::string)), this, SLOT(help_contextual(std::string)));
  756. connect(trainingPanel, SIGNAL(helpClicked_SegmentationUsage(std::string)), this, SLOT(help_contextual(std::string)));
  757. connect(drawingPanel, SIGNAL(clearMask(int)), this, SLOT(clearMask(int)));
  758. connect(drawingPanel, SIGNAL(CurrentBrushSizeChanged(int)), this, SLOT(ChangeBrushSize(int)));
  759. connect(drawingPanel, SIGNAL(UndoButtonClicked()), this, SLOT(UndoFunctionality()));
  760. //connect(drawingPanel, SIGNAL(FillButtonClicked(int)), this, SLOT(FillLabel(int)));
  761. connect(drawingPanel, SIGNAL(shapesButtonClicked(int)), this, SLOT(updateDrawMode(int)));
  762. connect(drawingPanel, SIGNAL(CurrentDrawingLabelChanged(int)), this, SLOT(updateDrawMode()));
  763. connect(drawingPanel, SIGNAL(CurrentMaskOpacityChanged(int)), this, SLOT(ChangeMaskOpacity(int)));
  764. connect(drawingPanel, SIGNAL(helpClicked_Interaction(std::string)), this, SLOT(help_contextual(std::string)));
  765. connect(drawingPanel, SIGNAL(sig_ChangeLabelValuesClicked(const std::string, const std::string)), this, SLOT(CallLabelValuesChange(const std::string, const std::string)));
  766. //connect(&recurrencePanel, SIGNAL(SubjectBasedRecurrenceEstimate(std::string, bool, bool, bool, bool)), this, SLOT(StartRecurrenceEstimate(const std::string &, bool, bool, bool, bool)));
  767. //connect(&recurrencePanel, SIGNAL(SubjectBasedExistingRecurrenceEstimate(std::string, std::string, bool, bool, bool, bool)), this, SLOT(LoadedSubjectExistingRecurrenceEstimate(const std::string &, const std::string &, bool, bool, bool, bool)));
  768. //connect(&recurrencePanel, SIGNAL(ExistingModelBasedRecurrenceEstimate(std::string, std::string, std::string, bool, bool, bool, bool)), this, SLOT(RecurrenceEstimateOnExistingModel(const std::string &, const std::string &, const std::string &, bool, bool, bool, bool)));
  769. //connect(&recurrencePanel, SIGNAL(TrainNewModel(std::string, std::string, bool, bool, bool, bool)), this, SLOT(TrainNewModelOnGivenData(const std::string &, const std::string &, bool, bool, bool, bool)));
  770. //connect(&pseudoPanel, SIGNAL(ExistingModelBasedPseudoprogressionEstimate(std::string, std::string, std::string, bool, bool, bool, bool)), this, SLOT(PseudoprogressionEstimateOnExistingModel(const std::string &, const std::string &, const std::string &, bool, bool, bool, bool)));
  771. //connect(&pseudoPanel, SIGNAL(TrainNewPseudoModel(std::string, std::string, bool, bool, bool, bool)), this, SLOT(TrainNewPseudoprogressionModelOnGivenData(const std::string &, const std::string &, bool, bool, bool, bool)));
  772. //connect(&survivalPanel, SIGNAL(SurvivalPredictionOnExistingModel(const std::string, const std::string, const std::string)), this, SLOT(CallForSurvivalPredictionOnExistingModelFromMain(const std::string, const std::string, const std::string)));
  773. //connect(&survivalPanel, SIGNAL(PrepareNewSurvivalPredictionModel(const std::string, const std::string)), this, SLOT(CallForNewSurvivalPredictionModelFromMain(const std::string, const std::string)));
  774. //connect(&egfrv3Panel, SIGNAL(EGFRvIIIPredictionOnExistingModel(const std::string, const std::string, const std::string)), this, SLOT(CallForEGFRvIIIPredictionOnExistingModelFromMain(const std::string, const std::string, const std::string)));
  775. //connect(&egfrv3Panel, SIGNAL(PrepareNewEGFRvIIIPredictionModel(const std::string, const std::string)), this, SLOT(CallForNewEGFRvIIIPredictionModelFromMain(const std::string, const std::string)));
  776. //connect(&msubtypePanel, SIGNAL(MolecularSubtypePredictionOnExistingModel(const std::string, const std::string, const std::string)), this, SLOT(CallForMolecularSubtypePredictionOnExistingModelFromMain(const std::string, const std::string, const std::string)));
  777. //connect(&msubtypePanel, SIGNAL(PrepareNewMolecularSubtypePredictionModel(const std::string, const std::string)), this, SLOT(CallForNewMolecularSubtypePredictionModelFromMain(const std::string, const std::string)));
  778. //connect(&skullStrippingPanel, SIGNAL(RunSkullStripping(const std::string, const std::string, const std::string, const std::string)), this, SLOT(CallImageSkullStripping(const std::string, const std::string, const std::string, const std::string)));
  779. //connect(&dcmConverter, SIGNAL(RunDICOMConverter(const std::string, const std::string)), this, SLOT(CallDCM2NIfTIConversion(const std::string, const std::string)));
  780. connect(&histoMatchPanel, SIGNAL(RunHistogramMatching(const std::string, const std::string, const std::string)), this, SLOT(CallImageHistogramMatching(const std::string, const std::string, const std::string)));
  781. //connect(&deepMedicNormPanel, SIGNAL(RunDeepMedicNormalizer(const std::string, const std::string, const std::string, const std::string, const std::string, const std::string, const std::string, bool)), this, SLOT(CallImageDeepMedicNormalizer(const std::string, const std::string, const std::string, const std::string, const std::string, const std::string, const std::string, bool)));
  782. //connect(&directionalityEstimator, SIGNAL(RunDirectionalityEstimator(const std::string, const std::string, const std::string)), this, SLOT(CallDirectionalityEstimator(const std::string, const std::string, const std::string)));
  783. connect(&bratsPipelineDialog, SIGNAL(RunBraTSPipeline(const std::string, const std::string, const std::string, const std::string, const std::string)), this, SLOT(CallBraTSPipeline(const std::string, const std::string, const std::string, const std::string, const std::string)));
  784. //connect(&pcaPanel, SIGNAL(ExistingModelBasedPCAEstimate(std::string, std::string, std::string)), this, SLOT(PCAEstimateOnExistingModel(const std::string &, const std::string &, const std::string &)));
  785. //connect(&pcaPanel, SIGNAL(TrainNewPCAModel(std::string, std::string)), this, SLOT(TrainNewPCAModelOnGivenData(const std::string &, const std::string &)));
  786. //connect(&pcaPanel, SIGNAL(RunPCAEstimation(const int, const std::string, const std::string)), this, SLOT(CallPCACalculation(const int, const std::string, const std::string)));
  787. //connect(&trainingPanel, SIGNAL(RunTrainingSimulation(const std::string, const std::string, const std::string, const std::string, int, int, int)), this, SLOT(CallTrainingSimulation(const std::string, const std::string, const std::string, const std::string, int, int, int)));
  788. //connect(&perfmeasuresPanel, SIGNAL(RunPerfusionMeasuresCalculation(const double, const bool, const bool, const bool, const std::string, const std::string)), this, SLOT(CallPerfusionMeasuresCalculation(const double, const bool, const bool, const bool, const std::string, const std::string)));
  789. //connect(&perfalignPanel, SIGNAL(RunPerfusionAlignmentCalculation(double,int, int,const std::string, const std::string, const std::string, const std::string)), this, SLOT(CallPerfusionAlignmentCalculation(double,int, int, const std::string, const std::string, const std::string, const std::string)));
  790. //connect(&diffmeasuresPanel, SIGNAL(RunDiffusionMeasuresCalculation(const std::string, const std::string, const std::string, const std::string, const bool, const bool, const bool, const bool, const std::string)), this,
  791. //SLOT(CallDiffusionMeasuresCalculation(const std::string, const std::string, const std::string, const std::string, const bool, const bool, const bool, const bool, const std::string)));
  792. //connect(&whiteStripeNormalizer, SIGNAL(RunWhiteStripe(double, int, int, int, double, double, int, bool, const std::string)), this, SLOT(CallWhiteStripe(double, int, int, int, double, double, int, bool, const std::string)));
  793. //connect(&atlasPanel, SIGNAL(GeneratePopualtionAtlas(const std::string, const std::string, const std::string, const std::string)), this, SLOT(CallGeneratePopualtionAtlas(const std::string, const std::string, const std::string, const std::string)));
  794. //connect(&nodulePanel, SIGNAL(SBRTNoduleParamReady(const std::string, const int)), this, SLOT(CallSBRTNodule(const std::string, const int)));
  795. connect(&deepMedicDialog, SIGNAL(RunDeepMedic(const std::string, const std::string)), this, SLOT(CallDeepMedicSegmentation(const std::string, const std::string)));
  796. //connect(&texturePipelineDialog, SIGNAL(RunTextureFeaturePipeline(const std::string)), this, SLOT(CallTexturePipeline(const std::string)));
  797. //connect(this, SIGNAL(SeedPointsFocused(bool)), tumorPanel, SLOT(sTableFocused(bool)));
  798. //connect(this, SIGNAL(TissuePointsFocused(bool)), tumorPanel, SLOT(tTableFocused(bool)));
  799. connect(m_tabWidget, SIGNAL(currentChanged(int)), this, SLOT(panelChanged(int)));
  800. connect(infoPanel, SIGNAL(MoveSlicerCursor(double, double, double, int)), this, SLOT(MoveSlicerCursor(double, double, double, int)));
  801. AxialViewWidget->hide();
  802. CoronalViewWidget->hide();
  803. SaggitalViewWidget->hide();
  804. infoPanel->show();
  805. windowLabel->setEnabled(false);
  806. windowSpinBox->setEnabled(false);
  807. levelSpinBox->setEnabled(false);
  808. levelLabel->setEnabled(false);
  809. thresholdLabel->setEnabled(false);
  810. thresholdSpinBox->setEnabled(false);
  811. presetLabel->setEnabled(false);
  812. presetComboBox->setEnabled(false);
  813. setAcceptDrops(true);
  814. mCustomImageToThreshold_min = 0;
  815. mCustomImageToThreshold_max = 0;
  816. m_drawShapeMode = SHAPE_MODE_NONE;
  817. m_messageLabel = new QLabel(":");
  818. statusBar()->addPermanentWidget(m_messageLabel);
  819. m_progressBar = new QProgressBar(this);
  820. QSize tempSize = this->size();
  821. m_progressBar->setFixedWidth(tempSize.width() * 0.75);
  822. statusBar()->addPermanentWidget(m_progressBar);
  823. m_progressBar->setValue(0);
  824. mHelpDlg = new fHelpDialog();
  825. //connect
  826. connect(m_toolTabdock, SIGNAL(topLevelChanged(bool)), this, SLOT(toolTabDockChanged(bool)));
  827. //recurrencePanel.SetCurrentLoggerPath(m_tempFolderLocation);
  828. //msubtypePanel.SetCurrentLoggerPath(m_tempFolderLocation);
  829. //survivalPanel.SetCurrentLoggerPath(m_tempFolderLocation);
  830. //
  831. actionLoad_Nifti_Images->setText(QApplication::translate("fMainWindow", "Image(s)", 0));
  832. actionLoad_Nifti_ROI->setText(QApplication::translate("fMainWindow", "ROI", 0));
  833. actionLoad_Dicom_Images->setText(QApplication::translate("fMainWindow", "Dicom", 0));
  834. actionPreferences->setText(QApplication::translate("fMainWindow", "Preferences", 0));
  835. actionSave_Nifti_Images->setText(QApplication::translate("fMainWindow", "Image (NIfTI)", 0));
  836. actionSave_Dicom_Images->setText(QApplication::translate("fMainWindow", "Image (DICOM)", 0));
  837. actionSave_ROI_Images->setText(QApplication::translate("fMainWindow", "ROI (NIfTI)", 0));
  838. actionSave_ROI_Dicom_Images->setText(QApplication::translate("fMainWindow", "ROI (DICOM)", 0));
  839. actionHelp_Interactions->setText(QApplication::translate("fMainWindow", "Usage", 0));
  840. help_discussion->setText(QApplication::translate("fMainWindow", "Discussion Forum", 0));
  841. help_forum->setText(QApplication::translate("fMainWindow", "Help Forum", 0));
  842. help_bugs->setText(QApplication::translate("fMainWindow", "Bugs and Feature", 0));
  843. help_features->setText(QApplication::translate("fMainWindow", "Feature Requests", 0));
  844. help_download->setText(QApplication::translate("fMainWindow", "Latest Downloads", 0));
  845. actionAbout->setText(QApplication::translate("fMainWindow", "About", 0));
  846. actionExit->setText(QApplication::translate("fMainWindow", "Exit", 0));
  847. actionAppGeodesic->setText(QApplication::translate("fMainWindow", "Geodesic segmentation", 0));
  848. actionAppGeodesicTraining->setText(QApplication::translate("fMainWindow", "Geodesic Training Segmentation", 0));
  849. //m_tabWidget->setTabText(m_tabWidget->indexOf(tumorPanel), QApplication::translate("fMainWindow", "Seed Points", 0));
  850. m_tabWidget->setTabText(m_tabWidget->indexOf(drawingPanel), QApplication::translate("fMainWindow", "Drawing", 0));
  851. m_tabWidget->setTabText(m_tabWidget->indexOf(imagesPanel), QApplication::translate("fMainWindow", "Images", 0));
  852. m_tabWidget->setTabText(m_tabWidget->indexOf(segmentationPanel), QApplication::translate("fMainWindow", "Segmentation", 0));
  853. m_tabWidget->setTabText(m_tabWidget->indexOf(trainingPanel), QApplication::translate("fMainWindow", "Training", 0));
  854. connect(segmentationPanel, SIGNAL(m_btnComputeClicked()), this, SLOT(OnSegmentationClicked()));
  855. connect(trainingPanel, SIGNAL(m_btnComputeClicked()), this, SLOT(OnTrainingClicked()));
  856. }
  857. fMainWindow::~fMainWindow()
  858. {
  859. for (int i = 0; i < (int)mSlicerManagers.size(); i++)
  860. {
  861. if (mSlicerManagers[i] != NULL)
  862. {
  863. delete mSlicerManagers[i];
  864. }
  865. }
  866. if (mLandmarks)
  867. {
  868. delete mLandmarks;
  869. }
  870. if (mSeedPoints)
  871. {
  872. delete mSeedPoints;
  873. }
  874. if (mTissuePoints)
  875. {
  876. delete mTissuePoints;
  877. }
  878. // delete the temp directory every single time
  879. //if (cbica::filesInDirectory(m_tempFolderLocation).empty())
  880. {
  881. cbica::deleteDir(m_tempFolderLocation);
  882. }
  883. if (m_skipTutorialOnNextRun)
  884. {
  885. std::ofstream file;
  886. file.open(tutorialScreen.c_str());
  887. file << "User doesn't need the tutorial screen.\n";
  888. file.close();
  889. }
  890. if (mHelpDlg)
  891. delete mHelpDlg;
  892. if (segmentationPanel)
  893. {
  894. delete segmentationPanel;
  895. }
  896. if (trainingPanel)
  897. {
  898. delete trainingPanel;
  899. }
  900. ApplicationPreferences::GetInstance()->SerializePreferences();
  901. }
  902. void fMainWindow::ImageBraTSPipeline()
  903. {
  904. // open a simple dialog box with reference image, input and output
  905. bratsPipelineDialog.SetCurrentImagePath(mInputPathName);
  906. bratsPipelineDialog.exec();
  907. }
  908. void fMainWindow::CallBraTSPipeline(const std::string t1ceImage, const std::string t1Image, const std::string t2Image, const std::string flImage, const std::string outputDir)
  909. {
  910. if (!t1ceImage.empty() && !t1Image.empty() && !t2Image.empty() && !flImage.empty() && !outputDir.empty())
  911. {
  912. auto bratsPipelineExe = getApplicationPath("BraTSPipeline");
  913. if (!cbica::exists(bratsPipelineExe))
  914. {
  915. ShowErrorMessage("Could not find the BraTSPipeline executable");
  916. return;
  917. }
  918. QStringList args;
  919. args << "-t1" << t1Image.c_str() <<
  920. "-t1c" << t1ceImage.c_str() <<
  921. "-t2" << t2Image.c_str() <<
  922. "-fl" << flImage.c_str() <<
  923. "-o" << outputDir.c_str();
  924. QMessageBox *box = new QMessageBox(QMessageBox::Question, "Long running Application",
  925. "BraTS Pipeline takes ~30 minutes to run, during which FeTS UI will not be responsive; press OK to continue...",
  926. QMessageBox::Ok | QMessageBox::Cancel);
  927. box->setAttribute(Qt::WA_DeleteOnClose); //makes sure the msgbox is deleted automatically when closed
  928. box->setWindowModality(Qt::NonModal);
  929. QCoreApplication::processEvents();
  930. if (box->exec() == QMessageBox::Ok)
  931. {
  932. updateProgress(5, "Starting BraTS Pipeline");
  933. if (startExternalProcess(bratsPipelineExe.c_str(), args) != 0)
  934. {
  935. ShowErrorMessage("BraTS Pipeline returned with exit code != 0");
  936. updateProgress(0, "");
  937. return;
  938. }
  939. }
  940. }
  941. else
  942. {
  943. ShowErrorMessage("All input images need to be provided for BraTS Pipeline to run.");
  944. return;
  945. }
  946. }
  947. void fMainWindow::loadFromCommandLine(std::vector< QString > files, bool comparisonMode, const std::string &maskImage, const float maskOpacity,
  948. const std::string &tumorPointFile, const std::string &tissuePointFile, bool firstRun)
  949. {
  950. auto qvectorString = QVector< QString >::fromStdVector(files);
  951. auto lst = QStringList::fromVector(QVector< QString >::fromStdVector(files));
  952. this->openImages(lst, true);
  953. if (!maskImage.empty())
  954. {
  955. this->readMaskFile(maskImage);
  956. this->ChangeMaskOpacity(maskOpacity * 10);
  957. }
  958. if (!tumorPointFile.empty())
  959. {
  960. //this->tumorPanel->sLoad(tumorPointFile.c_str());
  961. }
  962. if (!tissuePointFile.empty())
  963. {
  964. //this->tumorPanel->tLoad(tissuePointFile.c_str());
  965. }
  966. if (comparisonMode)
  967. {
  968. this->imagesPanel->CompareButtonClick();
  969. }
  970. #ifdef CAPTK_PACKAGE_PROJECT
  971. if (firstRun)
  972. {
  973. this->CloseAllImages();
  974. }
  975. #endif
  976. }
  977. std::string fMainWindow::ConversionFrom2Dto3D(const std::string &fileName)
  978. {
  979. using ImageTypeFloat2D = itk::Image< float, 2 >;
  980. auto reader = itk::ImageFileReader< ImageTypeFloat2D >::New();
  981. reader->SetFileName(fileName);
  982. auto ext = cbica::getFilenameExtension(fileName);
  983. if (cbica::IsDicom(fileName))
  984. {
  985. reader->SetImageIO(itk::GDCMImageIO::New());
  986. }
  987. else if ((ext == ".nii") || (ext == ".nii.gz"))
  988. {
  989. reader->SetImageIO(itk::NiftiImageIO::New());
  990. }
  991. try
  992. {
  993. reader->Update();
  994. }
  995. catch (itk::ExceptionObject& e)
  996. {
  997. ShowErrorMessage("Exception caught while reading the image '" + fileName + "':\n\n" + e.what());
  998. return "";
  999. }
  1000. auto image_2D = reader->GetOutput();
  1001. auto index2D = image_2D->GetLargestPossibleRegion().GetIndex();
  1002. auto size2D = image_2D->GetLargestPossibleRegion().GetSize();
  1003. auto spacing2D = image_2D->GetSpacing();
  1004. auto origin2D = image_2D->GetOrigin();
  1005. // write into m_tempFolderLocation and then read pass that file to LoadSlicerImages
  1006. auto image_3D = ImageTypeFloat3D::New();
  1007. ImageTypeFloat3D::RegionType region;
  1008. ImageTypeFloat3D::RegionType::SizeType size;
  1009. ImageTypeFloat3D::RegionType::IndexType start;
  1010. ImageTypeFloat3D::PointType origin;
  1011. ImageTypeFloat3D::SpacingType spacing;
  1012. // populate the region to place the slice in
  1013. size[0] = size2D[0];
  1014. size[1] = size2D[1];
  1015. size[2] = 1;
  1016. start[0] = index2D[0];
  1017. start[1] = index2D[1];
  1018. start[2] = 0;
  1019. spacing[0] = image_2D->GetSpacing()[0];
  1020. spacing[1] = image_2D->GetSpacing()[1];
  1021. spacing[2] = 1;
  1022. origin[0] = origin2D[0];
  1023. origin[1] = origin2D[1];
  1024. origin[2] = 0;
  1025. region.SetSize(size);
  1026. region.SetIndex(start);
  1027. image_3D->SetRegions(region);
  1028. image_3D->SetRequestedRegion(region);
  1029. image_3D->SetBufferedRegion(region);
  1030. image_3D->Allocate();
  1031. image_3D->FillBuffer(0);
  1032. image_3D->SetOrigin(origin);
  1033. image_3D->SetSpacing(spacing);
  1034. itk::ImageRegionIteratorWithIndex <ImageTypeFloat3D> iter(image_3D, image_3D->GetLargestPossibleRegion());
  1035. itk::ImageRegionIteratorWithIndex <ImageTypeFloat2D> iter2d(image_2D, image_2D->GetLargestPossibleRegion());
  1036. for (iter.GoToBegin(), iter2d.GoToBegin(); !iter2d.IsAtEnd(); ++iter, ++iter2d)
  1037. {
  1038. iter.Set(iter2d.Get());
  1039. }
  1040. auto imageName = m_tempFolderLocation + "/" + cbica::getFilenameBase(fileName) + ".nii.gz";
  1041. cbica::WriteImage< ImageTypeFloat3D >(image_3D, imageName);
  1042. return imageName;
  1043. }
  1044. void fMainWindow::about()
  1045. {
  1046. #if CAPTK_PACKAGE_PROJECT
  1047. mHelpTutorial.exec();
  1048. #endif
  1049. }
  1050. void fMainWindow::help_Interactions()
  1051. {
  1052. openLink("https://fets-ai.github.io/Front-End/");
  1053. }
  1054. void fMainWindow::help_Download(QAction* action)
  1055. {
  1056. auto currentApp = action->text().toStdString();
  1057. std::string path = getCaPTkDataDir();
  1058. auto currentLink = "ftp://www.nitrc.org/home/groups/captk/downloads/SampleData_1.6.0/" + currentApp + ".zip";
  1059. cbica::Logging(loggerFile, currentLink);
  1060. if (!openLink(currentLink))
  1061. {
  1062. ShowErrorMessage("CaPTk couldn't open the browser to download specified sample data.", this);
  1063. return;
  1064. }
  1065. }
  1066. void fMainWindow::help_BugTracker()
  1067. {
  1068. if (!openLink("https://github.com/CBICA/CaPTk/issues"))
  1069. {
  1070. ShowErrorMessage("CaPTk couldn't open the browser to open the Bug Tracker");
  1071. return;
  1072. }
  1073. }
  1074. void fMainWindow::EnableThresholdOfMask()
  1075. {
  1076. // only do calculations on current image(s)
  1077. auto items = m_imagesTable->selectedItems();
  1078. if (items.empty())
  1079. {
  1080. return;
  1081. }
  1082. int index = GetSlicerIndexFromItem(items[0]);
  1083. if (index < 0 || index >= (int)mSlicerManagers.size())
  1084. {
  1085. return;
  1086. }
  1087. typedef itk::MinimumMaximumImageCalculator < ImageTypeFloat3D > ImageCalculatorFilterType;
  1088. ImageCalculatorFilterType::Pointer imageCalculatorFilter = ImageCalculatorFilterType::New();
  1089. imageCalculatorFilter->SetImage(mSlicerManagers[index]->mITKImage);
  1090. imageCalculatorFilter->Compute();
  1091. double actualMin = imageCalculatorFilter->GetMinimum();
  1092. double actualMax = imageCalculatorFilter->GetMaximum();
  1093. thresholdSpinBox->setRange(actualMin, actualMax);
  1094. thresholdSpinBox->setValue((actualMin + actualMax) / 2);
  1095. }
  1096. void fMainWindow::SaveImage_withFile(int indexOfInputImageToWrite, QString saveFileName)
  1097. {
  1098. auto index = indexOfInputImageToWrite;
  1099. if (!saveFileName.isEmpty())
  1100. {
  1101. auto saveFileName_string = saveFileName.toStdString();
  1102. typedef ImageTypeFloat3D ImageType;
  1103. ImageType::DirectionType originalDirection;
  1104. originalDirection[0][0] = mSlicerManagers[index]->mDirection(0, 0);
  1105. originalDirection[0][1] = mSlicerManagers[index]->mDirection(0, 1);
  1106. originalDirection[0][2] = mSlicerManagers[index]->mDirection(0, 2);
  1107. originalDirection[1][0] = mSlicerManagers[index]->mDirection(1, 0);
  1108. originalDirection[1][1] = mSlicerManagers[index]->mDirection(1, 1);
  1109. originalDirection[1][2] = mSlicerManagers[index]->mDirection(1, 2);
  1110. originalDirection[2][0] = mSlicerManagers[index]->mDirection(2, 0);
  1111. originalDirection[2][1] = mSlicerManagers[index]->mDirection(2, 1);
  1112. originalDirection[2][2] = mSlicerManagers[index]->mDirection(2, 2);
  1113. ImageType::PointType originalOrigin;
  1114. originalOrigin = mSlicerManagers[index]->mOrigin;
  1115. if (mSlicerManagers[index]->GetPreset() == PRESET_THRESHOLD)
  1116. {
  1117. auto img = convertVtkToItk<ImageTypeFloat3D::PixelType, ImageTypeFloat3D::ImageDimension>(mSlicerManagers[index]->mImage);
  1118. double threshold = mSlicerManagers[index]->mThreshold;
  1119. //
  1120. auto duplicator = itk::ImageDuplicator< ImageTypeFloat3D >::New();
  1121. duplicator->SetInputImage(img);
  1122. duplicator->Update();
  1123. auto seg = duplicator->GetOutput();
  1124. //
  1125. itk::ImageRegionIterator< ImageTypeFloat3D > imgIterator(seg, seg->GetLargestPossibleRegion());
  1126. for (imgIterator.GoToBegin(); !imgIterator.IsAtEnd(); ++imgIterator)
  1127. {
  1128. // TBD: this was the original action to handle threshold -- needs testing
  1129. if (imgIterator.Get() <= threshold)
  1130. {
  1131. imgIterator.Set(1);
  1132. }
  1133. else
  1134. {
  1135. imgIterator.Set(0);
  1136. }
  1137. }
  1138. //
  1139. auto infoChanger = itk::ChangeInformationImageFilter< ImageType >::New();
  1140. infoChanger->SetInput(seg);
  1141. infoChanger->ChangeDirectionOn();
  1142. infoChanger->ChangeOriginOn();
  1143. infoChanger->SetOutputDirection(originalDirection);
  1144. infoChanger->SetOutputOrigin(originalOrigin);
  1145. infoChanger->Update();
  1146. cbica::WriteImage< ImageTypeFloat3D >(infoChanger->GetOutput(), correctExtension(saveFileName_string));
  1147. }
  1148. else
  1149. {
  1150. auto img = convertVtkToItk< ImageType::PixelType, ImageTypeFloat3D::ImageDimension>(mSlicerManagers[index]->mImage);
  1151. auto infoChanger = itk::ChangeInformationImageFilter< ImageType >::New();
  1152. infoChanger->SetInput(img);
  1153. infoChanger->ChangeDirectionOn();
  1154. infoChanger->ChangeOriginOn();
  1155. infoChanger->SetOutputDirection(originalDirection);
  1156. infoChanger->SetOutputOrigin(originalOrigin);
  1157. infoChanger->Update();
  1158. cbica::WriteImage< ImageType >(infoChanger->GetOutput(), correctExtension(saveFileName_string));
  1159. std::string InputPixelType = mSlicerManagers[index]->mImage->GetScalarTypeAsString();
  1160. if (InputPixelType == "short")
  1161. {
  1162. using ImageTypeToWrite = itk::Image<short, ImageTypeFloat3D::ImageDimension>;
  1163. auto img = convertVtkToItk<ImageTypeToWrite::PixelType, ImageTypeFloat3D::ImageDimension>(mSlicerManagers[index]->mImage);
  1164. auto infoChanger = itk::ChangeInformationImageFilter< ImageTypeToWrite >::New();
  1165. infoChanger->SetInput(img);
  1166. infoChanger->ChangeDirectionOn();
  1167. infoChanger->ChangeOriginOn();
  1168. infoChanger->SetOutputDirection(originalDirection);
  1169. infoChanger->SetOutputOrigin(originalOrigin);
  1170. infoChanger->Update();
  1171. cbica::WriteImage< ImageTypeToWrite >(infoChanger->GetOutput(), correctExtension(saveFileName_string));
  1172. }
  1173. else if (InputPixelType == "unsigned short")
  1174. {
  1175. using ImageTypeToWrite = itk::Image<unsigned short, ImageTypeFloat3D::ImageDimension>;
  1176. auto img = convertVtkToItk<ImageTypeToWrite::PixelType, ImageTypeFloat3D::ImageDimension>(mSlicerManagers[index]->mImage);
  1177. auto infoChanger = itk::ChangeInformationImageFilter< ImageTypeToWrite >::New();
  1178. infoChanger->SetInput(img);
  1179. infoChanger->ChangeDirectionOn();
  1180. infoChanger->ChangeOriginOn();
  1181. infoChanger->SetOutputDirection(originalDirection);
  1182. infoChanger->SetOutputOrigin(originalOrigin);
  1183. infoChanger->Update();
  1184. cbica::WriteImage< ImageTypeToWrite >(infoChanger->GetOutput(), correctExtension(saveFileName_string));
  1185. }
  1186. else if (InputPixelType == "char")
  1187. {
  1188. using ImageTypeToWrite = itk::Image<char, ImageTypeFloat3D::ImageDimension>;
  1189. auto img = convertVtkToItk<ImageTypeToWrite::PixelType, ImageTypeFloat3D::ImageDimension>(mSlicerManagers[index]->mImage);
  1190. auto infoChanger = itk::ChangeInformationImageFilter< ImageTypeToWrite >::New();
  1191. infoChanger->SetInput(img);
  1192. infoChanger->ChangeDirectionOn();
  1193. infoChanger->ChangeOriginOn();
  1194. infoChanger->SetOutputDirection(originalDirection);
  1195. infoChanger->SetOutputOrigin(originalOrigin);
  1196. infoChanger->Update();
  1197. cbica::WriteImage< ImageTypeToWrite >(infoChanger->GetOutput(), correctExtension(saveFileName_string));
  1198. }
  1199. else if (InputPixelType == "unsigned char")
  1200. {
  1201. using ImageTypeToWrite = itk::Image<unsigned char, ImageTypeFloat3D::ImageDimension>;
  1202. auto img = convertVtkToItk<ImageTypeToWrite::PixelType, ImageTypeFloat3D::ImageDimension>(mSlicerManagers[index]->mImage);
  1203. auto infoChanger = itk::ChangeInformationImageFilter< ImageTypeToWrite >::New();
  1204. infoChanger->SetInput(img);
  1205. infoChanger->ChangeDirectionOn();
  1206. infoChanger->ChangeOriginOn();
  1207. infoChanger->SetOutputDirection(originalDirection);
  1208. infoChanger->SetOutputOrigin(originalOrigin);
  1209. infoChanger->Update();
  1210. cbica::WriteImage< ImageTypeToWrite >(infoChanger->GetOutput(), correctExtension(saveFileName_string));
  1211. }
  1212. else if (InputPixelType == "int")
  1213. {
  1214. using ImageTypeToWrite = itk::Image<int, ImageTypeFloat3D::ImageDimension>;
  1215. auto img = convertVtkToItk<ImageTypeToWrite::PixelType, ImageTypeFloat3D::ImageDimension>(mSlicerManagers[index]->mImage);
  1216. auto infoChanger = itk::ChangeInformationImageFilter< ImageTypeToWrite >::New();
  1217. infoChanger->SetInput(img);
  1218. infoChanger->ChangeDirectionOn();
  1219. infoChanger->ChangeOriginOn();
  1220. infoChanger->SetOutputDirection(originalDirection);
  1221. infoChanger->SetOutputOrigin(originalOrigin);
  1222. infoChanger->Update();
  1223. cbica::WriteImage< ImageTypeToWrite >(infoChanger->GetOutput(), correctExtension(saveFileName_string));
  1224. }
  1225. else if (InputPixelType == "unsigned int")
  1226. {
  1227. using ImageTypeToWrite = itk::Image<unsigned int, ImageTypeFloat3D::ImageDimension>;
  1228. auto img = convertVtkToItk<ImageTypeToWrite::PixelType, ImageTypeFloat3D::ImageDimension>(mSlicerManagers[index]->mImage);
  1229. auto infoChanger = itk::ChangeInformationImageFilter< ImageTypeToWrite >::New();
  1230. infoChanger->SetInput(img);
  1231. infoChanger->ChangeDirectionOn();
  1232. infoChanger->ChangeOriginOn();
  1233. infoChanger->SetOutputDirection(originalDirection);
  1234. infoChanger->SetOutputOrigin(originalOrigin);
  1235. infoChanger->Update();
  1236. cbica::WriteImage< ImageTypeToWrite >(infoChanger->GetOutput(), correctExtension(saveFileName_string));
  1237. }
  1238. else if (InputPixelType == "double")
  1239. {
  1240. using ImageTypeToWrite = itk::Image<double, ImageTypeFloat3D::ImageDimension>;
  1241. auto img = convertVtkToItk<ImageTypeToWrite::PixelType, ImageTypeFloat3D::ImageDimension>(mSlicerManagers[index]->mImage);
  1242. auto infoChanger = itk::ChangeInformationImageFilter< ImageTypeToWrite >::New();
  1243. infoChanger->SetInput(img);
  1244. infoChanger->ChangeDirectionOn();
  1245. infoChanger->ChangeOriginOn();
  1246. infoChanger->SetOutputDirection(originalDirection);
  1247. infoChanger->SetOutputOrigin(originalOrigin);
  1248. infoChanger->Update();
  1249. cbica::WriteImage< ImageTypeToWrite >(infoChanger->GetOutput(), correctExtension(saveFileName_string));
  1250. }
  1251. else if (InputPixelType == "float")
  1252. {
  1253. using ImageTypeToWrite = itk::Image<float, ImageTypeFloat3D::ImageDimension>;
  1254. auto img = convertVtkToItk<ImageTypeToWrite::PixelType, ImageTypeFloat3D::ImageDimension>(mSlicerManagers[index]->mImage);
  1255. auto infoChanger = itk::ChangeInformationImageFilter< ImageTypeToWrite >::New();
  1256. infoChanger->SetInput(img);
  1257. infoChanger->ChangeDirectionOn();
  1258. infoChanger->ChangeOriginOn();
  1259. infoChanger->SetOutputDirection(originalDirection);
  1260. infoChanger->SetOutputOrigin(originalOrigin);
  1261. infoChanger->Update();
  1262. cbica::WriteImage< ImageTypeToWrite >(infoChanger->GetOutput(), correctExtension(saveFileName_string));
  1263. }
  1264. else
  1265. {
  1266. cbica::Logging(loggerFile, "Error, input pixel type, '" + InputPixelType + "' is unknown!");
  1267. }
  1268. updateProgress(0, "Image saved! (" + saveFileName_string + ")");
  1269. }
  1270. }
  1271. }
  1272. void fMainWindow::SaveImage()
  1273. {
  1274. auto items = m_imagesTable->selectedItems();
  1275. if (items.empty())
  1276. {
  1277. return;
  1278. }
  1279. int index = GetSlicerIndexFromItem(items[0]);
  1280. if (index < 0 || index >= (int)mSlicerManagers.size())
  1281. {
  1282. return;
  1283. }
  1284. //
  1285. QString saveFileName = getSaveFile(this, mInputPathName, mInputPathName + "_new.nii.gz");
  1286. SaveImage_withFile(index, saveFileName);
  1287. }
  1288. void fMainWindow::InitMask(vtkImageData* image)
  1289. {
  1290. int extent[6];
  1291. double spacing[3];
  1292. double origin[3];
  1293. int i, j, k;
  1294. image->GetExtent(extent);
  1295. image->GetSpacing(spacing);
  1296. image->GetOrigin(origin);
  1297. mMask->Initialize();
  1298. mMask->SetExtent(extent);
  1299. mMask->SetSpacing(spacing);
  1300. mMask->SetOrigin(origin);
  1301. #if VTK_MAJOR_VERSION <= 5
  1302. mMask->SetScalarTypeToFloat();
  1303. mMask->SetNumberOfScalarComponents(1);
  1304. mMask->AllocateScalars();
  1305. #else
  1306. mMask->AllocateScalars(VTK_FLOAT, 1);
  1307. #endif
  1308. {
  1309. int vd_x, vd_y, vd_z;
  1310. vd_x = mMask->GetDimensions()[0];
  1311. vd_y = mMask->GetDimensions()[1];
  1312. vd_z = mMask->GetDimensions()[2];
  1313. float* pData = (float*)mMask->GetScalarPointer();
  1314. for (k = 0; k < vd_z; k++)
  1315. {
  1316. for (j = 0; j < vd_y; j++)
  1317. {
  1318. for (i = 0; i < vd_x; i++)
  1319. {
  1320. *pData = 0;
  1321. pData++;
  1322. }
  1323. }
  1324. }
  1325. }
  1326. }
  1327. void fMainWindow::updateDrawMode(int shapeMode)
  1328. {
  1329. if (shapeMode >= 0)
  1330. {
  1331. m_drawShapeMode = SHAPE_MODE(shapeMode);
  1332. }
  1333. if (m_drawShapeMode == SHAPE_MODE_NONE)
  1334. {
  1335. AxialViewWidget->unsetCursor();
  1336. CoronalViewWidget->unsetCursor();
  1337. SaggitalViewWidget->unsetCursor();
  1338. return;
  1339. }
  1340. int color[4] = { 0, 0, 0, 0 };
  1341. int drawLabel = this->getSelectedDrawLabel();
  1342. int drawSize = this->getSelectedDrawSize();
  1343. switch (drawLabel)
  1344. {
  1345. case DRAW_MODE_LABEL_1: // near
  1346. color[0] = 255;
  1347. color[1] = 0;
  1348. color[2] = 0;
  1349. color[3] = 255;
  1350. break;
  1351. case DRAW_MODE_LABEL_2: // far
  1352. color[0] = 0;
  1353. color[1] = 255;
  1354. color[2] = 0;
  1355. color[3] = 255;
  1356. break;
  1357. case DRAW_MODE_LABEL_3:
  1358. color[0] = 255;
  1359. color[1] = 255;
  1360. color[2] = 0;
  1361. color[3] = 255;
  1362. break;
  1363. case DRAW_MODE_LABEL_4:
  1364. color[0] = 0;
  1365. color[1] = 0;
  1366. color[2] = 255;
  1367. color[3] = 255;
  1368. break;
  1369. case DRAW_MODE_LABEL_5:
  1370. color[0] = 255;
  1371. color[1] = 0;
  1372. color[2] = 255;
  1373. color[3] = 255;
  1374. break;
  1375. default:
  1376. break;
  1377. }
  1378. if (m_drawShapeMode == SHAPE_MODE_ERASER)
  1379. {
  1380. color[0] = 255;
  1381. color[1] = 255;
  1382. color[2] = 255;
  1383. color[3] = 255;
  1384. }
  1385. QImage img(33, 33, QImage::Format_ARGB32);
  1386. for (int j = -16; j <= 16; j++)
  1387. {
  1388. for (int i = -16; i <= 16; i++)
  1389. {
  1390. if (abs(i) <= drawSize && abs(j) <= drawSize)
  1391. {
  1392. img.setPixel(i + 16, j + 16, qRgba(color[0], color[1], color[2], color[3]));
  1393. }
  1394. else
  1395. {
  1396. img.setPixel(i + 16, j + 16, qRgba(0, 0, 0, 0));
  1397. }
  1398. }
  1399. }
  1400. AxialViewWidget->setCursor(QCursor(Qt::CrossCursor));
  1401. CoronalViewWidget->setCursor(QCursor(Qt::CrossCursor));
  1402. SaggitalViewWidget->setCursor(QCursor(Qt::CrossCursor));
  1403. }
  1404. void fMainWindow::LoadNonViewingImages(const std::string &directoryname, const int &imagetype_int, const int &imagesubtype)
  1405. {
  1406. for (unsigned int index = 0; index < mNonViewingImageManager.size(); index++)
  1407. {
  1408. if (mNonViewingImageManager[index]->GetPathFileName() == directoryname)
  1409. {
  1410. return;
  1411. }
  1412. }
  1413. SimpleImageManager* nonViewingImage = new SimpleImageManager();
  1414. nonViewingImage->SetPathFileName(directoryname);
  1415. nonViewingImage->SetFileName(directoryname);
  1416. if (imagetype_int == CAPTK::NIfTI)
  1417. nonViewingImage->ReadGivenNonViewingNiftiImage(directoryname, imagesubtype);
  1418. else
  1419. nonViewingImage->ReadGivenNonViewingDicomImage(directoryname, imagesubtype);
  1420. if (nonViewingImage->GetLastEncounteredError() != "")
  1421. delete nonViewingImage;
  1422. else
  1423. mNonViewingImageManager.push_back(nonViewingImage);
  1424. //Add image Information in NonViewing images table
  1425. //----------------------------------------------
  1426. nonViewingImage->mImageType = imagetype_int;
  1427. nonViewingImage->mImageSubType = imagesubtype;
  1428. std::string strImageType;
  1429. if (nonViewingImage->mImageSubType == CAPTK::ImageModalityType::IMAGE_TYPE_DTI)
  1430. strImageType = "DTI";
  1431. int rowindex = m_nonVisImagesTable->rowCount();
  1432. m_nonVisImagesTable->setRowCount(rowindex + 1);
  1433. QFileInfo fileinfo(nonViewingImage->GetFileName().c_str());
  1434. QString id = directoryname.c_str() + QString::number(mNonViewingImageManager.size() - 1);
  1435. {
  1436. QTableWidgetItem *item = new QTableWidgetItem(fileinfo.fileName());
  1437. item->setData(Qt::UserRole, directoryname.c_str());
  1438. QTablePushButton* cButton = new QTablePushButton;
  1439. cButton->setItem(item);
  1440. cButton->setText(tr("X"));
  1441. cButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
  1442. QString in = QString::fromStdString(strImageType);
  1443. QTableWidgetItem *item2 = new QTableWidgetItem(in);
  1444. item2->setData(Qt::UserRole, in.toStdString().c_str());
  1445. if (nonViewingImage->mImageSubType == CAPTK::ImageModalityType::IMAGE_TYPE_DTI)
  1446. connect(cButton, SIGNAL(clickedInto(QTableWidgetItem*)), this, SLOT(CloseNonViewingDTIImage(QTableWidgetItem*)));
  1447. m_nonVisImagesTable->setCellWidget(rowindex, TAB_IMAGES_COLUMN_CLOSE, cButton);
  1448. m_nonVisImagesTable->setItem(rowindex, TAB_IMAGES_COLUMN_NAME, item);
  1449. m_nonVisImagesTable->setItem(rowindex, TAB_IMAGES_COLUMN_TYPE, item2);
  1450. m_nonVisImagesTable->resizeRowsToContents();
  1451. }
  1452. }
  1453. void fMainWindow::LoadSlicerImages(const std::string &fileName, const int &imagetype_int, bool bSkipDup)
  1454. {
  1455. std::string fname;
  1456. auto extension = cbica::getFilenameExtension(fileName);
  1457. //if (extension != ".dcm")
  1458. {
  1459. if (extension == ".zip")
  1460. {
  1461. ShowErrorMessage("Please extract the zip file before trying to load into CaPTk.");
  1462. return;
  1463. }
  1464. if ((extension != ".nii") && (extension != ".nii.gz"))
  1465. {
  1466. ShowErrorMessage("Only DICOM (dcm) or NIfTI (nii/nii.gz) images are supported right now; please contact CBICA for adding extended support");
  1467. return;
  1468. }
  1469. //if ((extension == ".dcm") ||
  1470. // (extension == ".DCM") ||
  1471. // (extension == ".dicom") ||
  1472. // (extension == "") ||
  1473. // (extension == ".ima") ||
  1474. // (extension == ".IMA"))
  1475. if (cbica::IsDicom(fileName))
  1476. {
  1477. QDir d = QFileInfo(fileName.c_str()).absoluteDir();
  1478. fname = d.absolutePath().toStdString();
  1479. dicomfilename = fname;
  1480. }
  1481. else
  1482. fname = fileName;
  1483. auto imageInfo = cbica::ImageInfo(fname);
  1484. SlicerManager* imageManager = new SlicerManager(3, mLandmarks, mSeedPoints, mTissuePoints);
  1485. imageManager->mImageSubType = CAPTK::ImageModalityType::IMAGE_TYPE_UNDEFINED;
  1486. imageManager->SetComparisonMode(false);
  1487. bool bFirstLoad = false;
  1488. if (mSlicerManagers.empty())
  1489. {
  1490. bFirstLoad = true;
  1491. }
  1492. if (imageInfo.GetImageDimensions() == 2)
  1493. {
  1494. fname = ConversionFrom2Dto3D(fname);
  1495. }
  1496. else if (!bFirstLoad)
  1497. {
  1498. {
  1499. //auto temp_prev = cbica::normPath(m_tempFolderLocation + "/temp_prev.nii.gz");
  1500. //ImageTypeFloat3D::DirectionType originaldirection;
  1501. //originaldirection[0][0] = mSlicerManagers[0]->mDirection(0, 0);
  1502. //originaldirection[0][1] = mSlicerManagers[0]->mDirection(0, 1);
  1503. //originaldirection[0][2] = mSlicerManagers[0]->mDirection(0, 2);
  1504. //originaldirection[1][0] = mSlicerManagers[0]->mDirection(1, 0);
  1505. //originaldirection[1][1] = mSlicerManagers[0]->mDirection(1, 1);
  1506. //originaldirection[1][2] = mSlicerManagers[0]->mDirection(1, 2);
  1507. //originaldirection[2][0] = mSlicerManagers[0]->mDirection(2, 0);
  1508. //originaldirection[2][1] = mSlicerManagers[0]->mDirection(2, 1);
  1509. //originaldirection[2][2] = mSlicerManagers[0]->mDirection(2, 2);
  1510. //auto img = convertVtkToItk< ImageTypeFloat3D::PixelType, ImageTypeFloat3D::ImageDimension >(mSlicerManagers[0]->mImage);
  1511. //img->SetDirection(originaldirection);
  1512. //cbica::WriteImage< ImageTypeFloat3D >(img, temp_prev);
  1513. bool fourDImage = false;
  1514. if ((imageInfo.GetImageDimensions() == 4) || (mSlicerManagers[0]->mImageSubType == CAPTK::ImageModalityType::IMAGE_TYPE_PERFUSION))
  1515. {
  1516. fourDImage = true;
  1517. }
  1518. if (!cbica::ImageSanityCheck(fname, mSlicerManagers[0]->GetPathFileName(), fourDImage))
  1519. {
  1520. ShowErrorMessage("The physical dimensions of the previously loaded image and current image are inconsistent; cannot load");
  1521. return;
  1522. }
  1523. }
  1524. //{
  1525. // auto temp = cbica::normPath(m_tempFolderLocation + "/temp_prev.nii.gz");
  1526. // cbica::WriteImage< ImageTypeFloat3D >(mSlicerManagers[0]->mITKImage, temp);
  1527. // auto imageInfoPrev = cbica::ImageInfo(temp);
  1528. // auto sizePrev = imageInfoPrev.GetImageSize();
  1529. // auto size = imageInfo.GetImageSize();
  1530. // const std::string errorMsg = " not matching. Please register the image(s). Skipping file: ";
  1531. // for (size_t i = 0; i < ImageTypeFloat3D::ImageDimension; i++)
  1532. // {
  1533. // if (sizePrev[i] != size[i])
  1534. // {
  1535. // updateProgress(0, "Size" + errorMsg + fname);
  1536. // ShowErrorMessage("Size" + errorMsg + fname);
  1537. // return; //
  1538. // }
  1539. // }
  1540. // auto spacingPrev = imageInfoPrev.GetImageSpacings();
  1541. // auto spacing = imageInfo.GetImageSpacings();
  1542. // for (size_t i = 0; i < ImageTypeFloat3D::ImageDimension; i++)
  1543. // {
  1544. // if (spacing[i] != spacingPrev[i])
  1545. // {
  1546. // updateProgress(0, "Spacing" + errorMsg + fname);
  1547. // ShowErrorMessage("Spacing" + errorMsg + fname);
  1548. // return; //
  1549. // }
  1550. // }
  1551. // auto originPrev = imageInfoPrev.GetImageOrigins();
  1552. // auto origin = imageInfo.GetImageOrigins();
  1553. // if (!m_advancedVisualizer)
  1554. // {
  1555. // for (size_t i = 0; i < ImageTypeFloat3D::ImageDimension; i++)
  1556. // {
  1557. // if (origin[i] != originPrev[i])
  1558. // {
  1559. // updateProgress(0, "Origin" + errorMsg + fname);
  1560. // ShowErrorMessage("Origin" + errorMsg + fname);
  1561. // return; //
  1562. // }
  1563. // }
  1564. // }
  1565. //}
  1566. if (bSkipDup)
  1567. {
  1568. for (int j = 0; j < (int)mSlicerManagers.size(); j++)
  1569. {
  1570. if (fname == mSlicerManagers[j]->GetPathFileName())
  1571. {
  1572. updateProgress(0, "Duplicate file skipped :" + fname);
  1573. return;
  1574. }
  1575. }
  1576. }
  1577. }
  1578. QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
  1579. if (imageInfo.GetImageDimensions() == 4)
  1580. {
  1581. image4DSlider->setEnabled(true);
  1582. image4DSlider->setRange(0, imageInfo.GetImageSize()[3] - 1);
  1583. ImageTypeFloat4D::Pointer imagePerf = cbica::ReadImage<ImageTypeFloat4D>(fname);
  1584. imageManager->SetPerfImage(imagePerf);
  1585. imageManager->mImageSubType = CAPTK::ImageModalityType::IMAGE_TYPE_PERFUSION;
  1586. //return;
  1587. }
  1588. else
  1589. {
  1590. imageManager->SetOriginalOrigin(imageInfo.GetImageOrigins());
  1591. auto currentImage = cbica::ReadImage<ImageTypeFloat3D>(fname);
  1592. imageManager->SetOriginalDirection(currentImage->GetDirection());
  1593. imageManager->SetOriginalOrigin(currentImage->GetOrigin());
  1594. currentImage = ChangeImageDirectionToIdentity< ImageTypeFloat3D >(cbica::ReadImageWithOrientFix< ImageTypeFloat3D >(fname));
  1595. imageManager->SetImage(currentImage);
  1596. imageManager->mImageSubType = guessImageType(fname);
  1597. }
  1598. mInputPathName = cbica::getFilenamePath(fname).c_str();
  1599. imageManager->SetFilename(fname);
  1600. imageManager->SetMask(mMask);
  1601. imageManager->setTempFolderLocation(m_tempFolderLocation);
  1602. int rowIndex = (int)mSlicerManagers.size();
  1603. m_imagesTable->setRowCount(rowIndex + 1);
  1604. mSlicerManagers.push_back(imageManager);
  1605. QFileInfo fileinfo(imageManager->GetFileName().c_str());
  1606. QString id = fname.c_str() + QString::number(mSlicerManagers.size() - 1);
  1607. //
  1608. std::string strImageType = " IMAGE ";
  1609. {
  1610. QTableWidgetItem *item = new QTableWidgetItem(fileinfo.fileName());
  1611. item->setData(Qt::UserRole, id.toStdString().c_str());
  1612. item->setFlags(item->flags() & ~Qt::ItemIsEditable);
  1613. QTablePushButton* cButton = new QTablePushButton;
  1614. cButton->setItem(item);
  1615. cButton->setText(QString("X"));
  1616. connect(cButton, SIGNAL(clickedInto(QTableWidgetItem*)), this, SLOT(CloseImage(QTableWidgetItem*)));
  1617. QLabel * label = new QLabel;
  1618. label->setText(QString::fromStdString(strImageType));
  1619. m_imagesTable->setCellWidget(rowIndex, TAB_IMAGES_COLUMN_CLOSE, cButton);
  1620. m_imagesTable->setCellWidget(rowIndex, TAB_IMAGES_COLUMN_TYPE, label);
  1621. m_imagesTable->setItem(rowIndex, TAB_IMAGES_COLUMN_NAME, item);
  1622. }
  1623. imagesPanel->NewImageLoaded(id, imageManager->GetBaseFileName(), rowIndex, strImageType, imageManager->mImageSubType, this);
  1624. QTableWidgetItem *item = new QTableWidgetItem(fileinfo.fileName());
  1625. item->setData(Qt::UserRole, id.toStdString().c_str());
  1626. QTablePushButton* cButton = new QTablePushButton;
  1627. cButton->setItem(item);
  1628. cButton->setText(QString("X"));
  1629. connect(cButton, SIGNAL(clickedInto(QTableWidgetItem*)), this, SLOT(CloseImage(QTableWidgetItem*)));
  1630. mSlicerManagers.back()->SetId(id.toStdString());
  1631. connect(mSlicerManagers.back(), SIGNAL(LeftButtonReleaseSignal(int)), this, SLOT(propogateSlicerPosition(int)));
  1632. connect(mSlicerManagers.back(), SIGNAL(currentImageChanged(std::string &)), this, SLOT(CurrentImageChanged(std::string &)));
  1633. connect(mSlicerManagers.back(), SIGNAL(currentPickedImageChanged(std::string)), this, SLOT(CurrentPickedImageChanged(std::string)));
  1634. connect(mSlicerManagers.back(), SIGNAL(UpdatePosition(int, double, double, double, double, double, double, double)), this, SLOT(MousePositionChanged(int, double, double, double, double, double, double, double)));
  1635. connect(mSlicerManagers.back(), SIGNAL(WindowLevelChanged()), this, SLOT(WindowLevelChanged()));
  1636. connect(mSlicerManagers.back(), SIGNAL(UpdateSlice(int, int)), this, SLOT(UpdateSlice(int, int)));
  1637. connect(mSlicerManagers.back(), SIGNAL(UpdateSliceRange(int, int, int)), this, SLOT(UpdateSliceRange(int, int, int)));
  1638. connect(mSlicerManagers.back(), SIGNAL(UpdateLinkManager(std::string, int, double, double, double)), this, SLOT(UpdateLinkManager(std::string, int, double, double, double)));
  1639. connect(mSlicerManagers.back(), SIGNAL(ChangeImageWithOrder(SlicerManager*, int)), this, SLOT(ChangeImageWithOrder(SlicerManager*, int)));
  1640. connect(mSlicerManagers.back(), SIGNAL(UpdateBorderWidgetInMain(double, double, double, double)), this, SLOT(UpdateBorderWidget(double, double, double, double)));
  1641. connect(mSlicerManagers.back(), SIGNAL(UpdateBorderWidgetInMain(double, double)), this, SLOT(UpdateBorderWidget(double, double)));
  1642. connect(mSlicerManagers.back(), SIGNAL(UpdateActionInMain(const QVariantList&)), this, SLOT(UpdateActionQ(const QVariantList&)));
  1643. //connect(mSlicerManagers.back(), SIGNAL(SeedPointsAdded()), tumorPanel, SLOT(sAddPoint()));
  1644. //connect(mSlicerManagers.back(), SIGNAL(SeedPointsAdded(int, bool)), tumorPanel, SLOT(sAddPoint(int, bool)));
  1645. //connect(mSlicerManagers.back(), SIGNAL(TissuePointsAdded(int)), tumorPanel, SLOT(tAddPoint(int)));
  1646. //connect(m_tabWidget, SIGNAL(currentChanged(int)), tumorPanel, SLOT(tabSelected()));
  1647. InitSlicers();
  1648. if (bFirstLoad)
  1649. {
  1650. InitMask(mSlicerManagers.back()->mImage);
  1651. }
  1652. for (int j = 0; j < (int)mSlicerManagers.back()->mSlicers.size(); j++)
  1653. {
  1654. mSlicerManagers.back()->mSlicers[j]->SetMask(mSlicerManagers.back()->GetMask());
  1655. }
  1656. if (fname.find("scan_label_map") != std::string::npos)
  1657. {
  1658. mSlicerManagers.back()->SetPreset(PRESET_LABEL);
  1659. }
  1660. if (fname.find("gt") != std::string::npos)
  1661. {
  1662. mSlicerManagers.back()->SetPreset(PRESET_LABEL2);
  1663. }
  1664. if (fname.find("roiDE") != std::string::npos)
  1665. {
  1666. mSlicerManagers.back()->SetPreset(PRESET_PROB);
  1667. }
  1668. if (mSlicerManagers.size() > 0)
  1669. {
  1670. if (mSlicerManagers.back()->mMask->GetDimensions()[2] != 1)
  1671. {
  1672. CoronalViewWidget->show();
  1673. SaggitalViewWidget->show();
  1674. }
  1675. AxialViewWidget->show();
  1676. infoPanel->show();
  1677. windowLabel->setEnabled(true);
  1678. windowSpinBox->setEnabled(true);
  1679. levelLabel->setEnabled(true);
  1680. levelSpinBox->setEnabled(true);
  1681. presetLabel->setEnabled(true);
  1682. presetComboBox->setEnabled(true);
  1683. if (bFirstLoad)
  1684. {
  1685. for (int i = 0; i < 3; i++)
  1686. {
  1687. mSlicerManagers.back()->GetSlicer(i)->SetInitPosition();
  1688. }
  1689. DisplayChanged(item);
  1690. }
  1691. else
  1692. {
  1693. QTableWidgetItem* item = NULL;
  1694. for (int i = 0; i < (int)mSlicerManagers.size(); i++)
  1695. {
  1696. item = GetItemFromSlicerManager(mSlicerManagers[i]);
  1697. if (!item->isSelected())
  1698. {
  1699. item->setSelected(true);
  1700. }
  1701. }
  1702. DisplayChanged(item);
  1703. }
  1704. if (mSlicerManagers.size() > 1)
  1705. {
  1706. for (int i = 0; i < (int)mSlicerManagers.size(); i++)
  1707. {
  1708. for (int j = i + 1; j < (int)mSlicerManagers.size(); j++)
  1709. {
  1710. AddLink(/*QString::fromStdString*/(mSlicerManagers[i]->GetId().c_str()), /*QString::fromStdString*/(mSlicerManagers[j]->GetId().c_str()));
  1711. }
  1712. }
  1713. }
  1714. QTableWidgetItem* item = GetItemFromSlicerManager(mSlicerManagers.back());
  1715. item->setSelected(true);
  1716. InitDisplay();
  1717. }
  1718. propogateSlicerPosition();
  1719. updateProgress(0);
  1720. QApplication::restoreOverrideCursor();
  1721. }
  1722. // else
  1723. // {
  1724. // auto path = cbica::getFilenamePath(fileName);
  1725. // dicomfilename = fileName;
  1726. // auto filesInDir = cbica::filesInDirectory(path, false);
  1727. //
  1728. //#ifndef _WIN32
  1729. // for (auto it = filesInDir.begin(); it != filesInDir.end();)
  1730. // {
  1731. // if ((*it == ".") || (*it == ".."))
  1732. // {
  1733. // filesInDir.erase(it);
  1734. // }
  1735. // else
  1736. // {
  1737. // ++it;
  1738. // }
  1739. // }
  1740. //#endif
  1741. //
  1742. // // remove any files that aren't DICOM (thumbs.db and stuff like that)
  1743. // for (size_t i = 0; i < filesInDir.size(); i++)
  1744. // {
  1745. // if (cbica::getFilenameExtension(path + "/" + filesInDir[i]) != ".dcm")
  1746. // {
  1747. // filesInDir.erase(filesInDir.begin() + i);
  1748. // }
  1749. // }
  1750. //
  1751. // if (filesInDir.size() == 1) // single DICOM slice
  1752. // {
  1753. // ConversionFrom2Dto3D(fileName, true);
  1754. // }
  1755. // else // for 3D images, call dcm2nii
  1756. // {
  1757. // CallDCM2NIfTIConversion(fileName, true);
  1758. // }
  1759. //
  1760. // return;
  1761. // }
  1762. }
  1763. void fMainWindow::CurrentImageChanged(std::string &id)
  1764. {
  1765. if (id == mCurrentSelectedImageId)
  1766. {
  1767. return;
  1768. }
  1769. int selected = 0;
  1770. for (int i = 0; i < m_imagesTable->rowCount(); i++)
  1771. {
  1772. if (m_imagesTable->item(i, TAB_IMAGES_COLUMN_NAME)->data(Qt::UserRole).toString().toStdString() == id)
  1773. {
  1774. selected = i;
  1775. }
  1776. else
  1777. {
  1778. m_imagesTable->item(i, TAB_IMAGES_COLUMN_NAME)->setSelected(false);
  1779. }
  1780. }
  1781. m_imagesTable->item(selected, TAB_IMAGES_COLUMN_NAME)->setSelected(true);
  1782. mCurrentSelectedImageId = id;
  1783. emit SelectedImageHasChanged(mSlicerManagers[selected]);
  1784. m_imagesTable->resizeColumnsToContents();
  1785. m_imagesTable->resizeRowsToContents();
  1786. }
  1787. void fMainWindow::propogateSlicerPosition(int slicerId, int imageId)
  1788. {
  1789. //TBD this not a proper fix a lot work needs to be done to make slicer, slicerManager slicerManagerCommand to be made clean OOP
  1790. if (imageId < 0)
  1791. {
  1792. auto items = m_imagesTable->selectedItems();
  1793. if (!items.empty())
  1794. {
  1795. imageId = GetSlicerIndexFromItem(items[0]);
  1796. }
  1797. }
  1798. if (imageId < 0 || imageId >= (int)mSlicerManagers.size())
  1799. {
  1800. return;
  1801. }
  1802. const int MAX_SLICES = 3;
  1803. if (slicerId < 0 || slicerId >= MAX_SLICES)
  1804. {
  1805. return;
  1806. }
  1807. double* pos = mSlicerManagers[imageId]->GetSlicer(slicerId)->GetCurrentPosition();
  1808. for (size_t r = 0; r < mSlicerManagers.size(); r++)
  1809. {
  1810. for (size_t i = 0; i < MAX_SLICES; i++)
  1811. {
  1812. mSlicerManagers[r]->GetSlicer(i)->SetCurrentPosition(pos[0], pos[1], pos[2]);
  1813. }
  1814. }
  1815. }
  1816. void fMainWindow::CurrentPickedImageChanged(std::string id)
  1817. {
  1818. if (id == mCurrentPickedImageId) {
  1819. return;
  1820. }
  1821. int selected = 0;
  1822. for (int i = 0; i < m_imagesTable->rowCount(); i++) {
  1823. if (m_imagesTable->item(i, TAB_IMAGES_COLUMN_NAME)->data(Qt::UserRole).toString().toStdString() == id) {
  1824. selected = i;
  1825. }
  1826. else {
  1827. m_imagesTable->item(i, TAB_IMAGES_COLUMN_NAME)->setSelected(false);
  1828. }
  1829. }
  1830. m_imagesTable->item(selected, TAB_IMAGES_COLUMN_NAME)->setSelected(true);
  1831. mCurrentPickedImageId = id;
  1832. mCurrentPickedImageIndex = selected;
  1833. }
  1834. void fMainWindow::ImageInfoChanged()
  1835. {
  1836. auto items = m_imagesTable->selectedItems();
  1837. if (items.empty()) {
  1838. return;
  1839. }
  1840. int index = GetSlicerIndexFromItem(items[0]);
  1841. if (index < 0 || index >= (int)mSlicerManagers.size()) {
  1842. return;
  1843. }
  1844. vtkSmartPointer<vtkMatrix4x4> transformation;
  1845. QString image = m_imagesTable->selectedItems()[0]->data(Qt::DisplayRole).toString();
  1846. vtkSmartPointer<vtkImageData> imageSelected;
  1847. vtkSmartPointer<vtkTransform> transformSelected;
  1848. imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetImage();
  1849. transformSelected = mSlicerManagers[index]->GetSlicer(0)->GetTransform();
  1850. std::string vtktype = mSlicerManagers[index]->GetImage()->GetScalarTypeAsString();
  1851. QString pixelType = vtktype.c_str();
  1852. infoPanel->setFileName(image);
  1853. infoPanel->setSizePixel(imageSelected->GetDimensions()[0], imageSelected->GetDimensions()[1], imageSelected->GetDimensions()[2]);
  1854. infoPanel->setOrigin(mSlicerManagers[index]->mOrigin[0], mSlicerManagers[index]->mOrigin[1], mSlicerManagers[index]->mOrigin[2]);
  1855. infoPanel->setSpacing(imageSelected->GetSpacing()[0], imageSelected->GetSpacing()[1], imageSelected->GetSpacing()[2]);
  1856. transformation = transformSelected->GetMatrix();
  1857. //tumorPanel->SetCurrentSPoints(mSlicerManagers[index]->mSeedPoints);
  1858. //tumorPanel->SetCurrentTPoints(mSlicerManagers[index]->mTissuePoints);
  1859. //tumorPanel->SetCurrentPath(mInputPathName.toStdString());
  1860. for (int i = 0; i < 3; i++)
  1861. {
  1862. mSlicerManagers[index]->UpdateInfoOnCursorPosition(i);
  1863. }
  1864. WindowLevelChanged();
  1865. // reset SliceManager order
  1866. for (int j = 0; j < (int)mSlicerManagers.size(); j++) {
  1867. mSlicerManagers[j]->SetOrder(j);
  1868. }
  1869. for (int i = 0; i < m_imagesTable->rowCount(); i++) {
  1870. QString id_table = m_imagesTable->item(i, TAB_IMAGES_COLUMN_NAME)->data(Qt::UserRole).toString();
  1871. for (int j = 0; j < (int)mSlicerManagers.size(); j++) {
  1872. QString id_sm = mSlicerManagers[j]->GetId().c_str();
  1873. if (id_table == id_sm) {
  1874. mSlicerManagers[j]->SetOrder(i);
  1875. break;
  1876. }
  1877. }
  1878. }
  1879. }
  1880. void fMainWindow::DisplayChanged()
  1881. {
  1882. auto items = m_imagesTable->selectedItems();
  1883. if (items.empty())
  1884. {
  1885. return;
  1886. }
  1887. DisplayChanged(items[0]);
  1888. }
  1889. void fMainWindow::DisplayChanged(QTableWidgetItem *clickedItem)
  1890. {
  1891. int slicerManagerIndex = GetSlicerIndexFromItem(clickedItem);
  1892. if (slicerManagerIndex < 0 || slicerManagerIndex >= (int)mSlicerManagers.size())
  1893. {
  1894. return;
  1895. }
  1896. QTableWidgetItem* clickedParentItem = m_imagesTable->item(slicerManagerIndex, TAB_IMAGES_COLUMN_NAME);
  1897. for (int i = 0; i < (int)mSlicerManagers.size(); i++)
  1898. {
  1899. QTableWidgetItem* currentParentItem = m_imagesTable->item(i, TAB_IMAGES_COLUMN_NAME);
  1900. if (currentParentItem != clickedParentItem)
  1901. {
  1902. for (int j = 0; j < 3; j++)
  1903. {
  1904. mSlicerManagers[i]->UpdateSlicer(j, false);
  1905. }
  1906. }
  1907. else
  1908. {
  1909. int VisibleInWindow = 0;
  1910. for (int j = 0; j < 3; j++)
  1911. {
  1912. mSlicerManagers[i]->UpdateSlicer(j, true);
  1913. mSlicerManagers[i]->UpdateInfoOnCursorPosition(j);
  1914. DisplaySliders(i, j);
  1915. //
  1916. if (mSlicerManagers[i]->GetSlicer(j)->GetActive())
  1917. {
  1918. VisibleInWindow = j;
  1919. }
  1920. }
  1921. mSlicerManagers[i]->Picked();
  1922. mSlicerManagers[i]->UpdateViews(VisibleInWindow);
  1923. mSlicerManagers[i]->UpdateLinked(VisibleInWindow);
  1924. mSlicerManagers[i]->UpdateInfoOnCursorPosition(VisibleInWindow);
  1925. }
  1926. for (int j = 0; j < 3; j++)
  1927. {
  1928. mSlicerManagers[i]->mSlicers[j]->RemoveOverlay();
  1929. }
  1930. }
  1931. UpdateRenderWindows();
  1932. ImageInfoChanged();
  1933. }
  1934. int fMainWindow::GetSlicerIndexFromItem(QTableWidgetItem* item)
  1935. {
  1936. if (item != NULL) {
  1937. QString id = item->data(Qt::UserRole).toString();
  1938. std::string id_string = id.toStdString();
  1939. for (int i = 0; i < m_imagesTable->rowCount(); i++)
  1940. {
  1941. QString id_table_string = m_imagesTable->item(i, TAB_IMAGES_COLUMN_NAME)->data(Qt::UserRole).toString();
  1942. std::string table_string = id_table_string.toStdString();
  1943. if (m_imagesTable->item(i, TAB_IMAGES_COLUMN_NAME)->data(Qt::UserRole).toString() == id)
  1944. {
  1945. return i;
  1946. }
  1947. }
  1948. }
  1949. return -1;
  1950. }
  1951. QTableWidgetItem* fMainWindow::GetItemFromSlicerManager(SlicerManager* sm)
  1952. {
  1953. QString id = sm->GetId().c_str();
  1954. for (int i = 0; i < m_imagesTable->rowCount(); i++)
  1955. {
  1956. if (m_imagesTable->item(i, TAB_IMAGES_COLUMN_NAME)->data(Qt::UserRole).toString() == id)
  1957. {
  1958. return m_imagesTable->item(i, TAB_IMAGES_COLUMN_NAME);
  1959. }
  1960. }
  1961. return NULL;
  1962. }
  1963. void fMainWindow::InitSlicers()
  1964. {
  1965. if (mSlicerManagers.size()) {
  1966. mSlicerManagers.back()->GenerateDefaultLookupTable();
  1967. mSlicerManagers.back()->SetSlicerWindow(0, AxialViewWidget->GetRenderWindow());
  1968. mSlicerManagers.back()->SetSlicerWindow(1, CoronalViewWidget->GetRenderWindow());
  1969. mSlicerManagers.back()->SetSlicerWindow(2, SaggitalViewWidget->GetRenderWindow());
  1970. }
  1971. }
  1972. void fMainWindow::InitDisplay()
  1973. {
  1974. if (!mSlicerManagers.empty())
  1975. {
  1976. for (int j = 0; j < 3; j++)
  1977. {
  1978. InteractorStyleNavigator* style = InteractorStyleNavigator::New();
  1979. style->SetAutoAdjustCameraClippingRange(1);
  1980. for (int i = 0; i < m_imagesTable->rowCount(); i++)
  1981. {
  1982. mSlicerManagers[i]->SetInteractorStyleNavigator(j, style);
  1983. //
  1984. mSlicerManagers[i]->updateToRefCam(mSlicerManagers[i]->GetSlicer(0));
  1985. mSlicerManagers[i]->GetSlicer(j)->SetInitPosition();
  1986. }
  1987. style->Delete();
  1988. }
  1989. }
  1990. }
  1991. void fMainWindow::DisplaySliders(int slicer, int window)
  1992. {
  1993. int range[2];
  1994. mSlicerManagers[slicer]->GetSlicer(window)->GetSliceRange(range);
  1995. int position = mSlicerManagers[slicer]->GetSlicer(window)->GetSlice();
  1996. bool showVertical = false;
  1997. if (GetNumberOfDimensions(mSlicerManagers[slicer]->GetSlicer(window)->GetImage()) >= 3) {
  1998. showVertical = true;
  1999. }
  2000. if (showVertical) {
  2001. verticalSliders[window]->show();
  2002. }
  2003. else {
  2004. verticalSliders[window]->hide();
  2005. }
  2006. verticalSliders[window]->setRange(range[0], range[1]);
  2007. verticalSliders[window]->setValue(position);
  2008. }
  2009. void fMainWindow::CloseImage(QTableWidgetItem* item)
  2010. {
  2011. int index = GetSlicerIndexFromItem(item);
  2012. if (index < 0 || index >= (int)mSlicerManagers.size())
  2013. {
  2014. return;
  2015. }
  2016. if (mSlicerManagers.size() > 1)
  2017. {
  2018. for (int k = 0; k < (int)mSlicerManagers.size() - 1; k++)
  2019. {
  2020. if (k != index)
  2021. {
  2022. RemoveLink(/*QString::fromStdString*/(mSlicerManagers[k]->GetId()), /*QString::fromStdString*/(mSlicerManagers[index]->GetId()));
  2023. }
  2024. }
  2025. }
  2026. std::vector<SlicerManager*>::iterator Manageriter = mSlicerManagers.begin();
  2027. for (int i = 0; i < index; i++)
  2028. {
  2029. Manageriter++;
  2030. }
  2031. mSlicerManagers[index]->RemoveActors();
  2032. mSlicerManagers[index]->mTissuePoints->Clear();
  2033. mSlicerManagers[index]->mSeedPoints->Clear();
  2034. delete mSlicerManagers[index];
  2035. mSlicerManagers.erase(Manageriter);
  2036. m_imagesTable->removeRow(index);
  2037. if (mSlicerManagers.size() >= 1)
  2038. {
  2039. QTableWidgetItem* item_tmp = GetItemFromSlicerManager(mSlicerManagers.back());
  2040. item_tmp->setSelected(true);
  2041. DisplayChanged(item_tmp);
  2042. }
  2043. else
  2044. {
  2045. this->ResetNumberOfPoints();
  2046. AxialViewWidget->hide();
  2047. CoronalViewWidget->hide();
  2048. SaggitalViewWidget->hide();
  2049. for (int i = 0; i < 3; i++)
  2050. {
  2051. verticalSliders[i]->hide();
  2052. }
  2053. //
  2054. windowLabel->setEnabled(false);
  2055. windowSpinBox->setEnabled(false);
  2056. levelLabel->setEnabled(false);
  2057. levelSpinBox->setEnabled(false);
  2058. thresholdLabel->setEnabled(false);
  2059. thresholdSpinBox->setEnabled(false);
  2060. presetLabel->setEnabled(false);
  2061. presetComboBox->setEnabled(false);
  2062. m_imgGeodesicOut = NULL;
  2063. mLandmarks->Clear();
  2064. mSeedPoints->Clear();
  2065. mTissuePoints->Clear();
  2066. }
  2067. InitDisplay();
  2068. }
  2069. void fMainWindow::MousePositionChanged(int visibility, double x, double y, double z, double X, double Y, double Z, double value)
  2070. {
  2071. infoPanel->setCurrentInfo(visibility, x, y, z, X, Y, Z, value);
  2072. //tumorPanel->HighlightCurrentSelctedPoints(x, y, z, X, Y, Z, value);
  2073. }
  2074. void fMainWindow::WindowLevelChanged()
  2075. {
  2076. auto items = m_imagesTable->selectedItems();
  2077. if (items.empty()) {
  2078. return;
  2079. }
  2080. int index = GetSlicerIndexFromItem(items[0]);
  2081. if (index < 0 || index >= (int)mSlicerManagers.size())
  2082. {
  2083. return;
  2084. }
  2085. windowSpinBox->setValue(mSlicerManagers[index]->GetColorWindow());
  2086. levelSpinBox->setValue(mSlicerManagers[index]->GetColorLevel());
  2087. thresholdSpinBox->setValue(mSlicerManagers[index]->GetThresholdIndex());
  2088. presetComboBox->setCurrentIndex(mSlicerManagers[index]->GetPreset());
  2089. if (presetComboBox->currentIndex() == PRESET_THRESHOLD || presetComboBox->currentIndex() == PRESET_GEODESIC)
  2090. {
  2091. thresholdLabel->setEnabled(true);
  2092. thresholdSpinBox->setEnabled(true);
  2093. }
  2094. else
  2095. {
  2096. thresholdLabel->setEnabled(false);
  2097. thresholdSpinBox->setEnabled(false);
  2098. }
  2099. }
  2100. void fMainWindow::WindowLevelEdited()
  2101. {
  2102. presetComboBox->setCurrentIndex(PRESET_USER);
  2103. UpdateWindowLevel();
  2104. }
  2105. void fMainWindow::SetWindowLevel(double w, double l)
  2106. {
  2107. windowSpinBox->setValue(w);
  2108. levelSpinBox->setValue(l);
  2109. presetComboBox->setCurrentIndex(PRESET_USER);
  2110. UpdateWindowLevel();
  2111. }
  2112. void fMainWindow::UpdateWindowLevel()
  2113. {
  2114. if (!m_ComparisonMode)//! if comparison mode OFF
  2115. {
  2116. auto items = m_imagesTable->selectedItems();
  2117. if (items.empty()) {
  2118. return;
  2119. }
  2120. int index = GetSlicerIndexFromItem(items[0]);
  2121. if (index >= 0 && index < (int)mSlicerManagers.size())
  2122. {
  2123. mSlicerManagers[index]->SetColorWindow(windowSpinBox->value());
  2124. mSlicerManagers[index]->SetColorLevel(levelSpinBox->value());
  2125. mSlicerManagers[index]->SetPreset(presetComboBox->currentIndex());
  2126. mSlicerManagers[index]->Render();
  2127. //
  2128. if (presetComboBox->currentIndex() == PRESET_THRESHOLD || presetComboBox->currentIndex() == PRESET_GEODESIC) {
  2129. thresholdLabel->setEnabled(true);
  2130. thresholdSpinBox->setEnabled(true);
  2131. }
  2132. else
  2133. {
  2134. thresholdLabel->setEnabled(false);
  2135. thresholdSpinBox->setEnabled(false);
  2136. }
  2137. //
  2138. WindowLevelChanged();
  2139. }
  2140. }
  2141. else//! if comparison mode ON
  2142. {
  2143. std::vector<vtkSmartPointer<Slicer>> comparisonViewers = this->GetComparisonViewers();
  2144. for (int i = 0; i < comparisonViewers.size(); i++)
  2145. {
  2146. comparisonViewers[i]->SetColorWindow(windowSpinBox->value());
  2147. comparisonViewers[i]->SetColorLevel(levelSpinBox->value());
  2148. comparisonViewers[i]->Render();
  2149. }
  2150. }
  2151. }
  2152. void fMainWindow::thresholdSpinBoxChanged()
  2153. {
  2154. if (presetComboBox->currentIndex() == PRESET_THRESHOLD)
  2155. {
  2156. auto items = m_imagesTable->selectedItems();
  2157. if (items.empty())
  2158. {
  2159. return;
  2160. }
  2161. int index = GetSlicerIndexFromItem(items[0]);
  2162. if (index >= 0 && index < (int)mSlicerManagers.size())
  2163. {
  2164. mSlicerManagers[index]->SetThresholdIndex(thresholdSpinBox->value());
  2165. mSlicerManagers[index]->SetPreset(mSlicerManagers[index]->GetPreset());
  2166. mSlicerManagers[index]->Render();
  2167. WindowLevelChanged();
  2168. }
  2169. }
  2170. else if (presetComboBox->currentIndex() == PRESET_GEODESIC)
  2171. {
  2172. ApplicationGeodesicTreshold();
  2173. }
  2174. }
  2175. void fMainWindow::UpdateLinkManager(std::string id, int slicer, double x, double y, double z)
  2176. {
  2177. for (int i = 0; i < (int)mSlicerManagers.size(); i++)
  2178. {
  2179. if (mSlicerManagers[i]->GetId() == id)
  2180. {
  2181. mSlicerManagers[i]->GetSlicer(slicer)->SetCurrentPosition(x, y, z);
  2182. mSlicerManagers[i]->UpdateViews(slicer);
  2183. break;
  2184. }
  2185. }
  2186. }
  2187. void fMainWindow::UpdateLinkedNavigation(Slicer* refSlicer)
  2188. {
  2189. for (int i = 0; i < (int)mSlicerManagers.size(); i++)
  2190. {
  2191. mSlicerManagers[i]->updateToRefCam(refSlicer);
  2192. }
  2193. }
  2194. void fMainWindow::CloseImage()
  2195. {
  2196. auto items = m_imagesTable->selectedItems();
  2197. if (items.empty()) {
  2198. return;
  2199. }
  2200. CloseImage(items[0]);
  2201. }
  2202. void fMainWindow::CloseAllImages()
  2203. {
  2204. while (m_imagesTable->rowCount() > 0)
  2205. {
  2206. m_imagesTable->selectRow(0);//TBD speedup this
  2207. CloseImage();
  2208. }
  2209. infoPanel->setFileName("");
  2210. infoPanel->setSizePixel(0, 0, 0);
  2211. infoPanel->setOrigin(0, 0, 0);
  2212. infoPanel->setSpacing(0, 0, 0);
  2213. infoPanel->setCurrentInfo(0, 0, 0, 0, 0, 0, 0, 0);
  2214. }
  2215. void fMainWindow::ResetTransformationToIdentity()
  2216. {
  2217. auto items = m_imagesTable->selectedItems();
  2218. if (items.empty()) {
  2219. return;
  2220. }
  2221. int index = GetSlicerIndexFromItem(items[0]);
  2222. if (index >= 0 && index < (int)mSlicerManagers.size()) {
  2223. mSlicerManagers[index]->ResetTransformationToIdentity();
  2224. ImageInfoChanged();
  2225. }
  2226. }
  2227. void fMainWindow::AddLink(const std::string &image1, const std::string &image2)
  2228. {
  2229. for (int i = 0; i < (int)mSlicerManagers.size(); i++)
  2230. {
  2231. if (image1/*.toStdString()*/ == mSlicerManagers[i]->GetId())
  2232. {
  2233. mSlicerManagers[i]->AddLink(image2/*.toStdString()*/);
  2234. //sm1 = i;
  2235. }
  2236. if (image2/*.toStdString()*/ == mSlicerManagers[i]->GetId())
  2237. {
  2238. mSlicerManagers[i]->AddLink(image1/*.toStdString()*/);
  2239. //sm2 = i;
  2240. }
  2241. }
  2242. }
  2243. void fMainWindow::RemoveLink(const std::string &image1, const std::string &image2)
  2244. {
  2245. for (int i = 0; i < (int)mSlicerManagers.size(); i++)
  2246. {
  2247. if (image1/*.toStdString()*/ == mSlicerManagers[i]->GetId())
  2248. {
  2249. mSlicerManagers[i]->RemoveLink(image2/*.toStdString()*/);
  2250. }
  2251. if (image2/*.toStdString()*/ == mSlicerManagers[i]->GetId()) {
  2252. mSlicerManagers[i]->RemoveLink(image1/*.toStdString()*/);
  2253. }
  2254. }
  2255. }
  2256. void fMainWindow::ChangeImageWithOrder(SlicerManager *sm, int order)
  2257. {
  2258. if (mSlicerManagers.size() <= 1) {
  2259. return;
  2260. }
  2261. if (order >= (int)mSlicerManagers.size()) {
  2262. return;
  2263. }
  2264. QTableWidgetItem* item;
  2265. item = GetItemFromSlicerManager(mSlicerManagers[order]);
  2266. item->setSelected(true);
  2267. DisplayChanged(item);
  2268. }
  2269. void fMainWindow::SetImageInfoIntensityValue(double value)
  2270. {
  2271. this->infoPanel->setIntensityValue(value);
  2272. }
  2273. void fMainWindow::SetImageInfoZSlicePosition(int zslice)
  2274. {
  2275. this->infoPanel->setZSlicePosition(zslice);
  2276. }
  2277. void fMainWindow::OnSliderMovedInComparisonMode(int value)
  2278. {
  2279. if (AxialViewSlider->value() != value ||
  2280. CoronalViewSlider->value() != value ||
  2281. SaggitalViewSlider->value() != value)
  2282. {
  2283. AxialViewSlider->setValue(value);
  2284. CoronalViewSlider->setValue(value);
  2285. SaggitalViewSlider->setValue(value);
  2286. }
  2287. if (m_ComparisonViewerLeft->GetSlice() != value)
  2288. {
  2289. m_ComparisonViewerLeft->SetSlice(value);
  2290. m_ComparisonViewerCenter->SetSlice(value);
  2291. m_ComparisonViewerRight->SetSlice(value);
  2292. m_ComparisonViewerLeft->Render();
  2293. m_ComparisonViewerCenter->Render();
  2294. m_ComparisonViewerRight->Render();
  2295. }
  2296. }
  2297. void fMainWindow::AxialViewSliderChanged()
  2298. {
  2299. static int value = -1;
  2300. value = AxialViewSlider->value();
  2301. auto items = m_imagesTable->selectedItems();
  2302. if (items.empty()) {
  2303. return;
  2304. }
  2305. int index = GetSlicerIndexFromItem(items[0]);
  2306. if (index >= 0 && index < (int)mSlicerManagers.size()) {
  2307. if (mSlicerManagers[index]->GetSlicer(0)->GetSlice() != value) {
  2308. mSlicerManagers[index]->GetSlicer(0)->SetSlice(value);
  2309. mSlicerManagers[index]->VerticalSliderHasChanged(0, value);
  2310. mSlicerManagers[index]->UpdateSlice(0);
  2311. }
  2312. }
  2313. }
  2314. void fMainWindow::SaggitalViewSliderChanged()
  2315. {
  2316. static int value = -1;
  2317. if (value == SaggitalViewSlider->value())
  2318. {
  2319. return;
  2320. }
  2321. else {
  2322. value = SaggitalViewSlider->value();
  2323. }
  2324. auto items = m_imagesTable->selectedItems();
  2325. if (items.empty()) {
  2326. return;
  2327. }
  2328. int index = GetSlicerIndexFromItem(items[0]);
  2329. if (index >= 0 && index < (int)mSlicerManagers.size()) {
  2330. if (mSlicerManagers[index]->GetSlicer(2)->GetSlice() != value) {
  2331. mSlicerManagers[index]->GetSlicer(2)->SetSlice(value);
  2332. mSlicerManagers[index]->VerticalSliderHasChanged(2, value);
  2333. mSlicerManagers[index]->UpdateSlice(2);
  2334. }
  2335. }
  2336. }
  2337. void fMainWindow::CoronalViewSliderChanged()
  2338. {
  2339. static int value = -1;
  2340. if (value == CoronalViewSlider->value())
  2341. {
  2342. return;
  2343. }
  2344. else
  2345. {
  2346. value = CoronalViewSlider->value();
  2347. }
  2348. auto items = m_imagesTable->selectedItems();
  2349. if (items.empty()) {
  2350. return;
  2351. }
  2352. int index = GetSlicerIndexFromItem(items[0]);
  2353. if (index >= 0 && index < (int)mSlicerManagers.size()) {
  2354. if (mSlicerManagers[index]->GetSlicer(1)->GetSlice() != value) {
  2355. mSlicerManagers[index]->GetSlicer(1)->SetSlice(value);
  2356. mSlicerManagers[index]->VerticalSliderHasChanged(1, value);
  2357. mSlicerManagers[index]->UpdateSlice(1);
  2358. }
  2359. }
  2360. }
  2361. void fMainWindow::UpdateSlice(int slicer, int slice)
  2362. {
  2363. if (slicer == 0)
  2364. {
  2365. AxialViewSlider->setValue(slice);
  2366. }
  2367. else if (slicer == 1)
  2368. {
  2369. CoronalViewSlider->setValue(slice);
  2370. }
  2371. else if (slicer == 2)
  2372. {
  2373. SaggitalViewSlider->setValue(slice);
  2374. }
  2375. propogateSlicerPosition();
  2376. }
  2377. void fMainWindow::UpdateSliceRange(int slicer, int min, int max)
  2378. {
  2379. int position = int((min + max) / 2);
  2380. if (slicer == 0) {
  2381. AxialViewSlider->setValue(position);
  2382. AxialViewSlider->setRange(min, max);
  2383. }
  2384. else if (slicer == 1) {
  2385. CoronalViewSlider->setValue(position);
  2386. CoronalViewSlider->setRange(min, max);
  2387. }
  2388. else if (slicer == 2) {
  2389. SaggitalViewSlider->setValue(position);
  2390. SaggitalViewSlider->setRange(min, max);
  2391. }
  2392. }
  2393. void fMainWindow::UpdateRenderWindows()
  2394. {
  2395. if (m_imagesTable->rowCount() <= 0)
  2396. {
  2397. return;
  2398. }
  2399. auto items = m_imagesTable->selectedItems();
  2400. if (items.empty()) {
  2401. return;
  2402. }
  2403. QTableWidgetItem* item = items[0];
  2404. if (item == NULL) {
  2405. return;
  2406. }
  2407. int index = GetSlicerIndexFromItem(item);
  2408. if (index >= 0 && index < (int)mSlicerManagers.size())
  2409. {
  2410. mSlicerManagers[index]->Render();
  2411. }
  2412. //*/
  2413. }
  2414. void fMainWindow::SetActiveLandmarksType(int type, int row, int col)
  2415. {
  2416. mCurrentLandmarkTissueType = row;
  2417. if (type == LANDMARK_TYPE::DEFAULT)
  2418. {
  2419. emit LandmarksFocused(true);
  2420. emit SeedPointsFocused(false);
  2421. emit TissuePointsFocused(false);
  2422. }
  2423. else if (type == LANDMARK_TYPE::TUMOR_POINTS)
  2424. {
  2425. emit LandmarksFocused(false);
  2426. emit SeedPointsFocused(true);
  2427. emit TissuePointsFocused(false);
  2428. //tumorPanel->mTumorPointsSelected = true;
  2429. }
  2430. else if (type == LANDMARK_TYPE::TISSUE_POINTS)
  2431. {
  2432. emit LandmarksFocused(false);
  2433. emit SeedPointsFocused(false);
  2434. emit TissuePointsFocused(true);
  2435. }
  2436. else
  2437. {
  2438. emit LandmarksFocused(false);
  2439. emit SeedPointsFocused(false);
  2440. emit TissuePointsFocused(false);
  2441. }
  2442. for (int i = 0; i < (int)mSlicerManagers.size(); i++)
  2443. mSlicerManagers[i]->SetCurrentLandmarksType(type, row, col);
  2444. UpdateRenderWindows();
  2445. }
  2446. void fMainWindow::panelChanged(int current)
  2447. {
  2448. if (drawingPanel) //Reset shape mode on every panel switch
  2449. {
  2450. m_drawShapeMode = SHAPE_MODE_NONE;
  2451. drawingPanel->shapesNoneButtonFunctionality();
  2452. }
  2453. else
  2454. {
  2455. SetActiveLandmarksType(LANDMARK_TYPE::NONE, 0, 0);
  2456. }
  2457. //else if (current == TAB_TUMOR)
  2458. //{
  2459. // SetActiveLandmarksType(LANDMARK_TYPE::NONE, 0, 0);
  2460. // //tumorPanel->SetCurrentSelectedTissueType();
  2461. //}
  2462. }
  2463. void fMainWindow::MoveSlicerCursor(double x, double y, double z, int mode)
  2464. {
  2465. if (mCurrentPickedImageIndex < 0 || mCurrentPickedImageIndex >= (int)mSlicerManagers.size()) {
  2466. return;
  2467. }
  2468. //
  2469. if (mode == 0)
  2470. {
  2471. // x, y, z are LPS
  2472. mSlicerManagers[mCurrentPickedImageIndex]->GetSlicer(0)->SetCurrentPosition(x, y, z);
  2473. //
  2474. mSlicerManagers[mCurrentPickedImageIndex]->Picked();
  2475. mSlicerManagers[mCurrentPickedImageIndex]->UpdateViews(0);
  2476. mSlicerManagers[mCurrentPickedImageIndex]->UpdateLinked(0);
  2477. mSlicerManagers[mCurrentPickedImageIndex]->UpdateInfoOnCursorPosition(0);
  2478. }
  2479. else if (mode == 1)
  2480. {
  2481. // x, y, z are pixel
  2482. x = x * mSlicerManagers[mCurrentPickedImageIndex]->GetSlicer(0)->GetInput()->GetSpacing()[0] + mSlicerManagers[mCurrentPickedImageIndex]->GetSlicer(0)->GetInput()->GetOrigin()[0];
  2483. y = y * mSlicerManagers[mCurrentPickedImageIndex]->GetSlicer(0)->GetInput()->GetSpacing()[1] + mSlicerManagers[mCurrentPickedImageIndex]->GetSlicer(0)->GetInput()->GetOrigin()[1];
  2484. z = z * mSlicerManagers[mCurrentPickedImageIndex]->GetSlicer(0)->GetInput()->GetSpacing()[2] + mSlicerManagers[mCurrentPickedImageIndex]->GetSlicer(0)->GetInput()->GetOrigin()[2];
  2485. //
  2486. mSlicerManagers[mCurrentPickedImageIndex]->GetSlicer(0)->SetCurrentPosition(x, y, z);
  2487. //
  2488. mSlicerManagers[mCurrentPickedImageIndex]->Picked();
  2489. mSlicerManagers[mCurrentPickedImageIndex]->UpdateViews(0);
  2490. mSlicerManagers[mCurrentPickedImageIndex]->UpdateLinked(0);
  2491. mSlicerManagers[mCurrentPickedImageIndex]->UpdateInfoOnCursorPosition(0);
  2492. }
  2493. propogateSlicerPosition();
  2494. }
  2495. void fMainWindow::toolTabDockChanged(bool bUnDocked)
  2496. {
  2497. if (bUnDocked)
  2498. {
  2499. m_tabWidget->setMaximumHeight(m_tabWidget->minimumHeight() * 10);
  2500. m_toolTabdock->show();
  2501. }
  2502. else
  2503. {
  2504. m_tabWidget->setMaximumHeight(m_tabWidget->minimumHeight());
  2505. }
  2506. }
  2507. VectorVectorDouble fMainWindow::FormulateDrawingPointsForEdemaSegmentation()
  2508. {
  2509. VectorVectorDouble Indices;
  2510. if (mSlicerManagers.size() <= 0)
  2511. return Indices;
  2512. ImageTypeShort3D::Pointer img = convertVtkToItk<short, 3>(mSlicerManagers[0]->mMask);
  2513. typedef itk::ImageRegionIteratorWithIndex <ImageTypeShort3D> IteratorType;
  2514. IteratorType maskIt(img, img->GetLargestPossibleRegion());
  2515. maskIt.GoToBegin();
  2516. while (!maskIt.IsAtEnd())
  2517. {
  2518. if (maskIt.Get() == 1 || maskIt.Get() == 2)
  2519. {
  2520. VectorDouble localIndex;
  2521. localIndex.push_back(maskIt.GetIndex()[0]);
  2522. localIndex.push_back(maskIt.GetIndex()[1]);
  2523. localIndex.push_back(maskIt.GetIndex()[2]);
  2524. Indices.push_back(localIndex);
  2525. }
  2526. ++maskIt;
  2527. }
  2528. return Indices;
  2529. }
  2530. VectorVectorDouble fMainWindow::GetMaskLabelIndices(const int label)
  2531. {
  2532. VectorVectorDouble Indices;
  2533. if (mSlicerManagers.size() <= 0)
  2534. return Indices;
  2535. ImageTypeShort3D::Pointer img = convertVtkToItk<short, 3>(mSlicerManagers[0]->mMask);
  2536. typedef itk::ImageRegionIteratorWithIndex <ImageTypeShort3D> IteratorType;
  2537. IteratorType maskIt(img, img->GetLargestPossibleRegion());
  2538. maskIt.GoToBegin();
  2539. while (!maskIt.IsAtEnd())
  2540. {
  2541. if (maskIt.Get() == label)
  2542. {
  2543. VectorDouble localIndex;
  2544. localIndex.push_back(maskIt.GetIndex()[0]);
  2545. localIndex.push_back(maskIt.GetIndex()[1]);
  2546. localIndex.push_back(maskIt.GetIndex()[2]);
  2547. Indices.push_back(localIndex);
  2548. }
  2549. ++maskIt;
  2550. }
  2551. return Indices;
  2552. }
  2553. VectorVectorDouble fMainWindow::FormulateDrawingPointsForTumorSegmentation()
  2554. {
  2555. VectorVectorDouble Indices;
  2556. if (mSlicerManagers.size() <= 0)
  2557. return Indices;
  2558. ImageTypeShort3D::Pointer img = convertVtkToItk<short, 3>(mSlicerManagers[0]->mMask);
  2559. typedef itk::ImageRegionIteratorWithIndex <ImageTypeShort3D> IteratorType;
  2560. IteratorType maskIt(img, img->GetLargestPossibleRegion());
  2561. maskIt.GoToBegin();
  2562. while (!maskIt.IsAtEnd())
  2563. {
  2564. if (maskIt.Get() == 1)
  2565. {
  2566. VectorDouble localIndex;
  2567. localIndex.push_back(maskIt.GetIndex()[0]);
  2568. localIndex.push_back(maskIt.GetIndex()[1]);
  2569. localIndex.push_back(maskIt.GetIndex()[2]);
  2570. Indices.push_back(localIndex);
  2571. }
  2572. ++maskIt;
  2573. }
  2574. return Indices;
  2575. }
  2576. void fMainWindow::SaveDicomImage()
  2577. {
  2578. auto items = m_imagesTable->selectedItems();
  2579. if (items.empty())
  2580. return;
  2581. int index = GetSlicerIndexFromItem(items[0]);
  2582. typedef short PixelType;
  2583. const unsigned int Dimensions = 3;
  2584. QString directory = getExistingDirectory(this, mInputPathName);
  2585. if (directory.isNull())
  2586. return;
  2587. std::string directory_wrap = directory.toStdString();
  2588. if (directory_wrap[directory_wrap.length() - 1] != '/')
  2589. {
  2590. directory_wrap += "/";
  2591. }
  2592. typedef itk::Image<PixelType, Dimensions> ImageType;
  2593. typedef itk::CastImageFilter< itk::Image< float, Dimensions >, ImageType > CastFilterType;
  2594. CastFilterType::Pointer castFilter = CastFilterType::New();
  2595. castFilter->SetInput(mSlicerManagers[index]->mITKImage);
  2596. castFilter->Update();
  2597. try
  2598. {
  2599. updateProgress(0, "Image saved! (" + directory_wrap + ")");
  2600. }
  2601. catch (itk::ExceptionObject & excp)
  2602. {
  2603. ShowErrorMessage("Couldn't write mask as DICOM: " + std::string(excp.GetDescription()));
  2604. return;
  2605. }
  2606. }
  2607. void fMainWindow::SaveDicomDrawing()
  2608. {
  2609. auto items = m_imagesTable->selectedItems();
  2610. if (items.empty())
  2611. return;
  2612. int index = GetSlicerIndexFromItem(items[0]);
  2613. typedef short MaskPixelType;
  2614. const unsigned int Dimensions = 3;
  2615. typedef itk::Image<MaskPixelType, Dimensions> ImageTypeMask;
  2616. ImageTypeMask::Pointer imageToWrite = convertVtkToItk<MaskPixelType, Dimensions>(mSlicerManagers[index]->mMask);
  2617. typedef itk::MinimumMaximumImageCalculator< ImageTypeMask > CalculatorType;
  2618. CalculatorType::Pointer calculator = CalculatorType::New();
  2619. calculator->SetImage(imageToWrite);
  2620. calculator->Compute();
  2621. if (calculator->GetMaximum() == 0) // this means that the mask image contains no values at all
  2622. {
  2623. ShowErrorMessage("There should be at least one region to save.");
  2624. return;
  2625. }
  2626. QString directory = getExistingDirectory(this, mInputPathName);
  2627. if (directory.isNull())
  2628. return;
  2629. std::string directory_wrap = directory.toStdString();
  2630. if (directory_wrap[directory_wrap.length() - 1] != '/')
  2631. {
  2632. directory_wrap += "/";
  2633. }
  2634. if (cbica::getFilenamePath(mSlicerManagers[index]->mSeriesReader->GetFileNames()[0]) == directory_wrap)
  2635. {
  2636. ShowErrorMessage("Cannot save to source directory. Please select another.");
  2637. return;
  2638. }
  2639. try
  2640. {
  2641. updateProgress(0, "Success!");
  2642. }
  2643. catch (itk::ExceptionObject & excp)
  2644. {
  2645. ShowErrorMessage("Couldn't write mask as DICOM: " + std::string(excp.GetDescription()));
  2646. return;
  2647. }
  2648. }
  2649. void fMainWindow::SaveDrawing()
  2650. {
  2651. auto items = m_imagesTable->selectedItems();
  2652. if (items.empty())
  2653. return;
  2654. int index = GetSlicerIndexFromItem(items[0]);
  2655. typedef unsigned short MaskPixelType;
  2656. const unsigned int Dimensions = 3;
  2657. typedef itk::Image<MaskPixelType, Dimensions> ImageTypeMask;
  2658. ImageTypeMask::Pointer imageToWrite = convertVtkToItk<MaskPixelType, Dimensions>(mSlicerManagers[index]->mMask);
  2659. typedef itk::MinimumMaximumImageCalculator< ImageTypeMask > CalculatorType;
  2660. CalculatorType::Pointer calculator = CalculatorType::New();
  2661. calculator->SetImage(imageToWrite);
  2662. calculator->Compute();
  2663. if (calculator->GetMaximum() == 0) // this means that the mask image contains no values at all
  2664. {
  2665. ShowErrorMessage("There should be at least one region (near or far) for saving.");
  2666. return;
  2667. }
  2668. auto imageToWrite_wrap = imageToWrite;
  2669. imageToWrite->DisconnectPipeline();
  2670. if (mSlicerManagers[index]->mImageSubType != CAPTK::ImageModalityType::IMAGE_TYPE_PERFUSION)
  2671. {
  2672. ImageTypeMask::DirectionType originalDirection;
  2673. originalDirection[0][0] = mSlicerManagers[index]->mDirection(0, 0);
  2674. originalDirection[0][1] = mSlicerManagers[index]->mDirection(0, 1);
  2675. originalDirection[0][2] = mSlicerManagers[index]->mDirection(0, 2);
  2676. originalDirection[1][0] = mSlicerManagers[index]->mDirection(1, 0);
  2677. originalDirection[1][1] = mSlicerManagers[index]->mDirection(1, 1);
  2678. originalDirection[1][2] = mSlicerManagers[index]->mDirection(1, 2);
  2679. originalDirection[2][0] = mSlicerManagers[index]->mDirection(2, 0);
  2680. originalDirection[2][1] = mSlicerManagers[index]->mDirection(2, 1);
  2681. originalDirection[2][2] = mSlicerManagers[index]->mDirection(2, 2);
  2682. ImageTypeMask::PointType originalOrigin;
  2683. originalOrigin = mSlicerManagers[index]->mOrigin;
  2684. auto infoChanger = itk::ChangeInformationImageFilter< ImageTypeMask >::New();
  2685. infoChanger->SetInput(imageToWrite);
  2686. infoChanger->ChangeDirectionOn();
  2687. infoChanger->ChangeOriginOn();
  2688. infoChanger->SetOutputDirection(originalDirection);
  2689. infoChanger->SetOutputOrigin(originalOrigin);
  2690. infoChanger->Update();
  2691. imageToWrite_wrap = infoChanger->GetOutput();
  2692. }
  2693. QString saveFileName = getSaveFile(this, mInputPathName, mInputPathName + "mask.nii.gz");
  2694. if (!saveFileName.isEmpty())
  2695. {
  2696. std::string filename = saveFileName.toStdString();
  2697. cbica::WriteImage< ImageTypeMask >(imageToWrite_wrap, filename);
  2698. if (cbica::isFile(filename))
  2699. {
  2700. updateProgress(0, "ROI saved!(" + filename + ")");
  2701. }
  2702. else
  2703. {
  2704. ShowErrorMessage("Couldn't write to file: " + filename);
  2705. }
  2706. }
  2707. }
  2708. void fMainWindow::SaveSeedDrawing()
  2709. {
  2710. auto items = m_imagesTable->selectedItems();
  2711. if (items.empty())
  2712. return;
  2713. QString saveFileName = getSaveFile(this, mInputPathName, mInputPathName + "drawing_seed.nii.gz");
  2714. if (!saveFileName.isEmpty())
  2715. {
  2716. std::string filename = saveFileName.toStdString();
  2717. ImageTypeShort3D::Pointer img = convertVtkToItk<ImageTypeShort3D::PixelType, ImageTypeShort3D::ImageDimension>(mSlicerManagers[0]->mMask);
  2718. std::vector<ImageTypeShort3D::IndexType> seedIndices;
  2719. itk::ImageRegionIteratorWithIndex <ImageTypeShort3D> maskIt(img, img->GetLargestPossibleRegion());
  2720. maskIt.GoToBegin();
  2721. while (!maskIt.IsAtEnd())
  2722. {
  2723. if (maskIt.Get() == 3/*seeds are always defined as label '3'*/)
  2724. seedIndices.push_back(maskIt.GetIndex());
  2725. ++maskIt;
  2726. }
  2727. std::string errormsg = "";
  2728. if (seedIndices.size() == 0)
  2729. errormsg = "Draw seed points (label 3) before saving.";
  2730. QMessageBox box(this);
  2731. box.setIcon(QMessageBox::Information);
  2732. box.addButton(QMessageBox::Ok);
  2733. if (errormsg.length() > 0)
  2734. {
  2735. box.setText(QString::fromStdString(errormsg));
  2736. box.setWindowTitle(tr("Error message"));
  2737. box.exec();
  2738. return;
  2739. }
  2740. //save actual near and far region according to the current image type
  2741. std::string InputPixelType = mSlicerManagers[0]->mImage->GetScalarTypeAsString();
  2742. std::string subjectname = m_imagesTable->selectedItems()[0]->data(Qt::DisplayRole).toString().toStdString();
  2743. subjectname = subjectname.substr(0, subjectname.find("_"));
  2744. if (InputPixelType == "short")
  2745. {
  2746. using MaskPixelType = short;
  2747. auto img = convertVtkToItk<MaskPixelType, 3>(mSlicerManagers[0]->mImage);
  2748. mOutputManager.WriteSeedMasks< itk::Image<MaskPixelType, 3> >(img, filename, seedIndices);
  2749. }
  2750. else if (InputPixelType == "unsigned short")
  2751. {
  2752. using MaskPixelType = unsigned short;
  2753. auto img = convertVtkToItk<MaskPixelType, 3>(mSlicerManagers[0]->mImage);
  2754. mOutputManager.WriteSeedMasks<itk::Image<MaskPixelType, 3>>(img, filename, seedIndices);
  2755. }
  2756. else if (InputPixelType == "char")
  2757. {
  2758. using MaskPixelType = char;
  2759. auto img = convertVtkToItk<MaskPixelType, 3>(mSlicerManagers[0]->mImage);
  2760. mOutputManager.WriteSeedMasks<itk::Image<MaskPixelType, 3>>(img, filename, seedIndices);
  2761. }
  2762. else if (InputPixelType == "unsigned char")
  2763. {
  2764. using MaskPixelType = unsigned char;
  2765. auto img = convertVtkToItk<MaskPixelType, 3>(mSlicerManagers[0]->mImage);
  2766. mOutputManager.WriteSeedMasks<itk::Image<MaskPixelType, 3>>(img, filename, seedIndices);
  2767. }
  2768. else if (InputPixelType == "int")
  2769. {
  2770. using MaskPixelType = int;
  2771. auto img = convertVtkToItk<MaskPixelType, 3>(mSlicerManagers[0]->mImage);
  2772. mOutputManager.WriteSeedMasks<itk::Image<MaskPixelType, 3>>(img, filename, seedIndices);
  2773. }
  2774. else if (InputPixelType == "unsigned int")
  2775. {
  2776. using MaskPixelType = unsigned int;
  2777. auto img = convertVtkToItk<MaskPixelType, 3>(mSlicerManagers[0]->mImage);
  2778. mOutputManager.WriteSeedMasks<itk::Image<MaskPixelType, 3>>(img, filename, seedIndices);
  2779. }
  2780. else if (InputPixelType == "double")
  2781. {
  2782. using MaskPixelType = double;
  2783. auto img = convertVtkToItk<MaskPixelType, 3>(mSlicerManagers[0]->mImage);
  2784. mOutputManager.WriteSeedMasks<itk::Image<MaskPixelType, 3>>(img, subjectname, seedIndices);
  2785. }
  2786. else if (InputPixelType == "float")
  2787. {
  2788. using MaskPixelType = float;
  2789. auto img = convertVtkToItk<MaskPixelType, 3>(mSlicerManagers[0]->mImage);
  2790. mOutputManager.WriteSeedMasks<itk::Image<MaskPixelType, 3>>(img, filename, seedIndices);
  2791. }
  2792. else
  2793. {
  2794. cbica::Logging(loggerFile, "Error, input pixel type, '" + InputPixelType + "' is unknown!");
  2795. }
  2796. std::string msg = "Mask saved: " + filename;
  2797. updateProgress(0, msg);
  2798. }
  2799. }
  2800. void fMainWindow::makeStroke(std::vector<itk::Image<short, 3>::IndexType>& indices, const int value)
  2801. {
  2802. std::vector<PointVal> strokePoints;
  2803. for (unsigned int i = 0; i < indices.size(); i++)
  2804. {
  2805. float* pData = (float*)this->mSlicerManagers[0]->GetSlicer(0)->mMask->GetScalarPointer((int)indices[i][0], (int)indices[i][1], (int)indices[i][2]);
  2806. PointVal pt;
  2807. pt.x = indices[i][0];
  2808. pt.y = indices[i][1];
  2809. pt.z = indices[i][1];
  2810. pt.value = (int)*pData;
  2811. strokePoints.push_back(pt);
  2812. *pData = value;
  2813. }
  2814. UpdateAction(strokePoints);
  2815. return;
  2816. }
  2817. void fMainWindow::clearMask(int label)
  2818. {
  2819. if ((mSlicerManagers.size() <= 0))
  2820. return;
  2821. auto img = convertVtkToItk<ImageTypeShort3D::PixelType, 3>(mSlicerManagers[0]->mMask);
  2822. std::vector<ImageTypeShort3D::IndexType> indecesToErase;
  2823. itk::ImageRegionIteratorWithIndex <ImageTypeShort3D> maskIt(img, img->GetLargestPossibleRegion());
  2824. maskIt.GoToBegin();
  2825. while (!maskIt.IsAtEnd())
  2826. {
  2827. if (label < 0)//Clear all
  2828. {
  2829. if (maskIt.Get() > 0)
  2830. {
  2831. indecesToErase.push_back(maskIt.GetIndex());
  2832. }
  2833. }
  2834. else
  2835. {
  2836. if (maskIt.Get() == label)
  2837. {
  2838. indecesToErase.push_back(maskIt.GetIndex());
  2839. }
  2840. }
  2841. ++maskIt;
  2842. }
  2843. makeStroke(indecesToErase, 0);
  2844. this->mSlicerManagers[0]->GetSlicer(0)->mMask->Modified();
  2845. this->mSlicerManagers[0]->Render();
  2846. UpdateNumberOfPointsInTable();
  2847. }
  2848. //void fMainWindow::StartEGFREstimate()
  2849. //{
  2850. //}
  2851. ImageTypeFloat3D::Pointer fMainWindow::getMaskImage()
  2852. {
  2853. ImageTypeFloat3D::Pointer img = NULL;
  2854. if (mSlicerManagers[0]->mMask != NULL)
  2855. {
  2856. img = convertVtkToItk<float, 3>(mSlicerManagers[0]->mMask);
  2857. }
  2858. return img;
  2859. }
  2860. void fMainWindow::readMaskFile(const std::string &maskFileName)
  2861. {
  2862. auto maskFileName_toRead = maskFileName;
  2863. bool imageSanityCheckDone = false;
  2864. if (!mSlicerManagers.empty())
  2865. {
  2866. if (cbica::IsDicom(maskFileName_toRead))
  2867. {
  2868. auto path = cbica::getFilenamePath(maskFileName_toRead);
  2869. auto filesInDir = cbica::filesInDirectory(path, false);
  2870. if (filesInDir.size() == 1) // single DICOM slice
  2871. {
  2872. dicomfilename = maskFileName_toRead;
  2873. maskFileName_toRead = ConversionFrom2Dto3D(maskFileName_toRead);
  2874. }
  2875. else
  2876. {
  2877. auto temp_prev = cbica::normPath(m_tempFolderLocation + "/convertedMask.nii.gz");
  2878. auto maskFromDicom = cbica::ReadImage< ImageTypeFloat3D >(maskFileName_toRead);
  2879. cbica::WriteImage< ImageTypeFloat3D >(maskFromDicom, temp_prev);
  2880. maskFileName_toRead = temp_prev;
  2881. }
  2882. }
  2883. else
  2884. {
  2885. auto maskInfo = cbica::ImageInfo(maskFileName_toRead);
  2886. auto imageSize = mSlicerManagers[0]->mITKImage->GetLargestPossibleRegion().GetSize();
  2887. auto maskSize = maskInfo.GetImageSize();
  2888. if ((imageSize[2] == 1) || (maskSize[2] == 1) || (maskInfo.GetImageDimensions() == 2))
  2889. {
  2890. // this is actually a 2D image which has been loaded in CaPTk as a pseudo-3D image
  2891. auto origin_image = mSlicerManagers[0]->mOrigin;
  2892. auto spacings_image = mSlicerManagers[0]->mITKImage->GetSpacing();
  2893. auto size_image = imageSize;
  2894. auto origin_mask = maskInfo.GetImageOrigins();
  2895. auto spacings_mask = maskInfo.GetImageSpacings();
  2896. auto size_mask = maskInfo.GetImageSize();
  2897. //ImageType::DirectionType directions_image;
  2898. //directions_image[0][0] = mSlicerManagers[0]->mDirection(0, 0);
  2899. //directions_image[0][1] = mSlicerManagers[0]->mDirection(0, 1);
  2900. //directions_image[0][2] = mSlicerManagers[0]->mDirection(0, 2);
  2901. //directions_image[1][0] = mSlicerManagers[0]->mDirection(1, 0);
  2902. //directions_image[1][1] = mSlicerManagers[0]->mDirection(1, 1);
  2903. //directions_image[1][2] = mSlicerManagers[0]->mDirection(1, 2);
  2904. //directions_image[2][0] = mSlicerManagers[0]->mDirection(2, 0);
  2905. //directions_image[2][1] = mSlicerManagers[0]->mDirection(2, 1);
  2906. //directions_image[2][2] = mSlicerManagers[0]->mDirection(2, 2);
  2907. for (size_t i = 0; i < 2; i++)
  2908. {
  2909. if (origin_image[i] != origin_mask[i])
  2910. {
  2911. ShowErrorMessage("The origins of the previously loaded image and mask are inconsistent; cannot load");
  2912. return;
  2913. }
  2914. if (spacings_image[i] != spacings_mask[i])
  2915. {
  2916. auto percentageDifference = std::abs(spacings_image[i] - spacings_mask[i]) * 100;
  2917. percentageDifference /= spacings_image[i];
  2918. if (percentageDifference > 0.0001)
  2919. {
  2920. ShowErrorMessage("The spacings of the previously loaded image and mask are inconsistent; cannot load");
  2921. return;
  2922. }
  2923. }
  2924. if (size_image[i] != size_mask[i])
  2925. {
  2926. ShowErrorMessage("The sizes of the previously loaded image and mask are inconsistent; cannot load");
  2927. return;
  2928. }
  2929. }
  2930. maskFileName_toRead = ConversionFrom2Dto3D(maskFileName_toRead); // all sanity checks passed; load the mask
  2931. imageSanityCheckDone = true;
  2932. }
  2933. }
  2934. //auto temp_prev = cbica::normPath(m_tempFolderLocation + "/temp_prev.nii.gz");
  2935. auto mask_temp = cbica::ReadImageWithOrientFix< ImageTypeFloat3D >(maskFileName_toRead);
  2936. //SaveImage_withFile(0, temp_prev.c_str());
  2937. if (!imageSanityCheckDone)
  2938. {
  2939. if (!cbica::ImageSanityCheck< ImageTypeFloat3D >(mSlicerManagers[0]->mITKImage, mask_temp))
  2940. {
  2941. ShowErrorMessage("The physical dimensions of the previously loaded image and mask are inconsistent; cannot load");
  2942. return;
  2943. }
  2944. imageSanityCheckDone = true;
  2945. }
  2946. using ImageType = itk::Image<unsigned int, 3>;
  2947. auto inputImage = cbica::ReadImageWithOrientFix< ImageType >(maskFileName_toRead);
  2948. inputImage = ChangeImageDirectionToIdentity< ImageType >(inputImage);
  2949. auto minMaxCalc = itk::MinimumMaximumImageCalculator< ImageType >::New();
  2950. minMaxCalc->SetImage(inputImage);
  2951. minMaxCalc->Compute();
  2952. auto maxVal = minMaxCalc->GetMaximum();
  2953. if (maxVal > 0)
  2954. {
  2955. itk::ImageRegionIteratorWithIndex <ImageType> maskIt(inputImage, inputImage->GetLargestPossibleRegion());
  2956. maskIt.GoToBegin();
  2957. while (!maskIt.IsAtEnd())
  2958. {
  2959. /*
  2960. change to this & also in manual:
  2961. 1 for necrosis
  2962. 2 for edema
  2963. 3 for non-enhancing tumor
  2964. 4 for enhancing tumor
  2965. */
  2966. ImageType::IndexType currentIndex = maskIt.GetIndex();
  2967. float* pData = (float*)this->mSlicerManagers[0]->GetSlicer(0)->mMask->GetScalarPointer((int)currentIndex[0], (int)currentIndex[1], (int)currentIndex[2]);
  2968. *pData = 0; // this is done in order to ensure that previously loaded mask is removed
  2969. // this is done to take into account all possible label drawings
  2970. switch (maskIt.Get())
  2971. { // multiLabel: uncomment everything inside this loop and remove references to "near" and "far"
  2972. case DRAW_MODE_LABEL_1:
  2973. *pData = DRAW_MODE_LABEL_1;
  2974. break;
  2975. case 10: // GLISTR defines this as CSF
  2976. *pData = DRAW_MODE_LABEL_7;
  2977. break;
  2978. case DRAW_MODE_LABEL_2:
  2979. *pData = DRAW_MODE_LABEL_2;
  2980. break;
  2981. case 150: // GLISTR defines this is as GM
  2982. *pData = DRAW_MODE_LABEL_5;
  2983. break;
  2984. case DRAW_MODE_LABEL_3:
  2985. *pData = DRAW_MODE_LABEL_3;
  2986. break;
  2987. case 250: // GLISTR defines this is as WM
  2988. *pData = DRAW_MODE_LABEL_3;
  2989. break;
  2990. case DRAW_MODE_LABEL_4:
  2991. *pData = DRAW_MODE_LABEL_4;
  2992. break;
  2993. case 25: // GLISTR defines this is as VS
  2994. *pData = DRAW_MODE_LABEL_4;
  2995. break;
  2996. case DRAW_MODE_LABEL_5: // this is an ambiguous index since GLISTR also uses this for CB
  2997. {
  2998. if (maxVal > DRAW_MODE_LABEL_9) // this means we are reading in GLISTR output
  2999. {
  3000. *pData = DRAW_MODE_LABEL_9;
  3001. }
  3002. else
  3003. {
  3004. *pData = DRAW_MODE_LABEL_5;
  3005. }
  3006. break;
  3007. }
  3008. case 100: // GLISTR defines this is as ED
  3009. *pData = DRAW_MODE_LABEL_2;
  3010. break;
  3011. case DRAW_MODE_LABEL_6:
  3012. *pData = DRAW_MODE_LABEL_6;
  3013. break;
  3014. case 175: // GLISTR defines this is as NCR
  3015. *pData = DRAW_MODE_LABEL_1;
  3016. break;
  3017. case DRAW_MODE_LABEL_7:
  3018. *pData = DRAW_MODE_LABEL_7;
  3019. break;
  3020. case 200: // GLISTR defines this is as TU
  3021. *pData = DRAW_MODE_LABEL_4;
  3022. break;
  3023. case DRAW_MODE_LABEL_8:
  3024. *pData = DRAW_MODE_LABEL_8;
  3025. break;
  3026. case 185: // GLISTR defines this is as NE
  3027. *pData = DRAW_MODE_LABEL_1;
  3028. break;
  3029. case DRAW_MODE_LABEL_9:
  3030. *pData = DRAW_MODE_LABEL_9;
  3031. break;
  3032. case 255: // contingency case in case a map is defined as 255 and 0
  3033. *pData = DRAW_MODE_LABEL_1;
  3034. break;
  3035. default:
  3036. // nothing defined for other cases
  3037. break;
  3038. }
  3039. ++maskIt;
  3040. }
  3041. }
  3042. else
  3043. {
  3044. ShowErrorMessage("Mask file has no pixels greater than '0'");
  3045. }
  3046. UpdateRenderWindows();
  3047. updateProgress(0, "Mask loaded");
  3048. }
  3049. else
  3050. {
  3051. ShowErrorMessage("Please load an image before trying to load an ROI");
  3052. return;
  3053. }
  3054. // Force a render of the mask since updating the render windows doesn't cut it
  3055. this->mSlicerManagers[0]->GetSlicer(0)->mMask->Modified();
  3056. this->mSlicerManagers[0]->Render();
  3057. }
  3058. std::vector<ImageTypeFloat3D::Pointer> fMainWindow::getLodedImages(std::vector<std::string> &fileNames, std::vector<std::string> &modality, bool onlySelected)
  3059. {
  3060. std::vector < ImageTypeFloat3D::Pointer> images;
  3061. if (onlySelected)
  3062. {
  3063. auto items = m_imagesTable->selectedItems();
  3064. if (!items.empty())
  3065. {
  3066. int index = GetSlicerIndexFromItem(items[0]);
  3067. images.push_back(mSlicerManagers[index]->mITKImage);
  3068. fileNames.push_back(mSlicerManagers[index]->mFileName);
  3069. std::string pp = CAPTK::ImageModalityString[mSlicerManagers[index]->mImageSubType];
  3070. modality.push_back(CAPTK::ImageModalityString[mSlicerManagers[index]->mImageSubType]);
  3071. }
  3072. }
  3073. else
  3074. {
  3075. for (unsigned int index = 0; index < mSlicerManagers.size(); index++)
  3076. {
  3077. images.push_back(mSlicerManagers[index]->mITKImage);
  3078. fileNames.push_back(mSlicerManagers[index]->mFileName);
  3079. modality.push_back(CAPTK::ImageModalityString[mSlicerManagers[index]->mImageSubType]);
  3080. }
  3081. }
  3082. return images;
  3083. }
  3084. void fMainWindow::dragEnterEvent(QDragEnterEvent *event)
  3085. {
  3086. if (event->mimeData()->hasFormat("text/uri-list")) {
  3087. event->acceptProposedAction();
  3088. }
  3089. }
  3090. void fMainWindow::dropEvent(QDropEvent *event)
  3091. {
  3092. QList<QUrl> urls = event->mimeData()->urls();
  3093. QStringList vectorOfFiles;
  3094. for (int i = 0; i < (int)urls.size(); i++)
  3095. {
  3096. vectorOfFiles.push_back(urls[i].toLocalFile());
  3097. }
  3098. // if more than 1 files are dropped, assume they are images
  3099. if ((vectorOfFiles.size() > 1) || mSlicerManagers.empty())
  3100. {
  3101. openImages(vectorOfFiles);
  3102. }
  3103. else
  3104. {
  3105. // ask if it is an image or roi
  3106. QMessageBox *box = new QMessageBox(QMessageBox::Question,
  3107. "Image Type",
  3108. "Please select the type of image being loaded", QMessageBox::Ok | QMessageBox::Cancel);
  3109. box->button(QMessageBox::Ok)->setText("Image");
  3110. box->button(QMessageBox::Cancel)->setText("ROI");
  3111. box->setAttribute(Qt::WA_DeleteOnClose); //makes sure the msgbox is deleted automatically when closed
  3112. box->setWindowModality(Qt::NonModal);
  3113. QCoreApplication::processEvents();
  3114. if (box->exec() == QMessageBox::Ok)
  3115. {
  3116. openImages(vectorOfFiles);
  3117. }
  3118. else
  3119. {
  3120. readMaskFile(vectorOfFiles[0].toStdString());
  3121. }
  3122. }
  3123. }
  3124. void fMainWindow::CloseNonViewingDTIImage(QTableWidgetItem* item)
  3125. {
  3126. int itemIndexToBeDeleted = 0;
  3127. m_nonVisImagesTable->removeRow(item->row());
  3128. for (unsigned int index = 0; index < mNonViewingImageManager.size(); index++)
  3129. {
  3130. if (mNonViewingImageManager[index]->mImageType == CAPTK::ImageModalityType::IMAGE_TYPE_DTI)
  3131. {
  3132. itemIndexToBeDeleted = index;
  3133. delete mNonViewingImageManager[index];
  3134. break;
  3135. }
  3136. }
  3137. std::vector<SimpleImageManager*>::iterator simpleImageIterator = mNonViewingImageManager.begin();
  3138. for (int i = 0; i < itemIndexToBeDeleted; i++)
  3139. simpleImageIterator++;
  3140. mNonViewingImageManager.erase(simpleImageIterator);
  3141. }
  3142. void fMainWindow::UpdateNumberOfPointsInTable()
  3143. {
  3144. if (mSlicerManagers.size() <= 0)
  3145. return;
  3146. ImageTypeShort3D::Pointer img = convertVtkToItk<short, 3>(mSlicerManagers[0]->mMask);
  3147. int nearCounter = 0;
  3148. int farCounter = 0;
  3149. int initCounter = 0;
  3150. typedef itk::ImageRegionIteratorWithIndex <ImageTypeShort3D> IteratorType;
  3151. IteratorType maskIt(img, img->GetLargestPossibleRegion());
  3152. maskIt.GoToBegin();
  3153. while (!maskIt.IsAtEnd())
  3154. {
  3155. if (maskIt.Get() == DRAW_MODE_LABEL_1)
  3156. nearCounter++;
  3157. else if (maskIt.Get() == DRAW_MODE_LABEL_2)
  3158. farCounter++;
  3159. else if (maskIt.Get() == DRAW_MODE_LABEL_3)
  3160. initCounter++;
  3161. ++maskIt;
  3162. }
  3163. mCurrentNearPoints = nearCounter;
  3164. mCurrentFarPoints = farCounter;
  3165. mCurrentInitPoints = initCounter;
  3166. }
  3167. void fMainWindow::SetPresetComboBox()
  3168. {
  3169. presetComboBox->addItem("Auto Scale");
  3170. presetComboBox->addItem("User Scale");
  3171. presetComboBox->addItem("Label Map");
  3172. presetComboBox->addItem("Label Map 2");
  3173. presetComboBox->addItem("Threshold");
  3174. presetComboBox->addItem("Probability");
  3175. presetComboBox->addItem("Geodesic");
  3176. }
  3177. void fMainWindow::ResetNumberOfPoints()
  3178. {
  3179. UpdateNumberOfPointsInTable();
  3180. }
  3181. ImageTypeFloat3D::Pointer fMainWindow::RescaleImageIntensity(ImageTypeFloat3D::Pointer image)
  3182. {
  3183. typedef itk::RescaleIntensityImageFilter< ImageTypeFloat3D, ImageTypeFloat3D > RescaleFilterType;
  3184. RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New();
  3185. rescaleFilter->SetInput(image);
  3186. rescaleFilter->SetOutputMinimum(0);
  3187. rescaleFilter->SetOutputMaximum(255);
  3188. rescaleFilter->Update();
  3189. ImageTypeFloat3D::Pointer outputimage = rescaleFilter->GetOutput();
  3190. return outputimage;
  3191. }
  3192. #ifdef BUILD_RECURENCE
  3193. void fMainWindow::TrainNewModelOnGivenData(const std::string &inputdirectory, const std::string &outputdirectory, bool useConvData, bool useDTIData, bool usePerfData, bool useDistData)
  3194. {
  3195. std::string errorMsg;
  3196. if (inputdirectory.empty())
  3197. {
  3198. ShowErrorMessage("Please provide input directory.");
  3199. help_contextual("Glioblastoma_Recurrence.html");
  3200. return;
  3201. }
  3202. if (outputdirectory.empty())
  3203. {
  3204. ShowErrorMessage("Please provide output directory.");
  3205. help_contextual("Glioblastoma_Recurrence.html");
  3206. return;
  3207. }
  3208. if (!cbica::isDir(outputdirectory))
  3209. {
  3210. if (!cbica::createDir(outputdirectory))
  3211. {
  3212. ShowErrorMessage("Unable to create the output directory");
  3213. help_contextual("Glioblastoma_Recurrence.html");
  3214. return;
  3215. }
  3216. }
  3217. std::vector<double> finalresult;
  3218. std::vector<std::map<CAPTK::ImageModalityType, std::string>> QualifiedSubjects = LoadQualifiedSubjectsFromGivenDirectoryForRecurrence(CAPTK::MachineLearningApplicationSubtype::TRAINING, inputdirectory, useConvData, useDTIData, usePerfData, useDistData);
  3219. if (QualifiedSubjects.size() == 0)
  3220. {
  3221. ShowErrorMessage("The specified directory does not have any subject with all the required imaging sequences.");
  3222. help_contextual("Glioblastoma_Recurrence.html");
  3223. return;
  3224. }
  3225. if (mRecurrenceEstimator.TrainNewModelOnGivenData(QualifiedSubjects, outputdirectory, useConvData, useDTIData, usePerfData, useDistData))
  3226. ShowMessage("Trained infiltration model has been saved at the specified location.", this);
  3227. else
  3228. ShowErrorMessage("Recurrence Estimator wasn't able to save the training files as expected. See log file for details: " + loggerFile);
  3229. }
  3230. #endif
  3231. #ifdef BUILD_PSEUDOPROGRESSION
  3232. void fMainWindow::TrainNewPseudoprogressionModelOnGivenData(const std::string &inputdirectory, const std::string &outputdirectory, bool useConvData, bool useDTIData, bool usePerfData, bool useDistData)
  3233. {
  3234. std::string errorMsg;
  3235. if (inputdirectory.empty())
  3236. {
  3237. ShowErrorMessage("Please provide input directory.", this);
  3238. help_contextual("Glioblastoma_Pseudoprogression.html");
  3239. return;
  3240. }
  3241. if (outputdirectory.empty())
  3242. {
  3243. ShowErrorMessage("Please provide output directory.", this);
  3244. help_contextual("Glioblastoma_Pseudoprogression.html");
  3245. return;
  3246. }
  3247. if (!cbica::isDir(outputdirectory))
  3248. {
  3249. if (!cbica::createDir(outputdirectory))
  3250. {
  3251. ShowErrorMessage("Unable to create the output directory", this);
  3252. help_contextual("Glioblastoma_Pseudoprogression.html");
  3253. return;
  3254. }
  3255. }
  3256. std::vector<double> finalresult;
  3257. std::vector<std::map<CAPTK::ImageModalityType, std::string>> QualifiedSubjects = LoadQualifiedSubjectsFromGivenDirectoryForPseudoProgression(CAPTK::MachineLearningApplicationSubtype::TRAINING, inputdirectory, useConvData, useDTIData, usePerfData, useDistData);
  3258. if (QualifiedSubjects.size() == 0)
  3259. {
  3260. ShowErrorMessage("The specified directory does not have any subject with all the required imaging sequences.", this);
  3261. help_contextual("Glioblastoma_Pseudoprogression.html");
  3262. return;
  3263. }
  3264. if (QualifiedSubjects.size() > 0 && QualifiedSubjects.size() <= 20)
  3265. {
  3266. ShowErrorMessage("There should be atleast 20 patients to build reliable pseudo-progression model.");
  3267. return;
  3268. }
  3269. if (mPseudoEstimator.TrainNewModelOnGivenData(QualifiedSubjects, outputdirectory, useConvData, useDTIData, usePerfData, useDistData))
  3270. ShowMessage("Trained pseudoprogression model has been saved at the specified location.", this);
  3271. else
  3272. ShowErrorMessage("Pseudoprogression Estimator wasn't able to save the training files as expected. See log file for details: " + loggerFile, this);
  3273. }
  3274. #endif
  3275. #ifdef BUILD_PCA
  3276. void fMainWindow::TrainNewPCAModelOnGivenData(const std::string &inputdirectory, const std::string &outputdirectory)
  3277. {
  3278. std::string errorMsg;
  3279. if (inputdirectory.empty())
  3280. {
  3281. ShowErrorMessage("Please provide input directory.", this);
  3282. //help_contextual("Glioblastoma_Pseudoprogression.html");
  3283. return;
  3284. }
  3285. if (outputdirectory.empty())
  3286. {
  3287. ShowErrorMessage("Please provide output directory.", this);
  3288. //help_contextual("Glioblastoma_Pseudoprogression.html");
  3289. return;
  3290. }
  3291. if (!cbica::isDir(outputdirectory))
  3292. {
  3293. if (!cbica::createDir(outputdirectory))
  3294. {
  3295. ShowErrorMessage("Unable to create the output directory", this);
  3296. //help_contextual("Glioblastoma_Pseudoprogression.html");
  3297. return;
  3298. }
  3299. }
  3300. std::vector<double> finalresult;
  3301. std::vector<std::map<CAPTK::ImageModalityType, std::string>> QualifiedSubjects = LoadQualifiedSubjectsFromGivenDirectoryForPCA(inputdirectory);
  3302. if (QualifiedSubjects.size() == 0)
  3303. {
  3304. ShowErrorMessage("The specified directory does not have any subject with all the required imaging sequences.", this);
  3305. //help_contextual("Glioblastoma_Pseudoprogression.html");
  3306. return;
  3307. }
  3308. if (QualifiedSubjects.size() > 0 && QualifiedSubjects.size() <= 20)
  3309. {
  3310. ShowErrorMessage("There should be atleast 20 patients to build reliable pseudo-progression model.");
  3311. return;
  3312. }
  3313. PerfusionPCA mPCAEstimator;
  3314. if (mPCAEstimator.PrepareNewPCAModel(10,inputdirectory,outputdirectory,QualifiedSubjects))
  3315. ShowMessage("Trained pseudoprogression model has been saved at the specified location.", this);
  3316. else
  3317. ShowErrorMessage("Pseudoprogression Estimator wasn't able to save the training files as expected. See log file for details: " + loggerFile, this);
  3318. }
  3319. #endif
  3320. //
  3321. //void fMainWindow::LoadDicomDrawing()
  3322. //{
  3323. // std::string root_directory;
  3324. // QString directory = getExistingDirectory(this, mInputPathName);
  3325. // if (directory.isNull())
  3326. // return;
  3327. //
  3328. // typedef itk::Image<unsigned short, 3> InputImageType;
  3329. // typedef itk::ImageSeriesReader< InputImageType > ReaderType;
  3330. // ReaderType::Pointer seriesreader = ReaderType::New();
  3331. //
  3332. // typedef itk::GDCMImageIO ImageIOType;
  3333. // ImageIOType::Pointer dicomIO = ImageIOType::New();
  3334. // seriesreader->SetImageIO(dicomIO);
  3335. // typedef itk::GDCMSeriesFileNames NamesGeneratorType;
  3336. // NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New();
  3337. // nameGenerator->SetUseSeriesDetails(true);
  3338. // nameGenerator->AddSeriesRestriction("0008|0021");
  3339. //
  3340. // nameGenerator->SetInputDirectory(directory.toStdString());
  3341. // try
  3342. // {
  3343. // typedef std::vector< std::string > SeriesIdContainer;
  3344. // const SeriesIdContainer & seriesUID = nameGenerator->GetSeriesUIDs();
  3345. //
  3346. // SeriesIdContainer::const_iterator seriesItr = seriesUID.begin();
  3347. // SeriesIdContainer::const_iterator seriesEnd = seriesUID.end();
  3348. // while (seriesItr != seriesEnd)
  3349. // {
  3350. // typedef std::vector< std::string > FileNamesContainer;
  3351. // FileNamesContainer fileNames;
  3352. // fileNames = nameGenerator->GetFileNames(seriesItr->c_str());
  3353. // seriesreader->SetFileNames(fileNames);
  3354. // try
  3355. // {
  3356. // seriesreader->Update();
  3357. // typedef unsigned short ROIPixelType;
  3358. // typedef::itk::Image<ROIPixelType, 3> OutputImageType;
  3359. // OutputImageType::Pointer outputImage = seriesreader->GetOutput();
  3360. //
  3361. // typedef itk::ImageRegionIteratorWithIndex <OutputImageType> IteratorType;
  3362. // IteratorType maskIt(outputImage, outputImage->GetLargestPossibleRegion());
  3363. // maskIt.GoToBegin();
  3364. //
  3365. // auto minMaxCalc = itk::MinimumMaximumImageCalculator< OutputImageType >::New();
  3366. // minMaxCalc->SetImage(outputImage);
  3367. // minMaxCalc->Compute();
  3368. // auto maxVal = minMaxCalc->GetMaximum();
  3369. //
  3370. // while (!maskIt.IsAtEnd())
  3371. // {
  3372. // OutputImageType::IndexType currentIndex = maskIt.GetIndex();
  3373. // float* pData = (float*)this->mSlicerManagers[0]->GetSlicer(0)->mMask->GetScalarPointer((int)currentIndex[0], (int)currentIndex[1], (int)currentIndex[2]);
  3374. // // this is done to take into account all possible label drawings
  3375. // switch (maskIt.Get())
  3376. // { // multiLabel: uncomment everything inside this loop and remove references to "near" and "far"
  3377. // case DRAW_MODE_LABEL_1:
  3378. // *pData = DRAW_MODE_LABEL_1;
  3379. // break;
  3380. // case 10: // GLISTR map contingency case
  3381. // *pData = DRAW_MODE_LABEL_1;
  3382. // break;
  3383. // case DRAW_MODE_LABEL_2:
  3384. // *pData = DRAW_MODE_LABEL_2;
  3385. // break;
  3386. // case 150: // GLISTR map contingency case
  3387. // *pData = DRAW_MODE_LABEL_2;
  3388. // break;
  3389. // case DRAW_MODE_LABEL_3:
  3390. // *pData = DRAW_MODE_LABEL_3;
  3391. // break;
  3392. // case 250: // GLISTR map contingency case
  3393. // *pData = DRAW_MODE_LABEL_3;
  3394. // break;
  3395. // case DRAW_MODE_LABEL_4:
  3396. // *pData = DRAW_MODE_LABEL_4;
  3397. // break;
  3398. // case 25: // GLISTR map contingency case
  3399. // *pData = DRAW_MODE_LABEL_4;
  3400. // break;
  3401. // case DRAW_MODE_LABEL_5:
  3402. // if (maxVal > DRAW_MODE_LABEL_9) // if GLISTR map has been defined, this is Cerebellum, i.e., tissue #9
  3403. // {
  3404. // *pData = DRAW_MODE_LABEL_9;
  3405. // }
  3406. // else
  3407. // {
  3408. // *pData = DRAW_MODE_LABEL_5;
  3409. // }
  3410. // break;
  3411. // case 100: // GLISTR map contingency case
  3412. // *pData = DRAW_MODE_LABEL_5;
  3413. // break;
  3414. // case DRAW_MODE_LABEL_6:
  3415. // *pData = DRAW_MODE_LABEL_6;
  3416. // break;
  3417. // case 175: // GLISTR map contingency case
  3418. // *pData = DRAW_MODE_LABEL_6;
  3419. // break;
  3420. // case DRAW_MODE_LABEL_7:
  3421. // *pData = DRAW_MODE_LABEL_7;
  3422. // break;
  3423. // case 200: // GLISTR map contingency case
  3424. // *pData = DRAW_MODE_LABEL_7;
  3425. // break;
  3426. // case DRAW_MODE_LABEL_8:
  3427. // *pData = DRAW_MODE_LABEL_8;
  3428. // break;
  3429. // case 185: // GLISTR map contingency case
  3430. // *pData = DRAW_MODE_LABEL_8;
  3431. // break;
  3432. // case DRAW_MODE_LABEL_9:
  3433. // *pData = DRAW_MODE_LABEL_9;
  3434. // break;
  3435. // default:
  3436. // // nothing defined for other cases
  3437. // break;
  3438. // }
  3439. // ++maskIt;
  3440. // }
  3441. //
  3442. // this->mSlicerManagers[0]->GetSlicer(0)->mMask->Modified();
  3443. // this->mSlicerManagers[0]->Render();
  3444. // }
  3445. // catch (itk::ExceptionObject & err)
  3446. // {
  3447. // std::stringstream error;
  3448. // error << err;
  3449. // }
  3450. // ++seriesItr;
  3451. // }
  3452. // }
  3453. // catch (itk::ExceptionObject & err)
  3454. // {
  3455. // std::stringstream error;
  3456. // error << err;
  3457. // }
  3458. //}
  3459. void fMainWindow::LoadDrawing(const std::string &maskFile)
  3460. {
  3461. auto reader = itk::ImageIOFactory::CreateImageIO(maskFile.c_str(), itk::ImageIOFactory::ReadMode);
  3462. if (reader)
  3463. {
  3464. readMaskFile(maskFile);
  3465. }
  3466. }
  3467. void fMainWindow::LoadDrawing()
  3468. {
  3469. if (!mSlicerManagers.empty())
  3470. {
  3471. auto filename = getExistingFile(this, mInputPathName);
  3472. if (filename.isNull() || filename.isEmpty())
  3473. {
  3474. return;
  3475. }
  3476. std::string filename_string = filename.toStdString();
  3477. auto reader = itk::ImageIOFactory::CreateImageIO(filename_string.c_str(), itk::ImageIOFactory::ReadMode);
  3478. if (reader)
  3479. {
  3480. readMaskFile(filename_string);
  3481. }
  3482. }
  3483. else
  3484. {
  3485. ShowErrorMessage("Please load an image before trying to load an ROI", this);
  3486. return;
  3487. }
  3488. }
  3489. void fMainWindow::UpdateBorderWidget(double startX, double startY, double endX, double endY)
  3490. {
  3491. mBorderStartX = std::round(startX);
  3492. mBorderStartY = std::round(startY);
  3493. mBorderEndX = std::round(endX);
  3494. mBorderEndY = std::round(endY);
  3495. }
  3496. void fMainWindow::UpdateBorderWidget(double startZ, double endZ)
  3497. {
  3498. mBorderStartZ = std::round(startZ);
  3499. mBorderStartZ = std::round(startZ);
  3500. }
  3501. void fMainWindow::overlayUseStateChanged(int state)
  3502. {
  3503. if (state == 0)
  3504. {
  3505. for (int i = 0; i < (int)mSlicerManagers.size(); i++)
  3506. {
  3507. for (int j = 0; j < 3; j++) {
  3508. mSlicerManagers[i]->mSlicers[j]->RemoveOverlay();
  3509. }
  3510. }
  3511. UpdateRenderWindows();
  3512. }
  3513. }
  3514. void fMainWindow::overlaySliderChanged(int value)
  3515. {
  3516. auto items = m_imagesTable->selectedItems();
  3517. if (items.empty())
  3518. {
  3519. return;
  3520. }
  3521. int index = GetSlicerIndexFromItem(items[0]);
  3522. if (index >= 0 && index < (int)mSlicerManagers.size())
  3523. {
  3524. for (int i = 0; i < 3; i++)
  3525. {
  3526. mSlicerManagers[index]->GetSlicer(i)->SetOverlayOpacity((double)value / (10 + 1e-6));
  3527. }
  3528. }
  3529. UpdateRenderWindows();
  3530. }
  3531. void fMainWindow::imageModalityChanged(int value)
  3532. {
  3533. for (size_t i = 0; i < mSlicerManagers.size(); i++)
  3534. {
  3535. mSlicerManagers[i]->mImageSubType = imagesPanel->getModality(i);
  3536. }
  3537. }
  3538. //---------------------------------------------
  3539. void fMainWindow::imageSliderChanged()
  3540. {
  3541. static int value = -1;
  3542. if (value == image4DSlider->value())
  3543. return;
  3544. else
  3545. value = image4DSlider->value();
  3546. auto items = m_imagesTable->selectedItems();
  3547. if (items.empty())
  3548. return;
  3549. int index = GetSlicerIndexFromItem(items[0]);
  3550. if (mSlicerManagers[index]->mImageSubType == CAPTK::ImageModalityType::IMAGE_TYPE_PERFUSION)
  3551. {
  3552. mSlicerManagers[index]->Get3DImageAtCurrentPerfusionIndex(value);
  3553. }
  3554. AxialViewSliderChanged();
  3555. mSlicerManagers[index]->Picked();
  3556. mSlicerManagers[index]->UpdateViews(0);
  3557. mSlicerManagers[index]->UpdateLinked(0);
  3558. mSlicerManagers[index]->UpdateInfoOnCursorPosition(0);
  3559. }
  3560. //---------------------------------------------
  3561. void fMainWindow::overlayChanged()
  3562. {
  3563. overlayChanged(imagesPanel->getSelectedOverlay());
  3564. }
  3565. void fMainWindow::overlayChanged(QTableWidgetItem *clickedItem)
  3566. {
  3567. auto items = m_imagesTable->selectedItems();
  3568. if (items.empty())
  3569. {
  3570. return;
  3571. }
  3572. int slicerManagerIndex = GetSlicerIndexFromItem(items[0]);
  3573. if (slicerManagerIndex < 0 || slicerManagerIndex >= (int)mSlicerManagers.size())
  3574. {
  3575. return;
  3576. }
  3577. //
  3578. int slicerManagerOverlayIndex = GetSlicerIndexFromItem(clickedItem);
  3579. if (slicerManagerOverlayIndex < 0 || slicerManagerOverlayIndex >= (int)mSlicerManagers.size())
  3580. {
  3581. return;
  3582. }
  3583. for (unsigned int i = 0; i < mSlicerManagers.size(); i++)
  3584. {
  3585. if (i != static_cast<unsigned int>(slicerManagerIndex)) {
  3586. for (int j = 0; j < 3; j++) {
  3587. mSlicerManagers[i]->mSlicers[j]->RemoveOverlay();
  3588. }
  3589. }
  3590. else
  3591. {
  3592. for (int j = 0; j < 3; j++)
  3593. {
  3594. mSlicerManagers[slicerManagerIndex]->mSlicers[j]->SetOverlay(mSlicerManagers[slicerManagerOverlayIndex]->mSlicers[j]->mImage);
  3595. //
  3596. double window = mSlicerManagers[slicerManagerOverlayIndex]->mSlicers[j]->GetColorWindow();
  3597. double level = mSlicerManagers[slicerManagerOverlayIndex]->mSlicers[j]->GetColorLevel();
  3598. vtkLookupTable* LUT = static_cast<vtkLookupTable*>(mSlicerManagers[slicerManagerOverlayIndex]->mSlicers[j]->GetWindowLevel()->GetLookupTable());
  3599. if (LUT != NULL)
  3600. {
  3601. mSlicerManagers[slicerManagerIndex]->mSlicers[j]->mOverlayMapper->SetWindow(window);
  3602. mSlicerManagers[slicerManagerIndex]->mSlicers[j]->mOverlayMapper->SetLevel(level);
  3603. mSlicerManagers[slicerManagerIndex]->mSlicers[j]->mOverlayMapper->SetLookupTable(LUT);
  3604. }
  3605. else
  3606. {
  3607. mSlicerManagers[slicerManagerIndex]->mSlicers[j]->mOverlayMapper->SetLookupTable(NULL);
  3608. mSlicerManagers[slicerManagerIndex]->mSlicers[j]->mOverlayMapper->SetWindow(window);
  3609. mSlicerManagers[slicerManagerIndex]->mSlicers[j]->mOverlayMapper->SetLevel(level);
  3610. }
  3611. }
  3612. }
  3613. }
  3614. UpdateRenderWindows();
  3615. }
  3616. void fMainWindow::openImages(QStringList files, bool callingFromCmd)
  3617. {
  3618. if (files.isEmpty())
  3619. {
  3620. if (!callingFromCmd)
  3621. {
  3622. QString extensions = IMAGES_EXTENSIONS;
  3623. extensions += ";;All Files (*)";
  3624. files = QFileDialog::getOpenFileNames(this, tr("Load Images"), mInputPathName, extensions, 0, QFileDialog::DontResolveSymlinks | QFileDialog::DontUseNativeDialog);
  3625. if (files.isEmpty())
  3626. return;
  3627. }
  3628. else
  3629. {
  3630. return;
  3631. }
  3632. }
  3633. int i = 0, fileSizeCheck = files.size() + 1;
  3634. if (mSlicerManagers.empty())
  3635. {
  3636. {
  3637. std::string fileName = files[i].toStdString();
  3638. fileName = cbica::normPath(fileName);
  3639. updateProgress(i + 1, "Opening " + fileName, files.size());
  3640. //auto extension = cbica::getFilenameExtension(fileName);
  3641. //if (!extension.empty())
  3642. //{
  3643. // std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
  3644. //}
  3645. //if ((extension == ".dcm") || (extension == ".dicom") || (extension == "") ||
  3646. // (extension == ".ima"))
  3647. if (cbica::IsDicom(fileName))
  3648. {
  3649. QDir d = QFileInfo(fileName.c_str()).absoluteDir();
  3650. QString fname = d.absolutePath();
  3651. dicomfilename = fileName;
  3652. this->openDicomImages(fname);
  3653. }
  3654. else
  3655. {
  3656. LoadSlicerImages(fileName, CAPTK::ImageExtension::NIfTI);
  3657. }
  3658. }
  3659. fileSizeCheck = 1;
  3660. }
  3661. else
  3662. {
  3663. fileSizeCheck = 0;
  3664. }
  3665. // basic sanity check
  3666. if (files.size() > fileSizeCheck)
  3667. {
  3668. std::string erroredFiles, unsupportedExtension;
  3669. std::vector< std::string > basicSanityChecksPassedFiles;
  3670. for (int i = fileSizeCheck; i < files.size(); i++)
  3671. {
  3672. std::string fileName = files[i].toStdString();
  3673. fileName = cbica::normPath(fileName);
  3674. auto extension = cbica::getFilenameExtension(fileName);
  3675. if (!extension.empty())
  3676. {
  3677. std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
  3678. }
  3679. if (!((extension == ".dcm") || (extension == ".dicom") || (extension == "") ||
  3680. (extension == ".ima") || (extension == ".nii") || (extension == ".nii.gz")))
  3681. {
  3682. unsupportedExtension += fileName + "\n";
  3683. }
  3684. else if (!cbica::ImageSanityCheck(files[0].toStdString(), files[i].toStdString()))
  3685. {
  3686. erroredFiles += fileName + "\n";
  3687. }
  3688. else
  3689. {
  3690. basicSanityChecksPassedFiles.push_back(files[i].toStdString());
  3691. }
  3692. }
  3693. if (!unsupportedExtension.empty() && !erroredFiles.empty())
  3694. {
  3695. ShowErrorMessage("Extensions for the following files were not supported, CaPTk will try to load the rest:\n\n" + unsupportedExtension +
  3696. "\n\nAnd the following files are inconsistent with the first loaded image:\n\n" + erroredFiles, this);
  3697. return;
  3698. }
  3699. if (!unsupportedExtension.empty())
  3700. {
  3701. ShowErrorMessage("Extensions for the following files were not supported, CaPTk will try to load the rest:\n\n" + unsupportedExtension, this);
  3702. }
  3703. if (!erroredFiles.empty())
  3704. {
  3705. ShowErrorMessage("Extensions for the following files were not supported, CaPTk will try to load the rest:\n\n" + unsupportedExtension, this);
  3706. }
  3707. for (int i = 0; i < basicSanityChecksPassedFiles.size(); i++)
  3708. {
  3709. std::string fileName = basicSanityChecksPassedFiles[i];
  3710. fileName = cbica::normPath(fileName);
  3711. updateProgress(i + 1, "Opening " + fileName, files.size());
  3712. auto extension = cbica::getFilenameExtension(fileName);
  3713. if (!extension.empty())
  3714. {
  3715. std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
  3716. }
  3717. //if ((extension == ".dcm") || (extension == ".dicom") || (extension == "") ||
  3718. // (extension == ".ima"))
  3719. if (cbica::IsDicom(fileName))
  3720. {
  3721. QDir d = QFileInfo(fileName.c_str()).absoluteDir();
  3722. QString fname = d.absolutePath();
  3723. dicomfilename = fileName;
  3724. this->openDicomImages(fname);
  3725. }
  3726. else
  3727. {
  3728. LoadSlicerImages(fileName, CAPTK::ImageExtension::NIfTI);
  3729. }
  3730. }
  3731. }
  3732. updateProgress(0, "Loading complete", 100);
  3733. }
  3734. void fMainWindow::openDicomImages(QString dir)
  3735. {
  3736. //QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"),
  3737. // QDir::currentPath(),
  3738. // QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
  3739. //if (dir.isNull())
  3740. //{
  3741. // ShowErrorMessage("Please open a directory containing Dicom images.");
  3742. // return;
  3743. //}
  3744. //DicomSeriesReader *dicomSeriesReader = new DicomSeriesReader();
  3745. //dicomSeriesReader->SetDirectoryPath(dir.toStdString());
  3746. //bool loadstatus = dicomSeriesReader->LoadDicom();
  3747. //if (!loadstatus)
  3748. //{
  3749. // QMessageBox::critical(this, "Dicom Loading", "Dicom Load Failed");
  3750. // return;
  3751. //}
  3752. auto currentImage = cbica::ReadImage<ImageTypeFloat3D>(dir.toStdString());
  3753. if (!currentImage)
  3754. {
  3755. ShowMessage("Dicom Load Failed");
  3756. return;
  3757. }
  3758. SlicerManager* imageManager = new SlicerManager(3, mLandmarks, mSeedPoints, mTissuePoints);
  3759. imageManager->mImageSubType = CAPTK::ImageModalityType::IMAGE_TYPE_UNDEFINED;
  3760. bool bFirstLoad = false;
  3761. if (mSlicerManagers.empty())
  3762. {
  3763. bFirstLoad = true;
  3764. }
  3765. QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
  3766. imageManager->SetImage(currentImage);
  3767. imageManager->SetOriginalDirection(currentImage->GetDirection());
  3768. imageManager->SetOriginalOrigin(currentImage->GetOrigin());
  3769. //imageManager->SetImage(dicomSeriesReader->GetITKImage());
  3770. //delete dicomSeriesReader;
  3771. //imageManager->SetFilename(dir.toStdString());
  3772. imageManager->SetMask(mMask);
  3773. imageManager->setTempFolderLocation(m_tempFolderLocation);
  3774. imageManager->mImageSubType = guessImageType(dir.toStdString());
  3775. int rowIndex = (int)mSlicerManagers.size();
  3776. m_imagesTable->setRowCount(rowIndex + 1);
  3777. mSlicerManagers.push_back(imageManager);
  3778. QFileInfo fileinfo(imageManager->GetFileName().c_str());
  3779. std::string seriesDescLabel, seriesDescValue;
  3780. QDir d(dir);
  3781. seriesDescValue = d.dirName().toStdString();
  3782. imageManager->SetFilename(seriesDescValue);
  3783. QString id = QString(seriesDescValue.c_str()) + QString::number(mSlicerManagers.size() - 1);
  3784. //
  3785. std::string strImageType = " IMAGE ";
  3786. QTableWidgetItem *item = new QTableWidgetItem(seriesDescValue.c_str());
  3787. item->setData(Qt::UserRole, id.toStdString().c_str());
  3788. item->setFlags(item->flags() & ~Qt::ItemIsEditable);
  3789. QTablePushButton* cButton = new QTablePushButton;
  3790. cButton->setItem(item);
  3791. cButton->setText(QString("X"));
  3792. connect(cButton, SIGNAL(clickedInto(QTableWidgetItem*)), this, SLOT(CloseImage(QTableWidgetItem*)));
  3793. QLabel * label = new QLabel;
  3794. label->setText(QString::fromStdString(strImageType));
  3795. m_imagesTable->setCellWidget(rowIndex, TAB_IMAGES_COLUMN_CLOSE, cButton);
  3796. m_imagesTable->setCellWidget(rowIndex, TAB_IMAGES_COLUMN_TYPE, label);
  3797. m_imagesTable->setItem(rowIndex, TAB_IMAGES_COLUMN_NAME, item);
  3798. imagesPanel->NewImageLoaded(id, imageManager->GetBaseFileName(), rowIndex, strImageType, imageManager->mImageSubType, this);
  3799. mSlicerManagers.back()->SetId(id.toStdString());
  3800. connect(mSlicerManagers.back(), SIGNAL(LeftButtonReleaseSignal(int)), this, SLOT(propogateSlicerPosition(int)));
  3801. connect(mSlicerManagers.back(), SIGNAL(currentImageChanged(std::string &)), this, SLOT(CurrentImageChanged(std::string &)));
  3802. connect(mSlicerManagers.back(), SIGNAL(currentPickedImageChanged(std::string)), this, SLOT(CurrentPickedImageChanged(std::string)));
  3803. connect(mSlicerManagers.back(), SIGNAL(UpdatePosition(int, double, double, double, double, double, double, double)), this, SLOT(MousePositionChanged(int, double, double, double, double, double, double, double)));
  3804. connect(mSlicerManagers.back(), SIGNAL(WindowLevelChanged()), this, SLOT(WindowLevelChanged()));
  3805. connect(mSlicerManagers.back(), SIGNAL(UpdateSlice(int, int)), this, SLOT(UpdateSlice(int, int)));
  3806. connect(mSlicerManagers.back(), SIGNAL(UpdateSliceRange(int, int, int)), this, SLOT(UpdateSliceRange(int, int, int)));
  3807. connect(mSlicerManagers.back(), SIGNAL(UpdateLinkManager(std::string, int, double, double, double)), this, SLOT(UpdateLinkManager(std::string, int, double, double, double)));
  3808. connect(mSlicerManagers.back(), SIGNAL(ChangeImageWithOrder(SlicerManager*, int)), this, SLOT(ChangeImageWithOrder(SlicerManager*, int)));
  3809. connect(mSlicerManagers.back(), SIGNAL(UpdateBorderWidgetInMain(double, double, double, double)), this, SLOT(UpdateBorderWidget(double, double, double, double)));
  3810. connect(mSlicerManagers.back(), SIGNAL(UpdateBorderWidgetInMain(double, double)), this, SLOT(UpdateBorderWidget(double, double)));
  3811. connect(mSlicerManagers.back(), SIGNAL(UpdateActionInMain(const QVariantList&)), this, SLOT(UpdateActionQ(const QVariantList&)));
  3812. //connect(mSlicerManagers.back(), SIGNAL(SeedPointsAdded()), tumorPanel, SLOT(sAddPoint()));
  3813. //connect(mSlicerManagers.back(), SIGNAL(SeedPointsAdded(int, bool)), tumorPanel, SLOT(sAddPoint(int, bool)));
  3814. //connect(mSlicerManagers.back(), SIGNAL(TissuePointsAdded(int)), tumorPanel, SLOT(tAddPoint(int)));
  3815. //connect(m_tabWidget, SIGNAL(currentChanged(int)), tumorPanel, SLOT(tabSelected()));
  3816. InitSlicers();
  3817. if (bFirstLoad)
  3818. {
  3819. InitMask(mSlicerManagers.back()->mImage);
  3820. }
  3821. for (int j = 0; j < (int)mSlicerManagers.back()->mSlicers.size(); j++)
  3822. {
  3823. mSlicerManagers.back()->mSlicers[j]->SetMask(mSlicerManagers.back()->GetMask());
  3824. }
  3825. if (mSlicerManagers.size() > 0)
  3826. {
  3827. if (mSlicerManagers.back()->mMask->GetDimensions()[2] != 1)
  3828. {
  3829. CoronalViewWidget->show();
  3830. SaggitalViewWidget->show();
  3831. }
  3832. AxialViewWidget->show();
  3833. infoPanel->show();
  3834. windowLabel->setEnabled(true);
  3835. windowSpinBox->setEnabled(true);
  3836. levelLabel->setEnabled(true);
  3837. levelSpinBox->setEnabled(true);
  3838. presetLabel->setEnabled(true);
  3839. presetComboBox->setEnabled(true);
  3840. if (bFirstLoad)
  3841. {
  3842. for (int i = 0; i < 3; i++)
  3843. {
  3844. mSlicerManagers.back()->GetSlicer(i)->SetInitPosition();
  3845. }
  3846. QTableWidgetItem* item = NULL;
  3847. item = GetItemFromSlicerManager(mSlicerManagers[0]);
  3848. DisplayChanged(item);
  3849. }
  3850. else
  3851. {
  3852. QTableWidgetItem* item = NULL;
  3853. for (int i = 0; i < (int)mSlicerManagers.size(); i++)
  3854. {
  3855. item = GetItemFromSlicerManager(mSlicerManagers[i]);
  3856. if (!item->isSelected())
  3857. {
  3858. item->setSelected(true);
  3859. }
  3860. }
  3861. DisplayChanged(item);
  3862. }
  3863. if (mSlicerManagers.size() > 1)
  3864. {
  3865. for (int i = 0; i < (int)mSlicerManagers.size(); i++)
  3866. {
  3867. for (int j = i + 1; j < (int)mSlicerManagers.size(); j++)
  3868. {
  3869. AddLink(/*QString::fromStdString*/(mSlicerManagers[i]->GetId().c_str()), /*QString::fromStdString*/(mSlicerManagers[j]->GetId().c_str()));
  3870. }
  3871. }
  3872. }
  3873. QTableWidgetItem* item = GetItemFromSlicerManager(mSlicerManagers.back());
  3874. item->setSelected(true);
  3875. InitDisplay();
  3876. }
  3877. propogateSlicerPosition();
  3878. updateProgress(0);
  3879. QApplication::restoreOverrideCursor();
  3880. }
  3881. void fMainWindow::ApplicationGeodesicTreshold()
  3882. {
  3883. if (m_imgGeodesicOut.IsNull())
  3884. {
  3885. return;
  3886. }
  3887. itk::ImageRegionIterator<ImageTypeShort3D> imageIterator(m_imgGeodesicOut, m_imgGeodesicOut->GetLargestPossibleRegion());
  3888. while (!imageIterator.IsAtEnd())
  3889. {
  3890. auto currentIndex = imageIterator.GetIndex();
  3891. float val = imageIterator.Get();
  3892. float* pData = (float*)this->mSlicerManagers[0]->GetSlicer(0)->mMask->GetScalarPointer((int)currentIndex[0], (int)currentIndex[1], (int)currentIndex[2]);
  3893. if (val < thresholdSpinBox->value())
  3894. {
  3895. *pData = 1.0;
  3896. }
  3897. else
  3898. {
  3899. *pData = 0.0;
  3900. }
  3901. ++imageIterator;
  3902. }
  3903. this->mSlicerManagers[0]->GetSlicer(0)->mMask->Modified();
  3904. this->mSlicerManagers[0]->Render();
  3905. }
  3906. void fMainWindow::ImageDenoising()
  3907. {
  3908. auto items = m_imagesTable->selectedItems();
  3909. if (items.empty())
  3910. {
  3911. ShowErrorMessage("Please load the image you would like to de-noise", this);
  3912. return;
  3913. }
  3914. int index = GetSlicerIndexFromItem(items[0]);
  3915. if (index < 0 || index >= (int)mSlicerManagers.size())
  3916. return;
  3917. QString saveFileName = getSaveFile(this, mInputPathName, mInputPathName + "denoise.nii.gz");
  3918. if (!saveFileName.isEmpty())
  3919. {
  3920. auto saveFileName_string = saveFileName.toStdString();
  3921. //Job TBD replace with app name
  3922. typedef itk::ImageDuplicator<ImageTypeFloat3D> DuplicatorType;
  3923. DuplicatorType::Pointer duplicator = DuplicatorType::New();
  3924. duplicator->SetInputImage(mSlicerManagers[index]->mITKImage);
  3925. duplicator->Update();
  3926. ImageTypeFloat3D::Pointer inputImage = duplicator->GetOutput();
  3927. updateProgress(5, "Susan noise removal in process");
  3928. SusanDenoising denoising /*= SusanDenoising()*/;
  3929. ImageTypeFloat3D::Pointer outputImage = denoising.Run<ImageTypeFloat3D>(inputImage);
  3930. if (outputImage.IsNotNull())
  3931. {
  3932. updateProgress(80, "Saving file");
  3933. cbica::WriteImage< ImageTypeFloat3D >(outputImage, saveFileName_string);
  3934. if (cbica::fileExists(saveFileName_string))
  3935. {
  3936. updateProgress(90, "Displaying output");
  3937. LoadSlicerImages(saveFileName_string, CAPTK::ImageExtension::NIfTI);
  3938. }
  3939. updateProgress(0, "Susan noise removal finished");
  3940. }
  3941. else
  3942. {
  3943. updateProgress(0, "Error in Susan noise removal!!");
  3944. }
  3945. }
  3946. }
  3947. void fMainWindow::ImageBiasCorrection()
  3948. {
  3949. auto items = m_imagesTable->selectedItems();
  3950. if (items.empty())
  3951. {
  3952. ShowErrorMessage("Please load an image to run bias correction on", this);
  3953. return;
  3954. }
  3955. int index = GetSlicerIndexFromItem(items[0]);
  3956. if (index < 0 || index >= (int)mSlicerManagers.size())
  3957. return;
  3958. QString saveFileName = getSaveFile(this, mInputPathName, mInputPathName + "biasCorrect.nii.gz");
  3959. if (!saveFileName.isEmpty())
  3960. {
  3961. auto saveFileName_string = saveFileName.toStdString();
  3962. typedef itk::ImageDuplicator <ImageTypeFloat3D > DuplicatorType;
  3963. DuplicatorType::Pointer duplicator = DuplicatorType::New();
  3964. duplicator->SetInputImage(mSlicerManagers[index]->mITKImage);
  3965. duplicator->Update();
  3966. auto inputImage = duplicator->GetOutput();
  3967. updateProgress(5, "Bias correction in process");
  3968. N3BiasCorrection biasCorrecter /*= N3BiasCorrection()*/;
  3969. auto outputImage = biasCorrecter.Run<ImageTypeFloat3D>(inputImage);
  3970. if (outputImage.IsNotNull())
  3971. {
  3972. updateProgress(80, "Saving file");
  3973. cbica::WriteImage< ImageTypeFloat3D >(outputImage, saveFileName_string);
  3974. if (cbica::fileExists(saveFileName_string))
  3975. {
  3976. updateProgress(90, "Displaying output");
  3977. LoadSlicerImages(saveFileName_string, CAPTK::ImageExtension::NIfTI);
  3978. }
  3979. updateProgress(0, "Bias correction finished");
  3980. }
  3981. else
  3982. {
  3983. updateProgress(0, "Error in Bias correction!");
  3984. }
  3985. }
  3986. }
  3987. void fMainWindow::ImageRegistration()
  3988. {
  3989. registrationPanel.mInputPathName = mInputPathName;
  3990. registrationPanel.exec();
  3991. }
  3992. void fMainWindow::ImageHistogramMatching()
  3993. {
  3994. // open a simple dialog box with reference image, input and output
  3995. histoMatchPanel.SetCurrentImagePath(mInputPathName);
  3996. histoMatchPanel.exec();
  3997. }
  3998. void fMainWindow::ImageDeepMedicNormalizer()
  3999. {
  4000. #ifndef WIN32
  4001. ShowErrorMessage("DeepMedic is currently not available for your platform but will be soon.", this);
  4002. return;
  4003. #endif
  4004. // open a simple dialog box with reference image, input and output
  4005. //deepMedicNormPanel.exec();
  4006. }
  4007. void fMainWindow::ImageSkullStripping()
  4008. {
  4009. // open a simple dialog box with reference image, input and output
  4010. //skullStrippingPanel.exec();
  4011. }
  4012. void fMainWindow::ApplicationTheia()
  4013. {
  4014. if (!mSlicerManagers.empty())
  4015. {
  4016. if (isMaskDefined())
  4017. {
  4018. std::string maskFile = m_tempFolderLocation + "/theia_mask.nii.gz";
  4019. cbica::WriteImage< ImageTypeFloat3D >(getMaskImage(), maskFile);
  4020. auto items = m_imagesTable->selectedItems();
  4021. auto index = GetSlicerIndexFromItem(items[0]);
  4022. QStringList args;
  4023. args << "-i" << mSlicerManagers[index]->GetFileName().c_str() << "-m" << maskFile.c_str();
  4024. startExternalProcess(getApplicationPath("Theia").c_str(), args);
  4025. }
  4026. else
  4027. {
  4028. ShowErrorMessage("Please initialize a valid mask before trying 3D Visualizer", this);
  4029. return;
  4030. }
  4031. }
  4032. else
  4033. {
  4034. ShowErrorMessage("Please load at least a single image before trying 3D Visualizer", this);
  4035. return;
  4036. }
  4037. }
  4038. void fMainWindow::EnableComparisonMode(bool enable)
  4039. {
  4040. int nLoadedData = mSlicerManagers.size();
  4041. if (nLoadedData < 2 || nLoadedData > 3)
  4042. {
  4043. ShowMessage("Comparison mode only works with 2 or 3 datasets. Please load 2 or 3 datasets to enable comparison mode", this);
  4044. return;
  4045. }
  4046. if ((mSlicerManagers[0]->mITKImage->GetLargestPossibleRegion().GetSize()[2] == 1)) //! e.g. Mammography images
  4047. {
  4048. ShowErrorMessage("2D images are not currently supported in Comparison Mode.");
  4049. return;
  4050. }
  4051. this->SetComparisonMode(enable);
  4052. if (enable) //! enabling comparison
  4053. {
  4054. if (m_ComparisonViewerLeft.GetPointer() == nullptr &&
  4055. m_ComparisonViewerCenter.GetPointer() == nullptr &&
  4056. m_ComparisonViewerRight.GetPointer() == nullptr)
  4057. {
  4058. m_ComparisonViewerLeft = vtkSmartPointer<Slicer>::New();
  4059. m_ComparisonViewerCenter = vtkSmartPointer<Slicer>::New();
  4060. m_ComparisonViewerRight = vtkSmartPointer<Slicer>::New();
  4061. for (int i = 0; i < this->GetComparisonViewers().size(); i++)
  4062. {
  4063. this->GetComparisonViewers()[i]->SetComparisonMode(true);
  4064. }
  4065. }
  4066. for (int i = 0; i < this->GetComparisonViewers().size(); i++)
  4067. {
  4068. this->GetComparisonViewers()[i]->SetImage(mSlicerManagers[i]->GetSlicer(0)->GetImage(), mSlicerManagers[i]->GetSlicer(0)->GetTransform());
  4069. this->GetComparisonViewers()[i]->SetMask(mSlicerManagers[0]->GetMask());
  4070. this->GetComparisonViewers()[i]->SetRenderWindow(0, nullptr);
  4071. this->GetComparisonViewers()[i]->SetImageSeriesDescription(mSlicerManagers[i]->mBaseFileName);
  4072. }
  4073. if (nLoadedData == 2) //! 2 datasets are loaded
  4074. {
  4075. m_ComparisonViewerLeft->SetRenderWindow(0, AxialViewWidget->GetRenderWindow());
  4076. m_ComparisonViewerCenter->SetRenderWindow(0, CoronalViewWidget->GetRenderWindow());
  4077. SaggitalViewWidget->hide();
  4078. SaggitalViewSlider->hide();
  4079. }
  4080. else if (nLoadedData == 3) //! 3 datasets are loaded
  4081. {
  4082. m_ComparisonViewerLeft->SetRenderWindow(0, AxialViewWidget->GetRenderWindow());
  4083. m_ComparisonViewerCenter->SetRenderWindow(0, CoronalViewWidget->GetRenderWindow());
  4084. m_ComparisonViewerRight->SetRenderWindow(0, SaggitalViewWidget->GetRenderWindow());
  4085. }
  4086. for (int i = 0; i < this->GetComparisonViewers().size(); i++)
  4087. {
  4088. InteractorStyleNavigator* style = InteractorStyleNavigator::New();
  4089. ComparisonViewerCommand *smc = ComparisonViewerCommand::New();
  4090. smc->SetCurrentViewer(this->GetComparisonViewers()[i]);
  4091. smc->SetComparisonViewers(this->GetComparisonViewers());
  4092. smc->SM = mSlicerManagers[0];
  4093. style->AddObserver(vtkCommand::KeyPressEvent, smc);
  4094. style->AddObserver(vtkCommand::WindowLevelEvent, smc);
  4095. style->AddObserver(vtkCommand::EndWindowLevelEvent, smc);
  4096. style->AddObserver(vtkCommand::StartWindowLevelEvent, smc);
  4097. style->AddObserver(vtkCommand::PickEvent, smc);
  4098. style->AddObserver(vtkCommand::StartPickEvent, smc);
  4099. style->AddObserver(vtkCommand::LeaveEvent, smc);
  4100. style->AddObserver(vtkCommand::UserEvent, smc);
  4101. style->AddObserver(vtkCommand::MouseWheelForwardEvent, smc);
  4102. style->AddObserver(vtkCommand::MouseWheelBackwardEvent, smc);
  4103. style->AddObserver(vtkCommand::LeftButtonReleaseEvent, smc);
  4104. style->AddObserver(vtkCommand::EndPickEvent, smc);
  4105. style->AddObserver(vtkCommand::EndInteractionEvent, smc);
  4106. style->SetAutoAdjustCameraClippingRange(1);
  4107. this->GetComparisonViewers()[i]->SetInteractorStyle(style);
  4108. style->Delete();
  4109. }
  4110. //! when we enter comparison mode, the WL should be same as in regular mode
  4111. std::vector<vtkSmartPointer<Slicer>> comparisonViewers = this->GetComparisonViewers();
  4112. for (int i = 0; i < comparisonViewers.size(); i++)
  4113. {
  4114. comparisonViewers[i]->SetColorWindow(windowSpinBox->value());
  4115. comparisonViewers[i]->SetColorLevel(levelSpinBox->value());
  4116. }
  4117. for (int i = 0; i < comparisonViewers.size(); i++)
  4118. {
  4119. comparisonViewers[i]->SetDisplayMode(true);
  4120. }
  4121. //!comparison mode connections
  4122. disconnect(AxialViewSlider, SIGNAL(valueChanged(int)), this, SLOT(AxialViewSliderChanged()));
  4123. disconnect(CoronalViewSlider, SIGNAL(valueChanged(int)), this, SLOT(CoronalViewSliderChanged()));
  4124. disconnect(SaggitalViewSlider, SIGNAL(valueChanged(int)), this, SLOT(SaggitalViewSliderChanged()));
  4125. connect(AxialViewSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSliderMovedInComparisonMode(int)));
  4126. connect(CoronalViewSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSliderMovedInComparisonMode(int)));
  4127. connect(SaggitalViewSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSliderMovedInComparisonMode(int)));
  4128. for (int i = 0; i < comparisonViewers.size(); i++)
  4129. {
  4130. comparisonViewers[i]->Render();
  4131. }
  4132. }
  4133. else
  4134. {
  4135. //! disabling comparison and coming back to regular mode
  4136. if (nLoadedData == 2) //! 2 datasets loaded
  4137. {
  4138. mSlicerManagers[0]->SetImage(mSlicerManagers[0]->GetITKImage());
  4139. mSlicerManagers[1]->SetImage(mSlicerManagers[1]->GetITKImage());
  4140. mSlicerManagers[0]->GetSlicer(0)->SetRenderWindow(0, nullptr);
  4141. mSlicerManagers[1]->GetSlicer(0)->SetRenderWindow(0, nullptr);
  4142. mSlicerManagers[0]->GetSlicer(0)->SetRenderWindow(0, AxialViewWidget->GetRenderWindow());
  4143. mSlicerManagers[1]->GetSlicer(0)->SetRenderWindow(0, AxialViewWidget->GetRenderWindow());
  4144. SaggitalViewWidget->show();
  4145. SaggitalViewSlider->show();
  4146. }
  4147. else if (nLoadedData == 3) //! 3 datasets loaded
  4148. {
  4149. mSlicerManagers[0]->SetImage(mSlicerManagers[0]->GetITKImage());
  4150. mSlicerManagers[1]->SetImage(mSlicerManagers[1]->GetITKImage());
  4151. mSlicerManagers[2]->SetImage(mSlicerManagers[2]->GetITKImage());
  4152. mSlicerManagers[0]->GetSlicer(0)->SetRenderWindow(0, nullptr);
  4153. mSlicerManagers[1]->GetSlicer(0)->SetRenderWindow(0, nullptr);
  4154. mSlicerManagers[2]->GetSlicer(0)->SetRenderWindow(0, nullptr);
  4155. mSlicerManagers[0]->GetSlicer(0)->SetRenderWindow(0, AxialViewWidget->GetRenderWindow());
  4156. mSlicerManagers[1]->GetSlicer(0)->SetRenderWindow(0, AxialViewWidget->GetRenderWindow());
  4157. mSlicerManagers[2]->GetSlicer(0)->SetRenderWindow(0, AxialViewWidget->GetRenderWindow());
  4158. }
  4159. //!regular mode connections
  4160. connect(AxialViewSlider, SIGNAL(valueChanged(int)), this, SLOT(AxialViewSliderChanged()));
  4161. connect(CoronalViewSlider, SIGNAL(valueChanged(int)), this, SLOT(CoronalViewSliderChanged()));
  4162. connect(SaggitalViewSlider, SIGNAL(valueChanged(int)), this, SLOT(SaggitalViewSliderChanged()));
  4163. disconnect(AxialViewSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSliderMovedInComparisonMode(int)));
  4164. disconnect(CoronalViewSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSliderMovedInComparisonMode(int)));
  4165. disconnect(SaggitalViewSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSliderMovedInComparisonMode(int)));
  4166. for (int i = 0; i < this->GetComparisonViewers().size(); i++)
  4167. {
  4168. this->GetComparisonViewers()[i]->SetDisplayMode(false);
  4169. }
  4170. this->InitDisplay();
  4171. mSlicerManagers[0]->Render();
  4172. }
  4173. }
  4174. void fMainWindow::ApplicationDeepMedicSegmentation(int type)
  4175. {
  4176. if (type <= fDeepMedicDialog::SkullStripping) // different cases for individual models can be put in this way
  4177. {
  4178. if (mSlicerManagers.size() < 4)
  4179. {
  4180. ShowErrorMessage("This model needs the following images to work: T1CE, T1, T2, FLAIR", this);
  4181. return;
  4182. }
  4183. }
  4184. // redundancy check
  4185. if (type >= fDeepMedicDialog::Max)
  4186. {
  4187. ShowErrorMessage("Unsupported model type, please check", this);
  4188. return;
  4189. }
  4190. deepMedicDialog.SetDefaultModel(type);
  4191. deepMedicDialog.SetCurrentImagePath(mInputPathName);
  4192. deepMedicDialog.exec();
  4193. }
  4194. void fMainWindow::CallDeepMedicSegmentation(const std::string modelDirectory, const std::string outputDirectory)
  4195. {
  4196. std::string file_t1ce, file_t1, file_flair, file_t2;
  4197. cbica::createDir(outputDirectory);
  4198. auto file_mask = outputDirectory + "/dm_mask.nii.gz";
  4199. if (!isMaskDefined())
  4200. {
  4201. file_mask = "";
  4202. }
  4203. else
  4204. {
  4205. cbica::WriteImage< TImageType >(getMaskImage(), file_mask);
  4206. }
  4207. if (!cbica::isDir(modelDirectory))
  4208. {
  4209. ShowErrorMessage("Model directory was not found, please try with another");
  4210. return;
  4211. }
  4212. if (!cbica::isFile(modelDirectory + "/modelConfig.txt"))
  4213. {
  4214. ShowErrorMessage("'modelConfig.txt' was not found in the directory, please check");
  4215. return;
  4216. }
  4217. //if (!cbica::isFile(modelDirectory + "/model.ckpt"))
  4218. //{
  4219. // ShowErrorMessage("'model.ckpt' was not found in the directory, please check");
  4220. // return;
  4221. //}
  4222. auto modelConfigFile = modelDirectory + "/modelConfig.txt",
  4223. modelCkptFile = modelDirectory + "/model.ckpt";
  4224. std::string files_forCommand;
  4225. int progressBar = 0;
  4226. for (size_t i = 0; i < mSlicerManagers.size(); i++)
  4227. {
  4228. switch (mSlicerManagers[i]->mImageSubType)
  4229. {
  4230. case CAPTK::ImageModalityType::IMAGE_TYPE_T1CE:
  4231. {
  4232. auto temp = cbica::normPath(m_tempFolderLocation + "/t1ce.nii.gz");
  4233. SaveImage_withFile(i, temp.c_str());
  4234. file_t1ce = temp;
  4235. break;
  4236. }
  4237. case CAPTK::ImageModalityType::IMAGE_TYPE_T1:
  4238. {
  4239. auto temp = cbica::normPath(m_tempFolderLocation + "/t1.nii.gz");
  4240. SaveImage_withFile(i, temp.c_str());
  4241. file_t1 = temp;
  4242. break;
  4243. }
  4244. case CAPTK::ImageModalityType::IMAGE_TYPE_T2:
  4245. {
  4246. auto temp = cbica::normPath(m_tempFolderLocation + "/t2.nii.gz");
  4247. SaveImage_withFile(i, temp.c_str());
  4248. file_t2 = temp;
  4249. break;
  4250. }
  4251. case CAPTK::ImageModalityType::IMAGE_TYPE_T2FLAIR:
  4252. {
  4253. auto temp = cbica::normPath(m_tempFolderLocation + "/flair.nii.gz");
  4254. SaveImage_withFile(i, temp.c_str());
  4255. file_flair = temp;
  4256. break;
  4257. }
  4258. default:
  4259. ShowErrorMessage("DeepMedic needs the following images to work: T1-Gd, T1, T2, FLAIR", this);
  4260. break;
  4261. }
  4262. }
  4263. QMessageBox *box = new QMessageBox(QMessageBox::Question, "Long running Application",
  4264. "Deep Learning inference takes 5-30 minutes to run, during which FeTS will not be responsive; press OK to continue...",
  4265. QMessageBox::Ok | QMessageBox::Cancel);
  4266. box->setAttribute(Qt::WA_DeleteOnClose); //makes sure the msgbox is deleted automatically when closed
  4267. box->setWindowModality(Qt::NonModal);
  4268. QCoreApplication::processEvents();
  4269. if (box->exec() == QMessageBox::Ok)
  4270. {
  4271. // TBD: this requires cleanup
  4272. int type;
  4273. if (modelDirectory.find("tumor") != std::string::npos)
  4274. {
  4275. type = 0;
  4276. }
  4277. else if (modelDirectory.find("skull") != std::string::npos)
  4278. {
  4279. type = 1;
  4280. }
  4281. QStringList args;
  4282. args << "-md" << modelDirectory.c_str() << "-o" << outputDirectory.c_str();
  4283. // parsing the modality-agnostic case
  4284. auto modelDir_lower = modelDirectory;
  4285. std::transform(modelDir_lower.begin(), modelDir_lower.end(), modelDir_lower.begin(), ::tolower);
  4286. if (modelDir_lower.find("modalityagnostic") != std::string::npos)
  4287. {
  4288. // we only want to pick up a single modality, in this case, so the first one loaded is picked
  4289. // order of preference is t1, t1ce, t2, fl
  4290. if (!file_t1.empty())
  4291. {
  4292. files_forCommand += file_t1 + ",";
  4293. }
  4294. else if (!file_t1ce.empty())
  4295. {
  4296. files_forCommand += file_t1ce + ",";
  4297. }
  4298. else if (!file_t2.empty())
  4299. {
  4300. files_forCommand += file_t2 + ",";
  4301. }
  4302. else if (!file_flair.empty())
  4303. {
  4304. files_forCommand += file_flair + ",";
  4305. }
  4306. }
  4307. else
  4308. {
  4309. files_forCommand = file_t1 + "," + file_t1ce + "," + file_t2 + "," + file_flair + ",";
  4310. }
  4311. files_forCommand.pop_back(); // last "," removed
  4312. args << "-i" << files_forCommand.c_str() << "-o" << outputDirectory.c_str();
  4313. if (!file_mask.empty())
  4314. {
  4315. args << "-m" << file_mask.c_str();
  4316. }
  4317. updateProgress(5, "Starting DeepMedic Segmentation");
  4318. auto dmExe = getApplicationPath("DeepMedic");
  4319. if (!cbica::exists(dmExe))
  4320. {
  4321. ShowErrorMessage("DeepMedic executable doesn't exist; can't run");
  4322. updateProgress(0, "");
  4323. return;
  4324. }
  4325. if (startExternalProcess(dmExe.c_str(), args) != 0)
  4326. {
  4327. ShowErrorMessage("DeepMedic returned with exit code != 0");
  4328. updateProgress(0, "");
  4329. return;
  4330. }
  4331. auto output = outputDirectory + "/predictions/testApiSession/predictions/Segm.nii.gz";
  4332. if (cbica::exists(output))
  4333. {
  4334. readMaskFile(output);
  4335. updateProgress(100, "Completed.");
  4336. }
  4337. else
  4338. {
  4339. ShowErrorMessage("DeepMedic failed to generate results");
  4340. updateProgress(0, "");
  4341. }
  4342. }
  4343. return;
  4344. }
  4345. void fMainWindow::CallImageSkullStripping(const std::string referenceAtlas, const std::string referenceMask,
  4346. const std::string inputImageFile, const std::string outputImageFile)
  4347. {
  4348. ShowErrorMessage("Skull Stripping takes a long time to run, during which CaPTk will not be responsive.", this, "Long Running Application");
  4349. if (!cbica::isFile(referenceAtlas))
  4350. {
  4351. ShowErrorMessage("Reference Atlas is not a valid file, please re-check", this);
  4352. return;
  4353. }
  4354. if (!cbica::isFile(referenceMask))
  4355. {
  4356. ShowErrorMessage("Reference Mask is not a valid file, please re-check", this);
  4357. return;
  4358. }
  4359. if (!cbica::isFile(inputImageFile))
  4360. {
  4361. ShowErrorMessage("Input Image is not a valid file, please re-check", this);
  4362. return;
  4363. }
  4364. auto referenceAtlasImage = cbica::ReadImage< ImageTypeFloat3D >(referenceAtlas);
  4365. auto referenceAtlasMaskImage = cbica::ReadImage< ImageTypeFloat3D >(referenceMask);
  4366. auto inputImageImage = cbica::ReadImage< ImageTypeFloat3D >(inputImageFile);
  4367. auto outputImage = cbica::GetSkullStrippedImage< ImageTypeFloat3D >(inputImageImage, referenceAtlasImage, referenceAtlasMaskImage);
  4368. if ((cbica::getFilenameExtension(outputImageFile) != ".nii") && (cbica::getFilenameExtension(outputImageFile) != ".nii.gz"))
  4369. {
  4370. std::string path, base, ext;
  4371. cbica::splitFileName(outputImageFile, path, base, ext);
  4372. cbica::WriteImage< ImageTypeFloat3D >(outputImage, path + base + ".nii.gz");
  4373. LoadSlicerImages(path + base + ".nii.gz", CAPTK::ImageExtension::NIfTI);
  4374. }
  4375. else
  4376. {
  4377. cbica::WriteImage< ImageTypeFloat3D >(outputImage, outputImageFile);
  4378. LoadSlicerImages(outputImageFile, CAPTK::ImageExtension::NIfTI);
  4379. }
  4380. }
  4381. void fMainWindow::CallLabelValuesChange(const std::string oldValues, const std::string newValues)
  4382. {
  4383. if (!isMaskDefined())
  4384. {
  4385. ShowErrorMessage("A valid mask needs to be loaded");
  4386. return;
  4387. }
  4388. auto oldValues_string_split = cbica::stringSplit(oldValues, "x");
  4389. auto newValues_string_split = cbica::stringSplit(newValues, "x");
  4390. if (oldValues_string_split.size() != newValues_string_split.size())
  4391. {
  4392. ShowErrorMessage("Old and New values have the same number of inputs", this);
  4393. return;
  4394. }
  4395. auto output = cbica::ChangeImageValues< ImageTypeFloat3D >(getMaskImage(), oldValues, newValues);
  4396. if (output.IsNull())
  4397. {
  4398. ShowErrorMessage("Changing values did not work as expected, please try again with correct syntax");
  4399. return;
  4400. }
  4401. std::string tempFile = m_tempFolderLocation + "/mask_changedValues.nii.gz";
  4402. cbica::WriteImage< ImageTypeFloat3D >(output, tempFile);
  4403. readMaskFile(tempFile);
  4404. }
  4405. void fMainWindow::CallImageHistogramMatching(const std::string referenceImage, const std::string inputImageFile, const std::string outputImageFile)
  4406. {
  4407. if (!referenceImage.empty() && !inputImageFile.empty() && !outputImageFile.empty())
  4408. {
  4409. if (!cbica::isFile(referenceImage))
  4410. {
  4411. ShowErrorMessage("Reference Image is not a valid file, please re-check", this);
  4412. return;
  4413. }
  4414. if (!cbica::isFile(inputImageFile))
  4415. {
  4416. ShowErrorMessage("Input Image is not a valid file, please re-check", this);
  4417. return;
  4418. }
  4419. auto referenceAtlasImage = cbica::ReadImage< ImageTypeFloat3D >(referenceImage);
  4420. auto inputImageImage = cbica::ReadImage< ImageTypeFloat3D >(inputImageFile);
  4421. auto outputImage = cbica::GetHistogramMatchedImage< ImageTypeFloat3D >(inputImageImage, referenceAtlasImage);
  4422. cbica::WriteImage< ImageTypeFloat3D >(outputImage, outputImageFile);
  4423. LoadSlicerImages(outputImageFile, CAPTK::ImageExtension::NIfTI);
  4424. }
  4425. else
  4426. {
  4427. ShowErrorMessage("Please provide all inputs before trying histogram matching", this);
  4428. help_contextual("preprocessing_histoMatch.html");
  4429. return;
  4430. }
  4431. }
  4432. void fMainWindow::CustomPreprocessing()
  4433. {
  4434. }
  4435. void fMainWindow::ChangeBrushSize(int size)
  4436. {
  4437. updateDrawMode();
  4438. }
  4439. void fMainWindow::ChangeMaskOpacity(int newMaskOpacity) // multiLabel uncomment this function
  4440. {
  4441. double tempOpacity = newMaskOpacity * 0.1;
  4442. for (size_t i = 0; i < this->mSlicerManagers.size(); i++)
  4443. {
  4444. for (size_t j = 0; j < 3; j++)
  4445. {
  4446. this->mSlicerManagers[i]->GetSlicer(j)->mMaskOpacity = tempOpacity;
  4447. this->mSlicerManagers[i]->GetSlicer(j)->mMaskActor->SetOpacity(tempOpacity);
  4448. this->mSlicerManagers[i]->GetSlicer(j)->mMask->Modified();
  4449. }
  4450. }
  4451. this->mSlicerManagers[0]->Render();
  4452. }
  4453. void fMainWindow::ChangeDrawingLabel(int drawingLabel) // multiLabel uncomment this function
  4454. {
  4455. updateDrawMode();
  4456. }
  4457. /**
  4458. * Read a transform specification, format file,number
  4459. */
  4460. TransformSpec read_transform_spec(std::string &file)
  4461. {
  4462. std::string spec = file;
  4463. size_t pos = spec.find_first_of(',');
  4464. TransformSpec ts;
  4465. ts.filename = spec.substr(0, pos);
  4466. ts.exponent = 1.0;
  4467. if (!itksys::SystemTools::FileExists(ts.filename.c_str()))
  4468. throw GreedyException("File '%s' does not exist", ts.filename.c_str());
  4469. if (pos != std::string::npos)
  4470. {
  4471. errno = 0; char *pend;
  4472. std::string expstr = spec.substr(pos + 1);
  4473. ts.exponent = std::strtod(expstr.c_str(), &pend);
  4474. if (errno || *pend)
  4475. throw GreedyException("Expected a floating point number after comma in transform specification, instead got '%s'",
  4476. spec.substr(pos).c_str());
  4477. }
  4478. return ts;
  4479. }
  4480. //Reads radius for registration
  4481. std::vector<int> read_int_vector(std::string &nccRadii)
  4482. {
  4483. std::string arg = nccRadii;
  4484. std::istringstream f(arg);
  4485. std::string s;
  4486. std::vector<int> vector;
  4487. while (getline(f, s, 'x'))
  4488. {
  4489. errno = 0; char *pend;
  4490. long val = std::strtol(s.c_str(), &pend, 10);
  4491. //std::cout << "Radii: " << val <<std::endl;
  4492. if (errno || *pend)
  4493. throw GreedyException("Expected an integer vector as parameter, instead got '%s'",
  4494. arg.c_str());
  4495. vector.push_back((int)val);
  4496. }
  4497. if (!vector.size())
  4498. throw GreedyException("Expected an integer vector as parameter, instead got '%s'",
  4499. arg.c_str());
  4500. return vector;
  4501. }
  4502. std::vector<vtkSmartPointer<Slicer>> fMainWindow::GetComparisonViewers()
  4503. {
  4504. std::vector<vtkSmartPointer<Slicer>>comparisonViewers;
  4505. if (mSlicerManagers.size() == 2)
  4506. {
  4507. comparisonViewers.push_back(m_ComparisonViewerLeft);
  4508. comparisonViewers.push_back(m_ComparisonViewerCenter);
  4509. }
  4510. else if (mSlicerManagers.size() == 3)
  4511. {
  4512. comparisonViewers.push_back(m_ComparisonViewerLeft);
  4513. comparisonViewers.push_back(m_ComparisonViewerCenter);
  4514. comparisonViewers.push_back(m_ComparisonViewerRight);
  4515. }
  4516. return comparisonViewers;
  4517. }
  4518. void fMainWindow::Registration(std::string fixedFileName, std::vector<std::string> inputFileNames,
  4519. std::vector<std::string> outputFileNames, std::vector<std::string> matrixFileNames,
  4520. std::string metrics, bool rigidMode, bool affineMode, bool deformMode,
  4521. std::string radii, std::string iterations)
  4522. {
  4523. std::string configPathName;
  4524. std::string configFileName;
  4525. std::string extn = ".txt";
  4526. std::vector<std::string> affineMatrix;
  4527. std::vector<std::string> outputImage;
  4528. updateProgress(5, "Starting Registration");
  4529. //auto TargetImage = cbica::ReadImage< ImageTypeFloat3D >(fixedFileName);
  4530. if (outputFileNames.size() != inputFileNames.size() || outputFileNames.size() != matrixFileNames.size() || matrixFileNames.size() != inputFileNames.size())
  4531. {
  4532. ShowErrorMessage("Number of input, matrix and output file names do not match");
  4533. return;
  4534. }
  4535. configPathName = itksys::SystemTools::GetFilenamePath(matrixFileNames[0]).c_str();
  4536. configFileName = configPathName + "/" + itksys::SystemTools::GetFilenameWithoutExtension(matrixFileNames[0]).c_str() + extn;
  4537. for (unsigned int i = 0; i < inputFileNames.size(); i++)
  4538. {
  4539. if (!cbica::isFile(inputFileNames[i]))
  4540. {
  4541. ShowErrorMessage("Input file '" + std::to_string(i) + "' is undefined; please check");
  4542. return;
  4543. }
  4544. updateProgress(static_cast<int>(100 / ((i + 1) * inputFileNames.size())), "processing Registration");
  4545. QStringList args;
  4546. args << "-i" << inputFileNames[i].c_str();
  4547. args << "-o" << outputFileNames[i].c_str();
  4548. args << "-rIA" << matrixFileNames[i].c_str();
  4549. args << "-rFI" << fixedFileName.c_str();
  4550. args << "-rNI" << iterations.c_str();
  4551. if (metrics == "NCC")
  4552. args << ("-rME NCC-" + radii).c_str();
  4553. else
  4554. args << "-rME " << metrics.c_str();
  4555. args << "-reg";
  4556. if (rigidMode)
  4557. {
  4558. args << "Rigid";
  4559. }
  4560. else if (affineMode)
  4561. {
  4562. args << "Affine";
  4563. }
  4564. else
  4565. {
  4566. args << "Deformable";
  4567. }
  4568. std::string fullCommandToRun = getApplicationPath("Preprocessing");
  4569. if (startExternalProcess(fullCommandToRun.c_str(), args) != 0)
  4570. {
  4571. ShowErrorMessage("Couldn't register with the default parameters; please use command line functionality");
  4572. return;
  4573. }
  4574. else
  4575. {
  4576. affineMatrix.push_back(matrixFileNames[i] + ".mat");
  4577. }
  4578. if (matrixFileNames[i].find("remove") != std::string::npos)
  4579. {
  4580. if (cbica::isFile(matrixFileNames[i]))
  4581. {
  4582. if (std::remove(matrixFileNames[i].c_str()) == 0)
  4583. {
  4584. updateProgress(80, "Cleaning temporary files");
  4585. }
  4586. }
  4587. updateProgress(static_cast<int>(100 / ((i + 1) * inputFileNames.size())), "Writing File");
  4588. }
  4589. updateProgress(100, "Registration Complete.");
  4590. time_t t = std::time(0);
  4591. long int now = static_cast<long int> (t);
  4592. std::ofstream file;
  4593. file.open(configFileName.c_str());
  4594. std::string mode;
  4595. if (affineMode)
  4596. mode = "Affine";
  4597. else if (rigidMode)
  4598. mode = "Rigid";
  4599. else
  4600. mode = "Deformable";
  4601. if (file.is_open())
  4602. {
  4603. if (metrics != "NCC") {
  4604. file << fixedFileName << ","
  4605. << metrics << ","
  4606. << mode << ","
  4607. << iterations << ","
  4608. << now << "\n";
  4609. }
  4610. else {
  4611. file << fixedFileName << ","
  4612. << metrics << ","
  4613. << radii << ","
  4614. << mode << ","
  4615. << iterations << ","
  4616. << now << "\n";
  4617. }
  4618. }
  4619. file.close();
  4620. }
  4621. //// This happens because the qconcurrent doesn't allow more than 5 function parameters, without std::bind + not sure what else
  4622. //std::vector<std::string> compVector = {
  4623. // fixedFileName,
  4624. // ((registrationMode) ? "true" : "false"),
  4625. // metrics,
  4626. // ((affineMode) ? "true" : "false"),
  4627. // radii,
  4628. // iterations
  4629. //};
  4630. //QtConcurrent::run(this, &fMainWindow::RegistrationWorker,
  4631. // compVector,
  4632. // inputFileNames,
  4633. // outputFileNames,
  4634. // matrixFileNames
  4635. //);
  4636. /*QFuture<void> r = QtConcurrent::run(std::bind(
  4637. this, &fMainWindow::RegistrationWorker,
  4638. fixedFileName, inputFileNames, outputFileNames,
  4639. matrixFileNames, registrationMode, metrics, affineMode, radii, iterations
  4640. ));*/
  4641. }
  4642. void fMainWindow::RegistrationWorker(std::vector<std::string> compVector, std::vector<std::string> inputFileNames,
  4643. std::vector<std::string> outputFileNames, std::vector<std::string> matrixFileNames)
  4644. {
  4645. // "Unpacking" the variables
  4646. std::string fixedFileName = compVector[0];
  4647. bool registrationMode = (compVector[1] == "true");
  4648. std::string metrics = compVector[2];
  4649. bool affineMode = (compVector[3] == "true");
  4650. std::string radii = compVector[4];
  4651. std::string iterations = compVector[5];
  4652. std::string configPathName;
  4653. std::string configFileName;
  4654. std::string extn = ".txt";
  4655. std::vector<std::string> affineMatrix;
  4656. std::vector<std::string> outputImage;
  4657. updateProgress(5, "Starting Registration");
  4658. //auto TargetImage = cbica::ReadImage< ImageTypeFloat3D >(fixedFileName);
  4659. if (outputFileNames.size() != inputFileNames.size() || outputFileNames.size() != matrixFileNames.size() || matrixFileNames.size() != inputFileNames.size())
  4660. {
  4661. ShowErrorMessage("Number of input, matrix and output file names do not match");
  4662. return;
  4663. }
  4664. configPathName = itksys::SystemTools::GetFilenamePath(matrixFileNames[0]).c_str();
  4665. configFileName = configPathName + "/" + itksys::SystemTools::GetFilenameWithoutExtension(matrixFileNames[0]).c_str() + extn;
  4666. for (unsigned int i = 0; i < inputFileNames.size(); i++)
  4667. {
  4668. if (!cbica::isFile(inputFileNames[i]))
  4669. {
  4670. ShowErrorMessage("Input file '" + std::to_string(i) + "' is undefined; please check");
  4671. return;
  4672. }
  4673. updateProgress(static_cast<int>(100 / ((i + 1) * inputFileNames.size())), "processing Registration");
  4674. std::string fixedFileCommand = "-f " + fixedFileName;
  4675. std::string movingFileCommand = " -i " + inputFileNames[i];
  4676. std::string affineMatrixCommand = " -t " + matrixFileNames[i];
  4677. std::string outputCommand = " -o " + outputFileNames[i];
  4678. std::string metricsCommand = " -m " + metrics;
  4679. std::string iterationsCommand = " -n " + iterations;
  4680. QStringList args;
  4681. args << "-reg" << "-trf" << "-a" << "-f" << fixedFileName.c_str()
  4682. << "-i" << inputFileNames[i].c_str() << "-t" << matrixFileNames[i].c_str() << "-o" << outputFileNames[i].c_str()
  4683. << "-m" << metrics.c_str() << "-n" << iterations.c_str();
  4684. if (metrics == "NCC")
  4685. args << "-ri" << radii.c_str();
  4686. if (affineMode)
  4687. {
  4688. args << "-a";
  4689. }
  4690. else
  4691. {
  4692. args << "-r";
  4693. }
  4694. std::string fullCommandToRun = getApplicationPath("GreedyRegistration");
  4695. if (startExternalProcess(fullCommandToRun.c_str(), args) != 0)
  4696. {
  4697. ShowErrorMessage("Couldn't register with the default parameters; please use command line functionality");
  4698. return;
  4699. }
  4700. else
  4701. {
  4702. affineMatrix.push_back(matrixFileNames[i] + ".mat");
  4703. }
  4704. if (matrixFileNames[i].find("remove") != std::string::npos)
  4705. {
  4706. if (cbica::isFile(matrixFileNames[i]))
  4707. {
  4708. if (std::remove(matrixFileNames[i].c_str()) == 0)
  4709. {
  4710. updateProgress(80, "Cleaning temporary files");
  4711. }
  4712. }
  4713. updateProgress(static_cast<int>(100 / ((i + 1) * inputFileNames.size())), "Writing File");
  4714. }
  4715. updateProgress(100, "Registration Complete.");
  4716. time_t t = std::time(0);
  4717. long int now = static_cast<long int> (t);
  4718. std::ofstream file;
  4719. file.open(configFileName.c_str());
  4720. std::string mode;
  4721. if (affineMode == true)
  4722. mode = "Affine";
  4723. else
  4724. mode = "Rigid";
  4725. if (file.is_open())
  4726. {
  4727. if (metrics != "NCC") {
  4728. file << fixedFileName << ","
  4729. << metrics << ","
  4730. << mode << ","
  4731. << iterations << ","
  4732. << now << "\n";
  4733. }
  4734. else {
  4735. file << fixedFileName << ","
  4736. << metrics << ","
  4737. << radii << ","
  4738. << mode << ","
  4739. << iterations << ","
  4740. << now << "\n";
  4741. }
  4742. }
  4743. file.close();
  4744. }
  4745. //std::terminate();
  4746. }
  4747. void fMainWindow::UpdateAction(std::vector<PointVal> points)
  4748. {
  4749. mActionPoints.push_back(points);
  4750. }
  4751. void fMainWindow::FillLabel(int label)
  4752. {
  4753. //auto orientation = mSlicerManagers[0]->mSlicers[0]->GetOrientation();
  4754. }
  4755. void fMainWindow::UndoFunctionality()
  4756. {
  4757. if (mActionPoints.empty())
  4758. return;
  4759. std::vector<PointVal> OneStrkePoints = mActionPoints.back();
  4760. //Its important to do the undo in reverse order of what happened
  4761. for (std::vector<PointVal>::iterator it = OneStrkePoints.end(); it != OneStrkePoints.begin();)
  4762. {
  4763. --it;
  4764. PointVal pt = *it;
  4765. float* pData = (float*)this->mSlicerManagers[0]->GetSlicer(0)->mMask->GetScalarPointer(pt.x, pt.y, pt.z);
  4766. *pData = pt.value;
  4767. }
  4768. mActionPoints.pop_back();
  4769. this->mSlicerManagers[0]->GetSlicer(0)->mMask->Modified();
  4770. this->mSlicerManagers[0]->Render();
  4771. }
  4772. void fMainWindow::SetOpacity()
  4773. {
  4774. if (this->mSlicerManagers[0]->GetSlicer(0)->GetMaskOpacity() == 0)
  4775. ChangeMaskOpacity(drawingPanel->getCurrentOpacity());
  4776. else
  4777. ChangeMaskOpacity(0);
  4778. }
  4779. void fMainWindow::closeEvent(QCloseEvent* event)
  4780. {
  4781. if (m_NumberOfUnfinishedExternalProcesses > 0)
  4782. {
  4783. ShowErrorMessage("Please close all external applications before exiting.");
  4784. event->ignore();
  4785. return;
  4786. }
  4787. if (m_IsGeodesicTrainingRunning)
  4788. {
  4789. ShowErrorMessage("Please wait for GeodesicTraining execution to finish.");
  4790. event->ignore();
  4791. return;
  4792. }
  4793. if (!cbica::fileExists(closeConfirmation))
  4794. {
  4795. auto msgBox = new QMessageBox();
  4796. msgBox->setWindowTitle("Close Confirmation!");
  4797. msgBox->setText("Are you certain you would like to exit?");
  4798. msgBox->addButton(QMessageBox::Yes);
  4799. msgBox->addButton(QMessageBox::No);
  4800. msgBox->setDefaultButton(QMessageBox::No);
  4801. QCheckBox closeConfirmationBox("Never ask again");
  4802. closeConfirmationBox.blockSignals(true);
  4803. msgBox->addButton(&closeConfirmationBox, QMessageBox::ResetRole);
  4804. if (msgBox->exec() == QMessageBox::Yes)
  4805. {
  4806. if (closeConfirmationBox.checkState() == Qt::Checked)
  4807. {
  4808. std::ofstream file;
  4809. file.open(closeConfirmation.c_str());
  4810. file << "User doesn't want close confirmation.\n";
  4811. file.close();
  4812. }
  4813. //! close the help dialog forcefully as we are about to exit the application
  4814. bool closed = mHelpDlg->close();
  4815. event->accept();
  4816. }
  4817. else
  4818. {
  4819. event->ignore();
  4820. }
  4821. }
  4822. else
  4823. {
  4824. //! close the help dialog forcefully as we are about to exit the application
  4825. bool closed = mHelpDlg->close();
  4826. event->accept();
  4827. }
  4828. }
  4829. void fMainWindow::updateProgress(int progress, std::string message, int max)
  4830. {
  4831. #ifdef USE_PROCESSDIALOG
  4832. m_progressBar->setMaximum(max);
  4833. m_progressBar->setValue(progress);
  4834. m_messageLabel->setText(QString::fromStdString(message));
  4835. QTimer::singleShot(10000.0, m_messageLabel, SLOT(clear()));
  4836. qApp->processEvents();
  4837. #endif
  4838. }
  4839. std::vector<std::map<CAPTK::ImageModalityType, std::string>> fMainWindow::LoadQualifiedSubjectsFromGivenDirectoryForSurvival(const std::string directoryname)
  4840. {
  4841. std::map<CAPTK::ImageModalityType, std::string> OneQualifiedSubject;
  4842. std::vector<std::map<CAPTK::ImageModalityType, std::string>> QualifiedSubjects;
  4843. std::vector<std::string> subjectNames = cbica::subdirectoriesInDirectory(directoryname);
  4844. std::sort(subjectNames.begin(), subjectNames.end());
  4845. for (unsigned int sid = 0; sid < subjectNames.size(); sid++)
  4846. {
  4847. std::string subjectPath = directoryname + "/" + subjectNames[sid];
  4848. std::string t1ceFilePath = "";
  4849. std::string t1FilePath = "";
  4850. std::string t2FilePath = "";
  4851. std::string t2FlairFilePath = "";
  4852. std::string axFilePath = "";
  4853. std::string faFilePath = "";
  4854. std::string radFilePath = "";
  4855. std::string trFilePath = "";
  4856. std::string rcbvFilePath = "";
  4857. std::string psrFilePath = "";
  4858. std::string phFilePath = "";
  4859. std::string labelPath = "";
  4860. std::string atlasPath = "";
  4861. std::string parametersPath = "";
  4862. std::string featureFilePath = "";
  4863. std::vector<std::string> files;
  4864. if (cbica::directoryExists(subjectPath + "/SEGMENTATION"))
  4865. {
  4866. files = cbica::filesInDirectory(subjectPath + "/SEGMENTATION", false);
  4867. if (files.size() == 1)
  4868. {
  4869. labelPath = subjectPath + "/SEGMENTATION" + "/" + files[0];
  4870. }
  4871. else
  4872. {
  4873. for (unsigned int i = 0; i < files.size(); i++)
  4874. {
  4875. std::string filePath = subjectPath + "/SEGMENTATION" + "/" + files[i], filePath_lower;
  4876. std::string extension = cbica::getFilenameExtension(filePath, false);
  4877. filePath_lower = filePath;
  4878. std::transform(filePath_lower.begin(), filePath_lower.end(), filePath_lower.begin(), ::tolower);
  4879. if ((filePath_lower.find("atlas") != std::string::npos || filePath_lower.find("jakob_label") != std::string::npos)
  4880. && isExtensionSupported(extension))
  4881. atlasPath = subjectPath + "/SEGMENTATION" + "/" + files[i];
  4882. else if ((filePath_lower.find("segmentation") != std::string::npos)
  4883. && isExtensionSupported(extension))
  4884. labelPath = subjectPath + "/SEGMENTATION" + "/" + files[i];
  4885. else if ((filePath_lower.find("parameter") != std::string::npos)
  4886. && (extension == PARAM_EXT))
  4887. parametersPath = subjectPath + "/SEGMENTATION" + "/" + files[i];
  4888. }
  4889. }
  4890. }
  4891. if (cbica::directoryExists(subjectPath + "/CONVENTIONAL"))
  4892. {
  4893. files = cbica::filesInDirectory(subjectPath + "/CONVENTIONAL", false);
  4894. for (unsigned int i = 0; i < files.size(); i++)
  4895. {
  4896. std::string filePath = subjectPath + "/CONVENTIONAL" + "/" + files[i];
  4897. std::string extension = cbica::getFilenameExtension(filePath, false);
  4898. if ((guessImageType(files[i]) == CAPTK::ImageModalityType::IMAGE_TYPE_T1CE) && isExtensionSupported(extension))
  4899. t1ceFilePath = subjectPath + "/CONVENTIONAL" + "/" + files[i];
  4900. else if ((guessImageType(files[i]) == CAPTK::ImageModalityType::IMAGE_TYPE_T1) && isExtensionSupported(extension))
  4901. t1FilePath = subjectPath + "/CONVENTIONAL" + "/" + files[i];
  4902. else if ((guessImageType(files[i]) == CAPTK::ImageModalityType::IMAGE_TYPE_T2) && isExtensionSupported(extension))
  4903. t2FilePath = subjectPath + "/CONVENTIONAL" + "/" + files[i];
  4904. else if ((guessImageType(files[i]) == CAPTK::ImageModalityType::IMAGE_TYPE_T2FLAIR) && isExtensionSupported(extension))
  4905. t2FlairFilePath = subjectPath + "/CONVENTIONAL" + "/" + files[i];
  4906. }
  4907. }
  4908. if (cbica::directoryExists(subjectPath + "/PERFUSION"))
  4909. {
  4910. files = cbica::filesInDirectory(subjectPath + "/PERFUSION", false);
  4911. for (unsigned int i = 0; i < files.size(); i++)
  4912. {
  4913. std::string filePath = subjectPath + "/PERFUSION" + "/" + files[i], filePath_lower;
  4914. std::string extension = cbica::getFilenameExtension(filePath, false);
  4915. filePath_lower = filePath;
  4916. std::transform(filePath_lower.begin(), filePath_lower.end(), filePath_lower.begin(), ::tolower);
  4917. if ((guessImageType(files[i]) == CAPTK::ImageModalityType::IMAGE_TYPE_RCBV)
  4918. && isExtensionSupported(extension))
  4919. rcbvFilePath = subjectPath + "/PERFUSION" + "/" + files[i];
  4920. else if ((guessImageType(files[i]) == CAPTK::ImageModalityType::IMAGE_TYPE_PSR)
  4921. && isExtensionSupported(extension))
  4922. psrFilePath = subjectPath + "/PERFUSION" + "/" + files[i];
  4923. else if ((guessImageType(files[i]) == CAPTK::ImageModalityType::IMAGE_TYPE_PH)
  4924. && isExtensionSupported(extension))
  4925. phFilePath = subjectPath + "/PERFUSION" + "/" + files[i];
  4926. }
  4927. }
  4928. if (cbica::directoryExists(subjectPath + "/DTI"))
  4929. {
  4930. files = cbica::filesInDirectory(subjectPath + "/DTI", false);
  4931. for (unsigned int i = 0; i < files.size(); i++)
  4932. {
  4933. std::string filePath = subjectPath + "/DTI/" + files[i];
  4934. std::string extension = cbica::getFilenameExtension(filePath, false);
  4935. if ((guessImageType(files[i]) == CAPTK::ImageModalityType::IMAGE_TYPE_AX) && isExtensionSupported(extension))
  4936. axFilePath = subjectPath + "/DTI/" + files[i];
  4937. else if ((guessImageType(files[i]) == CAPTK::ImageModalityType::IMAGE_TYPE_FA) && isExtensionSupported(extension))
  4938. faFilePath = subjectPath + "/DTI/" + files[i];
  4939. else if ((guessImageType(files[i]) == CAPTK::ImageModalityType::IMAGE_TYPE_RAD) && isExtensionSupported(extension))
  4940. radFilePath = subjectPath + "/DTI/" + files[i];
  4941. else if ((guessImageType(files[i]) == CAPTK::ImageModalityType::IMAGE_TYPE_TR) && isExtensionSupported(extension))
  4942. trFilePath = subjectPath + "/DTI/" + files[i];
  4943. }
  4944. }
  4945. if (cbica::fileExists(subjectPath + "/features.csv"))
  4946. featureFilePath = subjectPath + "/features.csv";
  4947. if (labelPath.empty() || t1FilePath.empty() || t2FilePath.empty() || t1ceFilePath.empty() || t2FlairFilePath.empty() || rcbvFilePath.empty() || axFilePath.empty() || faFilePath
  4948. == "" || radFilePath.empty() || trFilePath.empty() || psrFilePath.empty() || phFilePath.empty() || featureFilePath.empty())
  4949. continue;
  4950. OneQualifiedSubject[CAPTK::ImageModalityType::IMAGE_TYPE_T1] = t1FilePath;
  4951. OneQualifiedSubject[CAPTK::ImageModalityType::IMAGE_TYPE_T2] = t2FilePath;
  4952. OneQualifiedSubject[CAPTK::ImageModalityType::IMAGE_TYPE_T1CE] = t1ceFilePath;
  4953. OneQualifiedSubject[CAPTK::ImageModalityType::IMAGE_TYPE_T2FLAIR] = t2FlairFilePath;
  4954. OneQualifiedSubject[CAPTK::ImageModalityType::IMAGE_TYPE_AX] = axFilePath;
  4955. OneQualifiedSubject[CAPTK::ImageModalityType::IMAGE_TYPE_FA] = faFilePath;
  4956. OneQualifiedSubject[CAPTK::ImageModalityType::IMAGE_TYPE_RAD] = radFilePath;
  4957. OneQualifiedSubject[CAPTK::Ima

fMainWindow.cpp at commit 70d94d8, under other · at the source

Overview

Authors: Divya D Reddy1, Niloufar Saadat1, James M Holcomb1, Benjamin C Wagner1, Nghi C Truong1, Jason Bowerman1, Kimmo J Hatanpaa2, Toral R Patel2, Marco C Pinho1, Fang Yu1, Kuan Zhang1, Sadeem Lodhi1, Ananth J Madhuranthakam3, Chandan Ganesh Bangalore Yogananda1, Joseph A Maldjian1
  1. Advanced Neuroscience Imaging Research lab, Department of Radiology, University of Texas Southwestern Medical Center, Dallas, Texas USA
  2. Department of Pathology, University of Texas Southwestern Medical Center, Dallas, Texas USA
  3. Department of Physiology and Biomedical Engineering, Mayo Clinic, Rochester, Minnesota, USA
Institutions: The University of Texas Southwestern Medical Center (United States); Mayo Clinic (United States)
Journal: Scientific data, volume 13, issue 1, article 934
Dates: received 28 July 2025; accepted 14 April 2026; published online 22 April 2026
Type: Data paper · Language: English
License: CC BY
Identifiers: DOI 10.1038/s41597-026-07274-4 · PMID 42020453 · PMCID PMC13287574 · OpenAlex W7155181318
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: structural MRI / diffusion (modality), human (organism), other condition (population), methods / tools (subfield)
Methods: fMRI & imaging
Keywords: CNS cancer, Cancer imaging, Diagnostic markers, Cancer genetics, Tumour biomarkers
MeSH: Biomarkers, Tumor*, Brain Neoplasms*, Glioma*, Magnetic Resonance Imaging*, Deep Learning, Humans, Mutation, Texas (* major topic)
Topic: Glioma Diagnosis and Treatment (Genetics, Medicine), according to OpenAlex
Funding: U.S. Department of Health & Human Services | NIH | Center for Information Technology (Center for Information Technology, National Institutes of Health) (R01CA260705); U.S. Department of Health & Human Services | NIH | NCI | Division of Cancer Epidemiology and Genetics, National Cancer Institute (National Cancer Institute Division of Cancer Epidemiology and Genetics) (R01CA260705); U.S. Department of Health &amp; Human Services | NIH | Center for Information Technology (R01CA260705); U.S. Department of Health &amp; Human Services | NIH | NCI | Division of Cancer Epidemiology and Genetics, National Cancer Institute (R01CA260705)
Citations: not cited yet (Europe PMC); 34 references in the paper

Abstract

Gliomas are the most common type of primary brain tumors. Their management options and outcomes depend significantly on the underlying molecular-marker profile. Traditionally, molecular markers are determined through pathological testing on a tissue specimen acquired through biopsy. Several Magnetic Resonance Imaging (MRI) based Deep Learning (DL) methods offer a promising, non-invasive approach to predict these markers. However, they often require high-quality, well-annotated datasets. To support this need, we present a well-curated brain tumor dataset developed at The University of Texas Southwestern (UTSW) Medical Center. This dataset includes multi-contrast-MRI, demographics, molecular-markers, and multi-label tumor segmentations for 625 patients treated at UTSW between 2006 and 2023. Each patient record contains four MRI contrasts: pre-contrast-T1w, post-contrast-T1w, T2w, and T2-weighted fluid-attenuated inversion recovery (T2w-FLAIR) images. The dataset also provides comprehensive genetic information, including IDH mutation-status, 1p19q co-deletion, MGMT promoter methylation, tumor-type, and tumor-grade. This dataset offers a valuable resource for exploring the relationship between MRI characteristics and tumor genetics. It also serves as a robust benchmark for developing and validating DL models for various downstream tasks.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repository

Its files are read in the Code ↔ Paper reader above, with 4 matches between paragraphs and lines of code.

FETS-AI/Front-End

License: other
State: the link answers, verified on 29 September 2026
Evidence: files inventoried
Commit: 70d94d885e67a42c68277b984a885eb5d65ebe14, 13 October 2023
Languages: C/C++ (510), C++ (100), MATLAB (79), Python (19), C (3), Shell (2), JavaScript (1)
Size: 1,222 files, 714 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, license file, environment (Dockerfile, src/applications/Utilities/HausdorffCLI/setup.py, src/applications/Utilities/dcmqi/docker/dcmqi/Dockerfile), continuous integration, documentation
Not found: CITATION.cff, tests
Availability: 1 check, the latest on 29 September 2026: the link answers
  • 29 September 2026: the link answers
717 files

Code availability

Publicly available FeTS platform29 was used to process our data and generate automated tumor segmentations. The platform is accessible at https://github.com/FETS-AI/Front-End.

Reproduced under the paper's license (CC BY), from the paper cited above.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 714 scripts, each with its path and the digest of its content;
  • 4 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Data availability

The UTSW-Glioma dataset is publicly available through The Cancer Imaging Archive (TCIA) at: https://www.cancerimagingarchive.net/collection/utsw-glioma/. The dataset includes MRI scans and corresponding tumor segmentations provided in Neuroimaging Informatics Technology Initiative (NIfTI) format. Associated metadata, including demographic, histopathological, and MRI acquisition information, are available as a tab-separated values (.tsv) file accompanying the collection. All data can be accessed via the TCIA repository under the UTSW-Glioma collection.

Reproduced under the paper's license (CC BY), from the paper cited above.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 29 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 15 authors, 5 keywords, 8 MeSH terms, 4 funders, 27 references.

Cite

This paper

Reddy, D. D., Saadat, N., Holcomb, J. M., Wagner, B. C., Truong, N. C., Bowerman, J., Hatanpaa, K. J., Patel, T. R., Pinho, M. C., Yu, F., Zhang, K., Lodhi, S., Madhuranthakam, A. J., Bangalore Yogananda, C. G., & Maldjian, J. A. (2026). The University of Texas Southwestern Glioma Dataset - MRI, Molecular Markers and Segmentations. Scientific data, 13(1), 934. https://doi.org/10.1038/s41597-026-07274-4

BibTeX

@article{reddy2026university,
author = {Reddy, Divya D and Saadat, Niloufar and Holcomb, James M and Wagner, Benjamin C and Truong, Nghi C and Bowerman, Jason and Hatanpaa, Kimmo J and Patel, Toral R and Pinho, Marco C and Yu, Fang and Zhang, Kuan and Lodhi, Sadeem and Madhuranthakam, Ananth J and Bangalore Yogananda, Chandan Ganesh and Maldjian, Joseph A},
title = {{The University of Texas Southwestern Glioma Dataset - MRI, Molecular Markers and Segmentations}},
journal = {Scientific data},
year = {2026},
month = apr,
volume = {13},
number = {1},
pages = {934},
publisher = {Nature Publishing Group},
issn = {2052-4463},
doi = {10.1038/s41597-026-07274-4},
url = {https://doi.org/10.1038/s41597-026-07274-4},
pmid = {42020453},
pmcid = {PMC13287574}
}

RIS

TY - JOUR
AU - Reddy, Divya D
AU - Saadat, Niloufar
AU - Holcomb, James M
AU - Wagner, Benjamin C
AU - Truong, Nghi C
AU - Bowerman, Jason
AU - Hatanpaa, Kimmo J
AU - Patel, Toral R
AU - Pinho, Marco C
AU - Yu, Fang
AU - Zhang, Kuan
AU - Lodhi, Sadeem
AU - Madhuranthakam, Ananth J
AU - Bangalore Yogananda, Chandan Ganesh
AU - Maldjian, Joseph A
TI - The University of Texas Southwestern Glioma Dataset - MRI, Molecular Markers and Segmentations
T2 - Scientific data
J2 - Sci Data
PY - 2026
DA - 2026/04/22
VL - 13
IS - 1
SP - 934
SN - 2052-4463
PB - Nature Publishing Group
DO - 10.1038/s41597-026-07274-4
UR - https://doi.org/10.1038/s41597-026-07274-4
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41597-026-07274-4",
"type": "article-journal",
"title": "The University of Texas Southwestern Glioma Dataset - MRI, Molecular Markers and Segmentations",
"container-title": "Scientific data",
"author": [
{
"family": "Reddy",
"given": "Divya D"
},
{
"family": "Saadat",
"given": "Niloufar"
},
{
"family": "Holcomb",
"given": "James M"
},
{
"family": "Wagner",
"given": "Benjamin C"
},
{
"family": "Truong",
"given": "Nghi C"
},
{
"family": "Bowerman",
"given": "Jason"
},
{
"family": "Hatanpaa",
"given": "Kimmo J"
},
{
"family": "Patel",
"given": "Toral R"
},
{
"family": "Pinho",
"given": "Marco C"
},
{
"family": "Yu",
"given": "Fang"
},
{
"family": "Zhang",
"given": "Kuan"
},
{
"family": "Lodhi",
"given": "Sadeem"
},
{
"family": "Madhuranthakam",
"given": "Ananth J"
},
{
"family": "Bangalore Yogananda",
"given": "Chandan Ganesh"
},
{
"family": "Maldjian",
"given": "Joseph A"
}
],
"container-title-short": "Sci Data",
"volume": "13",
"issue": "1",
"page": "934",
"DOI": "10.1038/s41597-026-07274-4",
"PMID": "42020453",
"PMCID": "PMC13287574",
"ISSN": "2052-4463",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41597-026-07274-4",
"language": "en",
"issued": {
"date-parts": [
[
2026,
4,
22
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1080/07853890.2026.2685416 [code]
Pulmonary and cerebral damage in COVID-19 survivors: is there any association?
Journal: Annals of medicine
In common: pydicom, SimpleITK, Tools for NIfTI and ANALYZE image (MATLAB), 4 other tools, structural MRI / diffusion, other condition
[2] doi:10.1038/s41586-026-10631-3 [code]
A prognostic human brain network for diffuse midline glioma.
Journal: Nature
In common: pydicom, Tools for NIfTI and ANALYZE image (MATLAB), Image Processing Toolbox, 2 other tools, other condition, 2 references
[3] doi:10.1371/journal.pone.0351405 [code]
Unimodal vs. multimodal deep learning for non-invasive MGMT promoter methylation prediction in glioblastoma: A systematic evaluation on the BraTS 2021 dataset.
Journal: PloS one
In common: SimpleITK, NumPy, methods / tools, structural MRI / diffusion, other condition, 4 references
[4] doi:10.1162/imag.a.1262 [code]
Frame-wise multi-echo distortion correction for superior functional MRI.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: pydicom, Tools for NIfTI and ANALYZE image (MATLAB), scikit-image, 3 other tools
[5] doi:10.1038/s41598-026-48496-1 [code]
A unified FLAIR hyperintensity segmentation model for various CNS tumor types and acquisition time points.
Journal: Scientific reports
In common: SimpleITK, scikit-image, NumPy, methods / tools, structural MRI / diffusion, other condition, 2 references
[6] doi:10.1002/hbm.70602 [code]
Neuroimaging Correlates of Post-Stroke Pain After Ischemic Stroke: Secondary Analysis of the INSPiRE-TMS Trial.
Journal: Human brain mapping
In common: pydicom, Tools for NIfTI and ANALYZE image (MATLAB), Image Processing Toolbox, 2 other tools, other condition
[7] doi:10.1016/j.crmeth.2026.101473 [code]
AmygdalaGo-BOLT for boundary-aware segmentation of the human amygdala.
Journal: Cell reports methods
In common: SimpleITK, scikit-image, Image Processing Toolbox, 2 other tools, methods / tools, structural MRI / diffusion
[8] doi:10.3389/frai.2026.1771088 [code]
Few-shot deployment of pretrained MRI transformers in brain imaging tasks.
Journal: Frontiers in artificial intelligence
In common: pydicom, SimpleITK, scikit-image, 1 other tool, methods / tools, structural MRI / diffusion
[9] doi:10.1111/ene.70678 [code]
Who Falls After a Stroke? Evidence From a Prospective Stroke Cohort.
Journal: European journal of neurology
In common: pydicom, Tools for NIfTI and ANALYZE image (MATLAB), Image Processing Toolbox, 2 other tools
[10] doi:10.1016/j.celrep.2026.117404 [code]
Action and rest tremor map to distinct networks within the primary motor cortex.
Journal: Cell reports
In common: pydicom, Tools for NIfTI and ANALYZE image (MATLAB), Image Processing Toolbox, 2 other tools

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.