mirror of
https://gitlab.ethz.ch/gfattori/glocalize.git
synced 2026-05-07 15:44:32 +02:00
Working version of gLocalize software installed at the CNAO.
This extends the embedded function in gOTS code with: - manual volume masking - visualization tools - no memory issues.
This commit is contained in:
Executable
+154
@@ -0,0 +1,154 @@
|
||||
cmake_minimum_required (VERSION 2.8)
|
||||
|
||||
IF (NOT CMAKE_BUILD_TYPE)
|
||||
SET (CMAKE_BUILD_TYPE "Release" CACHE STRING
|
||||
"Choose the type of build, options are: Debug Release
|
||||
RelWithDebInfo MinSizeRel." FORCE)
|
||||
ENDIF ()
|
||||
|
||||
project(gLocalize)
|
||||
set(TRG gLocalize)
|
||||
|
||||
|
||||
include_directories (BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
|
||||
find_package(VTK REQUIRED)
|
||||
include(${VTK_USE_FILE})
|
||||
ADD_DEFINITIONS(${VTK_DEFINITIONS})
|
||||
|
||||
find_package(Qt4 REQUIRED)
|
||||
include(${QT_USE_FILE})
|
||||
ADD_DEFINITIONS(${QT_DEFINITIONS})
|
||||
|
||||
|
||||
FIND_PACKAGE(GDCM REQUIRED)
|
||||
IF(NOT GDCM_DIR)
|
||||
MESSAGE(FATAL_ERROR "Please set GDCM_DIR.")
|
||||
ELSE(NOT GDCM_DIR)
|
||||
include(${GDCM_USE_FILE})
|
||||
INCLUDE_DIRECTORIES(${GDCM_INCLUDE_DIRS})
|
||||
ENDIF(NOT GDCM_DIR)
|
||||
|
||||
|
||||
SET(ITK_MIN_VERSION "3.20")
|
||||
|
||||
|
||||
FIND_PACKAGE(ITK REQUIRED)
|
||||
IF(NOT ITK_FOUND)
|
||||
MESSAGE(SEND_ERROR "ITK ${ITK_MIN_VERSION} not found. Please set the ITK_DIR variable.")
|
||||
ELSE(NOT ITK_FOUND)
|
||||
# The version check fails with cmake
|
||||
# 2.8.4+linux, manually perform check
|
||||
IF("${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}"
|
||||
VERSION_LESS
|
||||
${ITK_MIN_VERSION})
|
||||
MESSAGE(SEND_ERROR "ITK ${ITK_MIN_VERSION} not found (version ${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR} provided). Please set the ITK_DIR variable.")
|
||||
ELSE("${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}" VERSION_LESS ${ITK_MIN_VERSION})
|
||||
INCLUDE(${ITK_USE_FILE})
|
||||
ENDIF("${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}" VERSION_LESS ${ITK_MIN_VERSION})
|
||||
|
||||
ENDIF(NOT ITK_FOUND)
|
||||
|
||||
# set(QT_ROOT "C:/Qt/4.8.2")
|
||||
# SET(ZLIB_INCLUDE_DIRS "${QT_ROOT}/src/3rdparty/zlib")
|
||||
# message("QT_ROOT variable: ${QT_ROOT}")
|
||||
# message("${ZLIB_INCLUDE_DIRS}")
|
||||
# include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
|
||||
IF(UNIX)
|
||||
find_package(ZLIB REQUIRED)
|
||||
ELSE(UNIX)
|
||||
# SET(ZLIB_INCLUDE_DIRS
|
||||
# "${QT_ROOT}/src/3rdparty/zlib"
|
||||
# CACHE
|
||||
# STRING
|
||||
# "Path
|
||||
# to
|
||||
# ZLIB
|
||||
# headers
|
||||
# of
|
||||
# Qt")
|
||||
SET(ZLIB_LIBRARIES "")
|
||||
IF(NOT EXISTS "${ZLIB_INCLUDE_DIRS}/zlib.h")
|
||||
MESSAGE("Please specify a valid zlib include dir")
|
||||
ENDIF(NOT EXISTS "${ZLIB_INCLUDE_DIRS}/zlib.h")
|
||||
ENDIF(UNIX)
|
||||
|
||||
include_directories(${PROJECT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${PROJECT_SOURCE_DIR}/src)
|
||||
|
||||
set(SRCS
|
||||
${PROJECT_SOURCE_DIR}/main.cpp
|
||||
${PROJECT_SOURCE_DIR}/mainw.cpp
|
||||
${PROJECT_SOURCE_DIR}/mainw.h
|
||||
${PROJECT_SOURCE_DIR}/connectITKVTK.h
|
||||
${PROJECT_SOURCE_DIR}/dicomUtils.cpp
|
||||
${PROJECT_SOURCE_DIR}/dicomUtils.h
|
||||
${PROJECT_SOURCE_DIR}/gPatientRTGeneralInfos.h
|
||||
${PROJECT_SOURCE_DIR}/gRen.h
|
||||
${PROJECT_SOURCE_DIR}/gRen.cpp
|
||||
#${PROJECT_SOURCE_DIR}/loadDCM2VTK.h
|
||||
#${PROJECT_SOURCE_DIR}/loadDCM2VTK.cpp
|
||||
#${PROJECT_SOURCE_DIR}/wrkDirParser.cpp
|
||||
#${PROJECT_SOURCE_DIR}/wrkDirParser.h
|
||||
${PROJECT_SOURCE_DIR}/gLoadPatient.h
|
||||
${PROJECT_SOURCE_DIR}/gLoadPatient.cpp
|
||||
${PROJECT_SOURCE_DIR}/gLocalize.h
|
||||
${PROJECT_SOURCE_DIR}/gLocalize.cpp
|
||||
${PROJECT_SOURCE_DIR}/gSkullRemoval.h
|
||||
${PROJECT_SOURCE_DIR}/gSkullRemoval.cpp
|
||||
${PROJECT_SOURCE_DIR}/itkQtAdaptor.h
|
||||
)
|
||||
|
||||
set(HDR
|
||||
${PROJECT_SOURCE_DIR}/mainw.h
|
||||
${PROJECT_SOURCE_DIR}/connectITKVTK.h
|
||||
${PROJECT_SOURCE_DIR}/dicomUtils.h
|
||||
${PROJECT_SOURCE_DIR}/gPatientRTGeneralInfos.h
|
||||
${PROJECT_SOURCE_DIR}/gRen.h
|
||||
#${PROJECT_SOURCE_DIR}/loadDCM2VTK.h
|
||||
#${PROJECT_SOURCE_DIR}/wrkDirParser.h
|
||||
${PROJECT_SOURCE_DIR}/gLoadPatient.h
|
||||
${PROJECT_SOURCE_DIR}/gLocalize.h
|
||||
${PROJECT_SOURCE_DIR}/gSkullRemoval.h
|
||||
${PROJECT_SOURCE_DIR}/itkQtAdaptor.h
|
||||
|
||||
)
|
||||
QT4_WRAP_CPP(HDR_MOC ${HDR})
|
||||
|
||||
|
||||
# SET(RES ${PROJECT_SOURCE_DIR}/resources/images.qrc)
|
||||
# QT4_ADD_RESOURCES(RES_RCC ${RES})
|
||||
|
||||
|
||||
SET(RES ${PROJECT_SOURCE_DIR}/images.qrc)
|
||||
QT4_ADD_RESOURCES(RES_RCC ${RES})
|
||||
|
||||
|
||||
|
||||
ADD_DEFINITIONS(-Wall -O3 -DQT_DLL -DQT_THREAD_SUPPORT)
|
||||
|
||||
add_executable(${TRG} ${SRCS} ${HDR_MOC} ${RES_RCC} )
|
||||
#${RES_RCC} )
|
||||
|
||||
target_link_libraries(${TRG}
|
||||
${QT_LIBRARIES}
|
||||
${QT_QTMAIN_LIBRARY}
|
||||
QVTK
|
||||
${VTK_LIBRARIES}
|
||||
${QT_QTCORE_LIBRARY}
|
||||
${QT_QTGUI_LIBRARY}
|
||||
gdcmCommon
|
||||
gdcmDICT
|
||||
ITKIO
|
||||
ITKCommon
|
||||
ITKBasicFilters
|
||||
ITKAlgorithms
|
||||
ITKNumerics
|
||||
ITKStatistics
|
||||
ITKSpatialObject
|
||||
)
|
||||
|
||||
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#ifndef __ConnectVTKITK_h
|
||||
#define __ConnectVTKITK_h
|
||||
|
||||
|
||||
#include "itkVTKImageImport.h"
|
||||
#include "itkVTKImageExport.h"
|
||||
#include "itkVTKImageExportBase.h"
|
||||
#include <vtkImageImport.h>
|
||||
#include <vtkImageExport.h>
|
||||
|
||||
//template <typename ITK_Exporter, typename VTK_Importer>
|
||||
//void ConnectITKToVTK(ITK_Exporter in, VTK_Importer* out)
|
||||
|
||||
/*template <typename ImageType>
|
||||
void ConnectITKToVTK(itk::VTKImageExport<ImageType>* in, vtkImageImport* out) */
|
||||
template <typename ITK_Exporter, typename VTK_Importer>
|
||||
void ConnectITKToVTK(ITK_Exporter in, VTK_Importer* out)
|
||||
{
|
||||
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());
|
||||
};
|
||||
|
||||
//template <typename ImageType>
|
||||
//void ConnectVTKToITK(vtkImageExport* in, itk::VTKImageImport<ImageType>* out)
|
||||
template <typename VTK_Exporter, typename ITK_Importer>
|
||||
void ConnectVTKToITK(VTK_Exporter *in, ITK_Importer out)
|
||||
{
|
||||
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());
|
||||
};
|
||||
#endif
|
||||
Executable
+485
@@ -0,0 +1,485 @@
|
||||
#include "dicomUtils.h"
|
||||
|
||||
|
||||
//FUNCTION DECLARATION NECESSARY FOR COPY/PASTE FROM vtkGDCMImageReader
|
||||
// const char *gGetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds);
|
||||
|
||||
const char *gGetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds)
|
||||
{
|
||||
static std::string buffer;
|
||||
buffer = ""; // cleanup previous call
|
||||
if( ds.FindDataElement( t ) )
|
||||
{
|
||||
const gdcm::DataElement& de = ds.GetDataElement( t );
|
||||
const gdcm::ByteValue *bv = de.GetByteValue();
|
||||
if( bv ) // Can be Type 2
|
||||
{
|
||||
buffer = std::string( bv->GetPointer(), bv->GetLength() );
|
||||
// Will be padded with at least one \0
|
||||
}
|
||||
}
|
||||
// Since return is a const char* the very first \0 will be considered
|
||||
return buffer.c_str();
|
||||
};
|
||||
|
||||
//GENERAL INDEPENDENT FUNCTION TO CHECK FOR FILE DICOM MODALITY (PLAN, STRUCT, IMAGE) REQUIRES CORRECT PATH
|
||||
const char * gCheckDICOMModality(const char *filename)
|
||||
{
|
||||
gdcm::Reader gR;
|
||||
gR.SetFileName(filename);//str.toAscii().data());
|
||||
if(!gR.Read())
|
||||
return("NODCMFILE");
|
||||
|
||||
const gdcm::File &file = gR.GetFile();
|
||||
const gdcm::DataSet &ds = file.GetDataSet();
|
||||
return(gGetStringValueFromTag( gdcm::Tag(0x0008,0x0060), ds) ); //RETURN MODALITY
|
||||
};
|
||||
|
||||
int gCheckDICOMModalityToInt(const char *filename){
|
||||
|
||||
const char * tmp = gCheckDICOMModality(filename);
|
||||
//cout<< tmp<<endl;
|
||||
|
||||
if( !strcmp(tmp,"RTSTRUCT") )
|
||||
return RTSTRUCT;
|
||||
else if ( !strcmp(tmp,"RTPLAN") )
|
||||
return RTPLAN;
|
||||
else if( !strcmp(tmp,"CT") )
|
||||
return IMAGE;
|
||||
else
|
||||
return NODCMFILE;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
IonBeamProperties::IonBeamProperties(){
|
||||
BeamNumber = BADVALUE;
|
||||
BeamName = new char [MAXSTRINGLENGHT];
|
||||
SupportId = new char [MAXSTRINGLENGHT];
|
||||
SupportType = new char [MAXSTRINGLENGHT];
|
||||
GantryAngle = BADVALUE;
|
||||
IsocenterPosition = new double [3];
|
||||
TablePitchAngle= BADVALUE;
|
||||
TableRollAngle = BADVALUE;
|
||||
TableYawAngle= BADVALUE;
|
||||
TableLatDispl = BADVALUE;
|
||||
TableLongDispl= BADVALUE;
|
||||
TableVertDispl= BADVALUE;
|
||||
|
||||
}
|
||||
|
||||
IonBeamProperties::~IonBeamProperties(){
|
||||
delete[] BeamName;
|
||||
delete[] SupportId;
|
||||
delete[] IsocenterPosition;
|
||||
delete[] SupportType;
|
||||
}
|
||||
|
||||
|
||||
void IonBeamProperties::PrintSelf(){
|
||||
cout<< "__ IonBeamProperties print self ** " <<endl;
|
||||
cout<<" |_ BeamNumber = "<<BeamNumber<<endl;
|
||||
cout<<" |_ BeamName = "<<BeamName<<endl;
|
||||
cout<<" |_ SupportType = " <<SupportType<<endl;
|
||||
cout<<" |_ SupportId = "<<SupportId<<endl;
|
||||
cout<<" |_ GantryAngle = "<<GantryAngle<<endl;
|
||||
cout<<" |_ IsocenterPosition = "<<IsocenterPosition[0]<<
|
||||
IsocenterPosition[1]<<" "<<
|
||||
IsocenterPosition[2]<<endl;
|
||||
cout<<" |_ TableYawAngle = "<<TableYawAngle<<endl;
|
||||
cout<<" |_ TablePitchAngle = "<<TablePitchAngle<<endl;
|
||||
cout<<" |_ TableRollAngle = "<<TableRollAngle<<endl;
|
||||
cout<<" |_ TableLatDispl = "<<TableLatDispl<<endl;
|
||||
cout<<" |_ TableLongDispl = "<<TableLongDispl<<endl;
|
||||
cout<<" |_ TableVertDispl = "<<TableVertDispl<<endl;
|
||||
}
|
||||
|
||||
|
||||
/*-----*/
|
||||
//CLASS gIonBEAMProperties
|
||||
RTPlan::~RTPlan(){
|
||||
if(NumberOfBeams > 0)
|
||||
for(int ii=0;ii<NumberOfBeams;ii++)
|
||||
delete Beams[ii];
|
||||
delete [] Beams;
|
||||
delete [] PatientName;
|
||||
delete [] PatientID;
|
||||
delete [] PatientSex;
|
||||
delete [] PatientAge;
|
||||
delete [] PatientBirthDate;
|
||||
delete [] SeriesNumber;
|
||||
delete [] SeriesDescription;
|
||||
delete [] StudyID;
|
||||
delete [] StudyDescription;
|
||||
delete [] Modality;
|
||||
delete [] IsocenterPosition;
|
||||
delete [] VolumeCenter;
|
||||
delete [] BeamName;
|
||||
delete [] SupportType;
|
||||
delete [] PatientOrientation;
|
||||
}
|
||||
|
||||
RTPlan::RTPlan(){
|
||||
NumberOfBeams=0;
|
||||
PatientName = new char [MAXSTRINGLENGHT];
|
||||
PatientID = new char [MAXSTRINGLENGHT];
|
||||
PatientSex = new char [MAXSTRINGLENGHT];
|
||||
PatientAge = new char [MAXSTRINGLENGHT];
|
||||
PatientBirthDate = new char [MAXSTRINGLENGHT];
|
||||
|
||||
SeriesNumber = new char [MAXSTRINGLENGHT];
|
||||
SeriesDescription = new char [MAXSTRINGLENGHT];
|
||||
StudyID = new char [MAXSTRINGLENGHT];
|
||||
StudyDescription = new char [MAXSTRINGLENGHT];
|
||||
Modality = new char [MAXSTRINGLENGHT];
|
||||
|
||||
IsocenterPosition = new double[3];
|
||||
std::fill(IsocenterPosition,(IsocenterPosition+3),BADVALUE);
|
||||
VolumeCenter= new double[3];
|
||||
std::fill(VolumeCenter,(VolumeCenter+3),BADVALUE);
|
||||
|
||||
BeamNumber = BADVALUE;
|
||||
BeamName = new char [MAXSTRINGLENGHT];
|
||||
TableRollAngle = BADVALUE;
|
||||
TableYawAngle= BADVALUE;
|
||||
TablePitchAngle= BADVALUE;
|
||||
TableLatDispl= BADVALUE;
|
||||
TableVertDispl= BADVALUE;
|
||||
TableLongDispl= BADVALUE;
|
||||
SupportType = new char [MAXSTRINGLENGHT];
|
||||
SupportId = new char [MAXSTRINGLENGHT];
|
||||
PatientOrientation = new char [MAXSTRINGLENGHT];
|
||||
|
||||
}
|
||||
|
||||
void RTPlan::PrintSelf(){
|
||||
cout<< "** RTPlan print self ** " <<endl;
|
||||
cout<<"PatientName = "<<PatientName<<endl;
|
||||
cout<<"PatientID = "<<PatientID<<endl;
|
||||
cout<<"PatientSex = "<<PatientSex<<endl;
|
||||
cout<<"PatientAge = "<<PatientAge<<endl;
|
||||
cout<<"PatientBirthDate = "<<PatientBirthDate<<endl;
|
||||
cout<<"SeriesNumber = "<<SeriesNumber<<endl;
|
||||
cout<<"SeriesDescription = "<<SeriesDescription<<endl;
|
||||
cout<<"StudyID = "<<StudyID<<endl;
|
||||
cout<<"StudyDescription = "<<StudyDescription<<endl;
|
||||
cout<<"Modality = "<<Modality<<endl;
|
||||
cout<<"IsocenterPosition = "<<IsocenterPosition[0]<<" "<<
|
||||
IsocenterPosition[1]<<" "<<
|
||||
IsocenterPosition[2]<<endl;
|
||||
cout<<"VolumeCenter = "<<VolumeCenter[0]<<" "<<
|
||||
VolumeCenter[1]<<" "<<
|
||||
VolumeCenter[2]<<endl;
|
||||
cout<<"BeamNumber = "<<BeamNumber<<endl;
|
||||
cout<<"BeamName = "<<BeamName<<endl;
|
||||
cout<<"TableRollAngle = "<<TableRollAngle<<endl;
|
||||
cout<<"TableYawAngle = "<<TableYawAngle<<endl;
|
||||
cout<<"TablePitchAngle = "<<TablePitchAngle<<endl;
|
||||
cout<<"TableVertDispl = "<<TableVertDispl<<endl;
|
||||
cout<<"TableLongDispl = "<<TableLongDispl<<endl;
|
||||
cout<<"SupportType = "<<SupportType<<endl;
|
||||
cout<<"SupportId = "<<SupportId<<endl;
|
||||
cout<<"PatientOrientation = "<<PatientOrientation<<endl;
|
||||
|
||||
if(NumberOfBeams > 0)
|
||||
for(int ii=0; ii<NumberOfBeams;ii++)
|
||||
Beams[ii]->PrintSelf();
|
||||
}
|
||||
|
||||
bool RTPlan::fillRTPlan( char *filertionplan){
|
||||
|
||||
cout<<"reading filename: "<<filertionplan<<endl;
|
||||
|
||||
|
||||
gdcm::Reader R;
|
||||
R.SetFileName(filertionplan);
|
||||
if(!R.Read())
|
||||
{ cout<<"ERROR: cannot read filertionplan."<<endl;
|
||||
}
|
||||
const gdcm::File &file = R.GetFile();
|
||||
const gdcm::DataSet &ds = file.GetDataSet();
|
||||
|
||||
|
||||
//GENERAL PATIENT AND STUDY DATE
|
||||
//PATIENT NAME
|
||||
strcpy( PatientName,gGetStringValueFromTag( gdcm::Tag(0x0010,0x0010), ds));
|
||||
|
||||
// // // PATIENT ID For ex: DICOM (0010,0020) = 1933197
|
||||
strcpy(PatientID , gGetStringValueFromTag( gdcm::Tag(0x0010,0x0020), ds));
|
||||
// //
|
||||
// // // PATIENT AGE For ex: DICOM (0010,1010) = 031Y
|
||||
strcpy(PatientAge , gGetStringValueFromTag( gdcm::Tag(0x0010,0x1010), ds)) ;
|
||||
// //
|
||||
// // // PATIENT SEX For ex: DICOM (0010,0040) = M
|
||||
strcpy(PatientSex, gGetStringValueFromTag( gdcm::Tag(0x0010,0x0040), ds) );
|
||||
// //
|
||||
// // // PATIENT BIRTHDATE For ex: DICOM (0010,0030) = 19680427
|
||||
strcpy(PatientBirthDate, gGetStringValueFromTag( gdcm::Tag(0x0010,0x0030), ds) );
|
||||
// //
|
||||
// // // SERIES NUMBER For ex: DICOM (0020,0011) = 902
|
||||
strcpy(SeriesNumber, gGetStringValueFromTag( gdcm::Tag(0x0020,0x0011), ds) );
|
||||
// //
|
||||
// // // SERIES DESCRIPTION For ex: DICOM (0008,103e) = SCOUT
|
||||
strcpy(SeriesDescription , gGetStringValueFromTag( gdcm::Tag(0x0008,0x103e), ds) );
|
||||
// //
|
||||
// // // STUDY ID For ex: DICOM (0020,0010) = 37481
|
||||
strcpy(StudyID, gGetStringValueFromTag( gdcm::Tag(0x0020,0x0010), ds) );
|
||||
// //
|
||||
// // // STUDY DESCRIPTION For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL
|
||||
strcpy(StudyDescription, gGetStringValueFromTag( gdcm::Tag(0x0008,0x1030), ds) );
|
||||
// //
|
||||
// // // STUDY MODALITY For ex: DICOM (0008,0060)= CT
|
||||
strcpy(Modality, gGetStringValueFromTag( gdcm::Tag(0x0008,0x0060), ds) );
|
||||
|
||||
|
||||
//TREATMENT GEOMETRY
|
||||
//IONI 0x300a,0x00b0
|
||||
// radiation 0x300ax00c6
|
||||
//FIND TAG BEAMSequence
|
||||
//v04Build27 HANDLE PROTON vs CARBONION
|
||||
bool IsCarbon=false;
|
||||
//v04Build27 CHECK EXISTANCE SETUP SEQUENCE (PRESENT IN PROTN ABSENT IN IONS)
|
||||
if(!ds.FindDataElement(gdcm::Tag(0x300a,0x03a2)))
|
||||
IsCarbon=true;
|
||||
|
||||
|
||||
|
||||
//QUI HFP vs HFS
|
||||
//v04 Build29: LOOK FOR SETUP SEQUENCE TO SEARHC FOR PATINET ORIENTATION
|
||||
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(PatientOrientation, gGetStringValueFromTag(gdcm::Tag(0x0018, 0x5100),gPatSetupNest));
|
||||
|
||||
const gdcm::DataElement &gBeamSequence=ds.GetDataElement(gdcm::Tag(0x300a,(IsCarbon==false ? 0x03a2 : 0x00b0)));
|
||||
// (THESE ARE THE BEAMS)
|
||||
gdcm::SmartPointer<gdcm::SequenceOfItems> sqi = gBeamSequence.GetValueAsSQ();
|
||||
if(!sqi || !sqi->GetNumberOfItems())
|
||||
{
|
||||
cout<<"usteria" <<endl;//throw(gException("CRITICAL: Beam sequence not found in RTION Plan file"));
|
||||
}
|
||||
NumberOfBeams=sqi->GetNumberOfItems();
|
||||
//ALLOCATE BEAM STRUCTURES
|
||||
Beams=new IonBeamProperties* [NumberOfBeams];
|
||||
memset(Beams,NULL,NumberOfBeams*sizeof(IonBeamProperties *));
|
||||
|
||||
|
||||
//ITERATES ON BEAM NUMBER
|
||||
for(int i=0;i<NumberOfBeams;i++)
|
||||
{ const gdcm::Item & item = sqi->GetItem(i+1); //ITEM START FROM 1
|
||||
const gdcm::DataSet& gBeamNestedds = item.GetNestedDataSet(); //THIS IS BEAM DATASET
|
||||
|
||||
//ALLOCATE BEAM CLASS
|
||||
Beams[i]=new IonBeamProperties;
|
||||
//READ BEAM DATA
|
||||
Beams[i]->BeamNumber = (atoi(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x00c0),gBeamNestedds))); //BEAM NUMBER
|
||||
strcpy (Beams[i]->BeamName,(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x00c2),gBeamNestedds))); //BEAM NAME
|
||||
|
||||
if(IsCarbon==false)
|
||||
strcpy (Beams[i]->SupportType,gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0350),gBeamNestedds));//PATIENT SUPPORT TYPE IMPLEMENT TRICK FOR THE CHAIR
|
||||
else strcpy(Beams[i]->SupportType,"TABLE");
|
||||
|
||||
strcpy(Beams[i]->SupportId,gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0352),gBeamNestedds));//PATIENT SUPPORT TYPE IMPLEMENT TRICK FOR THE CHAIR
|
||||
|
||||
//gBeams[i]->gSetSupportType("CHAIR");
|
||||
|
||||
//READ GEOMETRY
|
||||
//READ SEQUENCE OF CONTROL POINTS
|
||||
//v04Build27 DO DIFFERENTLY IF PROTONS OR CARBONS
|
||||
const gdcm::DataElement &gCPSequence=gBeamNestedds.GetDataElement(gdcm::Tag(0x300a,IsCarbon==false ? 0x03a8 : 0x0111));
|
||||
//FIND ITEM SEQUENCE (THESE ARE THE CONTROL POINTS)
|
||||
gdcm::SmartPointer<gdcm::SequenceOfItems> sqicp = gCPSequence.GetValueAsSQ();
|
||||
|
||||
//READ DATA FROM ITEM 1
|
||||
const gdcm::DataSet& gCPNestedds = sqicp->GetItem(1).GetNestedDataSet();
|
||||
|
||||
//GANTRY ANGLE (NEEDED FOR CHAIR ?)
|
||||
Beams[i]->GantryAngle=atoi(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x011e),gCPNestedds));
|
||||
|
||||
//ISOCENTER POSITION (THIS IS BEAM POSITION NOT PATIENT ALIGNMENT (VOLUME CENTER) POSITION)
|
||||
double iso[3];
|
||||
char str[MAXSTRINGLENGHT];
|
||||
strcpy(str,gGetStringValueFromTag(gdcm::Tag(0x300a, 0x012c),gCPNestedds));
|
||||
|
||||
Beams[i]->IsocenterPosition[0]=atof(strtok(str,"\\"));
|
||||
Beams[i]->IsocenterPosition[1]=atof(strtok(NULL,"\\"));
|
||||
Beams[i]->IsocenterPosition[2]=atof(strtok(NULL,"\\"));
|
||||
// Beams[i]->IsocenterPosition[](iso[0],iso[1],iso[2]);
|
||||
|
||||
//SUPPORT ANGLE (YAW ANGLE OF SUPPORT WITH RESPECT TO FIXED REFERENCE SYSTEM) AROUND Z AXIS (VERTICAL)
|
||||
//POSITIVE COUNTER-CLOCKWISE WHEN VIEWED FROM TOP OF Z-Axis
|
||||
Beams[i]->TableYawAngle=atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0122),gCPNestedds));
|
||||
/*if(i==1)
|
||||
gBeams[i]->gSetTableYawAngle(0);
|
||||
*/
|
||||
//TABLE TOP PITCH (ROTATION AROUND X AXIS, i.e. LATERAL AXIS OF TABLE AND BEAM DIRECTION IN FIXED REF SYS)
|
||||
////v04Build27 IF PROTONS READ IT FROM PLAN; IF CARBONS SET DEFAULT VALUE (0.0) AND FORGET CHAIR
|
||||
if(IsCarbon==false)
|
||||
{ gdcm::Attribute <0x300a, 0x0140> pa;
|
||||
pa.SetFromDataElement(gCPNestedds.GetDataElement( pa.GetTag()));
|
||||
Beams[i]->TablePitchAngle =pa.GetValue();
|
||||
}
|
||||
else
|
||||
(Beams[i]->TablePitchAngle)=(0.0);
|
||||
|
||||
//v04 Build23 SET SUPPORT TYPE CORRECTLY IF PITCH IS 90 (IT IS CHAIR); DO IT FOR ALL BEAMS
|
||||
// if(i==0)
|
||||
// { if(Beams[i]->TablePitchAngle()>45)
|
||||
// strcpy (Beams[i]->SupportType,("CHAIR"));
|
||||
// }
|
||||
// else if (i>0)
|
||||
// { if(Beams[0]->SupportChair()==true)
|
||||
// Beams[i]->gSetSupportType("CHAIR");
|
||||
// }
|
||||
|
||||
//TABLE TOP ROLL (ROTATION AROUND Y AXIS, i.e. LONGITUDINAL AXIS OF TABLE)
|
||||
//v04Build27 IF PROTONS READ IT FROM PLAN; IF CARBONS SET DEFAULT VALUE (0.0)
|
||||
if(IsCarbon==false)
|
||||
{ gdcm::Attribute <0x300a, 0x0144> ra;
|
||||
ra.SetFromDataElement(gCPNestedds.GetDataElement(ra.GetTag()));
|
||||
Beams[i]->TableRollAngle =(ra.GetValue());
|
||||
}
|
||||
else
|
||||
(Beams[i]->TableRollAngle)=(0.0);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//WHAT ABOUT TABLE TOP VERTICAL POSITION, LOGITUDINAL AND LATERAL POSITION ? USEFUL SOMEHOW ?
|
||||
// THEY ARE READ AND USED TO REALIZE VOLUME CENTER ALIGNMENT IN ROOM ISOCENTER
|
||||
//FIND PATIENT SETUP SEQUENCE (IT IS UNIQUE FOR ALL BEAMS BUT I DO IT BEAM BY BEAM)
|
||||
//v04Build27 DO NOT LOOK FOR PATIENT SETUPSEQUENCE
|
||||
/* if(!ds.FindDataElement(gdcm::Tag(0x300a,0x0180)))
|
||||
throw(gException("CRITICAL: PATIENT SETUP SEQUENCE NOT FOUND IN RT ION PLAN"));
|
||||
const gdcm::DataElement &gPatientSetupSequence=ds.GetDataElement(gdcm::Tag(0x300a,0x0180));
|
||||
gdcm::SmartPointer<gdcm::SequenceOfItems> sqpt = gPatientSetupSequence.GetValueAsSQ();
|
||||
int psuseq=sqpt->GetNumberOfItems(); //CHECK NUMBER OF SETUPSEQUENCE VS BEAM NUMBER
|
||||
|
||||
//READ DATA FROM ITEM 1 OR BEAM IS MORE PATIENT SETUP SEQUENCE ARE FOUND (ATTENTION !!!!)
|
||||
//v03 Build30: READ TABLE POSITIONS FROM SETUPSEQUENCE
|
||||
const gdcm::DataSet& gPSNestedds = sqpt->GetItem((i+1)<=psuseq ? (i+1) : 1).GetNestedDataSet(); //IF PSTIENT SETUP SEQUENCE < THAN BEAMS USE FIRST
|
||||
*/
|
||||
//v04Build27 READ BEAMS ABSOLUTE GEOMETRY NOT FROM SETUP SEQUENCE BUT FROM CONTROL POINT SEQUENCE (NEW VERSION OIS FOR CARBONS)
|
||||
|
||||
/*float tablelat=atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x01d6),gPSNestedds));
|
||||
float tablelong=atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x01d4),gPSNestedds));
|
||||
float tablevert=atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x01d2),gPSNestedds));*/
|
||||
|
||||
float deltatablelat=atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x012a),gCPNestedds));
|
||||
float deltatablelong=atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0129),gCPNestedds));
|
||||
float deltatablevert=atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0128),gCPNestedds));
|
||||
|
||||
//v03 (Build 30) NOW ADD TO TREATMENT BEMA EVENTUAL RELATIVE SHIFTS BETWEEN SETUP SEQUENCE AND STORE IN BEAM STRUCTURE ONLY TO TREATMETN BEAMS
|
||||
// if(i==0) //THIS IS SETUP BEAM DO NOTHING
|
||||
//v04Build26 TREAT ALL BEAMS THE SAME WAY (SET-UP+BEAMS)(NEW VERSION OF OIS)
|
||||
//v04Build27 USE PPS GEOMETRY READ FROM POINT SEQUENCE
|
||||
{ Beams[i]->TableLatDispl=(deltatablelat);
|
||||
Beams[i]->TableLongDispl=(deltatablelong);
|
||||
Beams[i]->TableVertDispl=(deltatablevert);
|
||||
}
|
||||
/* else
|
||||
{ gBeams[i]->gSetTableLatDispl(tablelat);
|
||||
gBeams[i]->gSetTableLongDispl(tablelong);
|
||||
gBeams[i]->gSetTableVertDispl(tablevert);
|
||||
}*/
|
||||
//v04Build26 DO NOT ADD DELTASHIFTS (NEW VERSION OF OIS)
|
||||
//v04Build1: CHECK FOR VIRTUAL ISO
|
||||
|
||||
|
||||
//ADD DELTASHIFTS TO TABLE DISPLACEMENTS
|
||||
//v04Build26 DO NOT ADD DELTASHIFTS (NEW VERSION OF OIS)
|
||||
/*gBeams[i]->gSetTableLatDispl(tablelat+atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x012a),gCPNestedds)));
|
||||
gBeams[i]->gSetTableLongDispl(tablelong+atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0129),gCPNestedds)));
|
||||
gBeams[i]->gSetTableVertDispl(tablevert+atof(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0128),gCPNestedds)));
|
||||
|
||||
//UPDATE ISOCENTER POSITION ON TREATMENT BEAM USING CT REFERENCE (LONG IS Z COORDINATE; Y IS VERTICAL; Z I)
|
||||
//v04Build26 DO NOT ADD DELTASHIFTS (NEW VERSION OF OIS)
|
||||
|
||||
gBeams[i]->gSetIsocenterPosition(iso[0]-deltatablelat,iso[1]-deltatablevert,iso[2]-deltatablelong); //SIGNS AND COORDINATE TO BE CHECKED (OK for LONG)
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
//v04Build28 CORRECT ISO POSITION IN CASE OF VIRTUAL ISO
|
||||
/* if(i<0) //DO THIS ONLY FOR TREATMENT BEAMS
|
||||
gBeams[i]->gSetIsocenterPosition(iso[0]-(gBeams[i]->gGetTableLatDispl()-gBeams[0]->gGetTableLatDispl()),iso[1]-(gBeams[i]->gGetTableVertDispl()-gBeams[0]->gGetTableVertDispl()),iso[2]-(gBeams[i]->gGetTableLongDispl()-gBeams[0]->gGetTableLongDispl())); //SIGNS AND COORDINATE TO BE CHECKED (OK for LONG)
|
||||
*/
|
||||
//UPDATE AT FIRST CNAO PATIENT SET TABLE POSITION FROM PLAN AT THE ISOCENTER POSITION FOR EVERY BEAM
|
||||
/* gBeams[i]->gSetTableLatDispl(gBeams[i]->gGetIsocenterPosition()[0]);
|
||||
gBeams[i]->gSetTableLongDispl(gBeams[i]->gGetIsocenterPosition()[1]);gui
|
||||
gBeams[i]->gSetTableVertDispl(gBeams[i]->gGetIsocenterPosition()[2]);
|
||||
*/
|
||||
// FILL gPPS CLASS WITH CURRENT PPS CONFIGURATION UPDATING CONVENTIONS FROM PLAN TO PPS (-90 FOR CONVENTION CT-PPS)
|
||||
// Beams[i]->gGetCurrentPPS()->gSetPPSXPlan(gBeams[i]->gGetTableLatDispl());
|
||||
// Beams[i]->gGetCurrentPPS()->gSetPPSYPlan(gBeams[i]->gGetTableLongDispl());
|
||||
// Beams[i]->gGetCurrentPPS()->gSetPPSYOrig(gBeams[i]->gGetTableLongDispl()); //SAVE ALSO AN ORIGINAL COPY FROM PLAN OF LONGITUFINAL POSITION (FOR INDEXING DIALOG)
|
||||
// Beams[i]->gGetCurrentPPS()->gSetPPSZPlan(gBeams[i]->gGetTableVertDispl());
|
||||
//
|
||||
|
||||
|
||||
//v03 Build35: ADD TO TREATMENT BEAMS YAW THE YAW VALUE OF SETUP BEAM TO RECOVER ABSOLUTE VALUES FROM RELATIVE ONES AS SENT BY OIS
|
||||
if(i>0) // THIS IS TREATMENT BEAM
|
||||
{ //v04Build03 SET PROPER DELTA ANGLES FOR BEAM ROTATION (IF DELTA IS NEGATIVE SET IT NEGATIVE)
|
||||
double yaw=Beams[i]->TableYawAngle;
|
||||
if(yaw>180)
|
||||
yaw=yaw-360;
|
||||
//V04Build26 NEW VERSION OF MOSAIQ OIS DO NOT USE RELATIVE ANGLES
|
||||
//yaw=yaw+gBeams[0]->gGetTableYawAngle();
|
||||
Beams[i]->TableYawAngle=(yaw);
|
||||
|
||||
double pitch=Beams[i]->TablePitchAngle;
|
||||
if(pitch>180)
|
||||
pitch=pitch-360;
|
||||
//V04Build26 NEW VERSION OF MOSAIQ OIS DO NOT USE RELATIVE ANGLES
|
||||
//pitch=pitch+gBeams[0]->gGetTablePitchAngle();
|
||||
//v04Build23 SET ALL PITCH AT 90 (NOT STABLE) IT IS FOR THE CHAIR
|
||||
if(pitch>150) pitch=90;
|
||||
Beams[i]->TablePitchAngle=(pitch);
|
||||
|
||||
|
||||
double roll=Beams[i]->TableRollAngle;
|
||||
if(roll>180)
|
||||
roll=roll-360;
|
||||
//V04Build26 NEW VERSION OF MOSAIQ OIS DO NOT USE RELATIVE ANGLES
|
||||
//roll=roll+gBeams[0]->gGetTableRollAngle();
|
||||
Beams[i]->TableRollAngle=(roll);
|
||||
}
|
||||
|
||||
//HERE 90 DEGREES IS SUMMED IN ORDER TO SOLVE TEH AMBIGUITY BETWEEN TPS REFERENCE AND ROOM/ODEVIS REFERENCE
|
||||
//0 DEGREE YAW IN TPS BECOMES +90 YAW IN ROOM/PPS MEANING BEAM IS FROM LATERAL
|
||||
//THIS WE DO IT JUST FOR THE USER INTERFACE DISPLAYING DEGREES OF YAW ROTATION EXPECTED OR TO BE INSERTED IN THE PPS
|
||||
//v04Build24 ADJUST PPS YAW ANGLE FOR PPS AND CHAIR
|
||||
// double yaw=gBeams[0]->gIsSupportChair()==false ? gBeams[i]->gGetTableYawAngle()+90.0 : gBeams[i]->gGetTableYawAngle()-90.0;
|
||||
// //NOW SET +- 180 YAW ROTATION CONVENTION
|
||||
// if(yaw>180)
|
||||
// yaw=yaw-360;
|
||||
// gBeams[i]->gGetCurrentPPS()->gSetPPSRotateDegreePlan(yaw); //CONVERSION FROM CT BASE PLAN TO PPS (ANGLE RANGES -180 +180)
|
||||
//
|
||||
// //v04Build23 ATTENZIONE !
|
||||
// if(gBeams[0]->gIsSupportChair()==false) gBeams[i]->gGetCurrentPPS()->gSetPPSPitchDegreePlan(gBeams[i]->gGetTablePitchAngle());
|
||||
// else gBeams[i]->gGetCurrentPPS()->gSetPPSPitchDegreePlan(gBeams[i]->gGetTablePitchAngle()-90); //NEED TO SUBTRACT 90 DEGRESS FOR PPS CONFIGURATION : THERE IS THE CHAIR
|
||||
//
|
||||
// gBeams[i]->gGetCurrentPPS()->gSetPPSRollDegreePlan(gBeams[i]->gGetTableRollAngle());
|
||||
//
|
||||
//
|
||||
//
|
||||
// //SET CURRENT PPS CONFIGURATION WITH PLAN CONFIGURATION (THERE I TAKE CARE OF THE CHAIR)
|
||||
// gBeams[i]->gGetCurrentPPS()->gSetPlanConfig();
|
||||
|
||||
/* //UPDATE TABLE DISPLACEMENT ACCORDING TO SIEMENS TPS USING THE ISOCENTER CO-ORDINATESIF DEFINE W.R.T. INDEXING POINT
|
||||
//MIGHT NEED TO SUBTRACT COORDINATES OF STRUCTURE VOLUMECENTER IF RELATIVE REFERENCE SYSTEM IS NOT DEFINED IN TPS
|
||||
gBeams[i]->gSetTableLatDispl(gBeams[i]->gGetIsocenterPosition()[0]);
|
||||
gBeams[i]->gSetTableLongDispl(gBeams[i]->gGetIsocenterPosition()[1]);
|
||||
gBeams[i]->gSetTableVertDispl(gBeams[i]->gGetIsocenterPosition()[2]);*/
|
||||
// gBeams[i]->gSetIsocenterPosition(iso[0]- gBeams[i]->gGetCurrentPPS()->getPPSXPlan(),iso[1]- gBeams[i]->gGetCurrentPPS()->getPPSYPlan(),iso[2]- gBeams[i]->gGetCurrentPPS()->getPPSZPlan());
|
||||
|
||||
|
||||
}
|
||||
return true;
|
||||
};
|
||||
Executable
+95
@@ -0,0 +1,95 @@
|
||||
|
||||
//FUNCTION DECLARATION NECESSARY FOR COPY/PASTE FROM vtkGDCMImageReader
|
||||
// const char *gGetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds);
|
||||
|
||||
#ifndef DICOMUTILITIES
|
||||
#define DICOMUTILITIES
|
||||
//gdcm
|
||||
#include <gdcmReader.h>
|
||||
#include <gdcmAttribute.h>
|
||||
#include <gdcmDirectory.h>
|
||||
#include <gdcmScanner.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define MAXSTRINGLENGHT 255
|
||||
#define BADVALUE -9999
|
||||
|
||||
enum{
|
||||
RTPLAN,
|
||||
RTSTRUCT,
|
||||
IMAGE,
|
||||
NODCMFILE
|
||||
};
|
||||
|
||||
const char *gGetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds);
|
||||
const char * gCheckDICOMModality(const char *filename);
|
||||
int gCheckDICOMModalityToInt(const char *filename);
|
||||
|
||||
|
||||
class IonBeamProperties{
|
||||
public:
|
||||
IonBeamProperties();
|
||||
|
||||
~IonBeamProperties();
|
||||
|
||||
int BeamNumber;
|
||||
char* BeamName;
|
||||
char* SupportType;
|
||||
char* SupportId;
|
||||
int GantryAngle;
|
||||
double* IsocenterPosition;
|
||||
float TableYawAngle;
|
||||
float TablePitchAngle;
|
||||
float TableRollAngle;
|
||||
float TableLatDispl;
|
||||
float TableLongDispl;
|
||||
float TableVertDispl;
|
||||
|
||||
void PrintSelf();
|
||||
};
|
||||
|
||||
/*-----*/
|
||||
//CLASS gIonBEAMProperties
|
||||
class RTPlan
|
||||
{
|
||||
public:
|
||||
char* PatientName;
|
||||
char* PatientID;
|
||||
char* PatientSex;
|
||||
char* PatientAge;
|
||||
char* PatientBirthDate;
|
||||
char* SeriesNumber;
|
||||
char* SeriesDescription;
|
||||
char* StudyID;
|
||||
char* StudyDescription;
|
||||
char* Modality;
|
||||
|
||||
double* IsocenterPosition;
|
||||
double* VolumeCenter;
|
||||
int BeamNumber;
|
||||
char* BeamName;
|
||||
double TableRollAngle;
|
||||
double TableYawAngle;
|
||||
double TablePitchAngle;
|
||||
double TableLatDispl;
|
||||
double TableVertDispl;
|
||||
double TableLongDispl;
|
||||
char* SupportType;
|
||||
char* SupportId;
|
||||
char* PatientOrientation;
|
||||
int NumberOfBeams;
|
||||
|
||||
IonBeamProperties** Beams;
|
||||
|
||||
|
||||
~RTPlan();
|
||||
|
||||
RTPlan();
|
||||
void PrintSelf();
|
||||
|
||||
bool fillRTPlan( char *filertionplan);
|
||||
};
|
||||
|
||||
#endif
|
||||
Executable
+434
@@ -0,0 +1,434 @@
|
||||
#include "gLoadPatient.h"
|
||||
|
||||
|
||||
/*_________________________________________________________-
|
||||
|
||||
Patient loader for gLocalize.
|
||||
no wrkDir behaviour. just load data
|
||||
____________________________________________________________*/
|
||||
|
||||
|
||||
gLoadPatient::gLoadPatient(){
|
||||
patientInfos = new gPatientRTGeneralInfos;
|
||||
readRT=0;
|
||||
m_rtIsocenter=0;
|
||||
initialized=false;
|
||||
virtualIso=false;
|
||||
//cout<< "gLoadPatient::gLoadPatient" <<endl;
|
||||
}
|
||||
|
||||
|
||||
void gLoadPatient::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){
|
||||
memcpy(m_rtIsocenter, readRT->Beams[0]->IsocenterPosition, 3* sizeof(double) );
|
||||
if (strncmp (readRT->PatientOrientation,"HFS",3) == 0 )
|
||||
m_patientOrientation = SUPINE;
|
||||
else if (strncmp (readRT->PatientOrientation,"HFP",3) == 0 )
|
||||
m_patientOrientation = PRONE;
|
||||
else m_patientOrientation = NOTDEFINED;
|
||||
|
||||
emit 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[0]->IsocenterPosition[0] <<endl;
|
||||
//cout<< "iso2: "<<readRT->Beams[2]->IsocenterPosition[0]<<endl;
|
||||
//cout<< "iso0: "<<readRT->Beams[0]->IsocenterPosition[1] <<endl;
|
||||
//cout<< "iso2: "<<readRT->Beams[2]->IsocenterPosition[1]<<endl;
|
||||
//cout<< "iso0: "<<readRT->Beams[0]->IsocenterPosition[2] <<endl;
|
||||
//cout<< "iso2: "<<readRT->Beams[2]->IsocenterPosition[2]<<endl;
|
||||
|
||||
/*check for virtual iso, adapted from GB, gOTS v04Build34*/
|
||||
if(readRT->NumberOfBeams > 2 &&
|
||||
(readRT->Beams[0]->IsocenterPosition[0] != readRT->Beams[2]->IsocenterPosition[0] ||
|
||||
readRT->Beams[0]->IsocenterPosition[1] != readRT->Beams[2]->IsocenterPosition[1] ||
|
||||
readRT->Beams[0]->IsocenterPosition[2] != readRT->Beams[2]->IsocenterPosition[2])
|
||||
)
|
||||
virtualIso=true;
|
||||
else
|
||||
virtualIso=false;
|
||||
//cout << "virtual Iso: "<<virtualIso << endl;
|
||||
emit virtualIsoTested(virtualIso);
|
||||
|
||||
|
||||
} else {
|
||||
cout<<"Number of Beams = 0 in RTIonPlan, FAIL" <<endl;
|
||||
delete m_rtIsocenter;
|
||||
delete readRT;
|
||||
readRT = 0;
|
||||
m_rtIsocenter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cout<< "gLoadPatient::load2VTK _ 2 " <<endl;
|
||||
|
||||
|
||||
|
||||
this->loadDICOM(patientInfos->CTfiles);
|
||||
this->connectToVTK();
|
||||
this->changeRef(GOTSREF);
|
||||
//trueOffset_rot_prev=trueOffset_rot;
|
||||
|
||||
|
||||
//this->load2VTK(patientInfos);
|
||||
} else {
|
||||
//DO NOTHING. THE folderisempty signal was already emitted.
|
||||
}
|
||||
cout<< " gLoadPatient::load _ END" <<endl;
|
||||
}
|
||||
|
||||
void gLoadPatient::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){
|
||||
emit 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 gLoadPatient::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 gLoadPatient::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 gLoadPatient::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;
|
||||
emit loadEnd(vol3D);
|
||||
}
|
||||
|
||||
|
||||
void gLoadPatient::parse(QString p_loadDir){
|
||||
loadDir=p_loadDir;
|
||||
|
||||
std::cout<< " ______________________________ " <<endl;
|
||||
std::cout<< " __ gLoadPatient::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;
|
||||
emit statusInfo("CT files sorting succeeded");
|
||||
} else {
|
||||
|
||||
switch(result){
|
||||
|
||||
case PARSER_FOLDER_EMPTY:
|
||||
cout<< "Empty folder. Parse failed" <<endl;
|
||||
emit folderIsEmpty();
|
||||
break;
|
||||
|
||||
case PARSER_FOLDER_NOTEXISTING:
|
||||
emit statusInfo("NonExisting folder. Parse failed");
|
||||
break;
|
||||
|
||||
case PARSER_RTPLAN_NOTUNIQUE:
|
||||
emit statusInfo("RtIonPlan not unique. Parse failed");
|
||||
break;
|
||||
|
||||
case PARSER_RTSTRUCT_NOTUNIQUE:
|
||||
emit statusInfo("RtStructure not unique. Parse failed");
|
||||
break;
|
||||
|
||||
case PARSER_CT_FAILED_SORTING:
|
||||
emit statusInfo("Failed to sort CT files");
|
||||
emit folderIsEmpty();
|
||||
break;
|
||||
|
||||
case PARSER_CT_FILES_MISSING:
|
||||
emit statusInfo("CT file Missing");
|
||||
emit folderIsEmpty();
|
||||
break;
|
||||
|
||||
case PARSER_RTPLAN_MISSING:
|
||||
emit statusInfo("RtIonPlan missing");
|
||||
break;
|
||||
|
||||
case PARSER_RTSTRUCT_MISSING:
|
||||
emit statusInfo("rtStructure missing");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
emit parse_result(result,patientInfos);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Executable
+142
@@ -0,0 +1,142 @@
|
||||
#ifndef _GPATIENTLOADER_H_
|
||||
#define _GPATIENTLOADER_H_
|
||||
|
||||
#include <qobject.h>
|
||||
#include <qstring.h>
|
||||
#include "gPatientRTGeneralInfos.h"
|
||||
//#include "wrkDirParser.h"
|
||||
#include <qmainwindow.h>
|
||||
#include <qdir.h>
|
||||
#include <qthread.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 gLoadPatient : public QObject{
|
||||
Q_OBJECT
|
||||
public:
|
||||
gLoadPatient();
|
||||
|
||||
public slots:
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
Executable
+380
@@ -0,0 +1,380 @@
|
||||
#include "gLocalize.h"
|
||||
|
||||
#include <qeventloop.h>
|
||||
#include <qapplication.h>
|
||||
|
||||
gLocalize::gLocalize(){
|
||||
|
||||
abortSignal=false;
|
||||
}
|
||||
|
||||
|
||||
void gLocalize::localize(vtkImageData* vol,
|
||||
int march_tresh,
|
||||
double thrDown_D,
|
||||
double thrUp_D,
|
||||
double thr_HAUSD,
|
||||
double thr_S,
|
||||
QList <bool> selectedFilters){
|
||||
|
||||
abortSignal=false;
|
||||
int i=0;
|
||||
int progress=0;
|
||||
//variabili
|
||||
vtkSmartPointer<vtkImageData> fixOutput = vtkSmartPointer<vtkImageData>::New();
|
||||
|
||||
vtkSmartPointer<vtkPolyDataConnectivityFilter> filter = vtkSmartPointer<vtkPolyDataConnectivityFilter>::New();
|
||||
vtkSmartPointer<vtkMarchingCubes> marchingcubes = vtkSmartPointer<vtkMarchingCubes>::New() ;
|
||||
vtkSmartPointer<vtkWindowedSincPolyDataFilter> smoother = vtkSmartPointer<vtkWindowedSincPolyDataFilter>::New();
|
||||
vtkSmartPointer<vtkImageData> fixed = vtkSmartPointer<vtkImageData> :: New();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
marchingcubes->SetInput(vol);
|
||||
|
||||
|
||||
//The algorithm starts with a marching cube at a given intensity level threshold
|
||||
marchingcubes->SetValue(0,march_tresh); // Surface #0, iso-value=1
|
||||
marchingcubes->SetComputeNormals(0);
|
||||
if (marchingcubes.GetPointer()->GetNumberOfInputConnections(0)==0)
|
||||
{return;
|
||||
//EMIT FAIL QUALCOSA
|
||||
//return -1;
|
||||
}
|
||||
marchingcubes->Update();
|
||||
std::cout<< "inizio run" <<std::endl;
|
||||
QString item= item.number(marchingcubes->GetNumberOfContours());
|
||||
if(item.toInt()<=0){
|
||||
throw("CRITICAL: No surfaces found with given treshold");
|
||||
QList <surf> dummylist;
|
||||
// emit sendrenderMarkerList (dummylist);
|
||||
}
|
||||
|
||||
// Smoothing filter and normals calculation on marching cubes output data
|
||||
smoother->SetInput(marchingcubes->GetOutput());
|
||||
smoother->SetNumberOfIterations(20);
|
||||
smoother->NormalizeCoordinatesOn();
|
||||
smoother->SetPassBand(0.01);
|
||||
smoother->BoundarySmoothingOn();
|
||||
smoother->Update();
|
||||
|
||||
|
||||
vtkSmartPointer<vtkPolyDataNormals> normals=vtkSmartPointer<vtkPolyDataNormals>::New();
|
||||
normals->SetInput(smoother->GetOutput());
|
||||
vtkSmartPointer<vtkActor> normalact=vtkSmartPointer<vtkActor>::New();
|
||||
vtkSmartPointer<vtkPolyDataMapper> normalmap=vtkSmartPointer<vtkPolyDataMapper>::New();
|
||||
normalmap->SetInput( normals->GetOutput());
|
||||
normalact->SetMapper(normalmap);
|
||||
|
||||
// Start of marker recognitioning procedure
|
||||
|
||||
filter->AddInput(normals->GetOutput());
|
||||
filter->SetExtractionModeToAllRegions();
|
||||
filter->SetColorRegions(0);
|
||||
filter->Update();
|
||||
QString regionnumber = regionnumber.number(filter->GetNumberOfExtractedRegions());
|
||||
filter->SetExtractionModeToSpecifiedRegions();
|
||||
filter->Update();
|
||||
|
||||
//Some data allocation:
|
||||
//surflist: list of surfaces where the recognized marker are added
|
||||
//tempsurf: one surface used as temporary variable during geometrical filtering
|
||||
QList <surf> surflist;
|
||||
surflist.clear();
|
||||
surf tempsurf;
|
||||
|
||||
|
||||
//Double check on number of surface in ConnectivityFilter output
|
||||
if(regionnumber.toInt()==0){
|
||||
std::cout<<"ok"<<std::endl;
|
||||
throw("CRITICAL: No surfaces in ConnectivityFilter output");
|
||||
QList <surf> dummylist;
|
||||
|
||||
// emit sendrenderMarkerList (dummylist);
|
||||
};
|
||||
if(regionnumber.toInt()>3000){
|
||||
cout<<"ho trovato troppe superfici: "<<regionnumber.toInt()<<endl;
|
||||
};
|
||||
int ok;
|
||||
cout<<regionnumber.toDouble()<<endl;
|
||||
|
||||
|
||||
//progress bar initialization
|
||||
//emit recognitionProgress (regionnumber.toInt(),0);
|
||||
|
||||
int OKd=0;
|
||||
int OKh=0;
|
||||
int OKs=0;
|
||||
|
||||
for(double idouble=0;idouble<regionnumber.toDouble() ;idouble++)
|
||||
{
|
||||
|
||||
QApplication::processEvents();
|
||||
progress++;
|
||||
|
||||
emit localizationProgress( (double)progress/(double)regionnumber.toDouble() * 100 );
|
||||
|
||||
if(abortSignal==true){
|
||||
abortSignal=false;
|
||||
emit localizationAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
//flag need for good filtering driving
|
||||
ok=1;
|
||||
|
||||
//Add one surface at once and check for geometrical constraints
|
||||
filter->AddSpecifiedRegion(idouble);
|
||||
filter->Update();
|
||||
|
||||
// Filter on bounding box diagonal lenght
|
||||
if(selectedFilters.at(0))
|
||||
if(ok==1) {
|
||||
tempsurf.lenght=filter->GetOutput()->GetLength();
|
||||
if(tempsurf.lenght<thrDown_D || tempsurf.lenght>thrUp_D )
|
||||
ok=0;
|
||||
}
|
||||
|
||||
//Hausdorf reads from tempsurf the bounding box center and use it as reference center
|
||||
if(selectedFilters.at(1))
|
||||
if(ok==1) {
|
||||
OKd++;
|
||||
filter->GetOutput()->GetCenter(tempsurf.center);
|
||||
tempsurf.hausdorff=hausdorff(filter,tempsurf);
|
||||
if(tempsurf.hausdorff> (thr_HAUSD) )
|
||||
ok=0;
|
||||
|
||||
}
|
||||
|
||||
// Filter based on sides difference
|
||||
if(selectedFilters.at(2))
|
||||
if(ok==1) {
|
||||
OKh++;
|
||||
filter->GetOutput()->GetBounds(tempsurf.bounds);
|
||||
tempsurf.confronto_lati=lati(tempsurf.bounds);
|
||||
if(tempsurf.confronto_lati>thr_S)
|
||||
ok=0;
|
||||
}
|
||||
|
||||
//if all filters are verified, add a surface index and append it to the surflist
|
||||
if(ok==1) {
|
||||
OKs++;
|
||||
tempsurf.sorting=idouble; //indexing
|
||||
surflist.append(tempsurf);
|
||||
}
|
||||
|
||||
// MANDATORY filter cleaning
|
||||
filter->DeleteSpecifiedRegion(idouble);
|
||||
|
||||
}
|
||||
|
||||
cout<<"Nsurfaces"<<regionnumber.toInt() <<endl;
|
||||
cout<<"OKD "<< OKd<<" OKH "<<OKh<<" OKS "<<OKs<<endl;
|
||||
|
||||
|
||||
// marker center calculation
|
||||
// final_list: surf list returned through emit
|
||||
// tmp_p: surf used as temporary variable
|
||||
QList<surf> final_list;
|
||||
surf tmp_p;
|
||||
|
||||
if(surflist.count()!=0){
|
||||
for(i=0;i<surflist.count();i++){
|
||||
tmp_p=surflist.at(i);
|
||||
filter->AddSpecifiedRegion(surflist.at(i).sorting);
|
||||
filter->Update();
|
||||
|
||||
//Centroid calculation needs mesh vertex
|
||||
vtkSmartPointer<vtkExtractEdges> edge_extractor =vtkSmartPointer<vtkExtractEdges>::New();
|
||||
edge_extractor->RemoveAllInputs();
|
||||
edge_extractor->SetInput(filter->GetOutput());
|
||||
edge_extractor->Update();
|
||||
|
||||
vtkSmartPointer<vtkPolyData> tmp = vtkSmartPointer<vtkPolyData>::New();
|
||||
tmp=edge_extractor->GetOutput();
|
||||
tmp->Update();
|
||||
tmp->BuildCells();
|
||||
tmp->BuildLinks();
|
||||
|
||||
QList <point> punti;
|
||||
point ptemp;
|
||||
|
||||
for (int id=0;id< (int) tmp->GetNumberOfPoints();id++){
|
||||
ptemp.x=tmp->GetPoint(id)[0];
|
||||
ptemp.y=tmp->GetPoint(id)[1];
|
||||
ptemp.z=tmp->GetPoint(id)[2];
|
||||
/*cout<<filter->GetOutput()->GetPoint(id)[0]<<" "<<filter->GetOutput()->GetPoint(id)[1]<<" "<<filter->GetOutput()->GetPoint(id)[2]<<endl;*/
|
||||
punti.append(ptemp);
|
||||
};
|
||||
//Call centroid calculation
|
||||
tmp_p.centroid=centroid(punti);
|
||||
punti.clear();
|
||||
|
||||
// MANDATORY filter cleaning
|
||||
filter->DeleteSpecifiedRegion(surflist.at(i).sorting);
|
||||
|
||||
final_list.append(tmp_p);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
for(int ii=0;ii<final_list.size();ii++)
|
||||
{
|
||||
std::cout<<1000*final_list.at(ii).centroid.x<<
|
||||
" "<<1000*final_list.at(ii).centroid.y<<
|
||||
" "<<1000*final_list.at(ii).centroid.z<<std::endl;
|
||||
}
|
||||
|
||||
emit localizationEnd(final_list);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
///**
|
||||
// * Centroid calculation of a given points cloud
|
||||
// */
|
||||
point gLocalize::centroid(QList< point > punti)
|
||||
{
|
||||
int i;
|
||||
point centroide;
|
||||
centroide.x=0,centroide.y=0,centroide.z=0;
|
||||
for ( i=0;i<punti.size();i++){
|
||||
centroide.x+=punti.at(i).x/1000;
|
||||
centroide.y+=punti.at(i).y/1000;
|
||||
centroide.z+=punti.at(i).z/1000;
|
||||
};
|
||||
|
||||
centroide.x=centroide.x/punti.size();
|
||||
centroide.y=centroide.y/punti.size();
|
||||
centroide.z=centroide.z/punti.size();
|
||||
|
||||
return centroide;
|
||||
}
|
||||
//
|
||||
//
|
||||
///**
|
||||
// * performs bounding box side difference and return the larger one
|
||||
// */
|
||||
double gLocalize::lati(double p[6])
|
||||
{
|
||||
double x=p[1]-p[0];double y=p[3]-p[2];double z=p[5]-p[4];
|
||||
double d1=(x-y); double d2=(x-z); double d3=(y-z);
|
||||
if(d1<0) d1=d1*-1;if(d2<0) d2=d2*-1;if(d3<0) d3=d3*-1;
|
||||
|
||||
if(d1>d2 && d1>d3) return d1;
|
||||
if(d2>d1 && d2>d3) return d2;
|
||||
if(d3>d2 && d3>d1) return d3;
|
||||
return 9999;
|
||||
}
|
||||
|
||||
|
||||
int gLocalize::get_byteorder()
|
||||
{
|
||||
union {
|
||||
long l;
|
||||
char c[4];
|
||||
} test;
|
||||
test.l = 1;
|
||||
if( test.c[3] && !test.c[2] && !test.c[1] && !test.c[0] )
|
||||
return ORDER_BIGENDIAN;
|
||||
|
||||
if( !test.c[3] && !test.c[2] && !test.c[1] && test.c[0] )
|
||||
return ORDER_LITTLEENDIAN;
|
||||
|
||||
return ORDER_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of the Hausdorff distance from a reference 1 cm diameter sphere
|
||||
*/
|
||||
double gLocalize::hausdorff(vtkPolyDataConnectivityFilter* filter, surf tempsurf)
|
||||
{
|
||||
vtkSmartPointer<vtkSphereSource> source_sphere = vtkSmartPointer<vtkSphereSource>::New();
|
||||
source_sphere->SetCenter(tempsurf.center[0],tempsurf.center[1],tempsurf.center[2]);
|
||||
source_sphere->SetRadius(5.0);
|
||||
source_sphere->Update();
|
||||
|
||||
vtkSmartPointer<vtkPolyData> sphere = source_sphere->GetOutput();
|
||||
sphere->Update();
|
||||
sphere->BuildCells();
|
||||
|
||||
vtkSmartPointer<vtkExtractEdges> edge_extractor =vtkSmartPointer<vtkExtractEdges>::New();
|
||||
edge_extractor->RemoveAllInputs();
|
||||
edge_extractor->SetInput(filter->GetOutput());
|
||||
edge_extractor->Update();
|
||||
|
||||
vtkSmartPointer<vtkPolyData> tmp = vtkSmartPointer<vtkPolyData>::New();
|
||||
tmp=edge_extractor->GetOutput();
|
||||
tmp->Update();
|
||||
tmp->BuildCells();
|
||||
tmp->BuildLinks();
|
||||
|
||||
QList <point> punti_sup;
|
||||
point ptemp;
|
||||
|
||||
for (int id=0;id< (int) tmp->GetNumberOfPoints();id++){
|
||||
ptemp.x=tmp->GetPoint(id)[0];
|
||||
ptemp.y=tmp->GetPoint(id)[1];
|
||||
ptemp.z=tmp->GetPoint(id)[2];
|
||||
/*cout<<filter->GetOutput()->GetPoint(id)[0]<<" "<<filter->GetOutput()->GetPoint(id)[1]<<" "<<filter->GetOutput()->GetPoint(id)[2]<<endl;*/
|
||||
punti_sup.append(ptemp);
|
||||
};
|
||||
|
||||
|
||||
QList <point> punti_sphere;
|
||||
for (int id=0;id< (int) sphere->GetNumberOfPoints();id++){
|
||||
ptemp.x=sphere->GetPoint(id)[0];
|
||||
ptemp.y=sphere->GetPoint(id)[1];
|
||||
ptemp.z=sphere->GetPoint(id)[2];
|
||||
/*cout<<filter->GetOutput()->GetPoint(id)[0]<<" "<<filter->GetOutput()->GetPoint(id)[1]<<" "<<filter->GetOutput()->GetPoint(id)[2]<<endl;*/
|
||||
punti_sphere.append(ptemp);
|
||||
};
|
||||
|
||||
int nr_source_points = punti_sup.count();
|
||||
int nr_target_points = punti_sphere.count();
|
||||
|
||||
double summax = 0;
|
||||
double summin = 0;
|
||||
double maxmin = -1e9;
|
||||
double maxmax = -1e9;
|
||||
|
||||
for(int i=0; i < nr_source_points; i++) {
|
||||
double smallest = 1e9;
|
||||
double largest = 0;
|
||||
|
||||
double x1 = punti_sup.at(i).x;
|
||||
double y1 = punti_sup.at(i).y;
|
||||
double z1 = punti_sup.at(i).z;
|
||||
|
||||
for(int j=0; j < nr_target_points; j++) {
|
||||
double x2 = punti_sphere.at(j).x;
|
||||
double y2 = punti_sphere.at(j).y;
|
||||
double z2 = punti_sphere.at(j).z;
|
||||
|
||||
double dx = x1 - x2;
|
||||
double dy = y1 - y2;
|
||||
double dz = z1 - z2;
|
||||
|
||||
double dist = dx * dx + dy * dy + dz*dz;
|
||||
|
||||
if (dist < smallest) smallest = dist;
|
||||
if (dist > largest) largest = dist;
|
||||
}
|
||||
|
||||
summin += smallest;
|
||||
summax += largest;
|
||||
|
||||
if (smallest > maxmin) maxmin = smallest; // so this is max min
|
||||
if (largest > maxmax) maxmax = largest; // and this is max max
|
||||
}
|
||||
|
||||
punti_sphere.clear();
|
||||
punti_sup.clear();
|
||||
return maxmin; // Hausdorff distance
|
||||
}
|
||||
Executable
+215
@@ -0,0 +1,215 @@
|
||||
#ifndef _GLOCALIZE_H_
|
||||
#define _GLOCALIZE_H_
|
||||
|
||||
#include <QObject.h>
|
||||
#include <vtkImageData.h>
|
||||
#include <QThread>
|
||||
#include <vtkActor.h>
|
||||
#include <vtkAlgorithm.h>
|
||||
#include <vtkCellPicker.h>
|
||||
#include <vtkDataSet.h>
|
||||
#include <vtkExtractEdges.h>
|
||||
#include <vtkImageData.h>
|
||||
#include <vtkIterativeClosestPointTransform.h>
|
||||
#include <vtkImageMarchingCubes.h>
|
||||
#include <vtkImageData.h>
|
||||
#include <vtkImageThreshold.h>
|
||||
#include <vtkImagePlaneWidget.h>
|
||||
#include <vtkLandmarkTransform.h>
|
||||
#include <vtkMarchingCubes.h>
|
||||
#include <vtkPolyDataAlgorithm.h>
|
||||
#include <vtkPolyData.h>
|
||||
#include <vtkPolyDataMapper.h>
|
||||
#include <vtkPolyDataNormals.h>
|
||||
#include <vtkPolyDataConnectivityFilter.h>
|
||||
#include <vtkPolyDataCollection.h>
|
||||
#include <vtkPoints.h>
|
||||
#include <vtkProperty.h>
|
||||
#include <vtkSource.h>
|
||||
#include <vtkSmartPointer.h>
|
||||
#include <vtkPolyData.h>
|
||||
#include <vtkPolyDataConnectivityFilter.h>
|
||||
#include <vtkRenderWindowInteractor.h>
|
||||
#include <vtkRenderer.h>
|
||||
#include <vtkRenderWindow.h>
|
||||
#include <vtkPolyDataMapper.h>
|
||||
#include <vtkSphereSource.h>
|
||||
#include <vtkWindowedSincPolyDataFilter.h>
|
||||
|
||||
//#include "gSkullRemoval.h"
|
||||
|
||||
#include <qstring.h>
|
||||
#include <qlist.h>
|
||||
#include <QMetaType>
|
||||
#include <QProgressBar>
|
||||
#include <gdcmGlobal.h>
|
||||
#include <iostream>
|
||||
//#include "gTRiPtools_b.h"
|
||||
#include <vtkCamera.h>
|
||||
//#include "resampler.h"
|
||||
#include <vtkMetaImageReader.h>
|
||||
#include <vtkGDCMPolyDataReader.h>
|
||||
#include <vtkHomogeneousTransform.h>
|
||||
#include <gdcmReader.h>
|
||||
#include <gdcmAttribute.h>
|
||||
#include <gdcmStringFilter.h>
|
||||
#include <vtkMatrix4x4.h>
|
||||
#include <gdcmDict.h>
|
||||
#include <gdcmDirectory.h>
|
||||
#include <vtkImageChangeInformation.h>
|
||||
#include <vtkImageData.h>
|
||||
#include <vtkImageReslice.h>
|
||||
#include <vtkVolumeProperty.h>
|
||||
#include <vtkColorTransferFunction.h>
|
||||
#include <vtkPiecewiseFunction.h>
|
||||
#include <vtkVolume.h>
|
||||
#include <vtkSmartVolumeMapper.h>
|
||||
#include <vtkSmartPointer.h>
|
||||
#include <vtkRenderWindow.h>
|
||||
#include <vtkRenderer.h>
|
||||
#include <vtkRenderWindowInteractor.h>
|
||||
#include <vtkAxesActor.h>
|
||||
#include <vtkImageData.h>
|
||||
#include <vtkPolyDataMapper.h>
|
||||
#include <vtkProperty.h>
|
||||
#include <vtkAppendPolyData.h>
|
||||
#include <vtkSurfaceReconstructionFilter.h>
|
||||
#include <vtkContourFilter.h>
|
||||
#include <vtkCaptionActor2D.h>
|
||||
#include <vtkTextProperty.h>
|
||||
#include <vtkAbstractTransform.h>
|
||||
#include <ostream>
|
||||
|
||||
|
||||
#include <vtkTransform.h>
|
||||
#include <vtkPolyData.h>
|
||||
#include <vtkTransformPolyDataFilter.h>
|
||||
#include <vtkImageData.h>
|
||||
#include <vtkImageFlip.h>
|
||||
#include <vtkImageChangeInformation.h>
|
||||
#include <vtkSmartPointer.h>
|
||||
#include <vtkStringArray.h>
|
||||
#include <vtkCellData.h>
|
||||
#include <vtkPointData.h>
|
||||
#include <vtkGDCMImageReader.h>
|
||||
#include <vtkGDCMPolyDataReader.h>
|
||||
#include <gdcmDirectory.h>
|
||||
#include <gdcmIPPSorter.h>
|
||||
#include <gdcmSystem.h>
|
||||
#include <vtkMatrixToLinearTransform.h>
|
||||
// #include <qstring.h>
|
||||
#include <vtkCellArray.h>
|
||||
#include <vtkLine.h>
|
||||
#include <vtkGDCMThreadedImageReader.h>
|
||||
#include <vtkTransformFilter.h>
|
||||
#include <vtkSelectEnclosedPoints.h>
|
||||
#include <vtkPolygon.h>
|
||||
#include <string>
|
||||
#include <vtkImageWriter.h>
|
||||
#include <gdcmUIDs.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
||||
#define ORDER_BIGENDIAN 0
|
||||
#define ORDER_LITTLEENDIAN 1
|
||||
#define ORDER_UNKNOWN 2
|
||||
|
||||
// Some Macros to make the code more readable
|
||||
//
|
||||
|
||||
//#ifndef SWAP_TMP_INT
|
||||
// #define SWAP_TMP_INT
|
||||
// #define EVAL_INDEX(X,Y,L) (reference[ (Y)*(L) +(X)])
|
||||
// int swap_tmp_int;
|
||||
// #define INT_SWAP(X,Y) swap_tmp_int=X; X=Y; Y=swap_tmp_int;
|
||||
//#endif
|
||||
//
|
||||
//
|
||||
|
||||
#define N_ITERAZ_ICP 100
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
||||
public:
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
}point;
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
||||
public:
|
||||
int sorting;
|
||||
int surfn;
|
||||
double lenght;
|
||||
int ntriangle;
|
||||
int npoint;
|
||||
double bounds[6];
|
||||
double center[3];
|
||||
double volume;
|
||||
int ismarker;
|
||||
point centroid;
|
||||
double centroid_median [3];
|
||||
point fitting ;
|
||||
double confronto_lati;
|
||||
double hausdorff;
|
||||
}surf;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class gLocalize : public QObject{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
gLocalize();
|
||||
|
||||
public slots:
|
||||
void localize(vtkImageData* vol,
|
||||
int march_tresh,
|
||||
double thrDown_D,
|
||||
double thrUp_D,
|
||||
double thr_HAUSD,
|
||||
double thr_S,
|
||||
QList <bool> selectedFilters);
|
||||
void callAbort(){
|
||||
cout<< "Aborted" <<endl;
|
||||
abortSignal=true;
|
||||
};
|
||||
|
||||
signals:
|
||||
void localizationEnd(QList<surf>);
|
||||
void localizationProgress(int);
|
||||
void localizationAborted();
|
||||
|
||||
private:
|
||||
double hausdorff(vtkPolyDataConnectivityFilter* filter, surf tempsurf);
|
||||
int get_byteorder();
|
||||
double lati(double p[6]);
|
||||
point centroid(QList< point > punti);
|
||||
volatile bool abortSignal;
|
||||
|
||||
|
||||
/**
|
||||
* Functions for Qlist sorting
|
||||
*/
|
||||
bool lenghtLessThan(const surf &d1, const surf &d2){ return d1.lenght > d2.lenght; };
|
||||
bool tringleLessThan(const surf &d1, const surf &d2){ return d1.ntriangle > d2.ntriangle; };
|
||||
bool zLessThan(const surf &d1, const surf &d2){ return d1.center[2] < d2.center[2]; };
|
||||
bool confronto_latiLessThan(const surf &d1, const surf &d2){return d1.confronto_lati<d2.confronto_lati;};
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
Executable
+78
@@ -0,0 +1,78 @@
|
||||
#ifndef _GPATRTGENINFO_H_
|
||||
#define _GPATRTGENINFO_H_
|
||||
|
||||
#include <vector>
|
||||
#include <qstring.h>
|
||||
#define MAXSTRINGLENGHT 256
|
||||
|
||||
|
||||
class gPatientRTGeneralInfos {
|
||||
|
||||
public:
|
||||
gPatientRTGeneralInfos(){
|
||||
PatientName = new char [MAXSTRINGLENGHT];
|
||||
PatientID = new char [MAXSTRINGLENGHT];
|
||||
PatientSex = new char [MAXSTRINGLENGHT];
|
||||
PatientAge = new char [MAXSTRINGLENGHT];
|
||||
PatientBirthDate = new char [MAXSTRINGLENGHT];
|
||||
|
||||
SeriesNumber = new char [MAXSTRINGLENGHT];
|
||||
SeriesDescription = new char [MAXSTRINGLENGHT];
|
||||
StudyID = new char [MAXSTRINGLENGHT];
|
||||
StudyDescription = new char [MAXSTRINGLENGHT];
|
||||
|
||||
PatientOrientation= new char [MAXSTRINGLENGHT];
|
||||
|
||||
clearInfo();
|
||||
};
|
||||
|
||||
void clearInfo(){
|
||||
filenames.clear();
|
||||
CTfiles.clear();
|
||||
rtIonPlanPath.clear();
|
||||
rtStructurePath.clear();
|
||||
PatientName[0]=0;
|
||||
PatientID[0]=0;
|
||||
PatientSex[0]=0;
|
||||
PatientBirthDate[0]=0;
|
||||
SeriesNumber[0]=0;
|
||||
SeriesDescription[0]=0;
|
||||
StudyID[0]=0;
|
||||
StudyDescription[0]=0;
|
||||
PatientOrientation[0]=0;
|
||||
};
|
||||
|
||||
~gPatientRTGeneralInfos(){
|
||||
delete [] PatientName;
|
||||
delete [] PatientID;
|
||||
delete [] PatientSex;
|
||||
delete [] PatientAge;
|
||||
delete [] PatientBirthDate;
|
||||
delete [] SeriesNumber;
|
||||
delete [] SeriesDescription;
|
||||
delete [] StudyID;
|
||||
delete [] StudyDescription;
|
||||
delete [] PatientOrientation;
|
||||
};
|
||||
|
||||
public:
|
||||
char* PatientName;
|
||||
char* PatientID;
|
||||
char* PatientSex;
|
||||
char* PatientAge;
|
||||
char* PatientBirthDate;
|
||||
char* SeriesNumber;
|
||||
char* SeriesDescription;
|
||||
char* StudyID;
|
||||
char* StudyDescription;
|
||||
char* PatientOrientation;
|
||||
|
||||
std::vector<std::string> filenames;
|
||||
QString rtIonPlanPath;
|
||||
QString rtStructurePath;
|
||||
std::vector<std::string> CTfiles;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,434 @@
|
||||
|
||||
#include "gRen.h"
|
||||
|
||||
gRen::gRen( QVTKWidget* m_qvtk){
|
||||
CTinfos.clear();
|
||||
qvtk= m_qvtk;
|
||||
nmarker=0;
|
||||
|
||||
markerSources = 0;
|
||||
markerMappers = 0;
|
||||
markerActors = 0;
|
||||
|
||||
this-> buildRenderPipe();
|
||||
this-> createRenderers();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void gRen::onAutoSkullMaskEnd(vtkImageData* fixedVol){
|
||||
cout << "Auto masking complete"<<endl;
|
||||
//CTvolume=vtkSmartPointer<vtkImageData>::New();
|
||||
//CTvolume->Initialize();
|
||||
CTvolume->DeepCopy(fixedVol);
|
||||
CTvolume->Update();
|
||||
|
||||
extractVOI->Update();
|
||||
ren1->Render();
|
||||
qvtk->GetRenderWindow()->Render();
|
||||
}
|
||||
|
||||
|
||||
void gRen::loadVolume(vtkImageData* volCT){
|
||||
|
||||
CTvolume=vtkSmartPointer<vtkImageData>::New();
|
||||
CTvolume->Initialize();
|
||||
CTvolume->DeepCopy(volCT);
|
||||
CTvolume->Update();
|
||||
CTvolume->GetExtent(CTinfos.extent);
|
||||
CTvolume->GetSpacing(CTinfos.spacing);
|
||||
CTvolume->GetOrigin(CTinfos.origin);
|
||||
cout<< "ORIGIN REN: "<<CTinfos.origin[0]<<" "<<CTinfos.origin[1]<<" "<<CTinfos.origin[2]<<" " <<endl;
|
||||
|
||||
#if VTK_MAJOR_VERSION <= 5
|
||||
volumeMapper->SetInput(CTvolume/*extractVOI->GetOutput()*/);
|
||||
#else
|
||||
volumeMapper->SetInputData(CTvolume);
|
||||
#endif
|
||||
ren1->AddViewProp(volume);
|
||||
|
||||
if(volume->GetVisibility() == 0)
|
||||
volume->SetVisibility(false);
|
||||
else
|
||||
volume->SetVisibility(true);
|
||||
|
||||
extractVOI->SetInput(CTvolume);
|
||||
extractVOI->SetVOI(CTvolume->GetExtent());
|
||||
extractVOI->Update();
|
||||
|
||||
boxCallback_NEW->setNominalGeometry(volCT->GetExtent(),volCT->GetBounds(),volCT->GetSpacing());
|
||||
boxWidget_NEW->SetRotationEnabled(false);
|
||||
boxWidget_NEW->SetScalingEnabled(true);
|
||||
boxWidget_NEW->SetTranslationEnabled(true);
|
||||
boxWidget_NEW->SetPriority(1);
|
||||
boxWidget_NEW->SetInput((vtkDataSet *) CTvolume);
|
||||
boxWidget_NEW->PlaceWidget();
|
||||
boxWidget_NEW->InsideOutOn();
|
||||
boxWidget_NEW->GetOutlineProperty()->SetRepresentationToWireframe();
|
||||
boxWidget_NEW->GetOutlineProperty()->SetAmbient(1.0);
|
||||
boxWidget_NEW->GetOutlineProperty()->SetAmbientColor(1,1,1);
|
||||
boxWidget_NEW->GetOutlineProperty()->SetLineWidth(3);
|
||||
boxWidget_NEW->GetSelectedOutlineProperty()->SetRepresentationToWireframe();
|
||||
boxWidget_NEW->GetSelectedOutlineProperty()->SetAmbient(1.0);
|
||||
boxWidget_NEW->GetSelectedOutlineProperty()->SetAmbientColor(1,0,0);
|
||||
boxWidget_NEW->GetSelectedOutlineProperty()->SetLineWidth(3);
|
||||
|
||||
outline-> SetInputConnection(extractVOI->GetOutputPort());
|
||||
|
||||
planeWidgetX->SetInput(extractVOI->GetOutput());
|
||||
planeWidgetY->SetInput(extractVOI->GetOutput());
|
||||
planeWidgetZ->SetInput(extractVOI->GetOutput());
|
||||
|
||||
if(outlineActor->GetVisibility() == 0){
|
||||
}
|
||||
else{
|
||||
planeWidgetX->On();
|
||||
planeWidgetY->On();
|
||||
planeWidgetZ->On();
|
||||
}
|
||||
|
||||
orthoPlanes->SetPlane(0, planeWidgetX);
|
||||
orthoPlanes->SetPlane(1, planeWidgetY);
|
||||
orthoPlanes->SetPlane(2, planeWidgetZ);
|
||||
orthoPlanes->ResetPlanes();
|
||||
|
||||
vtkCamera * cam = ren1->GetActiveCamera();
|
||||
cam->SetPosition(0, 0, -1);
|
||||
cam->SetFocalPoint(0, 0, 0);
|
||||
cam->SetViewUp(0, -1, 0);
|
||||
|
||||
ren1->ResetCamera();
|
||||
ren1->Render();
|
||||
qvtk->GetRenderWindow()->Render();
|
||||
|
||||
emit PatientLoaded();
|
||||
}
|
||||
|
||||
void gRen::createRenderers(){
|
||||
ren1 = vtkRenderer::New();
|
||||
ren1->SetBackground(0.13, 0.25, 0.32);
|
||||
qvtk->GetRenderWindow()->AddRenderer(ren1);
|
||||
ren1->Render();
|
||||
|
||||
ren1->AddActor(assi);
|
||||
ren1->AddActor( outlineActor);
|
||||
|
||||
|
||||
boxWidget_NEW = vtkBoxWidget::New();
|
||||
boxWidget_NEW->SetInteractor(qvtk->GetInteractor());
|
||||
boxWidget_NEW->SetPlaceFactor(1.0);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
boxCallback_NEW->rcm=volumeMapper;
|
||||
|
||||
boxWidget_NEW->AddObserver(vtkCommand::InteractionEvent, boxCallback_NEW);
|
||||
}
|
||||
|
||||
void gRen::buildRenderPipe(){
|
||||
|
||||
outline = vtkSmartPointer<vtkOutlineFilter>::New();
|
||||
|
||||
vtkPolyDataMapper* outlineMapper = vtkPolyDataMapper::New();
|
||||
outlineMapper->SetInputConnection(outline->GetOutputPort());
|
||||
|
||||
outlineActor = vtkSmartPointer <vtkActor> ::New();
|
||||
outlineActor->SetMapper( outlineMapper);
|
||||
|
||||
vtkCellPicker* picker = vtkCellPicker::New();
|
||||
picker->SetTolerance(0.005);
|
||||
|
||||
vtkProperty* ipwProp = vtkProperty::New();
|
||||
//// //assign default props to the ipw's texture plane actor
|
||||
|
||||
planeWidgetX = vtkImagePlaneWidget::New();
|
||||
planeWidgetX->SetInteractor( qvtk->GetRenderWindow()->GetInteractor());
|
||||
planeWidgetX->SetKeyPressActivationValue('x');
|
||||
planeWidgetX->SetPicker(picker);
|
||||
planeWidgetX->RestrictPlaneToVolumeOn();
|
||||
planeWidgetX->GetPlaneProperty()->SetColor(1,0,0);
|
||||
planeWidgetX->SetTexturePlaneProperty(ipwProp);
|
||||
planeWidgetX->TextureInterpolateOff();
|
||||
planeWidgetX->SetResliceInterpolateToNearestNeighbour();
|
||||
planeWidgetX->SetPlaneOrientationToXAxes();
|
||||
planeWidgetX->DisplayTextOn();
|
||||
planeWidgetX->InteractionOff();
|
||||
planeWidgetX->InteractionOn();
|
||||
|
||||
planeWidgetY = vtkImagePlaneWidget::New();
|
||||
planeWidgetY->SetInteractor( qvtk->GetRenderWindow()->GetInteractor());
|
||||
planeWidgetY->SetKeyPressActivationValue('y');
|
||||
planeWidgetY->SetPicker(picker);
|
||||
planeWidgetY->GetPlaneProperty()->SetColor(1,1,0);
|
||||
planeWidgetY->SetTexturePlaneProperty(ipwProp);
|
||||
planeWidgetY->TextureInterpolateOn();
|
||||
planeWidgetY->SetResliceInterpolateToLinear();
|
||||
planeWidgetY->SetPlaneOrientationToYAxes();
|
||||
planeWidgetY->SetLookupTable( planeWidgetX->GetLookupTable());
|
||||
planeWidgetY->DisplayTextOn();
|
||||
planeWidgetY->UpdatePlacement();
|
||||
|
||||
planeWidgetZ = vtkImagePlaneWidget::New();
|
||||
planeWidgetZ->SetInteractor( qvtk->GetRenderWindow()->GetInteractor());
|
||||
planeWidgetZ->SetKeyPressActivationValue('z');
|
||||
planeWidgetZ->SetPicker(picker);
|
||||
planeWidgetZ->GetPlaneProperty()->SetColor(0,0,1);
|
||||
planeWidgetZ->SetTexturePlaneProperty(ipwProp);
|
||||
planeWidgetZ->TextureInterpolateOn();
|
||||
planeWidgetZ->SetResliceInterpolateToCubic();
|
||||
planeWidgetZ->SetPlaneOrientationToZAxes();
|
||||
planeWidgetZ->SetLookupTable( planeWidgetX->GetLookupTable());
|
||||
planeWidgetZ->DisplayTextOn();
|
||||
|
||||
|
||||
assi= vtkAxesActor::New();
|
||||
assi->SetOrigin(0,0,0);
|
||||
assi->AxisLabelsOff();
|
||||
assi->SetTotalLength(15,15,15);
|
||||
|
||||
volumeMapper = vtkSmartPointer<vtkSmartVolumeMapper>::New();
|
||||
volumeMapper->SetBlendModeToComposite(); // composite first
|
||||
|
||||
volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
|
||||
volumeProperty->ShadeOff();
|
||||
volumeProperty->SetInterpolationType(VTK_LINEAR_INTERPOLATION);
|
||||
|
||||
compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
|
||||
compositeOpacity->AddPoint(-3024, 0, 0.5, 0.0 );
|
||||
compositeOpacity->AddPoint(-16, 0, .49, .61 );
|
||||
compositeOpacity->AddPoint(-10, .1, .49, .4 );
|
||||
compositeOpacity->AddPoint(500, .4, .49, .4 );
|
||||
compositeOpacity->AddPoint(641, .72, .5, 0.0 );
|
||||
compositeOpacity->AddPoint(1700, .8, .5, 0.0 );
|
||||
compositeOpacity->AddPoint(2500, .8, .5, 0.0 );
|
||||
compositeOpacity->AddPoint(3071, .71, 0.5, 0.0);
|
||||
volumeProperty->SetScalarOpacity(compositeOpacity); // composite first.
|
||||
|
||||
|
||||
color = vtkSmartPointer<vtkColorTransferFunction>::New();
|
||||
color->AddRGBPoint( -3024, 0, 0, 0, 0.5, 0.0 );
|
||||
color->AddRGBPoint( -16, 0.73, 0.25, 0.30, 0.49, .61 );
|
||||
color->AddRGBPoint( -10, .3, .3, .3, .5, 0.0 );
|
||||
color->AddRGBPoint( 500, .7, .7, .7, .5, 0.0 );
|
||||
color->AddRGBPoint( 641, .90, .82, .56, .5, 0.0 );
|
||||
color->AddRGBPoint( 1700, 1, 0,0, .5, 1 );
|
||||
color->AddRGBPoint( 2500, 1, 0,0, .5,.1 );
|
||||
color->AddRGBPoint( 3071, 1, 1, 1, .5, 0.0 );
|
||||
volumeProperty->SetColor(color);
|
||||
|
||||
volumeProperty->ShadeOn();
|
||||
volumeProperty->SetAmbient(0.1);
|
||||
volumeProperty->SetDiffuse(0.9);
|
||||
volumeProperty->SetSpecular(0.2);
|
||||
volumeProperty->SetSpecularPower(10.0);
|
||||
volumeProperty->SetScalarOpacityUnitDistance(0.8919);
|
||||
|
||||
//compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
|
||||
//compositeOpacity->AddPoint(0.0,0.0);
|
||||
//compositeOpacity->AddPoint(80.0,1.0);
|
||||
//compositeOpacity->AddPoint(80.1,0.0);
|
||||
//compositeOpacity->AddPoint(255.0,0.0);
|
||||
//volumeProperty->SetScalarOpacity(compositeOpacity); // composite first.
|
||||
//
|
||||
//color = vtkSmartPointer<vtkColorTransferFunction>::New();
|
||||
//color->AddRGBPoint(0.0 ,0.0,0.0,1.0);
|
||||
//color->AddRGBPoint(40.0 ,1.0,0.0,0.0);
|
||||
//color->AddRGBPoint(255.0,1.0,1.0,1.0);
|
||||
//volumeProperty->SetColor(color);
|
||||
|
||||
volume = vtkSmartPointer<vtkVolume>::New();
|
||||
volume->SetMapper(volumeMapper);
|
||||
volume->SetProperty(volumeProperty);
|
||||
volume->SetVisibility(false);
|
||||
|
||||
outlineActor->SetVisibility(true);
|
||||
planeWidgetX->EnabledOn();
|
||||
planeWidgetY->EnabledOn();
|
||||
planeWidgetZ->EnabledOn();
|
||||
planeWidgetX->On();
|
||||
planeWidgetY->On();
|
||||
planeWidgetZ->On();
|
||||
|
||||
|
||||
extractVOI = vtkSmartPointer<vtkExtractVOI>::New();
|
||||
boxCallback_NEW = vtkSmartPointer<vtkMyCallback>::New();
|
||||
boxCallback_NEW->setExtractVoiFilter(extractVOI);
|
||||
|
||||
orthoPlanes = vtkImageOrthoPlanes::New();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void gRen::onSingleMarkerChange(int idx, bool state){
|
||||
|
||||
cout<< "onSingleMarkerChange : "<<idx<<" "<<(state == true? "true":"false")<<endl;
|
||||
|
||||
if(state){
|
||||
markerActors[idx]->GetProperty()->SetColor(0,1,0);
|
||||
} else {
|
||||
markerActors[idx]->GetProperty()->SetColor(1,1,1);
|
||||
}
|
||||
qvtk->GetRenderWindow()->Render();
|
||||
}
|
||||
|
||||
|
||||
void gRen::renderMarkers(QList<surf> marker_list){
|
||||
|
||||
cout << "renderMarkers" << endl;
|
||||
|
||||
if(markerSources != 0) {
|
||||
for(int ii=0;ii<nmarker;ii++){
|
||||
ren1->RemoveActor(markerActors[ii]);
|
||||
markerActors[ii]->RemoveAllObservers();
|
||||
markerMappers[ii]->RemoveAllObservers();
|
||||
markerSources[ii]->RemoveAllObservers();
|
||||
markerSources[ii]->Delete();
|
||||
markerActors[ii]->Delete();
|
||||
markerMappers[ii]->Delete();
|
||||
}
|
||||
delete [] markerActors;
|
||||
delete [] markerMappers;
|
||||
delete [] markerSources;
|
||||
ren1->RemoveActor(pointLabels);
|
||||
//modelPoints->Delete();
|
||||
//stringData->Delete();
|
||||
//pointLabels->Delete();
|
||||
//cells->Delete();
|
||||
//polyData->Delete();
|
||||
//ids->Delete();
|
||||
//ldm->Delete();
|
||||
}
|
||||
|
||||
nmarker = marker_list.size();
|
||||
markerSources = new vtkSphereSource* [nmarker];
|
||||
markerMappers = new vtkPolyDataMapper* [nmarker];
|
||||
markerActors = new vtkActor* [nmarker];
|
||||
|
||||
modelPoints = vtkSmartPointer<vtkPoints>::New();
|
||||
modelPoints->Reset();
|
||||
modelPoints->SetNumberOfPoints(nmarker);
|
||||
|
||||
|
||||
stringData = vtkSmartPointer<vtkStringArray>::New();
|
||||
stringData->Reset();
|
||||
stringData->SetName("Labels");
|
||||
|
||||
for(int i=0;i<nmarker;i++){
|
||||
stringData->InsertNextValue(QString::number(i).toLatin1().constData());
|
||||
modelPoints->InsertPoint(i,marker_list.at(i).centroid.x*1000,marker_list.at(i).centroid.y*1000,marker_list.at(i).centroid.z*1000);
|
||||
|
||||
markerSources[i] = vtkSphereSource::New();
|
||||
markerSources[i]->SetCenter(marker_list.at(i).centroid.x*1000,marker_list.at(i).centroid.y*1000,marker_list.at(i).centroid.z*1000);
|
||||
markerSources[i]->SetRadius(10);
|
||||
|
||||
markerMappers[i]= vtkPolyDataMapper::New();
|
||||
markerMappers[i]->SetInputConnection (markerSources[i]->GetOutputPort());
|
||||
|
||||
markerActors[i]= vtkActor::New();
|
||||
markerActors[i]->SetMapper(markerMappers[i]);
|
||||
markerActors[i]->GetProperty()->SetRepresentationToWireframe();
|
||||
markerActors[i]->GetProperty()->SetColor(0,1,0);
|
||||
ren1->AddActor(markerActors[i]);
|
||||
}
|
||||
|
||||
cout << "modelPoints" << endl;
|
||||
modelPoints->Modified();
|
||||
|
||||
cells = vtkSmartPointer<vtkCellArray>::New();
|
||||
cells->Reset();
|
||||
cells->InsertNextCell(nmarker);
|
||||
for(int i = 0; i < nmarker; i++)
|
||||
cells->InsertCellPoint(i);
|
||||
|
||||
polyData = vtkSmartPointer<vtkPolyData>::New();
|
||||
polyData->Reset();
|
||||
polyData->SetPoints(modelPoints);
|
||||
polyData->SetVerts(cells);
|
||||
polyData->GetPointData()->AddArray(stringData);
|
||||
|
||||
ids = vtkSmartPointer<vtkIdFilter>::New();
|
||||
ids->SetInput( polyData );
|
||||
ids->PointIdsOn();
|
||||
ids->CellIdsOn();
|
||||
ids->FieldDataOn();
|
||||
cout << "ids" << endl;
|
||||
ldm = vtkSmartPointer<vtkLabeledDataMapper>::New();
|
||||
ldm->SetInputConnection( ids->GetOutputPort() );
|
||||
ldm->SetLabelModeToLabelFieldData();
|
||||
ldm->GetLabelTextProperty()->SetShadow(false);
|
||||
ldm->GetLabelTextProperty()->SetFontSize(22);
|
||||
cout << "plab" << endl;
|
||||
pointLabels = vtkSmartPointer<vtkActor2D>::New();
|
||||
pointLabels->SetMapper( ldm );
|
||||
ren1->AddActor(pointLabels);
|
||||
qvtk->GetRenderWindow()->Render();
|
||||
}
|
||||
|
||||
void gRen::onReferenceChange(double dx, double dy, double dz){
|
||||
|
||||
if(markerSources == 0)
|
||||
return;
|
||||
|
||||
for(int i=0;i<nmarker;i++){
|
||||
markerSources[i]->SetCenter(
|
||||
markerSources[i]->GetCenter()[0]-dx,
|
||||
markerSources[i]->GetCenter()[1]-dy,
|
||||
markerSources[i]->GetCenter()[2]-dz);
|
||||
markerSources[i]->Update();
|
||||
|
||||
modelPoints->SetPoint(i,
|
||||
modelPoints->GetPoint(i)[0]-dx,
|
||||
modelPoints->GetPoint(i)[1]-dy,
|
||||
modelPoints->GetPoint(i)[2]-dz);
|
||||
}
|
||||
|
||||
modelPoints->Modified();
|
||||
qvtk->GetRenderWindow()->Render();
|
||||
}
|
||||
|
||||
void gRen::onRequestRenderChange(int idx){
|
||||
switch (idx){
|
||||
case 0:
|
||||
volume->SetVisibility(true);
|
||||
outlineActor->SetVisibility(false);
|
||||
planeWidgetX->EnabledOff();
|
||||
planeWidgetY->EnabledOff();
|
||||
planeWidgetZ->EnabledOff();
|
||||
ren1->Render();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
volume->SetVisibility(false);
|
||||
outlineActor->SetVisibility(true);
|
||||
planeWidgetX->EnabledOn();
|
||||
planeWidgetY->EnabledOn();
|
||||
planeWidgetZ->EnabledOn();
|
||||
ren1->Render();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gRen::onRequestManualMask(int idx){
|
||||
|
||||
switch (idx){
|
||||
case 0:
|
||||
boxWidget_NEW->On();
|
||||
qvtk->GetRenderWindow()->Render();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
boxWidget_NEW->Off();
|
||||
qvtk->GetRenderWindow()->Render();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
#ifndef _GREN_H_
|
||||
#define _GREN_H_
|
||||
|
||||
|
||||
#include <vtkImageData.h>
|
||||
#include <vtkSmartPointer.h>
|
||||
|
||||
#include <QVTKWidget.h>
|
||||
#include <vtkOutlineFilter.h>
|
||||
#include <vtkActor.h>
|
||||
#include <vtkImageMapToColors.h>
|
||||
#include <vtkImagePlaneWidget.h>
|
||||
#include <qobject.h>
|
||||
#include <vtkImageOrthoPlanes.h>
|
||||
#include <vtkRenderer.h>
|
||||
#include <vtkRenderWindow.h>
|
||||
#include <vtkPolyDataMapper.h>
|
||||
|
||||
#include <vtkCellPicker.h>
|
||||
#include <vtkProperty.h>
|
||||
#include <vtkAxesActor.h>
|
||||
#include "gLocalize.h"
|
||||
|
||||
|
||||
#include <vtkSmartVolumeMapper.h>
|
||||
|
||||
|
||||
#include <vtkPolyDataMapper.h>
|
||||
#include <vtkActor.h>
|
||||
#include <vtkRenderWindow.h>
|
||||
#include <vtkRenderer.h>
|
||||
#include <vtkRenderWindowInteractor.h>
|
||||
#include <vtkPolyData.h>
|
||||
#include <vtkSmartPointer.h>
|
||||
#include <vtkSphereSource.h>
|
||||
#include <vtkBoxWidget2.h>
|
||||
|
||||
#include <vtkBoxWidget.h>
|
||||
#include <vtkPlanes.h>
|
||||
|
||||
#include <vtkBoxRepresentation.h>
|
||||
#include <vtkCommand.h>
|
||||
#include <vtkExtractVOI.h>
|
||||
|
||||
|
||||
#include <vtkIdFilter.h>
|
||||
#include <vtkLabeledDataMapper.h>
|
||||
#include <vtkActor2D.h>
|
||||
|
||||
|
||||
|
||||
|
||||
class vtkMyCallback : public vtkCommand
|
||||
{
|
||||
public:
|
||||
vtkSmartVolumeMapper *rcm;
|
||||
static vtkMyCallback *New() { return new vtkMyCallback; }
|
||||
|
||||
virtual void Execute(vtkObject *caller, unsigned long, void*)
|
||||
{
|
||||
vtkBoxWidget *boxWidget = reinterpret_cast<vtkBoxWidget*>(caller);
|
||||
|
||||
// Get the actual box coordinates/planes
|
||||
vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
|
||||
//static_cast<vtkBoxRepresentation*>(boxWidget->GetRepresentation())->GetPolyData (polydata);
|
||||
|
||||
boxWidget->GetPolyData(polydata);
|
||||
double *ac_bounds=polydata->GetBounds();
|
||||
/*check if box is larger than volume size*/
|
||||
// double *ac_bounds= boxWidget->GetRepresentation()->GetBounds();
|
||||
|
||||
for(int ii =0 ;ii<6 ;ii+=2 ){
|
||||
if(ac_bounds[ii]<nominalBounds[ii])
|
||||
ac_bounds[ii]=nominalBounds[ii];
|
||||
}
|
||||
|
||||
for(int ii =1 ;ii<6 ;ii+=2 ){
|
||||
if(ac_bounds[ii]>nominalBounds[ii])
|
||||
ac_bounds[ii]=nominalBounds[ii];
|
||||
}
|
||||
|
||||
boxWidget->PlaceWidget(ac_bounds);
|
||||
// boxWidget->Render();
|
||||
|
||||
/*clip the orthoplanes*/
|
||||
extractVOI->SetVOI( nominalExtent[0] + (int) (abs(ac_bounds[0]-nominalBounds[0])/VolSpacing[0]),
|
||||
nominalExtent[1] - (int) (abs(ac_bounds[1]-nominalBounds[1])/VolSpacing[0]),
|
||||
nominalExtent[2] +(int) (abs(ac_bounds[2]-nominalBounds[2])/VolSpacing[1]),
|
||||
nominalExtent[3] -(int) (abs(ac_bounds[3]-nominalBounds[3])/VolSpacing[1]),
|
||||
nominalExtent[4] + (int) (abs(ac_bounds[4]-nominalBounds[4])/VolSpacing[2]),
|
||||
nominalExtent[5] -(int) (abs(ac_bounds[5]-nominalBounds[5])/VolSpacing[2])
|
||||
);
|
||||
|
||||
|
||||
/*clip the vol ren*/
|
||||
vtkPlanes *planes = vtkPlanes::New();
|
||||
// The implicit function vtkPlanes is used in conjunction with the
|
||||
// volume ray cast mapper to limit which portion of the volume is
|
||||
// volume rendered.
|
||||
boxWidget->GetPlanes(planes);
|
||||
this->rcm->SetClippingPlanes(planes);
|
||||
}
|
||||
|
||||
void setNominalGeometry(int* extents, double* bounds, double* spacing){
|
||||
memcpy(&nominalBounds,bounds,6*sizeof(double));
|
||||
memcpy(&nominalExtent,extents,6*sizeof(int));
|
||||
memcpy(&VolSpacing,spacing,3*sizeof(double));
|
||||
}
|
||||
|
||||
void setExtractVoiFilter(vtkExtractVOI* p_extractVOI){
|
||||
extractVOI=p_extractVOI;
|
||||
};
|
||||
|
||||
private:
|
||||
vtkExtractVOI* extractVOI;
|
||||
double nominalBounds[6];
|
||||
int nominalExtent[6];
|
||||
double VolSpacing[3];
|
||||
};
|
||||
|
||||
|
||||
// This does the actual work.
|
||||
// Callback for the interaction
|
||||
class vtkBoxCallback : public vtkCommand
|
||||
{
|
||||
public:
|
||||
static vtkBoxCallback *New()
|
||||
{
|
||||
return new vtkBoxCallback;
|
||||
}
|
||||
|
||||
void setExtractVoiFilter(vtkExtractVOI* p_extractVOI){
|
||||
extractVOI=p_extractVOI;
|
||||
};
|
||||
|
||||
void setVolumeMapper(vtkSmartVolumeMapper* p_mapper){
|
||||
volMapper=p_mapper;
|
||||
}
|
||||
|
||||
void setRenderer(vtkRenderer* p_ren){
|
||||
ren=p_ren;
|
||||
}
|
||||
|
||||
void setNominalGeometry(int* extents, double* bounds, double* spacing){
|
||||
memcpy(&nominalBounds,bounds,6*sizeof(double));
|
||||
memcpy(&nominalExtent,extents,6*sizeof(int));
|
||||
memcpy(&VolSpacing,spacing,3*sizeof(double));
|
||||
}
|
||||
|
||||
virtual void Execute(vtkObject *caller, unsigned long, void*)
|
||||
{
|
||||
|
||||
vtkBoxWidget2 *boxWidget = reinterpret_cast<vtkBoxWidget2*>(caller);
|
||||
|
||||
// Get the actual box coordinates/planes
|
||||
vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
|
||||
static_cast<vtkBoxRepresentation*>(boxWidget->GetRepresentation())->GetPolyData (polydata);
|
||||
|
||||
/*check if box is larger than volume size*/
|
||||
double *ac_bounds= boxWidget->GetRepresentation()->GetBounds();
|
||||
|
||||
for(int ii =0 ;ii<6 ;ii+=2 ){
|
||||
if(ac_bounds[ii]<nominalBounds[ii])
|
||||
ac_bounds[ii]=nominalBounds[ii];
|
||||
}
|
||||
|
||||
for(int ii =1 ;ii<6 ;ii+=2 ){
|
||||
if(ac_bounds[ii]>nominalBounds[ii])
|
||||
ac_bounds[ii]=nominalBounds[ii];
|
||||
}
|
||||
|
||||
boxWidget->GetRepresentation()->PlaceWidget(ac_bounds);
|
||||
boxWidget->Render();
|
||||
|
||||
// Display the center of the box
|
||||
// double p[3];
|
||||
// polydata->GetPoint(14,p); // As per the vtkBoxRepresentation documentation, the 15th point (index 14) is the center of the box
|
||||
//std::cout << "Box center: " << p[0] << " " << p[1] << " " << p[2] << std::endl;
|
||||
|
||||
//cout<<"nominal VOI"<<extractVOI->GetVOI()[0]<<" "<<extractVOI->GetVOI()[1]<<" "<<extractVOI->GetVOI()[2]<<" "<<
|
||||
// extractVOI->GetVOI()[3]<<" "<<extractVOI->GetVOI()[4]<<" "<<extractVOI->GetVOI()[5]<<endl;
|
||||
|
||||
cout<<"nominal VOI"<<nominalExtent[0]<<" "<<nominalExtent[1]<<" "<<nominalExtent[2]<<" "<<
|
||||
nominalExtent[3]<<" "<<nominalExtent[4]<<" "<<nominalExtent[5]<<endl;
|
||||
|
||||
cout<< "new VOI" << nominalExtent[0] + (int) (abs(ac_bounds[0]-nominalBounds[0])/VolSpacing[0])<<" "<<
|
||||
nominalExtent[1] - (int) (abs(ac_bounds[1]-nominalBounds[1])/VolSpacing[0])<<" "<<
|
||||
nominalExtent[2] +(int) (abs(ac_bounds[2]-nominalBounds[2])/VolSpacing[1])<<" "<<
|
||||
nominalExtent[3] -(int) (abs(ac_bounds[3]-nominalBounds[3])/VolSpacing[1])<<" "<<
|
||||
nominalExtent[4] + (int) (abs(ac_bounds[4]-nominalBounds[4])/VolSpacing[2])<<" "<<
|
||||
nominalExtent[5] -(int) (abs(ac_bounds[5]-nominalBounds[5])/VolSpacing[2]) <<endl;
|
||||
|
||||
extractVOI->SetVOI( nominalExtent[0] + (int) (abs(ac_bounds[0]-nominalBounds[0])/VolSpacing[0]),
|
||||
nominalExtent[1] - (int) (abs(ac_bounds[1]-nominalBounds[1])/VolSpacing[0]),
|
||||
nominalExtent[2] +(int) (abs(ac_bounds[2]-nominalBounds[2])/VolSpacing[1]),
|
||||
nominalExtent[3] -(int) (abs(ac_bounds[3]-nominalBounds[3])/VolSpacing[1]),
|
||||
nominalExtent[4] + (int) (abs(ac_bounds[4]-nominalBounds[4])/VolSpacing[2]),
|
||||
nominalExtent[5] -(int) (abs(ac_bounds[5]-nominalBounds[5])/VolSpacing[2])
|
||||
);
|
||||
|
||||
//extractVOI->Update();
|
||||
//volMapper->Update();
|
||||
ren->Render();
|
||||
|
||||
}
|
||||
vtkBoxCallback(){}
|
||||
|
||||
private:
|
||||
vtkExtractVOI* extractVOI;
|
||||
double nominalBounds[6];
|
||||
int nominalExtent[6];
|
||||
double VolSpacing[3];
|
||||
vtkRenderer* ren;
|
||||
vtkSmartVolumeMapper* volMapper;
|
||||
|
||||
};
|
||||
|
||||
class gRen : public QObject{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
gRen( QVTKWidget* m_qvtk);
|
||||
vtkImageData* getVolume(){return extractVOI->GetOutput();}
|
||||
double* getSpacing(){return CTvolume->GetSpacing();};
|
||||
|
||||
private:
|
||||
vtkSmartPointer<vtkImageData> CTvolume;
|
||||
vtkSmartPointer <vtkOutlineFilter> outline;
|
||||
vtkSmartPointer <vtkActor> outlineActor;
|
||||
vtkImageMapToColors* colorMap_X;
|
||||
vtkImagePlaneWidget* planeWidgetX;
|
||||
vtkImagePlaneWidget* planeWidgetY;
|
||||
vtkImagePlaneWidget* planeWidgetZ;
|
||||
QVTKWidget* qvtk;
|
||||
vtkImageOrthoPlanes* orthoPlanes;
|
||||
vtkAxesActor * assi;
|
||||
vtkRenderer* ren1;
|
||||
|
||||
vtkSmartPointer<vtkSmartVolumeMapper> volumeMapper;
|
||||
vtkSmartPointer<vtkColorTransferFunction> color;
|
||||
vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity;
|
||||
vtkSmartPointer<vtkVolume> volume;
|
||||
vtkSmartPointer<vtkVolumeProperty> volumeProperty;
|
||||
vtkSmartPointer<vtkBoxWidget2> boxWidget;
|
||||
vtkSmartPointer<vtkBoxRepresentation> boxRepresentation;
|
||||
vtkSmartPointer<vtkBoxCallback> boxCallback ;
|
||||
vtkSmartPointer<vtkMyCallback> boxCallback_NEW;
|
||||
vtkSmartPointer<vtkExtractVOI> extractVOI;
|
||||
vtkBoxWidget *boxWidget_NEW;
|
||||
|
||||
vtkSphereSource** markerSources;
|
||||
vtkPolyDataMapper** markerMappers;
|
||||
vtkActor** markerActors;
|
||||
vtkSmartPointer<vtkPoints> modelPoints;
|
||||
vtkSmartPointer<vtkActor2D> pointLabels;
|
||||
int nmarker;
|
||||
vtkSmartPointer<vtkStringArray> stringData;
|
||||
vtkSmartPointer<vtkCellArray> cells ;
|
||||
vtkSmartPointer<vtkPolyData> polyData;
|
||||
vtkSmartPointer<vtkIdFilter> ids;
|
||||
vtkSmartPointer<vtkLabeledDataMapper> ldm;
|
||||
|
||||
struct{
|
||||
int extent [6];
|
||||
double center [3];
|
||||
double origin [3];
|
||||
double spacing [3];
|
||||
QString fName;
|
||||
void clear(){
|
||||
std::fill(extent,extent+6,9999);
|
||||
std::fill(center,center+3,9999);
|
||||
std::fill(origin,origin+3,9999);
|
||||
std::fill(spacing,spacing+3,9999);
|
||||
fName.clear();
|
||||
};
|
||||
}CTinfos;
|
||||
|
||||
void buildRenderPipe();
|
||||
void createRenderers();
|
||||
|
||||
|
||||
public slots:
|
||||
void loadVolume (vtkImageData* volCT);
|
||||
void renderMarkers(QList<surf> marker_list);
|
||||
void onRequestRenderChange(int idx);
|
||||
void onRequestManualMask(int idx);
|
||||
void onAutoSkullMaskEnd(vtkImageData* fixedVol);
|
||||
void onSingleMarkerChange(int idx,bool state);
|
||||
void onReferenceChange(double dx, double dy, double dz);
|
||||
|
||||
|
||||
|
||||
signals:
|
||||
void PatientLoaded();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
Executable
+264
@@ -0,0 +1,264 @@
|
||||
#include "gSkullRemoval.h"
|
||||
//
|
||||
///**
|
||||
// * This will be setup as a callback for a progress event on an ITK
|
||||
// * filter.
|
||||
// */
|
||||
//struct ProgressDisplay
|
||||
//{
|
||||
//
|
||||
//public:
|
||||
// QString observedProcess;
|
||||
//
|
||||
// ProgressDisplay(itk::ProcessObject* process,QString observed): m_Process(process) {
|
||||
// observedProcess=observed;
|
||||
// }
|
||||
//
|
||||
// void Display()
|
||||
// {
|
||||
// float progress = m_Process->GetProgress()*100.0;
|
||||
// cout <<progress<<endl;
|
||||
// }
|
||||
// itk::ProcessObject::Pointer m_Process;
|
||||
//};
|
||||
|
||||
gSkullRemoval::gSkullRemoval()
|
||||
{
|
||||
|
||||
aborted=false;
|
||||
vtkImporter1=vtkSmartPointer<vtkImageImport>::New();
|
||||
vtkExporter = vtkSmartPointer<vtkImageExport>::New();
|
||||
smoothing = CurvatureFlowImageFilterType::New();
|
||||
connectedThreshold = ConnectedFilterType::New();
|
||||
binaryErodeFilter = ErodeFilterType::New();
|
||||
binaryDilateFilter = DilateFilterType::New();
|
||||
itkExporter1 = ExportFilter1Type::New();
|
||||
itkImporter = ImportFilterType::New();
|
||||
caster_writer_inv =CastingwriterINVFilterType::New();
|
||||
maskNegatedFilter = MaskNegatedFilterType::New();
|
||||
caster_writer = CastingwriterFilterType::New();
|
||||
caster = CastingFilterType::New();
|
||||
|
||||
/*TEST*/
|
||||
m_RedrawCommand = RedrawCommandType::New();
|
||||
m_RedrawCommand->SetCallbackFunction( this, &gSkullRemoval::ProcessEvent );
|
||||
m_RedrawCommand->SetCallbackFunction( this, &gSkullRemoval::ConstProcessEvent );
|
||||
|
||||
this->Observe(smoothing.GetPointer());
|
||||
this->Observe(connectedThreshold.GetPointer());
|
||||
this->Observe(binaryErodeFilter.GetPointer());
|
||||
this->Observe(binaryDilateFilter.GetPointer());
|
||||
this->Observe(maskNegatedFilter.GetPointer());
|
||||
}
|
||||
gSkullRemoval::~gSkullRemoval()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void gSkullRemoval::runFilter(vtkImageData* inputVolume,double thr_low, double thr_up)
|
||||
{
|
||||
// imageProcessing();
|
||||
// ProgressDisplay progDisplaySmooth (smoothing,"Smoothing");
|
||||
//itk::SimpleMemberCommand<ProgressDisplay>::Pointer progEventSmooth = itk::SimpleMemberCommand<ProgressDisplay>::New();
|
||||
//progEventSmooth->SetCallbackFunction(&progDisplaySmooth,&ProgressDisplay::Display);
|
||||
//smoothing->AddObserver(itk::ProgressEvent(), progEventSmooth);
|
||||
// ProgressDisplay progDisplayRegion (connectedThreshold,"Region growing");
|
||||
//itk::SimpleMemberCommand<ProgressDisplay>::Pointer progEventRegion = itk::SimpleMemberCommand<ProgressDisplay>::New();
|
||||
//progEventRegion->SetCallbackFunction(&progDisplayRegion,&ProgressDisplay::Display);
|
||||
//connectedThreshold->AddObserver(itk::ProgressEvent(), progEventRegion);
|
||||
|
||||
// ProgressDisplay progDisplayErode (binaryErodeFilter,"Morphological erode");
|
||||
// itk::SimpleMemberCommand<ProgressDisplay>::Pointer progEventErode = itk::SimpleMemberCommand<ProgressDisplay>::New();
|
||||
// progEventErode->SetCallbackFunction(&progDisplayErode,&ProgressDisplay::Display);
|
||||
// binaryErodeFilter->AddObserver(itk::ProgressEvent(), progEventErode);
|
||||
|
||||
// ProgressDisplay progDisplayDilate(binaryDilateFilter,"Morphological dilate");
|
||||
// itk::SimpleMemberCommand<ProgressDisplay>::Pointer progEventDilate = itk::SimpleMemberCommand<ProgressDisplay>::New();
|
||||
// progEventDilate->SetCallbackFunction(&progDisplayDilate,&ProgressDisplay::Display);
|
||||
// binaryDilateFilter->AddObserver(itk::ProgressEvent(), progEventDilate);
|
||||
|
||||
|
||||
vtkExporter->SetInput(inputVolume);
|
||||
ConnectPipelines(vtkExporter.GetPointer(), itkImporter);
|
||||
caster_writer_inv->SetInput(itkImporter->GetOutput());
|
||||
smoothing->SetInput( caster_writer_inv->GetOutput() );
|
||||
connectedThreshold->SetInput( smoothing->GetOutput() );
|
||||
connectedThreshold->Update();
|
||||
caster->SetInput( connectedThreshold->GetOutput() );
|
||||
smoothing->SetNumberOfIterations( 10 );
|
||||
smoothing->SetTimeStep( 0.125 );
|
||||
const InternalPixelType lowerThreshold = thr_low ;
|
||||
const InternalPixelType upperThreshold = thr_up;
|
||||
connectedThreshold->SetLower( lowerThreshold );
|
||||
connectedThreshold->SetUpper( upperThreshold );
|
||||
connectedThreshold->SetReplaceValue( 255 );
|
||||
InternalImageType::Pointer inputImage = caster_writer_inv->GetOutput();
|
||||
InternalImageType::SizeType size = inputImage->GetBufferedRegion().GetSize();
|
||||
InternalImageType::IndexType start = inputImage->GetBufferedRegion().GetIndex();
|
||||
|
||||
// set a seed by default in the center of the image.
|
||||
InternalImageType::IndexType seed;
|
||||
seed[0] = start[0] + size[0] / 2;
|
||||
seed[1] = start[1] + size[1] / 2;
|
||||
seed[2] = start[2] + size[2] / 2;
|
||||
connectedThreshold->SetSeed( seed );
|
||||
|
||||
StructuringElementType structuringElement;
|
||||
structuringElement.SetRadius( 10 );
|
||||
structuringElement.CreateStructuringElement();
|
||||
binaryDilateFilter->SetKernel( structuringElement );
|
||||
binaryErodeFilter->SetKernel( structuringElement );
|
||||
binaryDilateFilter->SetInput( caster->GetOutput() );
|
||||
binaryErodeFilter->SetInput( binaryDilateFilter->GetOutput() );
|
||||
binaryDilateFilter->SetDilateValue( 255 );
|
||||
binaryErodeFilter->SetErodeValue( 255 );
|
||||
|
||||
// if (dcmoutput == 1) writer->SetInput(binaryErodeFilter->GetOutput());
|
||||
maskNegatedFilter->SetInput1(caster_writer_inv->GetOutput());
|
||||
maskNegatedFilter->SetInput2(binaryErodeFilter->GetOutput());
|
||||
|
||||
// maskNegatedFilter->Update();
|
||||
|
||||
//caster_writer->SetInput(maskNegatedFilter->GetOutput());
|
||||
// if (dcmoutput == 1){ writer_internal->SetFileName( "/home/gio/dati/output/out_mask.dcm" );
|
||||
// writer_internal->SetInput(caster_writer->GetOutput());};
|
||||
|
||||
bool execeptCaught = false;
|
||||
|
||||
itkImporter->ReleaseDataFlagOn();
|
||||
//caster_writer_inv->ReleaseDataFlagOn();
|
||||
connectedThreshold->ReleaseDataFlagOn();
|
||||
binaryDilateFilter->ReleaseDataFlagOn();
|
||||
binaryErodeFilter->ReleaseDataFlagOn();
|
||||
|
||||
//maskNegatedFilter->ReleaseDataFlagOn();
|
||||
|
||||
try {
|
||||
maskNegatedFilter.GetPointer()->Update();
|
||||
}
|
||||
catch( itk::ExceptionObject & excep )
|
||||
{
|
||||
if (aborted) std::cerr << "Abort caught!" << std::endl;
|
||||
else {
|
||||
execeptCaught=true;
|
||||
emit errMsg(QString(excep.GetDescription()));
|
||||
std::cerr << "Exception caught !" << std::endl;
|
||||
std::cerr << excep << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
if (!aborted && execeptCaught==false){
|
||||
|
||||
|
||||
// fixedVolume->DeepCopy(inputVolume);
|
||||
|
||||
// try
|
||||
// {
|
||||
// // if (dcmoutput == 1) {writer->Update();
|
||||
// // writer_internal->Update();};
|
||||
// fixedVolume->DeepCopy(vtkImporter1->GetOutput());
|
||||
// cout<<"finito itk"<<endl;
|
||||
// }
|
||||
// catch( itk::ExceptionObject & excep )
|
||||
// {
|
||||
// std::cerr << "Exception caught !" << std::endl;
|
||||
// std::cerr << excep << std::endl;
|
||||
// };
|
||||
|
||||
|
||||
//typedef itk::ImageFileWriter< InternalImageType > WriterType;
|
||||
//WriterType::Pointer writer = WriterType::New();
|
||||
//writer->SetFileName("out.mha");
|
||||
//writer->SetInput( maskNegatedFilter->GetOutput() );
|
||||
//writer->Update();
|
||||
//
|
||||
|
||||
|
||||
itkExporter1->SetInput( maskNegatedFilter->GetOutput() );
|
||||
ConnectPipelines(itkExporter1.GetPointer(), vtkImporter1);
|
||||
vtkImporter1->Update();
|
||||
|
||||
emit skull_mask_end(vtkImporter1->GetOutput());
|
||||
//fixedVolume->DeepCopy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gSkullRemoval::abortSignal()
|
||||
{
|
||||
aborted=true;
|
||||
// cout<<"arrivato segnale di abort in itk: setto gli abort generate data"<<endl;
|
||||
|
||||
vtkImporter1->AbortExecuteOn();
|
||||
maskNegatedFilter.GetPointer()->AbortGenerateDataOn();
|
||||
binaryErodeFilter.GetPointer()->AbortGenerateDataOn();
|
||||
binaryDilateFilter.GetPointer()->AbortGenerateDataOn();
|
||||
connectedThreshold.GetPointer()->AbortGenerateDataOn();
|
||||
smoothing.GetPointer()->AbortGenerateDataOn();
|
||||
|
||||
// cout<<"fatto"<<endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*TEST*/
|
||||
|
||||
|
||||
|
||||
/** Manage a Progress event */
|
||||
void
|
||||
gSkullRemoval::ProcessEvent( itk::Object * caller,
|
||||
const itk::EventObject & event )
|
||||
{
|
||||
if( typeid( itk::ProgressEvent ) == typeid( event ) )
|
||||
{
|
||||
::itk::ProcessObject::Pointer process =
|
||||
dynamic_cast< itk::ProcessObject *>( caller );
|
||||
if(caller == smoothing)
|
||||
emit skull_mask_upd("2/5 : Surface smoothing...", process->GetProgress());
|
||||
|
||||
if(caller == connectedThreshold)
|
||||
emit skull_mask_upd("1/5 : Region growing...", process->GetProgress());
|
||||
|
||||
if(caller == binaryErodeFilter)
|
||||
emit skull_mask_upd("4/5 : Morphological erode...", process->GetProgress());
|
||||
|
||||
if(caller ==binaryDilateFilter)
|
||||
emit skull_mask_upd("3/5 : Morphological dilate...", process->GetProgress());
|
||||
|
||||
if(caller == maskNegatedFilter)
|
||||
emit skull_mask_upd("5/5 : Volume masking...", process->GetProgress());
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
gSkullRemoval::ConstProcessEvent( const itk::Object * caller,
|
||||
const itk::EventObject & event )
|
||||
{
|
||||
if( typeid( itk::ProgressEvent ) == typeid( event ) )
|
||||
{
|
||||
itk::ProcessObject::ConstPointer process =
|
||||
dynamic_cast< const itk::ProcessObject *>( caller );
|
||||
cout<< "B"<< process->GetProgress() <<endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Manage a Progress event */
|
||||
void
|
||||
gSkullRemoval::Observe( itk::Object *caller )
|
||||
{
|
||||
caller->AddObserver( itk::ProgressEvent(), m_RedrawCommand.GetPointer() );
|
||||
}
|
||||
Executable
+172
@@ -0,0 +1,172 @@
|
||||
#ifndef GSKULLREMOVAL_H
|
||||
#define GSKULLREMOVAL_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <itkImage.h>
|
||||
#include <itkVTKImageExport.h>
|
||||
#include <itkNormalizedCorrelationPointSetToImageMetric.h>
|
||||
#include <itkNormalizedCorrelationImageToImageMetric.h>
|
||||
#include <itkBinaryThresholdImageFilter.h>
|
||||
#include <itkPointSet.h>
|
||||
#include <itkConnectedThresholdImageFilter.h>
|
||||
#include <itkCastImageFilter.h>
|
||||
#include <itkCurvatureFlowImageFilter.h>
|
||||
#include <itkConnectedComponentImageFilter.h>
|
||||
#include <itkBinaryErodeImageFilter.h>
|
||||
#include <itkBinaryDilateImageFilter.h>
|
||||
#include <itkMaskNegatedImageFilter.h>
|
||||
#include <itkBinaryBallStructuringElement.h>
|
||||
#include <itkImageSeriesReader.h>
|
||||
#include <itkProcessObject.h>
|
||||
#include <itkCommand.h>
|
||||
#include <itkImage.h>
|
||||
#include <itkVTKImageExport.h>
|
||||
#include <itkVTKImageImport.h>
|
||||
#include <itkCastImageFilter.h>
|
||||
#include <itkImageFileWriter.h>
|
||||
#include <itkEventObject.h>
|
||||
#include <itkSmartPointer.h>
|
||||
|
||||
#include <vtkImageData.h>
|
||||
#include <vtkEvent.h>
|
||||
#include <vtkImageExport.h>
|
||||
#include <vtkExporter.h>
|
||||
#include <vtkImageImport.h>
|
||||
#include <vtkImporter.h>
|
||||
#include <vtkSmartPointer.h>
|
||||
#include <vtkObject.h>
|
||||
#include <vtkSmartPointer.h>
|
||||
#include "itkQtAdaptor.h"
|
||||
|
||||
|
||||
|
||||
const unsigned int Dimension = 3;
|
||||
//typedef float InternalPixelType;
|
||||
typedef signed short InternalPixelType;
|
||||
typedef itk::Image< InternalPixelType, Dimension > InternalImageType;
|
||||
typedef unsigned char OutputPixelType;
|
||||
typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
|
||||
typedef short int writerPixelType;
|
||||
typedef itk::Image< writerPixelType, Dimension > writerImageType;
|
||||
typedef itk::CastImageFilter< InternalImageType, writerImageType > CastingwriterFilterType;
|
||||
typedef itk::CastImageFilter< writerImageType, InternalImageType > CastingwriterINVFilterType;
|
||||
typedef itk::ConnectedThresholdImageFilter< InternalImageType, InternalImageType > ConnectedFilterType;
|
||||
typedef itk::CastImageFilter< InternalImageType, OutputImageType > CastingFilterType;
|
||||
typedef itk::ImageFileReader< InternalImageType > ReaderType;
|
||||
typedef itk::ImageFileWriter< OutputImageType > WriterType;
|
||||
typedef itk::CurvatureFlowImageFilter< InternalImageType, InternalImageType > CurvatureFlowImageFilterType;
|
||||
typedef itk::VTKImageImport<writerImageType> ImportFilterType;
|
||||
typedef itk::BinaryBallStructuringElement < unsigned char, 3 > StructuringElementType;
|
||||
typedef itk::BinaryErodeImageFilter < OutputImageType, OutputImageType, StructuringElementType> ErodeFilterType;
|
||||
typedef itk::BinaryDilateImageFilter < OutputImageType, OutputImageType, StructuringElementType> DilateFilterType;
|
||||
typedef itk::MaskNegatedImageFilter<InternalImageType, OutputImageType, InternalImageType> MaskNegatedFilterType;
|
||||
// typedef itk::ImageFileWriter< writerImageType > WriterTypeInternal;
|
||||
typedef unsigned char MaskPixelType;
|
||||
typedef itk::Image< MaskPixelType, Dimension > MaskImageType;
|
||||
typedef itk::VTKImageExport< InternalImageType > ExportFilter1Type;
|
||||
typedef itk::VTKImageExport< MaskImageType > ExportFilter2Type;
|
||||
|
||||
template <typename ITK_Exporter, typename VTK_Importer>
|
||||
void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer)
|
||||
{
|
||||
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
|
||||
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
|
||||
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
|
||||
importer->SetSpacingCallback(exporter->GetSpacingCallback());
|
||||
importer->SetOriginCallback(exporter->GetOriginCallback());
|
||||
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
|
||||
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
|
||||
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
|
||||
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
|
||||
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
|
||||
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
|
||||
importer->SetCallbackUserData(exporter->GetCallbackUserData());
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will connect the given vtkImageExport filter to
|
||||
* the given itk::VTKImageImport filter.
|
||||
*/
|
||||
template <typename VTK_Exporter, typename ITK_Importer>
|
||||
void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer)
|
||||
{
|
||||
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
|
||||
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
|
||||
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
|
||||
importer->SetSpacingCallback(exporter->GetSpacingCallback());
|
||||
importer->SetOriginCallback(exporter->GetOriginCallback());
|
||||
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
|
||||
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
|
||||
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
|
||||
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
|
||||
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
|
||||
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
|
||||
importer->SetCallbackUserData(exporter->GetCallbackUserData());
|
||||
}
|
||||
|
||||
|
||||
|
||||
class gSkullRemoval : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
gSkullRemoval();
|
||||
~gSkullRemoval();
|
||||
|
||||
|
||||
/*test*/
|
||||
|
||||
/** Command Class invoked for button redraw */
|
||||
typedef itk::MemberCommand< gSkullRemoval > RedrawCommandType;
|
||||
/** Get Command */
|
||||
RedrawCommandType * GetRedrawCommand( void ) const;
|
||||
|
||||
|
||||
/** Manage a Progress event */
|
||||
void ProcessEvent(itk::Object * caller, const itk::EventObject & event );
|
||||
void ConstProcessEvent(const itk::Object * caller, const itk::EventObject & event );
|
||||
|
||||
|
||||
/** Manage a Progress event */
|
||||
void Observe( itk::Object *caller );
|
||||
private:
|
||||
|
||||
RedrawCommandType::Pointer m_RedrawCommand;
|
||||
|
||||
/*ENDTEST*/
|
||||
public slots:
|
||||
void runFilter(vtkImageData* inputVolume,double thr_low, double thr_up);
|
||||
void abortSignal();
|
||||
|
||||
private:
|
||||
vtkImageData *fixedVolume;
|
||||
int dcmoutput;
|
||||
bool aborted;
|
||||
|
||||
|
||||
private:
|
||||
vtkSmartPointer<vtkImageImport> vtkImporter1;
|
||||
vtkSmartPointer<vtkImageExport> vtkExporter;
|
||||
CurvatureFlowImageFilterType::Pointer smoothing;
|
||||
ConnectedFilterType::Pointer connectedThreshold;
|
||||
ErodeFilterType::Pointer binaryErodeFilter;
|
||||
DilateFilterType::Pointer binaryDilateFilter;
|
||||
ExportFilter1Type::Pointer itkExporter1;
|
||||
CastingwriterINVFilterType::Pointer caster_writer_inv;
|
||||
MaskNegatedFilterType::Pointer maskNegatedFilter;
|
||||
ImportFilterType :: Pointer itkImporter;
|
||||
writerImageType *importedITK;
|
||||
InternalImageType *fixedITK;
|
||||
CastingwriterFilterType::Pointer caster_writer ;
|
||||
CastingFilterType::Pointer caster;
|
||||
|
||||
signals:
|
||||
void skull_mask_end(vtkImageData * fixedVolume);
|
||||
void errMsg(QString msg);
|
||||
void skull_mask_upd(QString msg, double val);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 81 KiB |
Executable
+8
@@ -0,0 +1,8 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>icons/pb_load.png</file>
|
||||
<file>icons/pb_quit.png</file>
|
||||
<file>icons/ortoIco.png</file>
|
||||
<file>icons/volrenIco.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
Executable
+162
@@ -0,0 +1,162 @@
|
||||
/*=========================================================================
|
||||
|
||||
Program: Insight Segmentation & Registration Toolkit
|
||||
Module: itkQtAdaptor.h
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Insight Consortium. All rights reserved.
|
||||
See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
|
||||
|
||||
|
||||
#include <qobject.h>
|
||||
#include "itkObject.h"
|
||||
#include "itkObjectFactory.h"
|
||||
#include "itkCommand.h"
|
||||
|
||||
|
||||
namespace itk {
|
||||
|
||||
/** Helper class that interface with Qt Signals and Slots */
|
||||
class QtTranslator : public QObject
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QtTranslator() {}
|
||||
virtual ~QtTranslator() {}
|
||||
|
||||
signals:
|
||||
void Signal();
|
||||
|
||||
public slots:
|
||||
virtual void Slot() {};
|
||||
virtual void Slot(int) {};
|
||||
virtual void Slot(double) {};
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Helper class that interface Methods with Qt Slots */
|
||||
template <typename T>
|
||||
class QtSlotAdaptor : public QtTranslator
|
||||
{
|
||||
typedef void (T::*TMemberFunctionVoidPointer)();
|
||||
typedef void (T::*TMemberFunctionIntPointer)(int);
|
||||
typedef void (T::*TMemberFunctionDoublePointer)(double);
|
||||
|
||||
public:
|
||||
QtSlotAdaptor():m_MemberFunctionVoid(0),
|
||||
m_MemberFunctionInt(0),
|
||||
m_MemberFunctionDouble(0) {}
|
||||
|
||||
virtual ~QtSlotAdaptor() {}
|
||||
|
||||
/** Specify the callback function. */
|
||||
void SetCallbackFunction(T* object,
|
||||
TMemberFunctionVoidPointer memberFunction)
|
||||
{
|
||||
m_This = object;
|
||||
m_MemberFunctionVoid = memberFunction;
|
||||
}
|
||||
|
||||
/** Specify the callback function. */
|
||||
void SetCallbackFunction(T* object,
|
||||
TMemberFunctionIntPointer memberFunction)
|
||||
{
|
||||
m_This = object;
|
||||
m_MemberFunctionInt = memberFunction;
|
||||
}
|
||||
|
||||
/** Specify the callback function. */
|
||||
void SetCallbackFunction(T* object,
|
||||
TMemberFunctionDoublePointer memberFunction)
|
||||
{
|
||||
m_This = object;
|
||||
m_MemberFunctionDouble = memberFunction;
|
||||
}
|
||||
|
||||
/** Slot to be connected to Qt Signals. */
|
||||
void Slot()
|
||||
{
|
||||
if( m_MemberFunctionVoid )
|
||||
{
|
||||
((*m_This).*(m_MemberFunctionVoid))();
|
||||
}
|
||||
}
|
||||
|
||||
/** Slot to be connected to Qt Signals. */
|
||||
void Slot(int value)
|
||||
{
|
||||
if( m_MemberFunctionInt )
|
||||
{
|
||||
((*m_This).*(m_MemberFunctionInt))(value);
|
||||
}
|
||||
}
|
||||
|
||||
/** Slot to be connected to Qt Signals. */
|
||||
void Slot(double value)
|
||||
{
|
||||
if( m_MemberFunctionDouble )
|
||||
{
|
||||
((*m_This).*(m_MemberFunctionDouble))(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
T* m_This;
|
||||
TMemberFunctionVoidPointer m_MemberFunctionVoid;
|
||||
TMemberFunctionIntPointer m_MemberFunctionInt;
|
||||
TMemberFunctionDoublePointer m_MemberFunctionDouble;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Helper class that interface Observers with Qt Signals */
|
||||
class QtSignalAdaptor : public QtTranslator
|
||||
{
|
||||
typedef SimpleMemberCommand<QtSignalAdaptor> CommandType;
|
||||
|
||||
public:
|
||||
QtSignalAdaptor()
|
||||
{
|
||||
m_Command = CommandType::New();
|
||||
m_Command->SetCallbackFunction( this, & QtSignalAdaptor::EmitSignal );
|
||||
}
|
||||
|
||||
virtual ~QtSignalAdaptor() {}
|
||||
|
||||
CommandType * GetCommand()
|
||||
{
|
||||
return m_Command;
|
||||
}
|
||||
|
||||
void EmitSignal()
|
||||
{
|
||||
emit Signal();
|
||||
}
|
||||
|
||||
private:
|
||||
CommandType::Pointer m_Command;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // end namespace
|
||||
@@ -0,0 +1,83 @@
|
||||
|
||||
|
||||
#include "mainw.h"
|
||||
#include <qfile.h>
|
||||
#include "itkTextOutput.h"
|
||||
|
||||
#include <qsettings.h>
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
std::cout << "Hello, world!" << std::endl;
|
||||
|
||||
vtkObject::SetGlobalWarningDisplay(false);
|
||||
itk::OutputWindow::SetInstance(itk::TextOutput::New());
|
||||
|
||||
QApplication app(argc,argv);
|
||||
|
||||
if(!QFile("config.ini").exists()){
|
||||
QMessageBox msgBox;
|
||||
msgBox.setIcon(QMessageBox::Icon::Critical);
|
||||
msgBox.setText("gLocalize config file missing... Exiting.");
|
||||
msgBox.setInformativeText("Please add config.ini file in the gLocalize path.");
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
int ret = msgBox.exec();
|
||||
cout<<"prequit" <<endl;
|
||||
app.quit();;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
QSettings *config = new QSettings ("config.ini",QSettings::IniFormat);
|
||||
|
||||
/*if in/out dir not found. just exit*/
|
||||
if(!QDir(config->value("Path/inDir").toString()).exists() || !QDir(config->value("Path/outDir").toString()).exists()){
|
||||
QString userMsg;
|
||||
userMsg.clear();
|
||||
userMsg.append("Please check config.ini file parameters:\n");
|
||||
( QDir(config->value("Path/inDir").toString()).exists() == true? "" : userMsg.append("- Patient directory : [Path]/inDir\n") );
|
||||
( QDir(config->value("Path/outDir").toString()).exists() == true? "" : userMsg.append("- Output directory : [Path]/outDir\n") );
|
||||
|
||||
QMessageBox msgBox;
|
||||
msgBox.setIcon(QMessageBox::Icon::Critical);
|
||||
msgBox.setText("gLocalize configuration error... Exiting.");
|
||||
msgBox.setInformativeText(userMsg);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
|
||||
QSpacerItem* horizonatlSpacer= new QSpacerItem(300,0,QSizePolicy::Minimum,QSizePolicy::Expanding);
|
||||
QGridLayout* layout = (QGridLayout*) msgBox.layout();
|
||||
layout->addItem(horizonatlSpacer, layout->rowCount(), 0 ,1 ,layout->columnCount());
|
||||
|
||||
int ret = msgBox.exec();
|
||||
cout<<"prequit" <<endl;
|
||||
app.quit();
|
||||
delete config;
|
||||
return -1;
|
||||
}
|
||||
delete config;
|
||||
|
||||
QFile qss("style.qss");
|
||||
qss.open(QFile::ReadOnly);
|
||||
app.setStyleSheet(qss.readAll());
|
||||
qss.close();
|
||||
|
||||
QString loadPath;
|
||||
loadPath.clear();
|
||||
|
||||
if(argc==2)
|
||||
loadPath = app.arguments().at(1);
|
||||
|
||||
MainWindow* mainW= new MainWindow(loadPath);
|
||||
mainW->show();
|
||||
int res= app.exec();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
#ifndef _MAINW_H_
|
||||
#define _MAINW_H_
|
||||
|
||||
//#define MULTIPLE_REF
|
||||
|
||||
|
||||
#include <qtoolbar.h>
|
||||
#include <QVTKWidget.h>
|
||||
#include <qdockwidget.h>
|
||||
#include <qpushbutton.h>
|
||||
#include <qmainwindow.h>
|
||||
#include <qradiobutton.h>
|
||||
#include <qbuttongroup.h>
|
||||
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtGui/QAction>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QButtonGroup>
|
||||
#include <QtGui/QCheckBox>
|
||||
#include <QtGui/QDoubleSpinBox>
|
||||
#include <QtGui/QFormLayout>
|
||||
#include <QtGui/QFrame>
|
||||
#include <QtGui/QHBoxLayout>
|
||||
#include <QtGui/QHeaderView>
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QMainWindow>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QtGui/QSpacerItem>
|
||||
#include <QtGui/QSpinBox>
|
||||
#include <QtGui/QStatusBar>
|
||||
#include <QtGui/QToolBar>
|
||||
#include <QtGui/QTreeWidget>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QWidget>
|
||||
#include<QtGui/qprogressbar.h>
|
||||
#include <QtGui/qtreeview.h>
|
||||
|
||||
#include <qstandarditemmodel.h>
|
||||
|
||||
|
||||
#include "gRen.h"
|
||||
|
||||
//#include "wrkDirParser.h"
|
||||
//#include "loadDCM2VTK.h"
|
||||
#include "gPatientRTGeneralInfos.h"
|
||||
#include "dicomUtils.h"
|
||||
#include "connectITKVTK.h"
|
||||
#include <qthread.h>
|
||||
#include "gLoadPatient.h"
|
||||
|
||||
#include "gLocalize.h"
|
||||
|
||||
#include <qfiledialog.h>
|
||||
#include <qactiongroup.h>
|
||||
|
||||
#include <qmessagebox.h>
|
||||
|
||||
#include "gSkullRemoval.h"
|
||||
|
||||
#include <QTextStream.h>
|
||||
|
||||
class gLoadPatDialog: public QDialog{
|
||||
public:
|
||||
gLoadPatDialog(QWidget *parent = 0)
|
||||
: QDialog(parent){
|
||||
QVBoxLayout * lay = new QVBoxLayout(this);
|
||||
this->setModal(true);
|
||||
|
||||
message = new QLabel(this);
|
||||
lay->addWidget(message);
|
||||
|
||||
message->setText("Loading patient from wrkDir... Please wait.");
|
||||
};
|
||||
|
||||
private:
|
||||
QLabel *message;
|
||||
|
||||
};
|
||||
|
||||
class Ui_MainWindow {
|
||||
public:
|
||||
Ui_MainWindow(){};
|
||||
|
||||
QVTKWidget* qvtk;
|
||||
QAction *actionLoad;
|
||||
QAction *actionQuit;
|
||||
QAction *actionVolRen;
|
||||
QAction *actionOrthoslice;
|
||||
QWidget *centralwidget;
|
||||
QHBoxLayout *horizontalLayout_8;
|
||||
QWidget *widget;
|
||||
QVBoxLayout *verticalLayout_5;
|
||||
QFrame *frame_2;
|
||||
QVBoxLayout *verticalLayout_2;
|
||||
QFormLayout *formLayout_2;
|
||||
QLabel *label_6;
|
||||
QLabel *l_patientID;
|
||||
QLabel *label_8;
|
||||
QLabel *l_patientID_2;
|
||||
QLabel *label_12;
|
||||
QLabel *l_patientID_6;
|
||||
QLabel *label_isoV;
|
||||
QLabel *l_isoV;
|
||||
|
||||
|
||||
QFrame *frame_5;
|
||||
QVBoxLayout *verticalLayout_4;
|
||||
QHBoxLayout *horizontalLayout_7;
|
||||
QLabel *label_7;
|
||||
QPushButton *pushButton_5;
|
||||
QFrame *frame_3;
|
||||
QVBoxLayout *verticalLayout;
|
||||
QHBoxLayout *horizontalLayout;
|
||||
QLabel *label;
|
||||
QSpacerItem *horizontalSpacer;
|
||||
QSpinBox *spinBox;
|
||||
QHBoxLayout *horizontalLayout_2;
|
||||
QCheckBox *checkBox_2;
|
||||
QLabel *label_2;
|
||||
QSpacerItem *horizontalSpacer_2;
|
||||
QDoubleSpinBox *doubleSpinBox_2;
|
||||
QDoubleSpinBox *doubleSpinBox_2bis;
|
||||
QHBoxLayout *horizontalLayout_3;
|
||||
QCheckBox *checkBox_3;
|
||||
QLabel *label_3;
|
||||
QSpacerItem *horizontalSpacer_3;
|
||||
QDoubleSpinBox *doubleSpinBox_3;
|
||||
QHBoxLayout *horizontalLayout_4;
|
||||
QSpacerItem *horizontalSpacer_4;
|
||||
QHBoxLayout *horizontalLayout_5;
|
||||
QCheckBox *checkBox_5;
|
||||
QLabel *label_5;
|
||||
QSpacerItem *horizontalSpacer_5;
|
||||
QDoubleSpinBox *doubleSpinBox_5;
|
||||
QHBoxLayout *horizontalLayout_6;
|
||||
QPushButton *pushButton_3;
|
||||
QPushButton *pushButton_4;
|
||||
QFrame *frame_4;
|
||||
QVBoxLayout *verticalLayout_3;
|
||||
QTreeView *treeView;
|
||||
QHBoxLayout *formLayout;
|
||||
QPushButton *pushButton;
|
||||
QPushButton *pushButton_2;
|
||||
QFrame *frame;
|
||||
QStatusBar *statusbar;
|
||||
QToolBar *toolBar;
|
||||
QProgressBar *progBar;
|
||||
QActionGroup* viewGroup;
|
||||
QPushButton* pb_manualMask;
|
||||
QPushButton* pb_save;
|
||||
#ifdef MULTIPLE_REF
|
||||
QButtonGroup* refGroup;
|
||||
QRadioButton* a_DCMref;
|
||||
QRadioButton* a_RTref;
|
||||
QRadioButton* a_OTSref;
|
||||
#endif
|
||||
void setupUi(QMainWindow *MainWindow);
|
||||
|
||||
};
|
||||
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow(QString p_loadPath);
|
||||
~MainWindow();
|
||||
|
||||
private:
|
||||
Ui_MainWindow* Ui;
|
||||
void retranslateUi(Ui_MainWindow* Ui, QMainWindow *MainWindow);
|
||||
void connectUi(Ui_MainWindow* Ui);
|
||||
|
||||
gRen * Visualizer;
|
||||
//gPatientLoader* patientLoader;
|
||||
gLoadPatient* loadPatient;
|
||||
QThread* loadPatient_thread;
|
||||
|
||||
//loadDCM2VTK* load2vtk;
|
||||
//QThread* load2VtkThread;
|
||||
gLocalize* localize_marker;
|
||||
QThread* localize_thread;
|
||||
gSkullRemoval* skullRemoval;
|
||||
QThread* skull_thread;
|
||||
|
||||
QStandardItemModel* treeModel;
|
||||
QString loadPath;
|
||||
gLoadPatDialog* loadDialog;
|
||||
|
||||
double regGrownParameters[2];
|
||||
|
||||
QString pathIn;
|
||||
QString pathOut;
|
||||
|
||||
|
||||
|
||||
private slots:
|
||||
void call_localize_start();
|
||||
void call_localize_cancel();
|
||||
void call_visualize_all();
|
||||
void call_hide_all();
|
||||
void call_ToolbarAction(QAction* action);
|
||||
void call_skullMask();
|
||||
void call_loadPatient();
|
||||
void call_saveDotCtFile();
|
||||
void call_quit();
|
||||
void call_quit_nothreads();
|
||||
|
||||
void onParsedOK(int result, gPatientRTGeneralInfos* data);
|
||||
void onParsedEmptyFolder();
|
||||
void onLocalizationEnd(QList<surf> marker_list);
|
||||
void onLocalizationAborted();
|
||||
void onVisualizationTrigger(QAction* trigger_action);
|
||||
void onManualMaskTrigger(bool state);
|
||||
void onAutoMaskError(QString msg);
|
||||
void onItemChanged(QStandardItem* item);
|
||||
void setStatusMsg(QString msg, int timeout);
|
||||
void onVirtualIsoTested(bool IsoV);
|
||||
|
||||
|
||||
#ifdef MULTIPLE_REF
|
||||
void onRefTrigger(QAbstractButton* trigger_button);
|
||||
#endif
|
||||
void onPatientlLoaded();
|
||||
void onRTIsoAvailable(double* iso);
|
||||
void onCTVolumeAvailable(double* bounds, double* spacing, int* dim);
|
||||
void updateMarkerPos(double dx, double dy, double dz);
|
||||
|
||||
void onSkullMaskingUpdt(QString msg, double val);
|
||||
void onAutoSkullMaskEnd(vtkImageData* img);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user