OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
LaserProfile.cpp
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2// $RCSfile: LaserProfile.cpp,v $
3// ------------------------------------------------------------------------
4// $Revision: 1.3.4.1 $
5// ------------------------------------------------------------------------
6// Copyright: see Copyright.readme
7// ------------------------------------------------------------------------
8//
9// Class: LaserProfile
10//
11// ------------------------------------------------------------------------
12
15#include "Utility/Inform.h"
18#include "Utilities/Util.h"
19
20#include <fstream>
21#include <filesystem>
22#include <iostream>
23#include <cmath>
24#include <cstdio>
25
26//#define TESTLASEREMISSION
27
28LaserProfile::LaserProfile(const std::string &fileName,
29 const std::string &imageName,
30 double intensityCut,
31 short flags):
32 sizeX_m(0),
33 sizeY_m(0),
34 hist2d_m(nullptr),
35 rng_m(nullptr),
36 pdf_m(nullptr),
37 centerMass_m(0.0),
39
40 unsigned short *image = readFile(fileName, imageName);
41 // saveData("originalLaserProfile", image);
42
43 if (flags & FLIPX) flipX(image);
44 if (flags & FLIPY) flipY(image);
45 if (flags & ROTATE90) {
46 swapXY(image);
47 flipX(image);
48 }
49 if (flags & ROTATE180) {
50 flipX(image);
51 flipY(image);
52 }
53 if (flags & ROTATE270) {
54 swapXY(image);
55 flipY(image);
56 }
57
58 filterSpikes(image);
59 normalizeProfileData(intensityCut, image);
61 // saveData("processedLaserProfile", image);
62 fillHistrogram(image);
63
64 delete[] image;
65
66 setupRNG();
67
68#ifdef TESTLASEREMISSION
70 sampleDist();
71#endif
72
73 printInfo();
74}
75
77 gsl_histogram2d_pdf_free(pdf_m);
78 gsl_histogram2d_free(hist2d_m);
79 gsl_rng_free(rng_m);
80}
81
82unsigned short * LaserProfile::readFile(const std::string &fileName,
83 const std::string &imageName) {
84 namespace fs = std::filesystem;
85 if (!fs::exists(fileName)) {
86 throw OpalException("LaserProfile::readFile",
87 "given file '" + fileName + "' does not exist");
88 }
89
90 size_t npos = fileName.find_last_of('.');
91 std::string ext = fileName.substr(npos + 1);
92
93 unsigned short *image;
94 if (ext == "pgm") {
95 image = readPGMFile(fileName);
96 } else {
97 image = readHDF5File(fileName, imageName);
98 }
99
100 return image;
101}
102
103unsigned short * LaserProfile::readPGMFile(const std::string &fileName) {
104 PortableGraymapReader reader(fileName);
105
106 sizeX_m = reader.getWidth();
107 sizeY_m = reader.getHeight();
108
109 unsigned short *image = new unsigned short[sizeX_m * sizeY_m];
110 unsigned int idx = 0;
111 for (unsigned int i = 0; i < sizeX_m; ++ i) {
112 for (unsigned int j = 0; j < sizeY_m; ++ j, ++ idx) {
113 image[idx] = reader.getPixel(j, i);
114 }
115 }
116
117 return image;
118}
119
120unsigned short * LaserProfile::readHDF5File(const std::string &fileName,
121 const std::string &imageName) {
122
123 hid_t h5 = H5Fopen(fileName.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
124 hid_t group = H5Gopen2 (h5, imageName.c_str(), H5P_DEFAULT);
125
126 if (group < 0) {
127 throw OpalException("LaserProfile::readFile",
128 "given image name '" + imageName + "' does not exist");
129 }
130
131 hsize_t dim[2];
132 hid_t dataSet = H5Dopen2 (group, "CameraData", H5P_DEFAULT);
133
134 if (dataSet < 0) {
135 throw OpalException("LaserProfile::readFile",
136 "data set 'CameraData' does not exist");
137 }
138
139 hid_t dataSetSpace = H5Dget_space(dataSet);
140 H5Sget_simple_extent_dims(dataSetSpace, dim, nullptr);
141 hid_t filespace = H5Screate_simple(2, dim, nullptr);
142
143 sizeX_m = dim[0];
144 sizeY_m = dim[1];
145
146 hsize_t startHyperslab[] = {0, 0};
147 hsize_t blockCount[] = {sizeX_m, sizeY_m};
148
149 H5Sselect_hyperslab(filespace, H5S_SELECT_SET, startHyperslab, nullptr, blockCount, nullptr);
150
151 unsigned short *image = new unsigned short [sizeX_m * sizeY_m];
152 hid_t mem = H5Screate_simple(2, blockCount, nullptr);
153
154 H5Dread(dataSet, H5T_NATIVE_USHORT, mem, filespace, H5P_DEFAULT, image);
155
156 H5Sclose(mem);
157 H5Sclose(filespace);
158 H5Dclose(dataSetSpace);
159 H5Dclose(dataSet);
160 H5Gclose(group);
161 H5Fclose(h5);
162
163 return image;
164}
165
166void LaserProfile::flipX(unsigned short *image) {
167 unsigned int col2 = sizeX_m - 1;
168 for (unsigned int col1 = 0; col1 < col2; ++ col1, -- col2) {
169
170 unsigned int pixel1 = col1 * sizeY_m;
171 unsigned int pixel2 = col2 * sizeY_m;
172 for (unsigned int row = 0; row < sizeY_m; ++ row) {
173 std::swap(image[pixel1 ++], image[pixel2 ++]);
174 }
175 }
176}
177
178void LaserProfile::flipY(unsigned short *image) {
179 for (unsigned int col = 0; col < sizeX_m; ++ col) {
180
181 unsigned int pixel1 = col * sizeY_m;
182 unsigned int pixel2 = (col + 1) * sizeY_m - 1;
183
184 unsigned int row2 = sizeY_m - 1;
185 for (unsigned int row1 = 0; row1 < row2; ++ row1, -- row2) {
186 std::swap(image[pixel1 ++], image[pixel2 --]);
187 }
188 }
189}
190
191void LaserProfile::swapXY(unsigned short *image) {
192 unsigned short *copy = new unsigned short [sizeX_m * sizeY_m];
193 for (unsigned int col = 0; col < sizeX_m; ++ col) {
194 for (unsigned int row = 0; row < sizeY_m; ++ row) {
195 unsigned int pixel1 = col * sizeY_m + row;
196 unsigned int pixel2 = row * sizeX_m + col;
197
198 copy[pixel2] = image[pixel1];
199 }
200 }
201
202 for (unsigned int pixel = 0; pixel < sizeX_m * sizeY_m; ++ pixel) {
203 image[pixel] = copy[pixel];
204 }
205
206 delete[] copy;
207
208 std::swap(sizeX_m, sizeY_m);
209}
210
211void LaserProfile::filterSpikes(unsigned short *image) {
212 hsize_t idx = sizeY_m + 1;
213 hsize_t idxN = idx - sizeY_m;
214 hsize_t idxNW = idxN - 1, idxNE = idxN + 1;
215 hsize_t idxW = idx - 1, idxE = idx + 1;
216 hsize_t idxS = idx + sizeY_m;
217 hsize_t idxSW = idxS - 1, idxSE = idxS + 1;
218
219 for (hsize_t i = 1; i < sizeX_m - 1; ++ i) {
220 for (hsize_t j = 1; j < sizeY_m - 1; ++ j) {
221
222 if (image[idx] > 0) {
223 if (image[idxNW] == 0 &&
224 image[idxN] == 0 &&
225 image[idxNE] == 0 &&
226 image[idxW] == 0 &&
227 image[idxE] == 0 &&
228 image[idxSW] == 0 &&
229 image[idxS] == 0 &&
230 image[idxSE] == 0) {
231
232 image[idx] = 0;
233 }
234 }
235
236 ++ idxNW; ++ idxN; ++ idxNE;
237 ++ idxW; ++ idx; ++ idxE;
238 ++ idxSW; ++ idxS; ++ idxSE;
239 }
240 }
241}
242
243void LaserProfile::normalizeProfileData(double intensityCut, unsigned short *image) {
244 unsigned short int profileMax = getProfileMax(image);
245
246 unsigned int pixel = 0;
247 for (unsigned int col = 0; col < sizeX_m; ++ col) {
248 for(unsigned int row = 0; row < sizeY_m; ++ row, ++ pixel) {
249 double val = (double(image[pixel]) / profileMax - intensityCut) / (1.0 - intensityCut);
250
251 val = std::max(0.0, val);
252 image[pixel] = std::round(val * profileMax);
253 }
254 }
255}
256
257void LaserProfile::computeProfileStatistics(unsigned short *image) {
258 double totalMass = 0.0;
259 centerMass_m = Vector_t(0.0);
261
262 unsigned int pixel = 0;
263 for(unsigned int col = 0; col < sizeX_m; ++ col) {
264 for(unsigned int row = 0; row < sizeY_m; ++ row, ++ pixel) {
265 double val = image[pixel];
266
267 centerMass_m(0) += val * col;
268 centerMass_m(1) += val * row;
269 standardDeviation_m(0) += val * col*col;
270 standardDeviation_m(1) += val * row*row;
271 totalMass += val;
272 }
273 }
274
275 centerMass_m /= totalMass;
276 standardDeviation_m(0) = std::sqrt(standardDeviation_m(0) / totalMass -
278 standardDeviation_m(1) = std::sqrt(standardDeviation_m(1) / totalMass -
280}
281
282void LaserProfile::fillHistrogram(unsigned short *image) {
283 unsigned int histSizeX = sizeX_m;
284 unsigned int histSizeY = sizeY_m;
285 double histRangeX = histSizeX / standardDeviation_m(0) / 2;
286 double histRangeY = histSizeY / standardDeviation_m(1) / 2;
287 double binSizeX = 1.0 / standardDeviation_m(0);
288 double binSizeY = 1.0 / standardDeviation_m(1);
289
290 hist2d_m = gsl_histogram2d_alloc(histSizeX, histSizeY);
291 gsl_histogram2d_set_ranges_uniform(hist2d_m,
292 -histRangeX, histRangeX,
293 -histRangeY, histRangeY);
294
295
296 unsigned int pixel = 0;
297 for (unsigned int col = 0; col < sizeX_m; ++ col) {
298 double x = (col - 0.5 * sizeX_m) / standardDeviation_m(0);
299 x = x + 0.5 * binSizeX;
300 // std::cout << "x = " << x << std::endl;
301
302 for (unsigned int row = 0; row < sizeY_m; ++ row, ++ pixel) {
303 double val = image[pixel];
304 double y = -(row - 0.5 * sizeY_m) / standardDeviation_m(1);
305 y = y + 0.5 * binSizeY;
306 // if (col == 0)
307 // std::cout << "y = " << y << std::endl;
308
309 gsl_histogram2d_accumulate(hist2d_m, x, y, val);
310 }
311 }
313}
314
316 unsigned int histSizeX = hist2d_m->nx, histSizeY = hist2d_m->ny;
317
318 gsl_rng_env_setup();
319
320 const gsl_rng_type *T = gsl_rng_default;
321 rng_m = gsl_rng_alloc(T);
322
323 pdf_m = gsl_histogram2d_pdf_alloc(histSizeX, histSizeY);
324 gsl_histogram2d_pdf_init(pdf_m, hist2d_m);
325}
326
328 INFOMSG(level3 << "* **********************************************************************************\n");
329 INFOMSG("* LASER PROFILE \n");
330 INFOMSG("* size = " << sizeX_m << " x " << sizeY_m << " pixels \n");
331 INFOMSG("* center of mass: x = " << centerMass_m(0) << ", y = " << centerMass_m(1) << "\n");
332 INFOMSG("* standard deviation: x = " << standardDeviation_m(0) << ", y = " << standardDeviation_m(1) << "\n");
333 INFOMSG("* **********************************************************************************" << endl);
334}
335
336void LaserProfile::saveData(const std::string &fname, unsigned short *image) {
337 std::ofstream out(
340 fname + ".pgm"}
341 ));
342
343 out << "P2" << std::endl;
344 out << sizeX_m << " " << sizeY_m << std::endl;
345 out << getProfileMax(image) << std::endl;
346
347 for (unsigned int j = 0; j < sizeY_m; ++ j) {
348 for (unsigned int i = 0; i < sizeX_m; ++ i) {
349 out << image[i * sizeY_m + j] << " ";
350 }
351 out << std::endl;
352 }
353}
354
356 std::string fname = Util::combineFilePath({
358 "LaserHistogram.dat"
359 });
360 FILE *fh = std::fopen(fname.c_str(), "w");
361 gsl_histogram2d_fprintf(fh, hist2d_m, "%g", "%g");
362 std::fclose(fh);
363}
364
366 std::string fname = Util::combineFilePath({
368 "LaserEmissionSampled.dat"
369 });
370
371 std::ofstream fh(fname);
372 double x, y;
373
374 for(int i = 0; i < 1000000; i++) {
375 getXY(x, y);
376 fh << x << "\t" << y << "\n";
377 }
378
379 fh.close();
380}
381
382void LaserProfile::getXY(double &x, double &y) {
383 double u = gsl_rng_uniform(rng_m);
384 double v = gsl_rng_uniform(rng_m);
385 gsl_histogram2d_pdf_sample(pdf_m, u, v, &x, &y);
386}
387
388unsigned short LaserProfile::getProfileMax(unsigned short *image) {
389 unsigned int numberPixels = sizeX_m * sizeY_m;
390
391 unsigned short maxIntensity = 0;
392
393 for(unsigned int i = 0; i < numberPixels; i++) {
394 if(image[i] > maxIntensity)
395 maxIntensity = image[i];
396 }
397
398 return maxIntensity;
399}
Inform & endl(Inform &inf)
Definition Inform.cpp:42
Inform & level3(Inform &inf)
Definition Inform.cpp:47
#define INFOMSG(msg)
Definition IpplInfo.h:348
std::string combineFilePath(std::initializer_list< std::string > ilist)
Definition Util.cpp:197
static OpalData * getInstance()
Definition OpalData.cpp:196
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
Definition OpalData.cpp:666
unsigned int getWidth() const
unsigned int getHeight() const
unsigned short getPixel(unsigned int i, unsigned int j) const
hsize_t sizeY_m
void normalizeProfileData(double intensityCut, unsigned short *image)
void getXY(double &x, double &y)
void saveData(const std::string &fname, unsigned short *image)
void fillHistrogram(unsigned short *image)
Vector_t centerMass_m
void flipY(unsigned short *image)
LaserProfile(const std::string &fileName, const std::string &imageName, double intensityCut, short flags)
void flipX(unsigned short *image)
gsl_histogram2d * hist2d_m
unsigned short * readPGMFile(const std::string &fileName)
unsigned short * readFile(const std::string &fileName, const std::string &imageName)
gsl_rng * rng_m
void swapXY(unsigned short *image)
unsigned short getProfileMax(unsigned short *image)
hsize_t sizeX_m
unsigned short * readHDF5File(const std::string &fileName, const std::string &imageName)
Vector_t standardDeviation_m
void computeProfileStatistics(unsigned short *image)
gsl_histogram2d_pdf * pdf_m
void filterSpikes(unsigned short *image)
The base class for all OPAL exceptions.
Vektor< double, 3 > Vector_t