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