GGEMS  1.1
GPU GEant4-based Monte Carlo Simulations
GGEMSMHDImage.cc
Go to the documentation of this file.
1 // ************************************************************************
2 // * This file is part of GGEMS. *
3 // * *
4 // * GGEMS is free software: you can redistribute it and/or modify *
5 // * it under the terms of the GNU General Public License as published by *
6 // * the Free Software Foundation, either version 3 of the License, or *
7 // * (at your option) any later version. *
8 // * *
9 // * GGEMS is distributed in the hope that it will be useful, *
10 // * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 // * GNU General Public License for more details. *
13 // * *
14 // * You should have received a copy of the GNU General Public License *
15 // * along with GGEMS. If not, see <https://www.gnu.org/licenses/>. *
16 // * *
17 // ************************************************************************
18 
31 #include <vector>
32 
37 
41 
43 : mhd_header_file_(""),
44  mhd_raw_file_(""),
45  output_dir_(""),
46  mhd_data_type_("MET_FLOAT")
47 {
48  GGcout("GGEMSMHDImage", "GGEMSMHDImage", 3) << "GGEMSMHDImage creating..." << GGendl;
49 
50 
51  element_sizes_.x = 0.0f;
52  element_sizes_.y = 0.0f;
53  element_sizes_.z = 0.0f;
54 
55  dimensions_.x_ = 0;
56  dimensions_.y_ = 0;
57  dimensions_.z_ = 0;
58 
59  GGcout("GGEMSMHDImage", "GGEMSMHDImage", 3) << "GGEMSMHDImage created!!!" << GGendl;
60 }
61 
65 
67 {
68  GGcout("GGEMSMHDImage", "~GGEMSMHDImage", 3) << "GGEMSMHDImage erasing!!!" << GGendl;
69 
70  GGcout("GGEMSMHDImage", "~GGEMSMHDImage", 3) << "GGEMSMHDImage erased!!!" << GGendl;
71 }
72 
76 
77 void GGEMSMHDImage::SetOutputFileName(std::string const& filename)
78 {
79  // Checking *.mhd suffixe
80  GGsize found_mhd = filename.find(".mhd");
81  if (found_mhd == std::string::npos) {
82  mhd_header_file_ += filename + ".mhd";
83  }
84  else {
85  mhd_header_file_ = filename;
86  }
87 
88  GGsize found_dir = filename.find_last_of("/\\");
89  if (found_dir != std::string::npos) {
90  output_dir_ = filename.substr(0, found_dir+1);
91  mhd_raw_file_ = filename.substr(found_dir+1, found_mhd-found_dir-1) + ".raw";
92  }
93  else {
94  mhd_raw_file_ = filename.substr(0, found_mhd) + ".raw";
95  }
96 }
97 
101 
102 void GGEMSMHDImage::SetElementSizes(GGfloat3 const& element_sizes)
103 {
104  element_sizes_ = element_sizes;
105 }
106 
110 
111 void GGEMSMHDImage::SetDataType(std::string const& data_type)
112 {
113  mhd_data_type_ = data_type;
114 }
115 
119 
120 void GGEMSMHDImage::SetDimensions(GGsize3 const& dimensions)
121 {
122  dimensions_ = dimensions;
123 }
124 
128 
129 void GGEMSMHDImage::Read(std::string const& image_mhd_header_filename, cl::Buffer* solid_data, GGsize const& thread_index)
130 {
131  GGcout("GGEMSMHDImage", "Read", 2) << "Reading MHD Image..." << GGendl;
132 
133  // Checking if file exists
134  std::ifstream in_header_stream(image_mhd_header_filename, std::ios::in);
135 
136  GGEMSFileStream::CheckInputStream(in_header_stream, image_mhd_header_filename);
137 
138  // Get the OpenCL manager
140 
141  // Get pointer on OpenCL device
142  GGEMSVoxelizedSolidData* solid_data_device = opencl_manager.GetDeviceBuffer<GGEMSVoxelizedSolidData>(solid_data, sizeof(GGEMSVoxelizedSolidData), thread_index);
143 
144  // Getting output directory
145  std::size_t found_dir = image_mhd_header_filename.find_last_of("/\\");
146  if (found_dir != std::string::npos) {
147  output_dir_ = image_mhd_header_filename.substr(0, found_dir+1);
148  }
149 
150  // Read the file
151  std::string line("");
152  while (std::getline(in_header_stream, line)) {
153  // Skip comment
154  GGEMSTextReader::SkipComment(in_header_stream, line);
155  // Check if blank line
156  if (GGEMSTextReader::IsBlankLine(line)) continue;
157 
158  // Getting the key
159  std::string const kKey = GGEMSMHDReader::ReadKey(line);
160 
161  // Getting the value in string stream
162  std::istringstream iss = GGEMSMHDReader::ReadValue(line);
163 
164  // Compare key and store data if valid
165  if (!kKey.compare("DimSize")) {
166  iss >> solid_data_device->number_of_voxels_xyz_.x >> solid_data_device->number_of_voxels_xyz_.y >> solid_data_device->number_of_voxels_xyz_.z;
167  // Computing number of voxels
168  solid_data_device->number_of_voxels_ = solid_data_device->number_of_voxels_xyz_.x * solid_data_device->number_of_voxels_xyz_.y * solid_data_device->number_of_voxels_xyz_.z;
169  }
170  else if (!kKey.compare("ElementSpacing")) {
171  iss >> solid_data_device->voxel_sizes_xyz_.x >> solid_data_device->voxel_sizes_xyz_.y >> solid_data_device->voxel_sizes_xyz_.z;
172  }
173  else if (!kKey.compare("ElementType")) {
174  iss >> mhd_data_type_;
175  }
176  else if (!kKey.compare("ElementDataFile")) {
177  iss >> mhd_raw_file_;
178  }
179  }
180 
181  // Closing the input header
182  in_header_stream.close();
183 
184  // Checking the values
185  if (solid_data_device->number_of_voxels_xyz_.x <= 0 || solid_data_device->number_of_voxels_xyz_.y <= 0 || solid_data_device->number_of_voxels_xyz_.z <= 0) {
186  std::ostringstream oss(std::ostringstream::out);
187  oss << "Dimension invalid for the key 'DimSize'!!! The values have to be > 0";
188  GGEMSMisc::ThrowException("GGEMSMHDImage", "Read", oss.str());
189  }
190 
191  if (solid_data_device->voxel_sizes_xyz_.x == 0.0 || solid_data_device->voxel_sizes_xyz_.y == 0.0 || solid_data_device->voxel_sizes_xyz_.z == 0.0) {
192  std::ostringstream oss(std::ostringstream::out);
193  oss << "Voxel size invalid for the key 'ElementSpacing'!!! The values have to be > 0";
194  GGEMSMisc::ThrowException("GGEMSMHDImage", "Read", oss.str());
195  }
196 
197  if (mhd_data_type_.empty() && mhd_data_type_.compare("MET_DOUBLE") && mhd_data_type_.compare("MET_FLOAT") && mhd_data_type_.compare("MET_SHORT") && mhd_data_type_.compare("MET_USHORT") && mhd_data_type_.compare("MET_UCHAR") && mhd_data_type_.compare("MET_CHAR") && mhd_data_type_.compare("MET_UINT") && mhd_data_type_.compare("MET_INT")) {
198  std::ostringstream oss(std::ostringstream::out);
199  oss << "Value invalid for the key 'ElementType'!!! The value have to be 'MET_DOUBLE' or 'MET_FLOAT' or 'MET_SHORT' or 'MET_USHORT' or 'MET_UCHAR' or 'MET_CHAR' or 'MET_UINT' or 'MET_INT'";
200  GGEMSMisc::ThrowException("GGEMSMHDImage", "Read", oss.str());
201  }
202 
203  if (mhd_raw_file_.empty()) {
204  std::ostringstream oss(std::ostringstream::out);
205  oss << "Value invalid for the key 'ElementDataFile'!!! A filename for raw data has to be given";
206  GGEMSMisc::ThrowException("GGEMSMHDImage", "Read", oss.str());
207  }
208 
209  // Computing bounding box borders automatically at isocenter
210  for (GGsize i = 0; i < 3; ++i) {
211  solid_data_device->obb_geometry_.border_min_xyz_.s[i] = -static_cast<GGfloat>(solid_data_device->number_of_voxels_xyz_.s[i]) * solid_data_device->voxel_sizes_xyz_.s[i] * 0.5f;
212  solid_data_device->obb_geometry_.border_max_xyz_.s[i] = static_cast<GGfloat>(solid_data_device->number_of_voxels_xyz_.s[i]) * solid_data_device->voxel_sizes_xyz_.s[i] * 0.5f;
213  }
214 
215  // Release the pointer
216  opencl_manager.ReleaseDeviceBuffer(solid_data, solid_data_device, thread_index);
217 }
218 
222 
223 void GGEMSMHDImage::Write(cl::Buffer* image, GGsize const& thread_index) const
224 {
225  GGcout("GGEMSMHDImage", "Write", 1) << "Writing MHD Image: " << mhd_header_file_ << "..." << GGendl;
226 
227  // Checking parameters before to write
228  CheckParameters();
229 
230  // header data
231  std::ofstream out_header_stream(mhd_header_file_, std::ios::out);
232  out_header_stream << "ObjectType = Image" << std::endl;
233  out_header_stream << "BinaryDataByteOrderMSB = False" << std::endl;
234  out_header_stream << "NDims = 3" << std::endl;
235  out_header_stream << "ElementSpacing = " << element_sizes_.x << " " << element_sizes_.y << " " << element_sizes_.z << std::endl;
236  out_header_stream << "DimSize = " << dimensions_.x_ << " " << dimensions_.y_ << " " << dimensions_.z_ << std::endl;
237  out_header_stream << "ElementType = " << mhd_data_type_ << std::endl;
238  out_header_stream << "ElementDataFile = " << mhd_raw_file_ << std::endl;
239  out_header_stream.close();
240 
241  // Writing raw data to file
242  if (!mhd_data_type_.compare("MET_CHAR")) WriteRaw<char>(image, thread_index);
243  else if (!mhd_data_type_.compare("MET_UCHAR")) WriteRaw<unsigned char>(image, thread_index);
244  else if (!mhd_data_type_.compare("MET_SHORT")) WriteRaw<GGshort>(image, thread_index);
245  else if (!mhd_data_type_.compare("MET_USHORT")) WriteRaw<GGushort>(image, thread_index);
246  else if (!mhd_data_type_.compare("MET_INT")) WriteRaw<GGint>(image, thread_index);
247  else if (!mhd_data_type_.compare("MET_UINT")) WriteRaw<GGuint>(image, thread_index);
248  else if (!mhd_data_type_.compare("MET_FLOAT")) WriteRaw<GGfloat>(image, thread_index);
249  else if (!mhd_data_type_.compare("MET_DOUBLE")) WriteRaw<GGfloat>(image, thread_index);
250 }
251 
255 
256 void GGEMSMHDImage::CheckParameters(void) const
257 {
258  if (mhd_header_file_.empty()) {
259  GGEMSMisc::ThrowException("GGEMSMHDImage", "CheckParameters", "MHD header filename is empty!!!");
260  }
261 
262  if (mhd_raw_file_.empty()) {
263  GGEMSMisc::ThrowException("GGEMSMHDImage", "CheckParameters", "MHD raw filename is empty!!!");
264  }
265 
266  // Checking phantom dimensions
267  if (dimensions_.x_ == 0 && dimensions_.y_ == 0 && dimensions_.z_ == 0) {
268  GGEMSMisc::ThrowException("GGEMSMHDImage", "CheckParameters", "Phantom dimensions have to be > 0!!!");
269  }
270 
271  // Checking size of voxels
272  if (element_sizes_.x == 0.0f && element_sizes_.y == 0.0f && element_sizes_.z == 0.0f) {
273  GGEMSMisc::ThrowException("GGEMSMHDImage", "CheckParameters", "Phantom voxel sizes have to be > 0.0!!!");
274  }
275 }
GGEMSTextReader::SkipComment
void SkipComment(std::ifstream &stream, std::string &line, char const comment='#')
skip a special line beginning by a comment caracter
Definition: GGEMSTextReader.cc:131
GGEMSVoxelizedSolidData_t::number_of_voxels_
GGint number_of_voxels_
Definition: GGEMSVoxelizedSolidData.hh:46
GGEMSVoxelizedSolidData_t
Structure storing the stack of data for voxelized solid.
Definition: GGEMSVoxelizedSolidData.hh:41
GGsize3_t
Structure storing 3 GGsize values.
Definition: GGEMSTypes.hh:267
GGEMSVoxelizedSolidData
struct GGEMSVoxelizedSolidData_t GGEMSVoxelizedSolidData
GGEMSMHDImage::SetDataType
void SetDataType(std::string const &data_type)
set the type of data
Definition: GGEMSMHDImage.cc:111
GGEMSMHDImage::CheckParameters
void CheckParameters(void) const
Check parameters before read/write MHD file.
Definition: GGEMSMHDImage.hh:161
GGEMSMHDImage::mhd_data_type_
std::string mhd_data_type_
Definition: GGEMSMHDImage.hh:184
GGEMSMHDImage::SetElementSizes
void SetElementSizes(GGfloat3 const &element_sizes)
set the size of the elements
Definition: GGEMSMHDImage.cc:102
GGEMSMHDImage::~GGEMSMHDImage
~GGEMSMHDImage(void)
GGEMSMHDImage destructor.
Definition: GGEMSMHDImage.cc:66
GGEMSOpenCLManager::ReleaseDeviceBuffer
void ReleaseDeviceBuffer(cl::Buffer *const device_ptr, T *host_ptr, GGsize const &thread_index)
Get the device pointer on host to write on it. Mandatory after a GetDeviceBufferWrite ou GetDeviceBuf...
Definition: GGEMSOpenCLManager.hh:495
GGEMSTools.hh
Namespaces for different useful fonctions.
GGEMSVoxelizedSolidData_t::obb_geometry_
GGEMSOBB obb_geometry_
Definition: GGEMSVoxelizedSolidData.hh:42
GGEMSVoxelizedSolidData.hh
Structure storing the stack of data for voxelized and analytical solid.
GGEMSVoxelizedSolidData_t::voxel_sizes_xyz_
GGfloat3 voxel_sizes_xyz_
Definition: GGEMSVoxelizedSolidData.hh:43
GGEMSVoxelizedSolidData_t::number_of_voxels_xyz_
GGint3 number_of_voxels_xyz_
Definition: GGEMSVoxelizedSolidData.hh:44
GGsize
#define GGsize
Definition: GGEMSTypes.hh:252
GGEMSMHDImage::Write
void Write(cl::Buffer *image, GGsize const &thread_index) const
Write mhd header/raw file.
Definition: GGEMSMHDImage.cc:223
GGEMSMHDImage::SetOutputFileName
void SetOutputFileName(std::string const &basename)
set the output filename (*.mhd)
Definition: GGEMSMHDImage.cc:77
GGEMSMHDImage::mhd_raw_file_
std::string mhd_raw_file_
Definition: GGEMSMHDImage.hh:182
GGsize3_t::z_
GGsize z_
Definition: GGEMSTypes.hh:270
GGfloat3
#define GGfloat3
Definition: GGEMSTypes.hh:275
GGEMSTextReader.hh
Namespaces for different useful fonctions reading input text file. Namespaces for material database f...
GGcout
GGEMSStream GGcout
Definition: GGEMSPrint.cc:34
GGEMSTextReader::IsBlankLine
bool IsBlankLine(std::string const &line)
check if the line is blank or not
Definition: GGEMSTextReader.cc:146
GGEMSOBB_t::border_max_xyz_
GGfloat3 border_max_xyz_
Definition: GGEMSPrimitiveGeometries.hh:44
GGEMSMHDImage::SetDimensions
void SetDimensions(GGsize3 const &dimensions)
set the dimensions of the image
Definition: GGEMSMHDImage.cc:120
GGsize3_t::x_
GGsize x_
Definition: GGEMSTypes.hh:268
GGEMSOpenCLManager::GetDeviceBuffer
T * GetDeviceBuffer(cl::Buffer *device_ptr, GGsize const &size, GGsize const &thread_index)
Get the device pointer on host to write on it. ReleaseDeviceBuffer must be used after this method!...
Definition: GGEMSOpenCLManager.hh:480
GGendl
#define GGendl
overload C++ std::endl
Definition: GGEMSPrint.hh:60
GGEMSMHDImage::Read
void Read(std::string const &image_mhd_header_filename, cl::Buffer *solid_data, GGsize const &thread_index)
read the mhd header
Definition: GGEMSMHDImage.cc:129
GGEMSMHDImage::output_dir_
std::string output_dir_
Definition: GGEMSMHDImage.hh:183
GGEMSOpenCLManager
Singleton class storing all informations about OpenCL and managing GPU/CPU devices,...
Definition: GGEMSOpenCLManager.hh:54
GGEMSMHDImage::mhd_header_file_
std::string mhd_header_file_
Definition: GGEMSMHDImage.hh:181
GGEMSFileStream::CheckInputStream
void CheckInputStream(std::ifstream const &input_stream, std::string const &filename)
check the input stream during the opening
Definition: GGEMSTools.cc:42
GGEMSOBB_t::border_min_xyz_
GGfloat3 border_min_xyz_
Definition: GGEMSPrimitiveGeometries.hh:43
GGEMSMHDReader::ReadKey
std::string ReadKey(std::string &line)
get the key of MHD header
Definition: GGEMSTextReader.cc:176
GGEMSMHDImage::GGEMSMHDImage
GGEMSMHDImage(void)
GGEMSMHDImage constructor.
Definition: GGEMSMHDImage.cc:42
GGEMSMHDReader::ReadValue
std::istringstream ReadValue(std::string &line)
get string stream of value
Definition: GGEMSTextReader.cc:192
GGEMSMHDImage.hh
I/O class handling MHD image file.
GGEMSMisc::ThrowException
void ThrowException(std::string const &class_name, std::string const &method_name, std::string const &message)
Throw a C++ exception.
Definition: GGEMSTools.cc:61
GGfloat
#define GGfloat
Definition: GGEMSTypes.hh:273
GGEMSMHDImage::dimensions_
GGsize3 dimensions_
Definition: GGEMSMHDImage.hh:186
GGEMSOpenCLManager::GetInstance
static GGEMSOpenCLManager & GetInstance(void)
Create at first time the Singleton.
Definition: GGEMSOpenCLManager.hh:72
GGsize3_t::y_
GGsize y_
Definition: GGEMSTypes.hh:269
GGEMSMHDImage::element_sizes_
GGfloat3 element_sizes_
Definition: GGEMSMHDImage.hh:185