Files
geant4/examples/extended/medical/DICOM/include/DicomPhantomZSliceHeader.hh
T
2024-06-28 13:08:51 +02:00

256 lines
9.4 KiB
C++

//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
/// \file medical/DICOM/include/DicomPhantomZSliceHeader.hh
/// \brief Definition of the DicomPhantomZSliceHeader class
//
#ifndef DicomPhantomZSliceHeader_h
#define DicomPhantomZSliceHeader_h 1
#include "globals.hh"
#include <fstream>
#include <vector>
class G4material;
//*******************************************************
/// DicomPhantomZSliceHeader class
///
/// Contains the meta data information corresponding to one or several
/// Z slices (number of voxels, dimension)
///
/// History: 30.11.07 First version
/// \author P. Arce
//*******************************************************
class DicomPhantomZSliceHeader
{
public:
DicomPhantomZSliceHeader(const G4String&);
DicomPhantomZSliceHeader(const DicomPhantomZSliceHeader&) = default;
// build object copying an existing one (except Z dimensions)
DicomPhantomZSliceHeader(std::ifstream& fin);
// build object reading data from a file
~DicomPhantomZSliceHeader();
// Get and set methods
G4int GetNoVoxelsX() const { return fNoVoxelsX; };
G4int GetNoVoxelsY() const { return fNoVoxelsY; };
G4int GetNoVoxelsZ() const { return fNoVoxelsZ; };
G4int GetNoVoxels() const { return fNoVoxelsX * fNoVoxelsY * fNoVoxelsZ; };
G4double GetMinX() const { return fMinX; };
G4double GetMinY() const { return fMinY; };
G4double GetMinZ() const { return fMinZ; };
G4double GetMaxX() const { return fMaxX; };
G4double GetMaxY() const { return fMaxY; };
G4double GetMaxZ() const { return fMaxZ; };
G4double GetVoxelHalfX() const { return (fMaxX - fMinX) / fNoVoxelsX / 2.; };
G4double GetVoxelHalfY() const { return (fMaxY - fMinY) / fNoVoxelsY / 2.; };
G4double GetVoxelHalfZ() const { return (fMaxZ - fMinZ) / fNoVoxelsZ / 2.; };
const std::vector<G4String>& GetMaterialNames() const { return fMaterialNames; };
void SetNoVoxelsX(const G4int& val) { fNoVoxelsX = val; }
void SetNoVoxelsY(const G4int& val) { fNoVoxelsY = val; }
void SetNoVoxelsZ(const G4int& val) { fNoVoxelsZ = val; }
void SetMinX(const G4double& val) { fMinX = val; };
void SetMaxX(const G4double& val) { fMaxX = val; };
void SetMinY(const G4double& val) { fMinY = val; };
void SetMaxY(const G4double& val) { fMaxY = val; };
void SetMinZ(const G4double& val) { fMinZ = val; };
void SetMaxZ(const G4double& val) { fMaxZ = val; };
void SetMaterialNames(std::vector<G4String>& mn) { fMaterialNames = mn; }
void operator+=(const DicomPhantomZSliceHeader& rhs);
DicomPhantomZSliceHeader operator+(const DicomPhantomZSliceHeader& rhs);
// add two slices that have the same dimensions, merging them in Z
//=================================================================
// NEW REVISION ( Jonathan Madsen - jonathan.madsen@cern.ch )
// December 2012
//
// New data handling format -> movement away from file-based to class based
// -- If density and mate ID data is not present -> read from file
//
// REASONING:
// -- DICOM data can contain inconsistencies, handling via class
// instead of via file
// allows safe/easy modification
//
// Adding Data to densities and fMateIDs
//
void SetFilename(const G4String& val) { fFilename = val; }
void SetSliceLocation(const G4double& val) { fSliceLocation = val; }
void AddMaterial(const G4String& val) { fMaterialNames.push_back(val); }
const G4double& GetSliceLocation() const { return fSliceLocation; }
void AddRow()
{
fValues.push_back(std::vector<G4double>(0));
fMateIDs.push_back(std::vector<G4int>(0));
}
void AddValue(G4double val)
{
(fValues.size() > 0) ? fValues.back().push_back(val)
: fValues.push_back(std::vector<G4double>(1, val));
}
void AddValue(const std::vector<G4double>& val) { fValues.push_back(val); }
void AddValue(const std::vector<std::vector<G4double>>& val)
{
for (unsigned int i = 0; i < val.size(); ++i) {
fValues.push_back(val.at(i));
}
}
void AddMateID(G4int val)
{
(fMateIDs.size() > 0) ? fMateIDs.back().push_back(val)
: fMateIDs.push_back(std::vector<G4int>(1, val));
}
void AddMateID(const std::vector<G4int>& val) { fMateIDs.push_back(val); }
void AddMateID(const std::vector<std::vector<G4int>>& val)
{
for (unsigned int i = 0; i < val.size(); ++i) {
fMateIDs.push_back(val.at(i));
}
}
const std::vector<std::vector<G4double>>& GetValues() const { return fValues; }
const std::vector<std::vector<G4int>>& GetMateIDs() const { return fMateIDs; }
void DumpToFile();
void ReadDataFromFile();
void DumpExcessMemory()
{
if (fFilename.length() != 0) {
fValues.clear();
fMateIDs.clear();
}
}
void FlipData();
private:
inline G4bool IsInteger(const G4String&);
template<typename T>
inline void Print(std::ostream&, const std::vector<T>&, const G4String&, G4int breakLine = -1);
template<typename T>
inline T G4s2n(const G4String&);
template<typename T>
inline bool CheckConsistency(const T&, const T&, G4String);
//
// END NEW REVISION
//=======================================================================
private:
G4bool CheckMaterialExists(const G4String& mateName);
// check that material read exists as a G4Material
private:
G4int fNoVoxelsX, fNoVoxelsY, fNoVoxelsZ; // number of voxels in each dimensions
G4double fMinX, fMinY, fMinZ; // minimum extension of voxels (position of wall)
G4double fMaxX, fMaxY, fMaxZ; // maximum extension of voxels (position of wall)
std::vector<G4String> fMaterialNames; // list of material names
G4String fFilename;
std::vector<std::vector<G4double>> fValues;
std::vector<std::vector<G4int>> fMateIDs;
G4double fSliceLocation;
};
//============================================================================
// This function flips all the data
// Otherwise, the image is upside-down
inline void DicomPhantomZSliceHeader::FlipData()
{
std::reverse(fValues.begin(), fValues.end());
std::reverse(fMateIDs.begin(), fMateIDs.end());
}
//=============================================================================
inline G4bool DicomPhantomZSliceHeader::IsInteger(const G4String& str)
{
return (str.find_first_not_of("0123456789") == std::string::npos) ? true : false;
}
//============================================================================
template<typename T>
inline T DicomPhantomZSliceHeader::G4s2n(const G4String& str)
{
std::istringstream iss(str);
T val;
iss >> val;
return val;
}
//============================================================================
template<typename T>
inline bool DicomPhantomZSliceHeader::CheckConsistency(const T& val1, const T& val2,
G4String category)
{
if (val1 != val2) {
G4Exception("DicomPhantomSliceZHeader::CheckConsistency",
"Consistency Mismatch : Keeping previous value if nonzero", JustWarning,
category.c_str());
return false;
}
return true;
}
//============================================================================
template<typename T>
inline void DicomPhantomZSliceHeader::Print(std::ostream& out, const std::vector<T>& val,
const G4String& delim, G4int breakLine)
{
for (unsigned int i = 0; i < val.size(); ++i) {
out << val.at(i);
if (breakLine < 0) {
if (i + 1 < val.size()) {
out << delim;
}
else {
out << G4endl;
}
}
else {
((i != 0 && i % breakLine == 0) ? (out << G4endl) : (out << delim));
}
}
}
//==========================================================================
#endif