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