OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
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 
29 LaserProfile::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(NULL),
36  rng_m(NULL),
37  pdf_m(NULL),
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
70  saveHistogram();
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 
83 unsigned 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 
104 unsigned 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 
121 unsigned 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, NULL);
142  hid_t filespace = H5Screate_simple(2, dim, NULL);
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, NULL, blockCount, NULL);
151 
152  unsigned short *image = new unsigned short [sizeX_m * sizeY_m];
153  hid_t mem = H5Screate_simple(2, blockCount, NULL);
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 
167 void 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 
179 void 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 
192 void 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 
212 void 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 
244 void 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 
258 void 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;
278  centerMass_m(0)*centerMass_m(0));
280  centerMass_m(1)*centerMass_m(1));
281 }
282 
283 void 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  }
313  saveHistogram();
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 
337 void 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 
383 void 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 
389 unsigned 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:139
FRONT * fs
Definition: hypervolume.cpp:59
static OpalData * getInstance()
Definition: OpalData.cpp:195
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
Definition: OpalData.cpp:650
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