Files
glocalize/DicomScanService.cpp
T

451 lines
16 KiB
C++

#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;
}