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:
Giovanni Fattori
2014-10-13 15:41:02 +02:00
commit f18e57ff0e
23 changed files with 4735 additions and 0 deletions
Executable
+154
View File
@@ -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
)
+51
View File
@@ -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
View File
@@ -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
View File
@@ -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
+434
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+78
View File
@@ -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
Executable
+434
View File
@@ -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;
}
}
Executable
+298
View File
@@ -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
+264
View File
@@ -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() );
}
+172
View File
@@ -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
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Executable
+8
View File
@@ -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
View File
@@ -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
Executable
+83
View File
@@ -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;
}
Executable
+1043
View File
File diff suppressed because it is too large Load Diff
Executable
+237
View File
@@ -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