mirror of
https://gitlab.ethz.ch/gfattori/glocalize.git
synced 2026-05-03 05:34:31 +02:00
adding service worker structure for dicomscan skullremoval and volumepreparation
This commit is contained in:
+12
-5
@@ -62,32 +62,39 @@ find_package(GDCM REQUIRED)
|
||||
|
||||
# --- Sources ---
|
||||
set(SRCS
|
||||
DicomScanService.cpp
|
||||
DicomScanWorker.cpp
|
||||
SkullRemovalService.cpp
|
||||
SkullRemovalWorker.cpp
|
||||
VolumePrepService.cpp
|
||||
VolumePrepWorker.cpp
|
||||
main.cpp
|
||||
mainw.cpp
|
||||
ui_mainw.cpp
|
||||
dicomUtils.cpp
|
||||
gRen.cpp
|
||||
gLoadPatient.cpp
|
||||
LocalizationService.cpp
|
||||
LocalizationWorker.cpp
|
||||
|
||||
gSkullRemoval.cpp
|
||||
)
|
||||
|
||||
set(HDR
|
||||
DicomScanService.h
|
||||
DicomScanWorker.h
|
||||
SkullRemovalService.h
|
||||
SkullRemovalWorker.h
|
||||
VolumePrepService.h
|
||||
VolumePrepWorker.h
|
||||
mainw.h
|
||||
ui_mainw.h
|
||||
connectITKVTK.h
|
||||
dicomUtils.h
|
||||
gPatientRTGeneralInfos.h
|
||||
gRen.h
|
||||
gLoadPatient.h
|
||||
LocalizationService.h
|
||||
LocalizationWorker.h
|
||||
types.h
|
||||
types_qt.h
|
||||
|
||||
gSkullRemoval.h
|
||||
itkQtAdaptor.h
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,450 @@
|
||||
#include "DicomScanService.h"
|
||||
|
||||
|
||||
/*_________________________________________________________-
|
||||
|
||||
Patient loader for gLocalize.
|
||||
no wrkDir behaviour. just load data
|
||||
____________________________________________________________*/
|
||||
|
||||
|
||||
DicomScanService::gLoadPatient(){
|
||||
patientInfos = new gPatientRTGeneralInfos;
|
||||
readRT=0;
|
||||
m_rtIsocenter=0;
|
||||
initialized=false;
|
||||
virtualIso=false;
|
||||
//cout<< "DicomScanService::gLoadPatient" <<endl;
|
||||
}
|
||||
|
||||
|
||||
void DicomScanService::load(QString p_loadDir){
|
||||
|
||||
this->parse(p_loadDir);
|
||||
|
||||
if(patientInfos->CTfiles .size()!=0){
|
||||
cout<< "this->load2VTK(patientInfos)" <<endl;
|
||||
|
||||
if(readRT!=0){
|
||||
delete readRT;
|
||||
readRT = 0;
|
||||
}
|
||||
if(m_rtIsocenter!=0){
|
||||
delete m_rtIsocenter;
|
||||
m_rtIsocenter = 0;
|
||||
}
|
||||
|
||||
if(!patientInfos->rtIonPlanPath.isEmpty()){
|
||||
readRT = new RTPlan;
|
||||
readRT->fillRTPlan(patientInfos->rtIonPlanPath.toLatin1().data() );
|
||||
m_rtIsocenter = new double[3];
|
||||
if (readRT->NumberOfBeams > 0){
|
||||
{
|
||||
const auto& iso = readRT->Beams.at(0)->IsocenterPosition;
|
||||
m_rtIsocenter[0] = iso[0];
|
||||
m_rtIsocenter[1] = iso[1];
|
||||
m_rtIsocenter[2] = iso[2];
|
||||
}
|
||||
if (readRT->PatientOrientation.rfind("HFS", 0) == 0)
|
||||
m_patientOrientation = SUPINE;
|
||||
else if (readRT->PatientOrientation.rfind("HFP", 0) == 0)
|
||||
m_patientOrientation = PRONE;
|
||||
else m_patientOrientation = NOTDEFINED;
|
||||
|
||||
if (callbacks.loadedRTIso) callbacks.loadedRTIso(m_rtIsocenter);
|
||||
//for (int ii=0;ii<readRT->NumberOfBeams; ii++){
|
||||
// cout<< readRT->Beams[ii]->IsocenterPosition[0]<<" ";
|
||||
// cout<< readRT->Beams[ii]->IsocenterPosition[1]<<" ";
|
||||
// cout<< readRT->Beams[ii]->IsocenterPosition[2]<<" "<<endl;
|
||||
//}
|
||||
//cout<< "nbeams: "<<readRT->NumberOfBeams <<endl;
|
||||
//cout<< "iso0: "<<readRT->Beams.at(0)->IsocenterPosition[0] <<endl;
|
||||
//cout<< "iso2: "<<readRT->Beams.at(2)->IsocenterPosition[0]<<endl;
|
||||
//cout<< "iso0: "<<readRT->Beams.at(0)->IsocenterPosition[1] <<endl;
|
||||
//cout<< "iso2: "<<readRT->Beams.at(2)->IsocenterPosition[1]<<endl;
|
||||
//cout<< "iso0: "<<readRT->Beams.at(0)->IsocenterPosition[2] <<endl;
|
||||
//cout<< "iso2: "<<readRT->Beams.at(2)->IsocenterPosition[2]<<endl;
|
||||
|
||||
/*check for virtual iso, adapted from GB, gOTS v04Build34*/
|
||||
if(readRT->NumberOfBeams > 2 &&
|
||||
(readRT->Beams.at(0)->IsocenterPosition[0] != readRT->Beams.at(2)->IsocenterPosition[0] ||
|
||||
readRT->Beams.at(0)->IsocenterPosition[1] != readRT->Beams.at(2)->IsocenterPosition[1] ||
|
||||
readRT->Beams.at(0)->IsocenterPosition[2] != readRT->Beams.at(2)->IsocenterPosition[2])
|
||||
)
|
||||
virtualIso=true;
|
||||
else
|
||||
virtualIso=false;
|
||||
//cout << "virtual Iso: "<<virtualIso << endl;
|
||||
if (callbacks.virtualIsoTested) callbacks.virtualIsoTested(virtualIso);
|
||||
|
||||
|
||||
} else {
|
||||
cout<<"Number of Beams = 0 in RTIonPlan, FAIL" <<endl;
|
||||
delete m_rtIsocenter;
|
||||
delete readRT;
|
||||
readRT = 0;
|
||||
m_rtIsocenter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cout<< "DicomScanService::load2VTK _ 2 " <<endl;
|
||||
|
||||
|
||||
|
||||
this->loadDICOM(patientInfos->CTfiles);
|
||||
this->connectToVTK();
|
||||
// this->changeRef(GOTSREF);
|
||||
/* use DCM as default */
|
||||
this->changeRef(DCMREF);
|
||||
//trueOffset_rot_prev=trueOffset_rot;
|
||||
|
||||
|
||||
//this->load2VTK(patientInfos);
|
||||
} else {
|
||||
//DO NOTHING. THE folderisempty signal was already emitted.
|
||||
}
|
||||
cout<< " DicomScanService::load _ END" <<endl;
|
||||
}
|
||||
|
||||
void DicomScanService::changeRef(int selectedRef){
|
||||
|
||||
switch (selectedRef){
|
||||
case DCMREF:
|
||||
trueOffset=origin;
|
||||
break;
|
||||
case RTREF:
|
||||
trueOffset=origin;
|
||||
if(m_patientOrientation == SUPINE) {
|
||||
cout<< " ***** Patient is SUPINE" <<endl;
|
||||
trueOffset[0]-= m_rtIsocenter[0];
|
||||
trueOffset[1]-= m_rtIsocenter[1];
|
||||
trueOffset[2]-= m_rtIsocenter[2];
|
||||
} else if (m_patientOrientation == PRONE) {
|
||||
|
||||
cout<< " ***** Patient is PRONE" <<endl;
|
||||
/* adapted from CThandler project*/
|
||||
trueOffset[0] = 0.0;
|
||||
trueOffset[1] = 0.0;
|
||||
trueOffset[2] = 0.0;
|
||||
cout<<" ***** Reset trueOffset: "<<trueOffset[0]<<" "<<trueOffset[1]<<" "<<trueOffset[2]<<endl;
|
||||
|
||||
trueOffset[0] += -origin[0] ;
|
||||
trueOffset[1] += -origin[1];
|
||||
trueOffset[2] += origin[2] ;
|
||||
cout<<" ***** Correct for CT isocenter trueOffset: "<<trueOffset[0]<<" "<<trueOffset[1]<<" "<<trueOffset[2]<<endl;
|
||||
|
||||
trueOffset[0] += +m_rtIsocenter[0];
|
||||
trueOffset[1] += +m_rtIsocenter[1];
|
||||
trueOffset[2] +=- m_rtIsocenter[2];
|
||||
cout<<" ***** Correct for rtIso and volume bounds trueOffset: "<<trueOffset[0]<<" "<<trueOffset[1]<<" "<<trueOffset[2]<<endl;
|
||||
|
||||
} else if (m_patientOrientation == NOTDEFINED) {
|
||||
cout<< "!!! Patient is NOT PRONE OR SUPINE! VERY VERY CRITICAL SITUATION !!!" <<endl;
|
||||
}
|
||||
break;
|
||||
case GOTSREF:
|
||||
trueOffset[0] = 0.0;
|
||||
trueOffset[1] = 0.0;
|
||||
trueOffset[2] = 0.0;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
directionToWCS.SetIdentity( );
|
||||
directionToWCS[0][0]=1;
|
||||
directionToWCS[1][0]=0;
|
||||
directionToWCS[2][0]=0;
|
||||
directionToWCS[0][1]=0;
|
||||
directionToWCS[1][1]=1;
|
||||
directionToWCS[2][1]=0;
|
||||
directionToWCS[0][2]=0;
|
||||
directionToWCS[1][2]=0;
|
||||
directionToWCS[2][2]=1;
|
||||
|
||||
imageDir *= directionToWCS;
|
||||
myImageType::PointType trueOffset_rot=trueOffset;
|
||||
|
||||
trueOffset_rot[0]= directionToWCS[0][0]* trueOffset[0]+directionToWCS[0][1]* trueOffset[1] + directionToWCS[0][2]* trueOffset[2];
|
||||
trueOffset_rot[1]= directionToWCS[1][0]* trueOffset[0]+directionToWCS[1][1]* trueOffset[1] + directionToWCS[1][2]* trueOffset[2];
|
||||
trueOffset_rot[2]= directionToWCS[2][0]* trueOffset[0]+directionToWCS[2][1]* trueOffset[1] + directionToWCS[2][2]* trueOffset[2];
|
||||
|
||||
/*vedi se è giusto ma prob lo è */
|
||||
myImage->SetDirection( /*imageDir*/directionToWCS );
|
||||
myImage->SetOrigin( trueOffset_rot );
|
||||
myImage->Update();
|
||||
|
||||
in->SetInput(myImage);
|
||||
this->connectToVTK();
|
||||
this->actualizeOut();
|
||||
|
||||
/*calculate deltas for marker representation update*/
|
||||
if(initialized){
|
||||
if (callbacks.referenceChange) callbacks.referenceChange(
|
||||
trueOffset_rot_prev[0]-trueOffset_rot[0],
|
||||
trueOffset_rot_prev[1]-trueOffset_rot[1],
|
||||
trueOffset_rot_prev[2]-trueOffset_rot[2]);
|
||||
trueOffset_rot_prev=trueOffset_rot;
|
||||
} else {
|
||||
trueOffset_rot_prev=trueOffset_rot;
|
||||
initialized=true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DicomScanService::loadDICOM(std::vector<std::string> CTfilenames){
|
||||
|
||||
myImage = myImageType::New();
|
||||
rDICOM = itk::ImageSeriesReader<myImageType>::New();
|
||||
iGDCMimage = itk::GDCMImageIO::New();
|
||||
myDICOMseries = itk::GDCMSeriesFileNames::New();
|
||||
|
||||
rDICOM->SetImageIO(iGDCMimage);
|
||||
rDICOM->SetFileNames(CTfilenames);
|
||||
// rDICOM->SetReverseOrder(true);
|
||||
try{
|
||||
rDICOM->Update();
|
||||
}
|
||||
catch (itk::ExceptionObject &ex){
|
||||
std::cout << ex << std::endl;
|
||||
return; // error!
|
||||
}
|
||||
|
||||
myImage=rDICOM->GetOutput();
|
||||
imageDir = myImage->GetDirection( );
|
||||
origin = myImage->GetOrigin( );
|
||||
sizeOfImage = myImage->GetLargestPossibleRegion().GetSize();
|
||||
|
||||
}
|
||||
|
||||
void DicomScanService::connectToVTK(){
|
||||
|
||||
|
||||
out = vtkSmartPointer<vtkImageImport>::New();
|
||||
|
||||
in = itk::VTKImageExport <myImageType>::New();
|
||||
in->SetInput(myImage);
|
||||
|
||||
out->SetUpdateInformationCallback(in->GetUpdateInformationCallback());
|
||||
out->SetPipelineModifiedCallback(in->GetPipelineModifiedCallback());
|
||||
out->SetWholeExtentCallback(in->GetWholeExtentCallback());
|
||||
out->SetSpacingCallback(in->GetSpacingCallback());
|
||||
out->SetOriginCallback(in->GetOriginCallback());
|
||||
out->SetScalarTypeCallback(in->GetScalarTypeCallback());
|
||||
out->SetNumberOfComponentsCallback(in->GetNumberOfComponentsCallback());
|
||||
out->SetPropagateUpdateExtentCallback(in->GetPropagateUpdateExtentCallback());
|
||||
out->SetUpdateDataCallback(in->GetUpdateDataCallback());
|
||||
out->SetDataExtentCallback(in->GetDataExtentCallback());
|
||||
out->SetBufferPointerCallback(in->GetBufferPointerCallback());
|
||||
out->SetCallbackUserData(in->GetCallbackUserData());
|
||||
|
||||
}
|
||||
|
||||
void DicomScanService::actualizeOut(){
|
||||
|
||||
//in->Update();
|
||||
out->Update();
|
||||
//vol3D = vtkSmartPointer <vtkImageData>::New();
|
||||
//vol3D->DeepCopy(out->GetOutput());
|
||||
//vol3D->Update();
|
||||
vol3D = out->GetOutput();
|
||||
cout<<vol3D->GetSpacing()[0] <<" "<<vol3D->GetSpacing()[1] <<" "<<vol3D->GetSpacing()[2] <<endl;
|
||||
cout<<"fatto update" <<endl;
|
||||
if (callbacks.loadEnd) callbacks.loadEnd(vol3D);
|
||||
}
|
||||
|
||||
|
||||
void DicomScanService::parse(QString p_loadDir){
|
||||
loadDir=p_loadDir;
|
||||
|
||||
std::cout<< " ______________________________ " <<endl;
|
||||
std::cout<< " __ DicomScanService::load __ " <<endl;
|
||||
|
||||
int result= NOERRORS;
|
||||
gdcm::Reader* fileReader;
|
||||
gdcm::MediaStorage msStructRTStruct;
|
||||
gdcm::MediaStorage msStructRTIonPlan;
|
||||
gdcm::Directory d;
|
||||
gdcm::IPPSorter s;
|
||||
std::cout<< " __ wrkDirParser::exec_parse __ patientInfos->clearInfo() " <<endl;
|
||||
patientInfos->clearInfo();
|
||||
|
||||
std::cout<<"parsing dir: "<<p_loadDir.toUtf8().constData()<<std::endl;
|
||||
|
||||
if( gdcm::System::FileIsDirectory( p_loadDir.toUtf8().constData() ) )
|
||||
{
|
||||
d.Load(p_loadDir.toUtf8().constData(), false);
|
||||
gdcm::Directory::FilenamesType const &files = d.GetFilenames();
|
||||
for( gdcm::Directory::FilenamesType::const_iterator it = files.begin(); it != files.end(); ++it )
|
||||
{
|
||||
if(QFileInfo (it->c_str()).fileName().split(".").last() != QString("raw") )
|
||||
patientInfos->filenames.push_back( it->c_str() );
|
||||
}
|
||||
patientInfos->filenames.size() == 0 ? result = PARSER_FOLDER_EMPTY : result = NOERRORS;
|
||||
} else {
|
||||
result=PARSER_FOLDER_NOTEXISTING;
|
||||
};
|
||||
|
||||
cout << " patientInfos->filenames.size() "<<endl;
|
||||
cout<< patientInfos->filenames.size() <<endl;
|
||||
|
||||
if(result == NOERRORS)
|
||||
for(int i=(patientInfos->filenames.size()-1);i>-1;i--)
|
||||
{
|
||||
//cout << gCheckDICOMModalityToInt(patientInfos->filenames.at(i).c_str()) <<endl;
|
||||
fileReader = new gdcm::Reader;
|
||||
fileReader->SetFileName (patientInfos->filenames.at(i).c_str());
|
||||
|
||||
if( !fileReader->Read() ) {
|
||||
cout<< "Error reading file: "<< patientInfos->filenames.at(i).data() <<endl;
|
||||
delete fileReader;
|
||||
patientInfos->filenames.erase(patientInfos->filenames.begin()+i);
|
||||
continue;
|
||||
}
|
||||
|
||||
//msStructRTIonPlan.SetFromFile( fileReader->GetFile() );
|
||||
//if( msStructRTIonPlan == gdcm::MediaStorage::RTIonPlanStorage )
|
||||
if( gCheckDICOMModalityToInt(patientInfos->filenames.at(i).c_str()) == RTPLAN )
|
||||
{
|
||||
if(!patientInfos->rtIonPlanPath.isEmpty()) {
|
||||
// result=PARSER_RTPLAN_NOTUNIQUE;
|
||||
continue;
|
||||
} else {
|
||||
const gdcm::File &file = fileReader->GetFile();
|
||||
const gdcm::DataSet &ds = file.GetDataSet();
|
||||
//PATIENT NAME
|
||||
strcpy( patientInfos->PatientName,gGetStringValueFromTag( gdcm::Tag(0x0010,0x0010), ds));
|
||||
// // // PATIENT ID For ex: DICOM (0010,0020) = 1933197
|
||||
strcpy( patientInfos->PatientID , gGetStringValueFromTag( gdcm::Tag(0x0010,0x0020), ds));
|
||||
// // // PATIENT AGE For ex: DICOM (0010,1010) = 031Y
|
||||
strcpy( patientInfos->PatientAge , gGetStringValueFromTag( gdcm::Tag(0x0010,0x1010), ds)) ;
|
||||
// // // PATIENT SEX For ex: DICOM (0010,0040) = M
|
||||
strcpy( patientInfos->PatientSex, gGetStringValueFromTag( gdcm::Tag(0x0010,0x0040), ds) );
|
||||
// // // PATIENT BIRTHDATE For ex: DICOM (0010,0030) = 19680427
|
||||
strcpy( patientInfos->PatientBirthDate, gGetStringValueFromTag( gdcm::Tag(0x0010,0x0030), ds) );
|
||||
// // // SERIES NUMBER For ex: DICOM (0020,0011) = 902
|
||||
strcpy( patientInfos->SeriesNumber, gGetStringValueFromTag( gdcm::Tag(0x0020,0x0011), ds) );
|
||||
// // // SERIES DESCRIPTION For ex: DICOM (0008,103e) = SCOUT
|
||||
strcpy( patientInfos->SeriesDescription , gGetStringValueFromTag( gdcm::Tag(0x0008,0x103e), ds) );
|
||||
// // // STUDY ID For ex: DICOM (0020,0010) = 37481
|
||||
strcpy( patientInfos->StudyID, gGetStringValueFromTag( gdcm::Tag(0x0020,0x0010), ds) );
|
||||
// // // STUDY DESCRIPTION For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL
|
||||
strcpy( patientInfos->StudyDescription, gGetStringValueFromTag( gdcm::Tag(0x0008,0x1030), ds) );
|
||||
|
||||
const gdcm::DataElement &gSetupSequence=ds.GetDataElement(gdcm::Tag(0x300a,0x0180));
|
||||
//LOOK FOR PATIENT ORIENTATION
|
||||
gdcm::SmartPointer<gdcm::SequenceOfItems> sqiPS = gSetupSequence.GetValueAsSQ();
|
||||
const gdcm::DataSet& gPatSetupNest = sqiPS->GetItem(1).GetNestedDataSet();
|
||||
//SET PATIENT ORIENTATION STRING
|
||||
strcpy(patientInfos->PatientOrientation, gGetStringValueFromTag(gdcm::Tag(0x0018, 0x5100),gPatSetupNest));
|
||||
|
||||
|
||||
|
||||
patientInfos->rtIonPlanPath=QString(patientInfos->filenames.at(i).c_str());
|
||||
cout<< "RTPlan import success" <<endl;
|
||||
result=NOERRORS;
|
||||
patientInfos->filenames.erase(patientInfos->filenames.begin()+i);
|
||||
delete fileReader;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// msStructRTStruct.SetFromFile( fileReader->GetFile() );
|
||||
// if( msStructRTStruct == gdcm::MediaStorage::RTStructureSetStorage ) {
|
||||
if( gCheckDICOMModalityToInt(patientInfos->filenames.at(i).c_str()) == RTSTRUCT ){
|
||||
if(!patientInfos->rtStructurePath.isEmpty()) {
|
||||
patientInfos->rtStructurePath.clear();
|
||||
// result=PARSER_RTSTRUCT_NOTUNIQUE;
|
||||
continue;
|
||||
} else {
|
||||
patientInfos->rtStructurePath=QString(patientInfos->filenames.at(i).c_str());
|
||||
cout<< "RTStruct import success" <<endl;
|
||||
result=NOERRORS;
|
||||
patientInfos->filenames.erase(patientInfos->filenames.begin()+i);
|
||||
delete fileReader;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
delete fileReader;
|
||||
}
|
||||
|
||||
|
||||
//OK
|
||||
//if(result == NOERRORS && patientInfos->rtIonPlanPath.isEmpty() )
|
||||
// result= PARSER_RTPLAN_MISSING;
|
||||
//if(result == NOERRORS && patientInfos->rtStructurePath.isEmpty())
|
||||
// result=PARSER_RTSTRUCT_MISSING;
|
||||
|
||||
s.SetComputeZSpacing( true );
|
||||
s.SetZSpacingTolerance( 1e-2 );
|
||||
|
||||
if(result==NOERRORS)
|
||||
if(!s.Sort( patientInfos->filenames ) ) {
|
||||
result=PARSER_CT_FAILED_SORTING;
|
||||
} else {
|
||||
s.GetFilenames().size() == 0 ? result = PARSER_CT_FILES_MISSING : result=NOERRORS;
|
||||
}
|
||||
|
||||
if(result == NOERRORS){
|
||||
patientInfos->CTfiles=s.GetFilenames ();
|
||||
//cout<< "CT files sorting succeeded" <<endl;
|
||||
if (callbacks.statusInfo) callbacks.statusInfo("CT files sorting succeeded");
|
||||
} else {
|
||||
|
||||
switch(result){
|
||||
|
||||
case PARSER_FOLDER_EMPTY:
|
||||
cout<< "Empty folder. Parse failed" <<endl;
|
||||
if (callbacks.folderIsEmpty) callbacks.folderIsEmpty();
|
||||
break;
|
||||
|
||||
case PARSER_FOLDER_NOTEXISTING:
|
||||
if (callbacks.statusInfo) callbacks.statusInfo("NonExisting folder. Parse failed");
|
||||
break;
|
||||
|
||||
case PARSER_RTPLAN_NOTUNIQUE:
|
||||
if (callbacks.statusInfo) callbacks.statusInfo("RtIonPlan not unique. Parse failed");
|
||||
break;
|
||||
|
||||
case PARSER_RTSTRUCT_NOTUNIQUE:
|
||||
if (callbacks.statusInfo) callbacks.statusInfo("RtStructure not unique. Parse failed");
|
||||
break;
|
||||
|
||||
case PARSER_CT_FAILED_SORTING:
|
||||
if (callbacks.statusInfo) callbacks.statusInfo("Failed to sort CT files");
|
||||
if (callbacks.folderIsEmpty) callbacks.folderIsEmpty();
|
||||
break;
|
||||
|
||||
case PARSER_CT_FILES_MISSING:
|
||||
if (callbacks.statusInfo) callbacks.statusInfo("CT file Missing");
|
||||
if (callbacks.folderIsEmpty) callbacks.folderIsEmpty();
|
||||
break;
|
||||
|
||||
case PARSER_RTPLAN_MISSING:
|
||||
if (callbacks.statusInfo) callbacks.statusInfo("RtIonPlan missing");
|
||||
break;
|
||||
|
||||
case PARSER_RTSTRUCT_MISSING:
|
||||
if (callbacks.statusInfo) callbacks.statusInfo("rtStructure missing");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (callbacks.parse_result) callbacks.parse_result(result,patientInfos);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
DicomScanService::~DicomScanService(){
|
||||
delete patientInfos;
|
||||
patientInfos=nullptr;
|
||||
if (m_rtIsocenter) { delete [] m_rtIsocenter; m_rtIsocenter=nullptr; }
|
||||
delete readRT;
|
||||
readRT=nullptr;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#ifndef _DICOMSCANSERVICE_H_
|
||||
#define _DICOMSCANSERVICE_H_
|
||||
|
||||
#include <qstring.h>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include "gPatientRTGeneralInfos.h"
|
||||
//#include "wrkDirParser.h"
|
||||
#include <qdir.h>
|
||||
#include <vtkSmartPointer.h>
|
||||
#include <vtkImageData.h>
|
||||
#include "dicomUtils.h"
|
||||
|
||||
|
||||
/*_________________________________________________________-
|
||||
|
||||
Patient loader for gLocalize.
|
||||
no wrkDir behaviour. just load data
|
||||
____________________________________________________________*/
|
||||
|
||||
|
||||
#include "connectITKVTK.h"
|
||||
//#include "itkAnalyzeImageIO.h"
|
||||
#include "itkChangeInformationImageFilter.h"
|
||||
#include "itkImage.h"
|
||||
#include "itkImage.h"
|
||||
#include "itkImageFileWriter.h"
|
||||
#include "itkOrientImageFilter.h"
|
||||
#include "itkPermuteAxesImageFilter.h"
|
||||
#include "itkRescaleIntensityImageFilter.h"
|
||||
#include "itkImageSeriesReader.h"
|
||||
#include "itkGDCMImageIO.h"
|
||||
#include "itkGDCMSeriesFileNames.h"
|
||||
#include "gdcmIPPSorter.h"
|
||||
|
||||
|
||||
#ifndef TPATIENTORIENTATION
|
||||
#define TPATIENTORIENTATION
|
||||
typedef enum {
|
||||
NOTDEFINED=0,
|
||||
SUPINE = 1,
|
||||
PRONE =2
|
||||
} t_patientOrientation;
|
||||
#endif
|
||||
|
||||
#ifndef PARSERVARIABLES
|
||||
#define PARSERVARIABLES
|
||||
enum patientErrors {
|
||||
NOERRORS,
|
||||
PARSER_FOLDER_NOTEXISTING,
|
||||
PARSER_FOLDER_EMPTY,
|
||||
PARSER_RTPLAN_NOTUNIQUE,
|
||||
PARSER_RTPLAN_MISSING,
|
||||
PARSER_RTSTRUCT_NOTUNIQUE,
|
||||
PARSER_RTSTRUCT_MISSING,
|
||||
PARSER_CT_FILES_MISSING,
|
||||
PARSER_CT_FAILED_SORTING,
|
||||
POPULATE_INCONSISTENT_DATASET,
|
||||
POPULATE_NOTEXISTING,
|
||||
CLEAR_FOLDER_NOTEXISTING
|
||||
};
|
||||
|
||||
|
||||
enum patientParseOption{
|
||||
NOCLEAN,
|
||||
CLEAN
|
||||
};
|
||||
enum patientCleanMode{
|
||||
JUSTCLEAR,
|
||||
ISLOADINGCHECK
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef _T_REFERENCE_
|
||||
#define _T_REFERENCE_
|
||||
typedef enum{
|
||||
DCMREF=0,
|
||||
RTREF=1,
|
||||
GOTSREF=2
|
||||
}t_reference;
|
||||
|
||||
#endif
|
||||
|
||||
typedef itk::Image<short,3> myImageType;
|
||||
|
||||
|
||||
class DicomScanService {
|
||||
public:
|
||||
DicomScanService();
|
||||
~DicomScanService();
|
||||
|
||||
struct Callbacks {
|
||||
std::function<void()> folderIsEmpty;
|
||||
std::function<void(QString)> statusInfo;
|
||||
std::function<void(int, gPatientRTGeneralInfos*)> parse_result;
|
||||
std::function<void(QString)> loadFail;
|
||||
std::function<void(vtkImageData*)> loadEnd;
|
||||
std::function<void(double*)> loadedRTIso;
|
||||
std::function<void(double*, double*, int*)> loadedVolBBox;
|
||||
std::function<void(double, double, double)> referenceChange;
|
||||
std::function<void(bool)> virtualIsoTested;
|
||||
};
|
||||
|
||||
void setCallbacks(Callbacks cb) { callbacks = std::move(cb); }
|
||||
|
||||
|
||||
public:
|
||||
void load(QString p_loadDir);
|
||||
void changeRef(int selectedRef);
|
||||
|
||||
private:
|
||||
QString loadDir;
|
||||
gPatientRTGeneralInfos* patientInfos;
|
||||
void loadDICOM(std::vector<std::string> CTfilenames);
|
||||
void connectToVTK();
|
||||
void actualizeOut();
|
||||
void parse(QString p_loadDir);
|
||||
t_patientOrientation m_patientOrientation;
|
||||
vtkSmartPointer <vtkImageData> vol3D;
|
||||
|
||||
myImageType::Pointer myImage;
|
||||
itk::ImageSeriesReader<myImageType>::Pointer rDICOM;
|
||||
itk::GDCMImageIO::Pointer iGDCMimage ;
|
||||
itk::GDCMSeriesFileNames::Pointer myDICOMseries;
|
||||
myImageType::DirectionType imageDir;
|
||||
myImageType::PointType origin;
|
||||
myImageType::SizeType sizeOfImage;
|
||||
myImageType::PointType trueOffset;
|
||||
myImageType::PointType trueOffset_rot;
|
||||
myImageType::PointType trueOffset_rot_prev;
|
||||
myImageType::DirectionType directionToWCS;
|
||||
|
||||
bool initialized;
|
||||
|
||||
vtkSmartPointer<vtkImageImport> out;
|
||||
itk::VTKImageExport <myImageType>::Pointer in;
|
||||
|
||||
RTPlan * readRT;
|
||||
double* m_rtIsocenter;
|
||||
bool virtualIso;
|
||||
t_reference m_reference;
|
||||
|
||||
|
||||
private:
|
||||
Callbacks callbacks;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "DicomScanWorker.h"
|
||||
|
||||
DicomScanWorker::DicomScanWorker(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
DicomScanService::Callbacks cb;
|
||||
cb.folderIsEmpty = [&]() { emit folderIsEmpty(); };
|
||||
cb.statusInfo = [&](QString msg) { emit statusInfo(msg); };
|
||||
cb.parse_result = [&](int r, gPatientRTGeneralInfos* infos) { emit parse_result(r, infos); };
|
||||
cb.loadFail = [&](QString msg) { emit loadFail(msg); };
|
||||
cb.loadEnd = [&](vtkImageData* vol) { emit loadEnd(vol); };
|
||||
cb.loadedRTIso = [&](double* iso) { emit loadedRTIso(iso); };
|
||||
cb.loadedVolBBox = [&](double* bbox, double* spacing, int* dim) { emit loadedVolBBox(bbox, spacing, dim); };
|
||||
cb.referenceChange = [&](double dx, double dy, double dz) { emit referenceChange(dx, dy, dz); };
|
||||
cb.virtualIsoTested = [&](bool b) { emit virtualIsoTested(b); };
|
||||
svc.setCallbacks(std::move(cb));
|
||||
}
|
||||
|
||||
void DicomScanWorker::load(QString p_loadDir)
|
||||
{
|
||||
m_abort.store(false);
|
||||
if (m_abort.load()) { emit aborted(); return; }
|
||||
svc.load(p_loadDir);
|
||||
if (m_abort.load()) emit aborted();
|
||||
}
|
||||
|
||||
void DicomScanWorker::changeRef(int selectedRef)
|
||||
{
|
||||
svc.changeRef(selectedRef);
|
||||
}
|
||||
|
||||
void DicomScanWorker::abort()
|
||||
{
|
||||
m_abort.store(true);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <atomic>
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "DicomScanService.h"
|
||||
|
||||
class vtkImageData;
|
||||
class gPatientRTGeneralInfos;
|
||||
|
||||
// Qt wrapper around DicomScanService (runs in a worker thread).
|
||||
class DicomScanWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DicomScanWorker(QObject* parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void load(QString p_loadDir);
|
||||
void changeRef(int selectedRef);
|
||||
void abort();
|
||||
|
||||
signals:
|
||||
void folderIsEmpty();
|
||||
void statusInfo(QString msg);
|
||||
void parse_result(int result, gPatientRTGeneralInfos* patientInfos);
|
||||
void loadFail(QString msg);
|
||||
void loadEnd(vtkImageData* vol);
|
||||
void loadedRTIso(double* iso);
|
||||
void loadedVolBBox(double* bbox, double* spacing, int* dimension);
|
||||
void referenceChange(double dx, double dy, double dz);
|
||||
void virtualIsoTested(bool virtualIso);
|
||||
void aborted();
|
||||
|
||||
private:
|
||||
std::atomic_bool m_abort{false};
|
||||
DicomScanService svc;
|
||||
};
|
||||
@@ -0,0 +1,138 @@
|
||||
#include "SkullRemovalService.h"
|
||||
|
||||
#include "connectITKVTK.h"
|
||||
|
||||
#include <vtkImageData.h>
|
||||
#include <vtkImageExport.h>
|
||||
#include <vtkImageImport.h>
|
||||
#include <vtkSmartPointer.h>
|
||||
|
||||
#include <itkBinaryDilateImageFilter.h>
|
||||
#include <itkBinaryErodeImageFilter.h>
|
||||
#include <itkBinaryThresholdImageFilter.h>
|
||||
#include <itkCastImageFilter.h>
|
||||
#include <itkConnectedThresholdImageFilter.h>
|
||||
#include <itkCurvatureFlowImageFilter.h>
|
||||
#include <itkImage.h>
|
||||
#include <itkMaskNegatedImageFilter.h>
|
||||
#include <itkVTKImageImport.h>
|
||||
#include <itkExceptionObject.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace
|
||||
{
|
||||
using InternalPixelType = float;
|
||||
constexpr unsigned int Dimension = 3;
|
||||
|
||||
using InternalImageType = itk::Image<InternalPixelType, Dimension>;
|
||||
using MaskPixelType = unsigned char;
|
||||
using MaskImageType = itk::Image<MaskPixelType, Dimension>;
|
||||
|
||||
using ImportFilterType = itk::VTKImageImport<InternalImageType>;
|
||||
using CastingINVFilterType = itk::CastImageFilter<InternalImageType, InternalImageType>;
|
||||
using CurvatureFlowImageFilterType = itk::CurvatureFlowImageFilter<InternalImageType, InternalImageType>;
|
||||
using ConnectedThresholdImageFilterType = itk::ConnectedThresholdImageFilter<InternalImageType, MaskImageType>;
|
||||
using CastingFilterType = itk::CastImageFilter<MaskImageType, MaskImageType>;
|
||||
|
||||
using StructuringElementType = itk::BinaryBallStructuringElement<MaskPixelType, Dimension>;
|
||||
using DilateFilterType = itk::BinaryDilateImageFilter<MaskImageType, MaskImageType, StructuringElementType>;
|
||||
using ErodeFilterType = itk::BinaryErodeImageFilter<MaskImageType, MaskImageType, StructuringElementType>;
|
||||
using MaskNegatedFilterType = itk::MaskNegatedImageFilter<InternalImageType, MaskImageType, InternalImageType>;
|
||||
} // namespace
|
||||
|
||||
vtkImageData* SkullRemovalService::run(vtkImageData* inputVolume,
|
||||
double thr_low,
|
||||
double thr_up,
|
||||
std::atomic_bool* abortFlag,
|
||||
std::function<void(const std::string&, double)> progressCb)
|
||||
{
|
||||
if (!inputVolume)
|
||||
throw std::runtime_error("SkullRemovalService::run: inputVolume is null");
|
||||
|
||||
auto isAborted = [&]() -> bool { return abortFlag && abortFlag->load(); };
|
||||
|
||||
if (progressCb) progressCb("Skull masking: preparing pipeline", 0.0);
|
||||
if (isAborted()) return nullptr;
|
||||
|
||||
// VTK -> ITK
|
||||
vtkSmartPointer<vtkImageExport> vtkExporter = vtkSmartPointer<vtkImageExport>::New();
|
||||
vtkExporter->SetInputData(inputVolume);
|
||||
|
||||
auto itkImporter = ImportFilterType::New();
|
||||
ConnectPipelines(vtkExporter.GetPointer(), itkImporter);
|
||||
|
||||
// Pipeline (mirrors old gSkullRemoval::runFilter in a pure form)
|
||||
auto smoothing = CurvatureFlowImageFilterType::New();
|
||||
auto connectedThreshold = ConnectedThresholdImageFilterType::New();
|
||||
auto caster_mask = CastingFilterType::New();
|
||||
auto binaryDilateFilter = DilateFilterType::New();
|
||||
auto binaryErodeFilter = ErodeFilterType::New();
|
||||
auto maskNegatedFilter = MaskNegatedFilterType::New();
|
||||
|
||||
smoothing->SetNumberOfIterations(10);
|
||||
smoothing->SetTimeStep(0.125);
|
||||
|
||||
smoothing->SetInput(itkImporter->GetOutput());
|
||||
connectedThreshold->SetInput(smoothing->GetOutput());
|
||||
|
||||
connectedThreshold->SetLower(static_cast<InternalPixelType>(thr_low));
|
||||
connectedThreshold->SetUpper(static_cast<InternalPixelType>(thr_up));
|
||||
connectedThreshold->SetReplaceValue(255);
|
||||
|
||||
// Seed at volume center
|
||||
connectedThreshold->UpdateOutputInformation();
|
||||
InternalImageType::Pointer in = itkImporter->GetOutput();
|
||||
const auto region = in->GetBufferedRegion();
|
||||
const auto size = region.GetSize();
|
||||
const auto start = region.GetIndex();
|
||||
|
||||
InternalImageType::IndexType seed;
|
||||
seed[0] = start[0] + static_cast<long>(size[0] / 2);
|
||||
seed[1] = start[1] + static_cast<long>(size[1] / 2);
|
||||
seed[2] = start[2] + static_cast<long>(size[2] / 2);
|
||||
connectedThreshold->SetSeed(seed);
|
||||
|
||||
caster_mask->SetInput(connectedThreshold->GetOutput());
|
||||
|
||||
StructuringElementType kernel;
|
||||
kernel.SetRadius(10);
|
||||
kernel.CreateStructuringElement();
|
||||
|
||||
binaryDilateFilter->SetKernel(kernel);
|
||||
binaryErodeFilter->SetKernel(kernel);
|
||||
binaryDilateFilter->SetDilateValue(255);
|
||||
binaryErodeFilter->SetErodeValue(255);
|
||||
|
||||
binaryDilateFilter->SetInput(caster_mask->GetOutput());
|
||||
binaryErodeFilter->SetInput(binaryDilateFilter->GetOutput());
|
||||
|
||||
maskNegatedFilter->SetInput1(itkImporter->GetOutput());
|
||||
maskNegatedFilter->SetInput2(binaryErodeFilter->GetOutput());
|
||||
|
||||
if (progressCb) progressCb("Skull masking: running", 0.5);
|
||||
if (isAborted()) return nullptr;
|
||||
|
||||
try {
|
||||
maskNegatedFilter->Update();
|
||||
} catch (const itk::ExceptionObject& ex) {
|
||||
if (isAborted()) return nullptr;
|
||||
throw std::runtime_error(std::string("SkullRemovalService: ITK exception: ") + ex.GetDescription());
|
||||
}
|
||||
|
||||
if (isAborted()) return nullptr;
|
||||
|
||||
// ITK -> VTK
|
||||
vtkSmartPointer<vtkImageImport> vtkImporter = vtkSmartPointer<vtkImageImport>::New();
|
||||
auto itkExporter = itk::VTKImageExport<InternalImageType>::New();
|
||||
itkExporter->SetInput(maskNegatedFilter->GetOutput());
|
||||
ConnectPipelines(itkExporter, vtkImporter);
|
||||
|
||||
vtkImporter->Update();
|
||||
|
||||
vtkImageData* out = vtkImageData::New();
|
||||
out->DeepCopy(vtkImporter->GetOutput());
|
||||
|
||||
if (progressCb) progressCb("Skull masking: done", 1.0);
|
||||
return out;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
class vtkImageData;
|
||||
|
||||
// Pure skull removal / masking pipeline (no Qt).
|
||||
class SkullRemovalService
|
||||
{
|
||||
public:
|
||||
SkullRemovalService() = default;
|
||||
|
||||
// Returns a NEW vtkImageData* (caller owns; use vtkSmartPointer if you prefer).
|
||||
// Throws std::runtime_error on failure (unless aborted).
|
||||
vtkImageData* run(vtkImageData* inputVolume,
|
||||
double thr_low,
|
||||
double thr_up,
|
||||
std::atomic_bool* abortFlag = nullptr,
|
||||
std::function<void(const std::string&, double)> progressCb = {});
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "SkullRemovalWorker.h"
|
||||
#include "SkullRemovalService.h"
|
||||
|
||||
#include <vtkImageData.h>
|
||||
|
||||
#include <QString>
|
||||
|
||||
SkullRemovalWorker::SkullRemovalWorker(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void SkullRemovalWorker::run(vtkImageData* inputVolume, double thr_low, double thr_up)
|
||||
{
|
||||
m_abort.store(false);
|
||||
emit skull_mask_upd("Skull masking...", 0.0);
|
||||
|
||||
SkullRemovalService svc;
|
||||
try {
|
||||
vtkImageData* out = svc.run(
|
||||
inputVolume, thr_low, thr_up, &m_abort,
|
||||
[&](const std::string& msg, double p) { emit skull_mask_upd(QString::fromStdString(msg), p * 100.0); });
|
||||
|
||||
if (m_abort.load()) {
|
||||
if (out) out->Delete();
|
||||
emit aborted();
|
||||
return;
|
||||
}
|
||||
|
||||
emit skull_mask_upd("Skull masking done", 100.0);
|
||||
emit skull_mask_end(out); // receiver should Delete() if needed (or deep copy)
|
||||
} catch (const std::exception& e) {
|
||||
if (m_abort.load()) {
|
||||
emit aborted();
|
||||
return;
|
||||
}
|
||||
emit errMsg(QString(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void SkullRemovalWorker::abort()
|
||||
{
|
||||
m_abort.store(true);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <atomic>
|
||||
|
||||
class vtkImageData;
|
||||
|
||||
class SkullRemovalWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SkullRemovalWorker(QObject* parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void run(vtkImageData* inputVolume, double thr_low, double thr_up);
|
||||
void abort();
|
||||
|
||||
signals:
|
||||
void skull_mask_end(vtkImageData* maskedVolume);
|
||||
void errMsg(QString msg);
|
||||
void skull_mask_upd(QString msg, double val);
|
||||
void aborted();
|
||||
|
||||
private:
|
||||
std::atomic_bool m_abort{false};
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "VolumePrepService.h"
|
||||
|
||||
#include <vtkImageData.h>
|
||||
|
||||
vtkImageData* VolumePrepService::prepare(vtkImageData* input)
|
||||
{
|
||||
if (!input) return nullptr;
|
||||
vtkImageData* out = vtkImageData::New();
|
||||
out->DeepCopy(input);
|
||||
out->Modified();
|
||||
return out;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
class vtkImageData;
|
||||
|
||||
// Simple volume preparation (deep copy / detaching from loader thread).
|
||||
class VolumePrepService
|
||||
{
|
||||
public:
|
||||
vtkImageData* prepare(vtkImageData* input);
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "VolumePrepWorker.h"
|
||||
#include "VolumePrepService.h"
|
||||
|
||||
#include <vtkImageData.h>
|
||||
|
||||
VolumePrepWorker::VolumePrepWorker(QObject* parent) : QObject(parent) {}
|
||||
|
||||
void VolumePrepWorker::run(vtkImageData* input)
|
||||
{
|
||||
m_abort.store(false);
|
||||
emit progress(0.0);
|
||||
|
||||
if (m_abort.load()) { emit aborted(); return; }
|
||||
|
||||
VolumePrepService svc;
|
||||
vtkImageData* out = svc.prepare(input);
|
||||
|
||||
if (m_abort.load()) {
|
||||
if (out) out->Delete();
|
||||
emit aborted();
|
||||
return;
|
||||
}
|
||||
|
||||
emit progress(100.0);
|
||||
emit finished(out);
|
||||
}
|
||||
|
||||
void VolumePrepWorker::abort()
|
||||
{
|
||||
m_abort.store(true);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <atomic>
|
||||
|
||||
class vtkImageData;
|
||||
|
||||
class VolumePrepWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VolumePrepWorker(QObject* parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void run(vtkImageData* input);
|
||||
void abort();
|
||||
|
||||
signals:
|
||||
void finished(vtkImageData* prepared);
|
||||
void error(QString msg);
|
||||
void progress(double percent);
|
||||
void aborted();
|
||||
|
||||
private:
|
||||
std::atomic_bool m_abort{false};
|
||||
};
|
||||
@@ -84,6 +84,12 @@ MainWindow::MainWindow(QString p_loadPath){
|
||||
loadPatient->moveToThread(loadPatient_thread);
|
||||
loadPatient_thread->start();
|
||||
|
||||
// Volume preparation worker (detaches volumes from the loader thread)
|
||||
volumePrep = new VolumePrepWorker;
|
||||
volumePrep_thread = new QThread;
|
||||
volumePrep->moveToThread(volumePrep_thread);
|
||||
volumePrep_thread->start();
|
||||
|
||||
qRegisterMetaType< gPatientRTGeneralInfos* >("gPatientRTGeneralInfos *");
|
||||
qRegisterMetaType< std::vector<std::string> >("std::vector<std::string>");
|
||||
qRegisterMetaType< std::string >("std::string");
|
||||
@@ -94,7 +100,8 @@ MainWindow::MainWindow(QString p_loadPath){
|
||||
qRegisterMetaType<MarkerList>("MarkerList");
|
||||
qRegisterMetaType<LocalizationParams>("LocalizationParams");
|
||||
|
||||
connect(loadPatient, SIGNAL(loadEnd(vtkImageData*)), Visualizer,SLOT(loadVolume (vtkImageData* )));
|
||||
connect(loadPatient, SIGNAL(loadEnd(vtkImageData*)), volumePrep, SLOT(run(vtkImageData* )));
|
||||
connect(volumePrep, SIGNAL(finished(vtkImageData*)), Visualizer, SLOT(loadVolume (vtkImageData* )));
|
||||
connect(loadPatient, SIGNAL(folderIsEmpty()),this,SLOT(onParsedEmptyFolder()));
|
||||
connect(loadPatient, SIGNAL(parse_result(int , gPatientRTGeneralInfos* )),this,SLOT(onParsedOK(int , gPatientRTGeneralInfos* )));
|
||||
connect(loadPatient, SIGNAL(loadedRTIso(double*)),this,SLOT(onRTIsoAvailable(double*)));
|
||||
@@ -562,7 +569,7 @@ void MainWindow::call_skullMask(){
|
||||
Q_ARG(QString, "Skull masking..." ),
|
||||
Q_ARG(int, 3000));
|
||||
|
||||
QMetaObject::invokeMethod(skullRemoval, "runFilter", Qt::QueuedConnection,
|
||||
QMetaObject::invokeMethod(skullRemoval, "run", Qt::QueuedConnection,
|
||||
Q_ARG(vtkImageData*, Visualizer->getVolume()),
|
||||
Q_ARG(double, regGrownParameters[1]),
|
||||
Q_ARG(double,regGrownParameters[0]));
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
|
||||
class Ui_MainWindow; // forward declaration (defined in ui_mainw.h)
|
||||
class gRen;
|
||||
class gLoadPatient;
|
||||
class DicomScanWorker;
|
||||
class LocalizationWorker;
|
||||
class gSkullRemoval;
|
||||
class SkullRemovalWorker;
|
||||
class VolumePrepWorker;
|
||||
class gLoadPatDialog;
|
||||
|
||||
//#include "wrkDirParser.h"
|
||||
@@ -19,14 +20,15 @@ class gLoadPatDialog;
|
||||
#include "gPatientRTGeneralInfos.h"
|
||||
#include "dicomUtils.h"
|
||||
#include "connectITKVTK.h"
|
||||
#include "gLoadPatient.h"
|
||||
|
||||
#include "LocalizationWorker.h"
|
||||
#include "DicomScanWorker.h"
|
||||
#include "SkullRemovalWorker.h"
|
||||
#include "VolumePrepWorker.h"
|
||||
#include "types_qt.h"
|
||||
|
||||
|
||||
|
||||
#include "gSkullRemoval.h"
|
||||
|
||||
|
||||
class gLoadPatDialog: public QDialog{
|
||||
@@ -65,12 +67,15 @@ private:
|
||||
void connectUi(Ui_MainWindow* Ui);
|
||||
|
||||
gRen * Visualizer;
|
||||
gLoadPatient* loadPatient;
|
||||
DicomScanWorker* loadPatient;
|
||||
QThread* loadPatient_thread;
|
||||
|
||||
VolumePrepWorker* volumePrep{nullptr};
|
||||
QThread* volumePrep_thread{nullptr};
|
||||
|
||||
LocalizationWorker* localize_marker{nullptr};
|
||||
QThread* localize_thread;
|
||||
gSkullRemoval* skullRemoval;
|
||||
SkullRemovalWorker* skullRemoval;
|
||||
QThread* skull_thread;
|
||||
|
||||
QStandardItemModel* treeModel;
|
||||
|
||||
Reference in New Issue
Block a user