Merge branch 'codeRev' into 'master'

Code rev

See merge request gfattori/glocalize!1
This commit is contained in:
gfattori
2026-01-05 21:43:45 +00:00
23 changed files with 976 additions and 828 deletions
Executable → Regular
+146 -114
View File
@@ -1,132 +1,164 @@
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.22)
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)
project(gLocalize LANGUAGES CXX)
set(TRG gLocalize)
SET(SOURCE_FILES ${CMAKE_SOURCE_DIR})
INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}
${SOURCE_FILES}
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
${CMAKE_BINARY_DIR}
)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
find_package(HDF5 REQUIRED COMPONENTS C CXX HL)
INCLUDE_DIRECTORIES(${HDF5_INCLUDE_DIRS})
find_package(Qt6Core REQUIRED)
find_package(Qt6Gui REQUIRED)
find_package(Qt6Widgets REQUIRED)
find_package(Qt6Network REQUIRED)
find_package(Qt6Xml REQUIRED)
find_package(Qt6Svg REQUIRED)
include_directories(
${Qt6Core_INCLUDE_DIRS}
${Qt65Gui_INCLUDE_DIRS}
${Qt6Widgets_INCLUDE_DIRS}
${Qt6Network_INCLUDE_DIRS}
${Qt6Xml_INCLUDE_DIRS}
${Qt6Svg_INCLUDE_DIRS}
)
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
INCLUDE_DIRECTORIES(${ITK_INCLUDE_DIRS})
find_package(VTK REQUIRED)
INCLUDE_DIRECTORIES(${VTK_INCLUDE_DIRS})
FIND_PACKAGE(GDCM REQUIRED)
include(${GDCM_USE_FILE})
INCLUDE_DIRECTORIES(${GDCM_INCLUDE_DIRS})
set(SRCS
${SOURCE_FILES}/main.cpp
${SOURCE_FILES}/mainw.cpp
${SOURCE_FILES}/mainw.h
${SOURCE_FILES}/connectITKVTK.h
${SOURCE_FILES}/dicomUtils.cpp
${SOURCE_FILES}/dicomUtils.h
${SOURCE_FILES}/gPatientRTGeneralInfos.h
${SOURCE_FILES}/gRen.h
${SOURCE_FILES}/gRen.cpp
${SOURCE_FILES}/gLoadPatient.h
${SOURCE_FILES}/gLoadPatient.cpp
${SOURCE_FILES}/gLocalize.h
${SOURCE_FILES}/gLocalize.cpp
${SOURCE_FILES}/gSkullRemoval.h
${SOURCE_FILES}/gSkullRemoval.cpp
${SOURCE_FILES}/itkQtAdaptor.h
)
set(HDR
${SOURCE_FILES}/mainw.h
${SOURCE_FILES}/connectITKVTK.h
${SOURCE_FILES}/dicomUtils.h
${SOURCE_FILES}/gPatientRTGeneralInfos.h
${SOURCE_FILES}/gRen.h
${SOURCE_FILES}/gLoadPatient.h
${SOURCE_FILES}/gLocalize.h
${SOURCE_FILES}/gSkullRemoval.h
${SOURCE_FILES}/itkQtAdaptor.h
)
SET(RES ${PROJECT_SOURCE_DIR}/images.qrc)
QT6_ADD_RESOURCES(RES_RCC ${RES})
add_executable(${TRG}
${SRCS}
${RES_RCC}
)
set(GDCM_PREFIX "/usr/local/gdcm" CACHE PATH "GDCM install prefix")
set(GDCM_LIBDIR "${GDCM_PREFIX}/lib")
if(EXISTS "${GDCM_PREFIX}/lib64")
set(GDCM_LIBDIR "${GDCM_PREFIX}/lib64")
# --- Build type default ---
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()
set_property(TARGET gLocalize PROPERTY BUILD_RPATH "${GDCM_LIBDIR}")
set_property(TARGET gLocalize PROPERTY INSTALL_RPATH "${GDCM_LIBDIR}")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
target_link_options(gLocalize PRIVATE "-Wl,-rpath,/usr/local/gdcm/lib")
# Qt: enable automoc/uic/rcc
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
target_link_libraries(${TRG}
PRIVATE
Qt6::Network
# Prefer sane RPATH behavior without hardcoding /usr/local paths.
# If dependencies are properly installed in system paths, no RPATH is needed.
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_BUILD_RPATH_USE_ORIGIN TRUE)
# --- Dependencies ---
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Network Xml Svg OpenGL OpenGLWidgets)
# HDF5: use imported targets if provided, otherwise fall back to variables.
find_package(HDF5 REQUIRED COMPONENTS C CXX HL)
# ITK config package generally exports ITK_LIBRARIES as imported targets.
find_package(ITK REQUIRED)
# VTK: list the modules actually used by the code (Qt widget + volume rendering + widgets + imaging).
find_package(VTK REQUIRED
COMPONENTS
CommonCore
CommonDataModel
CommonTransforms
FiltersCore
FiltersGeneral
FiltersGeometry
FiltersModeling
FiltersSources
ImagingCore
ImagingGeneral
ImagingHybrid
InteractionStyle
InteractionWidgets
RenderingCore
RenderingOpenGL2
RenderingVolumeOpenGL2
RenderingAnnotation
RenderingFreeType
RenderingImage
RenderingQt
GUISupportQt
)
# GDCM: prefer config targets when available.
find_package(GDCM REQUIRED)
# --- Sources ---
set(SRCS
main.cpp
mainw.cpp
dicomUtils.cpp
gRen.cpp
gLoadPatient.cpp
gLocalize.cpp
gSkullRemoval.cpp
)
set(HDR
mainw.h
connectITKVTK.h
dicomUtils.h
gPatientRTGeneralInfos.h
gRen.h
gLoadPatient.h
gLocalize.h
gSkullRemoval.h
itkQtAdaptor.h
)
qt_add_resources(RES_RCC images.qrc)
add_executable(${TRG}
${SRCS}
${HDR}
${RES_RCC}
)
# Do NOT define QT_NO_KEYWORDS here: this project uses Qt's 'signals/slots/emit'
# keywords in headers, and disabling them breaks moc.
target_include_directories(${TRG}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
# --- Link libraries ---
target_link_libraries(${TRG}
PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
Qt6::OpenGL
Qt6::OpenGLWidgets
Qt6::Network
Qt6::Xml
Qt6::Svg
${VTK_LIBRARIES}
${ITK_LIBRARIES}
${GDCM_LIBRARIES}
m
${HDF5_CXX_LIBRARIES}
${HDF5_LIBRARIES}
)
# ITK: imported targets are typically in ITK_LIBRARIES
if(DEFINED ITK_LIBRARIES)
target_link_libraries(${TRG} PRIVATE ${ITK_LIBRARIES})
endif()
# VTK
target_link_libraries(${TRG} PRIVATE ${VTK_LIBRARIES})
# VTK 9.x + --as-needed: ensure GUISupportQt is explicitly linked when using QVTKOpenGLNativeWidget
if(TARGET VTK::GUISupportQt)
target_link_libraries(${TRG} PRIVATE VTK::GUISupportQt)
endif()
# VTK module auto-init (needed especially when VTK is built static or with some build options)
if(COMMAND vtk_module_autoinit)
vtk_module_autoinit(
TARGETS ${TRG}
MODULES ${VTK_LIBRARIES}
)
endif()
# GDCM (prefer targets; otherwise fallback to variables)
if(TARGET GDCM::gdcmMSFF)
target_link_libraries(${TRG} PRIVATE GDCM::gdcmMSFF)
elseif(DEFINED GDCM_LIBRARIES)
target_link_libraries(${TRG} PRIVATE ${GDCM_LIBRARIES})
endif()
# HDF5 (prefer targets; otherwise fallback to variables)
if(TARGET hdf5::hdf5_cpp)
target_link_libraries(${TRG} PRIVATE hdf5::hdf5_cpp)
endif()
if(TARGET hdf5::hdf5_hl_cpp)
target_link_libraries(${TRG} PRIVATE hdf5::hdf5_hl_cpp)
endif()
if(DEFINED HDF5_LIBRARIES)
target_link_libraries(${TRG} PRIVATE ${HDF5_LIBRARIES})
endif()
if(DEFINED HDF5_CXX_LIBRARIES)
target_link_libraries(${TRG} PRIVATE ${HDF5_CXX_LIBRARIES})
endif()
# math lib (Linux)
target_link_libraries(${TRG} PRIVATE m)
# Helpful warnings (tweak as you like)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(${TRG} PRIVATE -Wall -Wextra -Wpedantic)
endif()
Executable → Regular
View File
Executable → Regular
+248 -157
View File
@@ -1,26 +1,118 @@
#include "dicomUtils.h"
#include <sstream>
#include <algorithm>
#include <cctype>
using std::cout;
using std::endl;
namespace {
static inline std::string Trim(std::string s)
{
auto notSpace = [](unsigned char c) { return !std::isspace(c); };
s.erase(s.begin(), std::find_if(s.begin(), s.end(), notSpace));
s.erase(std::find_if(s.rbegin(), s.rend(), notSpace).base(), s.end());
return s;
}
static inline int ParseIntOr(const std::string& s, int fallback)
{
const std::string t = Trim(s);
if (t.empty()) return fallback;
try
{
size_t idx = 0;
int v = std::stoi(t, &idx);
(void)idx;
return v;
}
catch (...)
{
return fallback;
}
}
static inline double ParseDoubleOr(const std::string& s, double fallback)
{
const std::string t = Trim(s);
if (t.empty()) return fallback;
try
{
size_t idx = 0;
double v = std::stod(t, &idx);
(void)idx;
return v;
}
catch (...)
{
return fallback;
}
}
static inline int GetTagIntOr(const gdcm::Tag& t, const gdcm::DataSet& ds, int fallback)
{
return ParseIntOr(gGetStringValueFromTagStr(t, ds), fallback);
}
static inline double GetTagDoubleOr(const gdcm::Tag& t, const gdcm::DataSet& ds, double fallback)
{
return ParseDoubleOr(gGetStringValueFromTagStr(t, ds), fallback);
}
// Parse a DICOM "DS" multi-value string with 3 components separated by '\\'.
// Returns {BADVALUE,BADVALUE,BADVALUE} if parsing fails.
std::array<double, 3> Parse3Doubles(const std::string& s)
{
std::array<double, 3> out{BADVALUE, BADVALUE, BADVALUE};
if (s.empty()) return out;
std::stringstream ss(s);
std::string token;
for (int i = 0; i < 3; ++i)
{
if (!std::getline(ss, token, '\\')) return out;
try
{
out[static_cast<size_t>(i)] = std::stod(token);
}
catch (...)
{
return {BADVALUE, BADVALUE, BADVALUE};
}
}
return out;
}
} // namespace
//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)
const char *gGetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds)
{
// NOTE: legacy API returning pointer into a static buffer.
// Keep for older call sites.
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
buffer = gGetStringValueFromTagStr(t, ds);
return buffer.c_str();
};
}
std::string gGetStringValueFromTagStr(const gdcm::Tag& t, const gdcm::DataSet& ds)
{
if (!ds.FindDataElement(t)) return {};
const gdcm::DataElement& de = ds.GetDataElement(t);
const gdcm::ByteValue* bv = de.GetByteValue();
if (!bv) return {};
std::string s(bv->GetPointer(), bv->GetLength());
// DICOM strings are often space/\0 padded.
while (!s.empty() && (s.back() == '\0' || s.back() == ' ' || s.back() == '\r' || s.back() == '\n' || s.back() == '\t'))
s.pop_back();
return s;
}
//GENERAL INDEPENDENT FUNCTION TO CHECK FOR FILE DICOM MODALITY (PLAN, STRUCT, IMAGE) REQUIRES CORRECT PATH
const char * gCheckDICOMModality(const char *filename)
@@ -55,27 +147,20 @@ int gCheckDICOMModalityToInt(const char *filename){
IonBeamProperties::IonBeamProperties(){
BeamNumber = BADVALUE;
BeamName = new char [MAXSTRINGLENGHT];
SupportId = new char [MAXSTRINGLENGHT];
SupportType = new char [MAXSTRINGLENGHT];
GantryAngle = BADVALUE;
IsocenterPosition = new double [3];
TablePitchAngle= BADVALUE;
IonBeamProperties::IonBeamProperties()
{
BeamNumber = BADVALUE;
BeamName.clear();
SupportId.clear();
SupportType.clear();
GantryAngle = BADVALUE;
IsocenterPosition = {BADVALUE, BADVALUE, BADVALUE};
TablePitchAngle = BADVALUE;
TableRollAngle = BADVALUE;
TableYawAngle= BADVALUE;
TableLatDispl = BADVALUE;
TableLongDispl= BADVALUE;
TableVertDispl= BADVALUE;
}
IonBeamProperties::~IonBeamProperties(){
delete[] BeamName;
delete[] SupportId;
delete[] IsocenterPosition;
delete[] SupportType;
TableYawAngle = BADVALUE;
TableLatDispl = BADVALUE;
TableLongDispl = BADVALUE;
TableVertDispl = BADVALUE;
}
@@ -86,9 +171,9 @@ void IonBeamProperties::PrintSelf(){
cout<<" |_ SupportType = " <<SupportType<<endl;
cout<<" |_ SupportId = "<<SupportId<<endl;
cout<<" |_ GantryAngle = "<<GantryAngle<<endl;
cout<<" |_ IsocenterPosition = "<<IsocenterPosition[0]<<
IsocenterPosition[1]<<" "<<
IsocenterPosition[2]<<endl;
cout<<" |_ IsocenterPosition = "<<IsocenterPosition[0]<<" "
<<IsocenterPosition[1]<<" "
<<IsocenterPosition[2]<<endl;
cout<<" |_ TableYawAngle = "<<TableYawAngle<<endl;
cout<<" |_ TablePitchAngle = "<<TablePitchAngle<<endl;
cout<<" |_ TableRollAngle = "<<TableRollAngle<<endl;
@@ -100,60 +185,36 @@ void IonBeamProperties::PrintSelf(){
/*-----*/
//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];
RTPlan::RTPlan()
{
NumberOfBeams = 0;
PatientName.clear();
PatientID.clear();
PatientSex.clear();
PatientAge.clear();
PatientBirthDate.clear();
SeriesNumber = new char [MAXSTRINGLENGHT];
SeriesDescription = new char [MAXSTRINGLENGHT];
StudyID = new char [MAXSTRINGLENGHT];
StudyDescription = new char [MAXSTRINGLENGHT];
Modality = new char [MAXSTRINGLENGHT];
SeriesNumber.clear();
SeriesDescription.clear();
StudyID.clear();
StudyDescription.clear();
Modality.clear();
IsocenterPosition = new double[3];
std::fill(IsocenterPosition,(IsocenterPosition+3),BADVALUE);
VolumeCenter= new double[3];
std::fill(VolumeCenter,(VolumeCenter+3),BADVALUE);
IsocenterPosition = {BADVALUE, BADVALUE, BADVALUE};
VolumeCenter = {BADVALUE, BADVALUE, 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];
}
BeamNumber = BADVALUE;
BeamName.clear();
TableRollAngle = BADVALUE;
TableYawAngle = BADVALUE;
TablePitchAngle = BADVALUE;
TableLatDispl = BADVALUE;
TableVertDispl = BADVALUE;
TableLongDispl = BADVALUE;
SupportType.clear();
SupportId.clear();
PatientOrientation.clear();
}
void RTPlan::PrintSelf(){
cout<< "** RTPlan print self ** " <<endl;
@@ -185,11 +246,13 @@ RTPlan::~RTPlan(){
cout<<"PatientOrientation = "<<PatientOrientation<<endl;
if(NumberOfBeams > 0)
for(int ii=0; ii<NumberOfBeams;ii++)
Beams[ii]->PrintSelf();
for(const auto& b : Beams)
if(b) b->PrintSelf();
}
bool RTPlan::fillRTPlan( char *filertionplan){
bool RTPlan::fillRTPlan(const char *filertionplan){
LastError.clear();
cout<<"reading filename: "<<filertionplan<<endl;
@@ -197,42 +260,45 @@ RTPlan::~RTPlan(){
gdcm::Reader R;
R.SetFileName(filertionplan);
if(!R.Read())
{ cout<<"ERROR: cannot read filertionplan."<<endl;
}
{
LastError = "Cannot read RT Plan file";
cout<<"ERROR: cannot read filertionplan."<<endl;
return false;
}
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));
PatientName = gGetStringValueFromTagStr(gdcm::Tag(0x0010,0x0010), ds);
// // // PATIENT ID For ex: DICOM (0010,0020) = 1933197
strcpy(PatientID , gGetStringValueFromTag( gdcm::Tag(0x0010,0x0020), ds));
PatientID = gGetStringValueFromTagStr(gdcm::Tag(0x0010,0x0020), ds);
// //
// // // PATIENT AGE For ex: DICOM (0010,1010) = 031Y
strcpy(PatientAge , gGetStringValueFromTag( gdcm::Tag(0x0010,0x1010), ds)) ;
PatientAge = gGetStringValueFromTagStr(gdcm::Tag(0x0010,0x1010), ds);
// //
// // // PATIENT SEX For ex: DICOM (0010,0040) = M
strcpy(PatientSex, gGetStringValueFromTag( gdcm::Tag(0x0010,0x0040), ds) );
PatientSex = gGetStringValueFromTagStr(gdcm::Tag(0x0010,0x0040), ds);
// //
// // // PATIENT BIRTHDATE For ex: DICOM (0010,0030) = 19680427
strcpy(PatientBirthDate, gGetStringValueFromTag( gdcm::Tag(0x0010,0x0030), ds) );
PatientBirthDate = gGetStringValueFromTagStr(gdcm::Tag(0x0010,0x0030), ds);
// //
// // // SERIES NUMBER For ex: DICOM (0020,0011) = 902
strcpy(SeriesNumber, gGetStringValueFromTag( gdcm::Tag(0x0020,0x0011), ds) );
SeriesNumber = gGetStringValueFromTagStr(gdcm::Tag(0x0020,0x0011), ds);
// //
// // // SERIES DESCRIPTION For ex: DICOM (0008,103e) = SCOUT
strcpy(SeriesDescription , gGetStringValueFromTag( gdcm::Tag(0x0008,0x103e), ds) );
SeriesDescription = gGetStringValueFromTagStr(gdcm::Tag(0x0008,0x103e), ds);
// //
// // // STUDY ID For ex: DICOM (0020,0010) = 37481
strcpy(StudyID, gGetStringValueFromTag( gdcm::Tag(0x0020,0x0010), ds) );
StudyID = gGetStringValueFromTagStr(gdcm::Tag(0x0020,0x0010), ds);
// //
// // // STUDY DESCRIPTION For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL
strcpy(StudyDescription, gGetStringValueFromTag( gdcm::Tag(0x0008,0x1030), ds) );
StudyDescription = gGetStringValueFromTagStr(gdcm::Tag(0x0008,0x1030), ds);
// //
// // // STUDY MODALITY For ex: DICOM (0008,0060)= CT
strcpy(Modality, gGetStringValueFromTag( gdcm::Tag(0x0008,0x0060), ds) );
Modality = gGetStringValueFromTagStr(gdcm::Tag(0x0008,0x0060), ds);
//TREATMENT GEOMETRY
@@ -249,71 +315,91 @@ RTPlan::~RTPlan(){
//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));
// Patient orientation comes from Patient Setup Sequence, when present.
PatientOrientation.clear();
if (ds.FindDataElement(gdcm::Tag(0x300a,0x0180)))
{
const gdcm::DataElement &gSetupSequence=ds.GetDataElement(gdcm::Tag(0x300a,0x0180));
gdcm::SmartPointer<gdcm::SequenceOfItems> sqiPS = gSetupSequence.GetValueAsSQ();
if (sqiPS && sqiPS->GetNumberOfItems() >= 1)
{
const gdcm::DataSet& gPatSetupNest = sqiPS->GetItem(1).GetNestedDataSet();
PatientOrientation = gGetStringValueFromTagStr(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"));
LastError = "Beam sequence not found in RT Plan file";
cout<<"usteria" <<endl;
return false;
}
NumberOfBeams=sqi->GetNumberOfItems();
//ALLOCATE BEAM STRUCTURES
Beams=new IonBeamProperties* [NumberOfBeams];
//memset(Beams,NULL,NumberOfBeams*sizeof(IonBeamProperties *));
memset(Beams, 0, NumberOfBeams * sizeof(IonBeamProperties*));
const int expectedBeams = static_cast<int>(sqi->GetNumberOfItems());
NumberOfBeams = expectedBeams;
// Own and manage beams with RAII.
Beams.clear();
Beams.reserve(static_cast<size_t>(expectedBeams));
//ITERATES ON BEAM NUMBER
for(int i=0;i<NumberOfBeams;i++)
{ const gdcm::Item & item = sqi->GetItem(i+1); //ITEM START FROM 1
for(int i = 0; i < expectedBeams; 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;
auto beam = std::make_unique<IonBeamProperties>();
IonBeamProperties* b = beam.get();
//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
b->BeamNumber = GetTagIntOr(gdcm::Tag(0x300a, 0x00c0), gBeamNestedds, 0);
b->BeamName = gGetStringValueFromTagStr(gdcm::Tag(0x300a, 0x00c2), gBeamNestedds);
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");
if(IsCarbon == false)
b->SupportType = gGetStringValueFromTagStr(gdcm::Tag(0x300a, 0x0350), gBeamNestedds);
else
b->SupportType = "TABLE";
strcpy(Beams[i]->SupportId,gGetStringValueFromTag(gdcm::Tag(0x300a, 0x0352),gBeamNestedds));//PATIENT SUPPORT TYPE IMPLEMENT TRICK FOR THE CHAIR
b->SupportId = gGetStringValueFromTagStr(gdcm::Tag(0x300a, 0x0352), gBeamNestedds);
//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)
const gdcm::Tag cpTag(0x300a, IsCarbon==false ? 0x03a8 : 0x0111);
if (!gBeamNestedds.FindDataElement(cpTag))
{
// Skip this beam if control points are missing.
continue;
}
const gdcm::DataElement &gCPSequence=gBeamNestedds.GetDataElement(cpTag);
gdcm::SmartPointer<gdcm::SequenceOfItems> sqicp = gCPSequence.GetValueAsSQ();
//READ DATA FROM ITEM 1
if (!sqicp || sqicp->GetNumberOfItems() < 1)
{
continue;
}
const gdcm::DataSet& gCPNestedds = sqicp->GetItem(1).GetNestedDataSet();
//GANTRY ANGLE (NEEDED FOR CHAIR ?)
Beams[i]->GantryAngle=atoi(gGetStringValueFromTag(gdcm::Tag(0x300a, 0x011e),gCPNestedds));
b->GantryAngle = GetTagIntOr(gdcm::Tag(0x300a, 0x011e), gCPNestedds, 0);
//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,"\\"));
// ISOCENTER POSITION (this is beam position, not patient/volume center).
// DICOM tag (300A,012C) is a multi-value DS string: "x\\y\\z".
{
const std::string isoStr = gGetStringValueFromTagStr(gdcm::Tag(0x300a, 0x012c), gCPNestedds);
const auto iso = Parse3Doubles(isoStr);
b->IsocenterPosition[0] = iso[0];
b->IsocenterPosition[1] = iso[1];
b->IsocenterPosition[2] = iso[2];
}
// 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));
b->TableYawAngle = static_cast<float>(GetTagDoubleOr(gdcm::Tag(0x300a, 0x0122), gCPNestedds, 0.0));
/*if(i==1)
gBeams[i]->gSetTableYawAngle(0);
*/
@@ -322,10 +408,10 @@ RTPlan::~RTPlan(){
if(IsCarbon==false)
{ gdcm::Attribute <0x300a, 0x0140> pa;
pa.SetFromDataElement(gCPNestedds.GetDataElement( pa.GetTag()));
Beams[i]->TablePitchAngle =pa.GetValue();
b->TablePitchAngle = pa.GetValue();
}
else
(Beams[i]->TablePitchAngle)=(0.0);
b->TablePitchAngle = 0.0;
//v04 Build23 SET SUPPORT TYPE CORRECTLY IF PITCH IS 90 (IT IS CHAIR); DO IT FOR ALL BEAMS
// if(i==0)
@@ -342,10 +428,10 @@ RTPlan::~RTPlan(){
if(IsCarbon==false)
{ gdcm::Attribute <0x300a, 0x0144> ra;
ra.SetFromDataElement(gCPNestedds.GetDataElement(ra.GetTag()));
Beams[i]->TableRollAngle =(ra.GetValue());
b->TableRollAngle = ra.GetValue();
}
else
(Beams[i]->TableRollAngle)=(0.0);
b->TableRollAngle = 0.0;
@@ -371,17 +457,17 @@ RTPlan::~RTPlan(){
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));
float deltatablelat = static_cast<float>(GetTagDoubleOr(gdcm::Tag(0x300a, 0x012a), gCPNestedds, 0.0));
float deltatablelong = static_cast<float>(GetTagDoubleOr(gdcm::Tag(0x300a, 0x0129), gCPNestedds, 0.0));
float deltatablevert = static_cast<float>(GetTagDoubleOr(gdcm::Tag(0x300a, 0x0128), gCPNestedds, 0.0));
//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);
{ b->TableLatDispl = deltatablelat;
b->TableLongDispl = deltatablelong;
b->TableVertDispl = deltatablevert;
}
/* else
{ gBeams[i]->gSetTableLatDispl(tablelat);
@@ -426,29 +512,29 @@ RTPlan::~RTPlan(){
//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;
double yaw = b->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);
b->TableYawAngle = yaw;
double pitch=Beams[i]->TablePitchAngle;
double pitch = b->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);
b->TablePitchAngle = pitch;
double roll=Beams[i]->TableRollAngle;
double roll = b->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);
b->TableRollAngle = roll;
}
//HERE 90 DEGREES IS SUMMED IN ORDER TO SOLVE TEH AMBIGUITY BETWEEN TPS REFERENCE AND ROOM/ODEVIS REFERENCE
@@ -480,6 +566,11 @@ RTPlan::~RTPlan(){
// gBeams[i]->gSetIsocenterPosition(iso[0]- gBeams[i]->gGetCurrentPPS()->getPPSXPlan(),iso[1]- gBeams[i]->gGetCurrentPPS()->getPPSYPlan(),iso[2]- gBeams[i]->gGetCurrentPPS()->getPPSZPlan());
}
return true;
// Store the parsed beam.
Beams.push_back(std::move(beam));
}
// Keep legacy field in sync with actual parsed beams.
NumberOfBeams = static_cast<int>(Beams.size());
return true;
};
Executable → Regular
+53 -41
View File
@@ -11,7 +11,12 @@
#include <gdcmScanner.h>
#include <iostream>
using namespace std;
#include <array>
#include <memory>
#include <string>
#include <vector>
// Avoid `using namespace` in headers; keep symbols qualified.
#define MAXSTRINGLENGHT 255
#define BADVALUE -9999
@@ -23,7 +28,10 @@ enum{
NODCMFILE
};
// Legacy helper: returns a pointer to an internal static buffer.
// Prefer gGetStringValueFromTagStr() in new code.
const char *gGetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds);
std::string gGetStringValueFromTagStr(const gdcm::Tag& t, const gdcm::DataSet& ds);
const char * gCheckDICOMModality(const char *filename);
int gCheckDICOMModalityToInt(const char *filename);
@@ -32,20 +40,20 @@ class IonBeamProperties{
public:
IonBeamProperties();
~IonBeamProperties();
~IonBeamProperties() = default;
int BeamNumber;
char* BeamName;
char* SupportType;
char* SupportId;
int GantryAngle;
double* IsocenterPosition;
float TableYawAngle;
float TablePitchAngle;
float TableRollAngle;
float TableLatDispl;
float TableLongDispl;
float TableVertDispl;
int BeamNumber;
std::string BeamName;
std::string SupportType;
std::string SupportId;
int GantryAngle;
std::array<double, 3> IsocenterPosition;
float TableYawAngle;
float TablePitchAngle;
float TableRollAngle;
float TableLatDispl;
float TableLongDispl;
float TableVertDispl;
void PrintSelf();
};
@@ -55,41 +63,45 @@ void PrintSelf();
class RTPlan
{
public:
char* PatientName;
char* PatientID;
char* PatientSex;
char* PatientAge;
char* PatientBirthDate;
char* SeriesNumber;
char* SeriesDescription;
char* StudyID;
char* StudyDescription;
char* Modality;
std::string PatientName;
std::string PatientID;
std::string PatientSex;
std::string PatientAge;
std::string PatientBirthDate;
std::string SeriesNumber;
std::string SeriesDescription;
std::string StudyID;
std::string StudyDescription;
std::string 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;
std::array<double, 3> IsocenterPosition;
std::array<double, 3> VolumeCenter;
int BeamNumber;
std::string BeamName;
double TableRollAngle;
double TableYawAngle;
double TablePitchAngle;
double TableLatDispl;
double TableVertDispl;
double TableLongDispl;
std::string SupportType;
std::string SupportId;
std::string PatientOrientation;
int NumberOfBeams;
IonBeamProperties** Beams;
// Owns all beams.
std::vector<std::unique_ptr<IonBeamProperties>> Beams;
// Last error message set by fillRTPlan() when it returns false.
std::string LastError;
~RTPlan();
~RTPlan() = default;
RTPlan();
void PrintSelf();
bool fillRTPlan( char *filertionplan);
bool fillRTPlan(const char *filertionplan);
};
#endif
Executable → Regular
+441 -436
View File
@@ -1,436 +1,441 @@
#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);
/* use DCM as default */
this->changeRef(DCMREF);
//trueOffset_rot_prev=trueOffset_rot;
//this->load2VTK(patientInfos);
} else {
//DO NOTHING. THE folderisempty signal was already emitted.
}
cout<< " 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);
}
#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){
{
const auto& iso = readRT->Beams.at(0)->IsocenterPosition;
m_rtIsocenter[0] = iso[0];
m_rtIsocenter[1] = iso[1];
m_rtIsocenter[2] = iso[2];
}
if (readRT->PatientOrientation.rfind("HFS", 0) == 0)
m_patientOrientation = SUPINE;
else if (readRT->PatientOrientation.rfind("HFP", 0) == 0)
m_patientOrientation = PRONE;
else m_patientOrientation = NOTDEFINED;
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.at(0)->IsocenterPosition[0] <<endl;
//cout<< "iso2: "<<readRT->Beams.at(2)->IsocenterPosition[0]<<endl;
//cout<< "iso0: "<<readRT->Beams.at(0)->IsocenterPosition[1] <<endl;
//cout<< "iso2: "<<readRT->Beams.at(2)->IsocenterPosition[1]<<endl;
//cout<< "iso0: "<<readRT->Beams.at(0)->IsocenterPosition[2] <<endl;
//cout<< "iso2: "<<readRT->Beams.at(2)->IsocenterPosition[2]<<endl;
/*check for virtual iso, adapted from GB, gOTS v04Build34*/
if(readRT->NumberOfBeams > 2 &&
(readRT->Beams.at(0)->IsocenterPosition[0] != readRT->Beams.at(2)->IsocenterPosition[0] ||
readRT->Beams.at(0)->IsocenterPosition[1] != readRT->Beams.at(2)->IsocenterPosition[1] ||
readRT->Beams.at(0)->IsocenterPosition[2] != readRT->Beams.at(2)->IsocenterPosition[2])
)
virtualIso=true;
else
virtualIso=false;
//cout << "virtual Iso: "<<virtualIso << endl;
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);
/* use DCM as default */
this->changeRef(DCMREF);
//trueOffset_rot_prev=trueOffset_rot;
//this->load2VTK(patientInfos);
} else {
//DO NOTHING. THE folderisempty signal was already emitted.
}
cout<< " 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 → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
+64 -62
View File
@@ -1,6 +1,6 @@
#include "gRen.h"
#include <vtkOpenGLGPUVolumeRayCastMapper.h>
#include <vtkGPUVolumeRayCastMapper.h>
gRen::gRen(QVTKOpenGLNativeWidget *m_qvtk){
@@ -8,12 +8,9 @@ gRen::gRen(QVTKOpenGLNativeWidget *m_qvtk){
qvtk= m_qvtk;
nmarker=0;
markerSources = 0;
markerMappers = 0;
markerActors = 0;
markerSources.clear();
markerMappers.clear();
markerActors.clear();
return;
}
@@ -136,20 +133,20 @@ void gRen::loadVolume(vtkImageData* volCT){
void gRen::createRenderers(){
ren1 = vtkRenderer::New();
ren1 = vtkSmartPointer<vtkRenderer>::New();
ren1->SetBackground(0.13, 0.25, 0.32);
qvtk->renderWindow()->AddRenderer(ren1);
ren1->AddActor(assi);
ren1->AddActor( outlineActor);
boxWidget_NEW = vtkBoxWidget::New();
boxWidget_NEW = vtkSmartPointer<vtkBoxWidget>::New();
boxWidget_NEW->SetInteractor(qvtk->interactor());
boxWidget_NEW->SetPlaceFactor(1.0);
// - - - - - - - - - - - - - - - - - - - - -
boxCallback_NEW->rcm=volumeMapper;
boxCallback_NEW->rcm=volumeMapper.GetPointer();
boxWidget_NEW->AddObserver(vtkCommand::InteractionEvent, boxCallback_NEW);
return;
@@ -163,23 +160,23 @@ void gRen::buildRenderPipe(){
qDebug()<<"buildRenderPipe: outlineMapper";
vtkPolyDataMapper* outlineMapper = vtkPolyDataMapper::New();
vtkNew<vtkPolyDataMapper> outlineMapper;
outlineMapper->SetInputConnection(outline->GetOutputPort());
outlineActor = vtkSmartPointer <vtkActor> ::New();
outlineActor->SetMapper( outlineMapper);
outlineActor->SetMapper(outlineMapper);
qDebug()<<"buildRenderPipe: picker";
vtkCellPicker* picker = vtkCellPicker::New();
vtkNew<vtkCellPicker> picker;
picker->SetTolerance(0.005);
vtkProperty* ipwProp = vtkProperty::New();
vtkNew<vtkProperty> ipwProp;
//// //assign default props to the ipw's texture plane actor
qDebug()<<"buildRenderPipe: planeX";
planeWidgetX = vtkImagePlaneWidget::New();
planeWidgetX = vtkSmartPointer<vtkImagePlaneWidget>::New();
planeWidgetX->SetInteractor( qvtk->interactor());
planeWidgetX->SetKeyPressActivationValue('x');
planeWidgetX->SetPicker(picker);
@@ -195,7 +192,7 @@ void gRen::buildRenderPipe(){
qDebug()<<"buildRenderPipe: planeY";
planeWidgetY = vtkImagePlaneWidget::New();
planeWidgetY = vtkSmartPointer<vtkImagePlaneWidget>::New();
planeWidgetY->SetInteractor( qvtk->interactor());
planeWidgetY->SetKeyPressActivationValue('y');
planeWidgetY->SetPicker(picker);
@@ -210,7 +207,7 @@ void gRen::buildRenderPipe(){
qDebug()<<"buildRenderPipe: planeZ";
planeWidgetZ = vtkImagePlaneWidget::New();
planeWidgetZ = vtkSmartPointer<vtkImagePlaneWidget>::New();
planeWidgetZ->SetInteractor( qvtk->interactor());
planeWidgetZ->SetKeyPressActivationValue('z');
planeWidgetZ->SetPicker(picker);
@@ -225,7 +222,7 @@ void gRen::buildRenderPipe(){
qDebug()<<"buildRenderPipe: assi";
assi= vtkAxesActor::New();
assi = vtkSmartPointer<vtkAxesActor>::New();
assi->SetOrigin(0,0,0);
assi->AxisLabelsOff();
assi->SetTotalLength(15,15,15);
@@ -233,7 +230,7 @@ void gRen::buildRenderPipe(){
qDebug()<<"buildRenderPipe: volMapper";
// Create mapper (as vtkVolumeMapper smart pointer)
auto gpuMapper = vtkSmartPointer<vtkOpenGLGPUVolumeRayCastMapper>::New();
auto gpuMapper = vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();
gpuMapper->SetBlendModeToComposite();
if (!gpuMapper)
{
@@ -309,7 +306,7 @@ void gRen::buildRenderPipe(){
qDebug()<<"buildRenderPipe: orthoplanes";
orthoPlanes = vtkImageOrthoPlanes::New();
orthoPlanes = vtkSmartPointer<vtkImageOrthoPlanes>::New();
return;
}
@@ -318,11 +315,17 @@ 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);
}
if (idx < 0 || idx >= static_cast<int>(markerActors.size()))
return;
auto &act = markerActors.at(static_cast<size_t>(idx));
if (!act)
return;
if(state)
act->GetProperty()->SetColor(0,1,0);
else
act->GetProperty()->SetColor(1,1,1);
qvtk->renderWindow()->Render();
return;
@@ -333,26 +336,25 @@ 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;
// Remove previous marker actors/labels
for (auto &a : markerActors)
{
if (a)
ren1->RemoveActor(a);
}
markerActors.clear();
markerMappers.clear();
markerSources.clear();
if (pointLabels)
{
ren1->RemoveActor(pointLabels);
pointLabels = nullptr;
}
nmarker = marker_list.size();
markerSources = new vtkSphereSource* [nmarker];
markerMappers = new vtkPolyDataMapper* [nmarker];
markerActors = new vtkActor* [nmarker];
markerSources.reserve(static_cast<size_t>(nmarker));
markerMappers.reserve(static_cast<size_t>(nmarker));
markerActors.reserve(static_cast<size_t>(nmarker));
modelPoints = vtkSmartPointer<vtkPoints>::New();
modelPoints->Reset();
@@ -367,19 +369,22 @@ void gRen::renderMarkers(QList<surf> marker_list){
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);
// markerSources[i]->SetRadius(2);
auto src = vtkSmartPointer<vtkSphereSource>::New();
src->SetCenter(marker_list.at(i).centroid.x*1000,marker_list.at(i).centroid.y*1000,marker_list.at(i).centroid.z*1000);
src->SetRadius(10);
markerMappers[i]= vtkPolyDataMapper::New();
markerMappers[i]->SetInputConnection (markerSources[i]->GetOutputPort());
auto map = vtkSmartPointer<vtkPolyDataMapper>::New();
map->SetInputConnection(src->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]);
auto act = vtkSmartPointer<vtkActor>::New();
act->SetMapper(map);
act->GetProperty()->SetRepresentationToWireframe();
act->GetProperty()->SetColor(0,1,0);
ren1->AddActor(act);
markerSources.push_back(src);
markerMappers.push_back(map);
markerActors.push_back(act);
}
cout << "modelPoints" << endl;
@@ -415,20 +420,17 @@ void gRen::renderMarkers(QList<surf> marker_list){
void gRen::onReferenceChange(double dx, double dy, double dz){
if(markerSources == 0)
if (markerSources.empty())
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();
auto &src = markerSources.at(static_cast<size_t>(i));
const double* c = src->GetCenter();
src->SetCenter(c[0]-dx, c[1]-dy, c[2]-dz);
src->Update();
modelPoints->SetPoint(i,
modelPoints->GetPoint(i)[0]-dx,
modelPoints->GetPoint(i)[1]-dy,
modelPoints->GetPoint(i)[2]-dz);
const double* p = modelPoints->GetPoint(i);
modelPoints->SetPoint(i, p[0]-dx, p[1]-dy, p[2]-dz);
}
modelPoints->Modified();
Executable → Regular
+24 -18
View File
@@ -1,6 +1,7 @@
#ifndef _GREN_H_
#define _GREN_H_
#include <vector>
#include <vtkImageData.h>
#include <vtkSmartPointer.h>
@@ -100,13 +101,17 @@ public:
);
/*clip the vol ren*/
vtkPlanes *planes = vtkPlanes::New();
/* clip the vol ren */
// Keep the vtkPlanes object alive for as long as the callback lives.
if (!this->Planes)
{
this->Planes = vtkSmartPointer<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);
boxWidget->GetPlanes(this->Planes);
this->rcm->SetClippingPlanes(this->Planes);
}
void setNominalGeometry(int* extents, double* bounds, double* spacing){
@@ -124,6 +129,7 @@ private:
double nominalBounds[6];
int nominalExtent[6];
double VolSpacing[3];
vtkSmartPointer<vtkPlanes> Planes;
};
@@ -237,19 +243,19 @@ private:
vtkSmartPointer<vtkImageData> CTvolume;
vtkSmartPointer <vtkOutlineFilter> outline;
vtkSmartPointer <vtkActor> outlineActor;
vtkImageMapToColors* colorMap_X;
vtkImagePlaneWidget* planeWidgetX;
vtkImagePlaneWidget* planeWidgetY;
vtkImagePlaneWidget* planeWidgetZ;
vtkSmartPointer<vtkImageMapToColors> colorMap_X;
vtkSmartPointer<vtkImagePlaneWidget> planeWidgetX;
vtkSmartPointer<vtkImagePlaneWidget> planeWidgetY;
vtkSmartPointer<vtkImagePlaneWidget> planeWidgetZ;
QVTKOpenGLNativeWidget* qvtk;
// vtkSmartPointer<vtkGenericOpenGLRenderWindow> myrenderWindow;
vtkImageOrthoPlanes* orthoPlanes;
vtkAxesActor * assi;
vtkRenderer* ren1;
vtkSmartPointer<vtkImageOrthoPlanes> orthoPlanes;
vtkSmartPointer<vtkAxesActor> assi;
vtkSmartPointer<vtkRenderer> ren1;
//vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper;
//vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper;
vtkSmartPointer<vtkVolumeMapper> volumeMapper;
// NOTE: vtkGPUVolumeRayCastMapper is used at runtime, but we keep a
// concrete smart pointer for stability and to avoid nullptr issues.
vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper;
vtkSmartPointer<vtkColorTransferFunction> color;
vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity;
@@ -260,11 +266,11 @@ private:
vtkSmartPointer<vtkBoxCallback> boxCallback ;
vtkSmartPointer<vtkMyCallback> boxCallback_NEW;
vtkSmartPointer<vtkExtractVOI> extractVOI;
vtkBoxWidget *boxWidget_NEW;
vtkSmartPointer<vtkBoxWidget> boxWidget_NEW;
vtkSphereSource** markerSources;
vtkPolyDataMapper** markerMappers;
vtkActor** markerActors;
std::vector<vtkSmartPointer<vtkSphereSource>> markerSources;
std::vector<vtkSmartPointer<vtkPolyDataMapper>> markerMappers;
std::vector<vtkSmartPointer<vtkActor>> markerActors;
vtkSmartPointer<vtkPoints> modelPoints;
vtkSmartPointer<vtkActor2D> pointLabels;
int nmarker;
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Executable → Regular
View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Executable → Regular
View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Executable → Regular
View File

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File