CFEL - ASG Software Suite  2.5.0
CASS
common_data.cpp
Go to the documentation of this file.
1 //Copyright (C) 2011 Lutz Foucar
2 
3 /**
4  * @file common_data.cpp data contains commonly used for all AdvancedDetectors.
5  *
6  * @author Lutz Foucar
7  */
8 
9 #include <stdexcept>
10 #include <sstream>
11 #include <fstream>
12 #include <algorithm>
13 #include <iterator>
14 #include <cmath>
15 
16 #include <QtCore/QFile>
17 #include <QtCore/QDateTime>
18 #include <QtCore/QFileInfo>
19 #include <QtCore/QtGlobal>
20 
21 #include "common_data.h"
22 
23 #include "cass_settings.h"
24 #include "cass_event.h"
25 #include "advanced_pixeldetector.h"
26 #include "mapcreator_base.h"
27 #include "pixeldetector_mask.h"
28 #include "hlltypes.hpp"
29 #include "log.h"
31 
32 using namespace cass;
33 using namespace pixeldetector;
34 using namespace std;
35 
36 namespace cass
37 {
38 namespace pixeldetector
39 {
40 /** will read the file containing the offset and noise map in the hll format
41  *
42  * The Hll darkcal file format starts with a 1024 bit long header. Then an array
43  * of staDataType objects containing more info than just the offset (mean) and
44  * the noise (sigma) of the pixels.
45  *
46  * After that data a list of chars containing the bad pixel map is recorded.
47  * The length of the arrays is according to the size of the frame.
48  *
49  * The header first contains a string to identify that it is a proper darkcal
50  * file "HE pixel statistics map". Then it is followed by the following the
51  * height, the width and the overall length of the frame. See HllFileHeader for
52  * details.
53  *
54  * since the arrays for the offset and noise map are in the HLL layout, we
55  * need to copy the individual information from the staDataType structure to
56  * temporary arrays, which we then can convert to the layout that CASS is using.
57  *
58  * @param filename the filename of file containing the offset and noise maps.
59  * @param data the data storage where the info should be written to.
60  *
61  * @author Lutz Foucar
62  */
63 void readHLLOffsetFile(const string &filename, CommonData& data)
64 {
65  using Streaming::operator >>;
66  ifstream hllfile(filename.c_str(),ios::in);
67  if (!hllfile.is_open())
68  {
69  Log::add(Log::WARNING,"readHllOffsetFile: Could not open '" + filename +
70  "'. Skip loading the offset and noise map.");
71  return;
72  }
74  hllfile >> header;
75  if ((string("HE pixel statistics map") != header.identifystring) ||
76  (header.columns * header.rows != header.length))
77  {
78  throw invalid_argument("readHLLOffsetFile(): Error file '" + filename +
79  "' has either wrong header identify string '" +
80  header.identifystring + "' or the header information"
81  " is inconsistent columns * rows != length '" +
82  toString(header.columns)+ "*" + toString(header.rows) +
83  "!=" + toString(header.length) +"'");
84  }
85  vector<hllDataTypes::statistics> pixelStatistics(header.length);
86  const size_t pixelStatisticsLength(sizeof(hllDataTypes::statistics)*header.length);
87  hllfile.read(reinterpret_cast<char*>(&pixelStatistics.front()),pixelStatisticsLength);
88  vector<char> badpixmap(header.length);
89  hllfile.read(&badpixmap[0],header.length);
90 
91  Detector::frame_t hlloffsets(header.length);
92  Detector::frame_t::iterator hlloffset(hlloffsets.begin());
93  Detector::frame_t hllnoises(header.length);
94  Detector::frame_t::iterator hllnoise(hllnoises.begin());
95  vector<hllDataTypes::statistics>::iterator pixelstatistic(pixelStatistics.begin());
96  for( size_t i(0); i < header.length; ++i, ++hlloffset, ++hllnoise, ++pixelstatistic )
97  {
98  *hlloffset = pixelstatistic->offset;
99  *hllnoise = pixelstatistic->sigma;
100  }
101  QWriteLocker lock(&data.lock);
102  data.offsetMap.resize(header.length);
103  hllDataTypes::HLL2CASS(hlloffsets,data.offsetMap,header.rows,header.rows,header.columns);
104  data.noiseMap.resize(header.length);
105  hllDataTypes::HLL2CASS(hllnoises,data.noiseMap,header.rows,header.rows,header.columns);
106  data.mask.resize(header.length);
107  hllDataTypes:: HLL2CASS(badpixmap,data.mask,header.rows,header.rows,header.columns);
108 }
109 
110 /** save the maps to a hll type darkcal file
111  *
112  * see readHLLOffsetFile for details about the fileformat. There is no need to
113  * lock the maps since they are still locked by the lock started in createMaps
114  *
115  * @param filename the name of the file to write the data to
116  * @param data the container including the maps to write to file
117  *
118  * @author Lutz Foucar
119  */
120 void saveHLLOffsetFile(const string &filename, CommonData& data)
121 {
122  ofstream out(filename.c_str(),ios::out|ios::trunc);
123  if (!out.is_open())
124  {
125  throw invalid_argument("saveHLLOffsetFile(): Error opening file '" +
126  filename + "'");
127  }
129  {
130  "HE pixel statistics map",
131  static_cast<uint32_t>(data.columns*2),
132  static_cast<uint32_t>(data.rows*0.5),
133  static_cast<uint32_t>(data.rows * data.columns),
134  ""
135  };
136 
137  out.write(reinterpret_cast<char*>(&header),sizeof(hllDataTypes::DarkcalFileHeader));
138  Detector::frame_t hlloffsets(data.offsetMap);
139  hllDataTypes::CASS2HLL(data.offsetMap,hlloffsets,header.rows,header.rows,data.columns);
140  Detector::frame_t hllnoises(data.noiseMap);
141  hllDataTypes::CASS2HLL(data.noiseMap,hllnoises,header.rows,header.rows,data.columns);
142  Detector::frame_t::const_iterator hlloffset(hlloffsets.begin());
143  Detector::frame_t::const_iterator hllnoise(hllnoises.begin());
144  vector<hllDataTypes::statistics> pixelStatistics(header.length);
145  vector<hllDataTypes::statistics>::iterator pixelstatistic(pixelStatistics.begin());
146  for(; hlloffset != hlloffsets.end(); ++hlloffset, ++hllnoise, ++pixelstatistic )
147  {
148  pixelstatistic->offset = *hlloffset;
149  pixelstatistic->sigma = *hllnoise;
150  }
151  const size_t pixelStatisticsLength(sizeof(hllDataTypes::statistics)*header.length);
152  out.write(reinterpret_cast<char*>(&pixelStatistics.front()),pixelStatisticsLength);
153  CommonData::mask_t hllmask(data.mask);
154  hllDataTypes::CASS2HLL(data.mask,hllmask,header.rows,header.rows,data.columns);
155  const size_t maskLength(sizeof(char)*header.length);
156  out.write(reinterpret_cast<char*>(&hllmask[0]),maskLength);
157 }
158 
159 /** will read the file containing the offset and noise map in the former CASS format
160  *
161  * open the file then determine its size from which one can extract the size of
162  * the frame. Then read data into temporary containers for double and then copy
163  * the data to the final float containers
164  *
165  * @param filename the filename of file containing the offset and noise maps.
166  * @param data the data storage where the info should be written to.
167  *
168  * @author Lutz Foucar
169  */
170 void readCASSOffsetFile(const string &filename, CommonData& data)
171 {
172  ifstream in(filename.c_str(), ios::binary);
173  if (!in.is_open())
174  {
175  Log::add(Log::WARNING,"readCASSOffsetFile: Could not open '" + filename +
176  "'. Skipping reading the noise and offset maps.");
177  return;
178  }
179  in.seekg(0,std::ios::end);
180  const size_t size = in.tellg() / 2 / sizeof(double);
181  in.seekg(0,std::ios::beg);
182  vector<double> offsets(size);
183  in.read(reinterpret_cast<char*>(&offsets[0]), size*sizeof(double));
184  vector<double> noises(size);
185  in.read(reinterpret_cast<char*>(&noises[0]), size*sizeof(double));
186  QWriteLocker lock(&data.lock);
187  data.offsetMap.resize(size);
188  copy(offsets.begin(),offsets.end(),data.offsetMap.begin());
189  data.noiseMap.resize(size);
190  copy(noises.begin(),noises.end(),data.noiseMap.begin());
191 }
192 
193 /** will save the file containing the offset and noise map in the former CASS format
194  *
195  * write the offset and noise map into a file. The values will just be written
196  * in a binary stream of doubles.
197  *
198  * The maps are still locked by the createMaps lock when writing.
199  *
200  * @param filename the filename of file containing the offset and noise maps.
201  * @param data the data storage where the info should be written to.
202  *
203  * @author Lutz Foucar
204  */
205 void saveCASSOffsetFile(const string &filename, CommonData& data)
206 {
207  ofstream out(filename.c_str(), ios::binary);
208  if (!out.is_open())
209  {
210  throw invalid_argument("saveCASSOffsetFile(): Error opening file '" +
211  filename + "'");
212  }
213  vector<double> offsets(data.offsetMap.size());
214  copy(data.offsetMap.begin(),data.offsetMap.end(),offsets.begin());
215  out.write(reinterpret_cast<char*>(&offsets[0]), offsets.size()*sizeof(double));
216  vector<double> noises(data.noiseMap.size());
217  copy(data.noiseMap.begin(),data.noiseMap.end(),noises.begin());
218  out.write(reinterpret_cast<char*>(&noises[0]), noises.size()*sizeof(double));
219 }
220 
221 /** will read the file containing the gain and cte corretion factors in the HLL format
222  *
223  * read in HLL gain/CTE correction format from a given file. If no filename is given
224  * just return from the function without doing anything.
225  *
226  * the first four lines look like the following
227 @verbatim
228 HE File containing gain and CTE values
229 VERSION 3
230 HE #Column Gain CTE0
231 GC 0 1 0.999977
232 [...]
233 @endverbatim
234  *
235  * the third line and following lines have different spacing, depending on
236  * how xonline is writing these files.
237  *
238  * column is related to the way the ccd is read out. The ccd
239  * consists of four segments
240  *
241  * BC
242  * AD
243  *
244  * that are placed ABCD for the HLL file format with the
245  * following numbers
246  *
247  * 1023 <- 512 1535 <- 1024
248  *
249  * 0 -> 512 1536 -> 2048
250  *
251  * The segments are read out bottom up for AD and
252  * top down for BC (actually shifted to the corresponding edge).
253  *
254  * The memory representation is continuously
255  *
256  * ...
257  * 1024 -> 2047
258  * 0 -> 1023
259  *
260  * @param filename the filename of file containing the offset and noise maps.
261  * @param data the data storage where the info should be written to.
262  *
263  * @author Mirko Scholz
264  * @author Lutz Foucar
265  */
266 void readHLLGainFile(const string &filename, CommonData& data)
267 {
268  if (filename.empty())
269  {
270  Log::add(Log::WARNING,"readHLLGainFile: No filename given therefore gain / cte will be set to 1");
271  return;
272  }
273  ifstream in(filename.c_str(), ios::binary);
274  if (!in.is_open())
275  {
276  Log::add(Log::WARNING,"readHLLGainFile: File '" + filename +
277  "' does not exist. Skipping reading the Gain/CTE file");
278  return;
279  }
280  char line[80];
281  in.getline(line, 80);
282  if (line != string("HE File containing gain and CTE values"))
283  {
284  throw runtime_error("readHLLGainFile: Wrong file format: " + std::string(line));
285  }
286  in.getline(line, 80);
287  if (strncmp(line, "VERSION 3", 9))
288  {
289  throw runtime_error("readHLLGainFile: Wrong file format: " + std::string(line));
290  }
291  in.getline(line, 80);
292 
293  vector<float> gains;
294  vector<float> ctes;
295 
296  char g='G', c='C';
297  int col;
298  float gain, cte;
299 
300  while(true)
301  {
302  in>>g;
303  in>>c;
304  in>>skipws>>col;
305  in>>skipws>>gain;
306  in>>skipws>>cte;
307  if ((g != 'G') || (c != 'C'))
308  break;
309  gains.push_back(gain);
310  ctes.push_back(cte);
311  }
312 
313  //build up gain + cte map in HLL format
314  Detector::frame_t hllgaincteMap;
315  const size_t rows(512);
316  const size_t columns(gains.size());
317  for (size_t row(0); row < rows; ++row)
318  {
319  for (size_t column(0); column < columns; ++column)
320  {
321  hllgaincteMap.push_back(gains[column] / pow(ctes[column], static_cast<int>(row+1)));
322  }
323  }
324  //convert HLL format to CASS format
325  QWriteLocker lock(&data.lock);
326  data.gain_cteMap.resize(hllgaincteMap.size());
327  hllDataTypes::HLL2CASS(hllgaincteMap,data.gain_cteMap,512,512,columns);
328 }
329 
330 /** read the CASS generated gain file
331  *
332  * @param filename the filename of file containing the gain maps.
333  * @param data the data storage where the info should be written to.
334  *
335  * @author Lutz Foucar
336  */
337 void readCASSGainFile(const string &filename, CommonData& data)
338 {
339  ifstream in(filename.c_str(), ios::binary);
340  if (!in.is_open())
341  {
342  Log::add(Log::WARNING,"readCASSGainFile: Could not open '" + filename +
343  "'. Skipping reading the gain map.");
344  return;
345  }
346  in.seekg(0,std::ios::end);
347  const size_t size = in.tellg() / sizeof(Detector::pixel_t);
348  in.seekg(0,std::ios::beg);
349  QWriteLocker lock(&data.lock);
350  Detector::frame_t &gains(data.gain_cteMap);
351  gains.resize(size);
352  in.read(reinterpret_cast<char*>(&gains.front()), size*sizeof(Detector::pixel_t));
353 }
354 
355 /** save the gain map to CASS style file
356  *
357  * @param filename the filename of file were the gains will be written to
358  * @param data the data storage where the info should be taken from.
359  *
360  * @author Lutz Foucar
361  */
362 void saveCASSGainFile(const string &filename, const CommonData& data)
363 {
364  ofstream out(filename.c_str(), ios::binary);
365  if (!out.is_open())
366  {
367  throw invalid_argument("saveCASSGainFile(): Error opening file '" +
368  filename + "'");
369  }
370  const Detector::frame_t &gains(data.gain_cteMap);
371  out.write(reinterpret_cast<const char*>(&gains.front()), gains.size()*sizeof(Detector::pixel_t));
372 }
373 
374 
375 /** read the CASS generated hotpixels file
376  *
377  * @param filename the filename of file containing the hot pixel mask.
378  * @param data the data storage where the info should be written to.
379  *
380  * @author Lutz Foucar
381  */
382 void readCASSHotPixFile(const string &filename, CommonData& data)
383 {
384  ifstream in(filename.c_str(), ios::binary);
385  if (!in.is_open())
386  {
387  Log::add(Log::WARNING,"readCASSHotPixFile: Could not open '" + filename +
388  "'. Skipping reading the hot pixels mask.");
389  return;
390  }
391  in.seekg(0,std::ios::end);
392  const int valuesize(sizeof(CommonData::mask_t::value_type));
393  const size_t size = in.tellg() / valuesize;
394  in.seekg(0,std::ios::beg);
395  QWriteLocker lock(&data.lock);
396  CommonData::mask_t &hotpix(data.hotpixels);
397  hotpix.resize(size);
398  in.read(reinterpret_cast<char*>(&hotpix.front()), size*valuesize);
399 }
400 
401 /** save the hot pixels to CASS style file
402  *
403  * @param filename the filename of file were the hot pixel mask will be written to
404  * @param data the data storage where the info should be taken from.
405  *
406  * @author Lutz Foucar
407  */
408 void saveCASSHotPixFile(const string &filename, const CommonData& data)
409 {
410  ofstream out(filename.c_str(), ios::binary);
411  if (!out.is_open())
412  {
413  throw invalid_argument("saveCASSHotPixFile(): Error opening file '" +
414  filename + "'");
415  }
416  const CommonData::mask_t &hotpix(data.hotpixels);
417  const int valuesize(sizeof(CommonData::mask_t::value_type));
418  out.write(&hotpix.front(), hotpix.size()*valuesize);
419 }
420 
421 /** check whether the frame has the same size as the maps.
422  *
423  * if not resize the maps to the right size and initialize them with values, that
424  * will let the hitfinder find no pixels and the correction make does not alter
425  * the frame.
426  *
427  * this function relys on that the maps are locked. Usually they are since this
428  * is called by the operators of the map creators. These are locked because
429  * the function calling the operators will lock the maps before.
430  *
431  * @param frame the Frame to check
432  * @param data the container for all maps.
433  *
434  * @author Lutz Foucar
435  */
436 void isSameSize(const Frame& frame, CommonData& data)
437 {
438  QWriteLocker lock(&data.lock);
439  bool changed(false);
440  if ((frame.columns * frame.rows) != static_cast<int>(data.offsetMap.size()))
441  {
442  Log::add(Log::WARNING,"isSameSize():The offsetMap does not have the right size '" +
443  toString(data.offsetMap.size()) +
444  "' to accommodate the frames with size '" +
445  toString(frame.columns * frame.rows) +
446  "'. Resizing the offsetMap");
447  data.offsetMap.resize(frame.columns*frame.rows, 0);
448  changed=true;
449  }
450  if ((frame.columns * frame.rows) != static_cast<int>(data.noiseMap.size()))
451  {
452  Log::add(Log::WARNING,"isSameSize():The noiseMap does not have the right size '" +
453  toString(data.noiseMap.size()) +
454  "' to accommodate the frames with size '" +
455  toString(frame.columns * frame.rows) + "'. Resizing the noiseMap");
456  data.noiseMap.resize(frame.columns*frame.rows, 4000);
457  changed=true;
458  }
459  if ((frame.columns * frame.rows) != static_cast<int>(data.mask.size()))
460  {
461  Log::add(Log::WARNING,"isSameSize():The mask does not have the right size '" +
462  toString(data.mask.size()) +
463  "' to accommodate the frames with size '" +
464  toString(frame.columns * frame.rows) + "'. Resizing and reloading the mask");
465  data.mask.resize(frame.columns*frame.rows, 1);
466  CASSSettings s;
467  s.beginGroup("PixelDetectors");
469  s.beginGroup("CorrectionMaps");
470  data.columns = frame.columns;
471  data.rows = frame.rows;
472  createCASSMask(data,s);
473  changed=true;
474  }
475  if ((frame.columns * frame.rows) != static_cast<int>(data.gain_cteMap.size()))
476  {
477  Log::add(Log::WARNING,"isSameSize():The gain_cteMap does not have the right size '" +
478  toString(data.gain_cteMap.size()) +
479  "' to accommodate the frames with size '" +
480  toString(frame.columns * frame.rows) +
481  "'. Resizing the gain_cteMap");
482  data.gain_cteMap.resize(frame.columns*frame.rows, 1);
483  changed=true;
484  }
485  if ((frame.columns * frame.rows) != static_cast<int>(data.correctionMap.size()))
486  {
487  Log::add(Log::WARNING,"isSameSize():The correctionMap does not have the right size '" +
488  toString(data.correctionMap.size()) +
489  "' to accommodate the frames with size '" +
490  toString(frame.columns * frame.rows) +
491  "'. Resizing the correctionMap");
492  data.correctionMap.resize(frame.columns*frame.rows, 1);
493  changed=true;
494  }
495  if ((frame.columns * frame.rows) != static_cast<int>(data.hotpixels.size()))
496  {
497  Log::add(Log::WARNING,"isSameSize():The hotpixelMask does not have the right size '" +
498  toString(data.hotpixels.size()) +
499  "' to accommodate the frames with size '" +
500  toString(frame.columns * frame.rows) +
501  "'. Resizing the correctionMap");
502  data.hotpixels.resize(frame.columns*frame.rows, 0);
503  changed=true;
504  }
505  if(changed)
506  {
507  throw runtime_error("IsSameSize: Should not happen");
508  data.columns = frame.columns;
509  data.rows = frame.rows;
510  data.createCorMap();
511  }
512 }
513 
514 
515 } //end namespace pixeldetector
516 } //end namespace cass
517 
518 //initialize static members//
521 
523 {
524  QMutexLocker lock(&_mutex);
525  if (_instances.find(detector) == _instances.end())
526  {
527  Log::add(Log::DEBUG0,"CommonData::instance(): creating an instance of the" +
528  string(" common data container for detector '") + detector + "'");
529  _instances[detector] = CommonData::shared_pointer(new CommonData(detector));
530  }
531  return _instances[detector];
532 }
533 
534 void CommonData::controlCalibration(const string& command)
535 {
536  QMutexLocker locker(&_mutex);
537  instancesmap_t::iterator instance(_instances.begin());
538  instancesmap_t::const_iterator end(_instances.end());
539  for (; instance != end; ++instance)
540  {
541  Log::add(Log::DEBUG1,"CommonData::controlCalibration: Starting calibration of '" +
542  instance->first +"'");
543  if(command == "startDarkcal")
544  instance->second->_offsetnoiseMapcreator->controlCalibration(command);
545  else if (command == "startGain")
546  instance->second->_gainCreator->controlCalibration(command);
547  else
548  throw invalid_argument("CommonData::controlCalibration: command '" +
549  command + "' is unknown.");
550  }
551 }
552 
553 CommonData::CommonData(const instancesmap_t::key_type& /*detname*/)
554  : columns(1024),
555  rows(1024),
556  detectorId(-1),
557  _settingsLoaded(false),
558  _noiseRange(make_pair(0,0))
559 {}
560 
562 {
563  if (!_settingsLoaded)
564  {
566  s.beginGroup("CorrectionMaps");
567 
568  /** try do deduce the frame size from the detectorname, if it can't be
569  * deduced read it from the settings file and resize the maps accordingly.
570  */
572  columns = s.value("nColumns",static_cast<unsigned>(shape.first)).toUInt();
573  rows = s.value("nRows",static_cast<unsigned>(shape.second)).toUInt();
574  Log::add(Log::VERBOSEINFO,string("CommonData::loadSettings: ") +
575  "The shape of detector '" + detectorname + "' is set to '" +
576  toString(columns) + "'x'" + toString(rows) + "'.");
577  offsetMap.resize(columns*rows, 0);
578  noiseMap.resize(columns*rows, 4000);
579  mask.resize(columns*rows, 1);
580  hotpixels.resize(columns*rows, 0);
581  gain_cteMap.resize(columns*rows, 1);
582  correctionMap.resize(columns*rows, 1);
583 
584  /** load info for getting the right cor value from the noise maps */
585  _noiseRange.first = s.value("LowerNoisyPixelThreshold",0).toFloat();
586  _noiseRange.second = s.value("NoisyPixelThreshold",40000).toFloat();
587  _autoNoiseThreshold = qFuzzyCompare(_noiseRange.second,-1.f);
588  _autoMultiplier = s.value("AutoMultiplier",4.f).toFloat();
589 
590  /** setup how the offset/noise maps will be created */
591  string mapcreatortype(s.value("MapCreatorType","none").toString().toStdString());
593  _offsetnoiseMapcreator->loadSettings(s);
594 
595  /** setup how and where the offset/noise maps will be read from.
596  * If offset filename is a link, try to deduce the real filename
597  */
598  string offsetfilename(s.value("InputOffsetNoiseFilename",
599  QString::fromStdString("darkcal_"+toString(detectorId)+".lnk")).toString().toStdString());
600  QFileInfo offsetfilenameInfo(QString::fromStdString(offsetfilename));
601  if (offsetfilenameInfo.isSymLink())
602  {
603  if (offsetfilenameInfo.exists())
604  offsetfilename = offsetfilenameInfo.symLinkTarget().toStdString();
605  else
606  Log::add(Log::WARNING,"CommonData::loadSettings: The given offset filename '" +
607  offsetfilename + "' is a link that referes to a non existing file!");
608  }
609  if (offsetfilename != _inputOffsetFilename)
610  {
611  Log::add(Log::VERBOSEINFO, "CommonData::loadSettings(): Load Darkcal data " +
612  string(" for detector with name '") + detectorname + "' which has id '" +
613  toString(detectorId) + "' from file '" + offsetfilename +"'");
614  _inputOffsetFilename = offsetfilename;
615  string offsetfiletype(s.value("InputOffsetNoiseFiletype","hll").toString().toStdString());
616  if (offsetfiletype == "hll")
617  readHLLOffsetFile(offsetfilename, *this);
618  else if(offsetfiletype == "cass")
619  readCASSOffsetFile(offsetfilename, *this);
620  else
621  throw invalid_argument("CommonData::loadSettings: OffsetNoiseFiletype '" +
622  offsetfiletype + "' does not exist");
623  }
624 
625  /** setup how and where the offset/noise maps will be written to */
626  _outputOffsetFilename = (s.value("OutputOffsetNoiseFilename","darkcal").toString().toStdString());
627  string outputoffsetfiletype(s.value("OutputOffsetNoiseFiletype","hll").toString().toStdString());
628  if (outputoffsetfiletype == "hll")
630  else if(outputoffsetfiletype == "cass")
632  else
633  throw invalid_argument("CommonData::loadSettings: OutputOffsetNoiseFiletype '" +
634  outputoffsetfiletype + "' does not exist");
635 
636  /** setup how the offset/noise maps will be created */
637  string gainmapcreatortype(s.value("GainMapCreatorType","none").toString().toStdString());
638  _gainCreator = MapCreatorBase::instance(gainmapcreatortype);
639  _gainCreator->loadSettings(s);
640 
641  /** setup how and from where the gain file will be read and read it */
642  string gainfilename(s.value("InputGainFilename",
643  QString::fromStdString("gain_"+toString(detectorId)+".lnk")).toString().toStdString());
644  QFileInfo gainfilenameInfo(QString::fromStdString(gainfilename));
645  if (gainfilenameInfo.isSymLink())
646  {
647  if (gainfilenameInfo.exists())
648  gainfilename = gainfilenameInfo.symLinkTarget().toStdString();
649  else
650  Log::add(Log::WARNING,"CommonData::loadSettings: The given gain filename '" +
651  gainfilename + "' is a link that referes to a non existing file!");
652  }
653  if (gainfilename != _inputGainFilename)
654  {
655  Log::add(Log::VERBOSEINFO, "CommonData::loadSettings(): Load gain data " +
656  string(" for detector with name '") + detectorname + "' which has id '" +
657  toString(detectorId) + "' from file '" + gainfilename +"'");
658  _inputGainFilename = gainfilename;
659  string gainFiletype(s.value("InputGainFiletype","hll").toString().toStdString());
660  if (gainFiletype == "hll")
662  else if (gainFiletype == "cass")
664  else
665  throw invalid_argument("CommonData::loadSettings: GainFiletype '" +
666  gainFiletype + "' does not exist");
667  }
668 
669  /** setup how and where the gain map will be written to */
670  _outputGainFilename = (s.value("OutputGainFilename","gain").toString().toStdString());
671  string outputgainfiletype(s.value("OutputGainFiletype","cass").toString().toStdString());
672  if (outputgainfiletype == "cass")
674  else
675  throw invalid_argument("CommonData::loadSettings: OutputGainFiletype '" +
676  outputgainfiletype + "' does not exist");
677 
678  /** setup how and from where the hot pixels mask file will be read and read it */
679  string hotpixfilename(s.value("InputHotPixMaskFilename",
680  QString::fromStdString("hotpix_"+toString(detectorId)+".lnk")).toString().toStdString());
681  QFileInfo hotpixfilenameInfo(QString::fromStdString(hotpixfilename));
682  if (hotpixfilenameInfo.isSymLink())
683  {
684  if (hotpixfilenameInfo.exists())
685  hotpixfilename = hotpixfilenameInfo.symLinkTarget().toStdString();
686  else
687  Log::add(Log::WARNING,"CommonData::loadSettings: The given hotpix filename '" +
688  hotpixfilename + "' is a link that referes to a non existing file!");
689  }
690  if (hotpixfilename != _inputHotPixFilename)
691  {
692  Log::add(Log::VERBOSEINFO, "CommonData::loadSettings(): Load hotpix mask " +
693  string(" for detector with name '") + detectorname + "' which has id '" +
694  toString(detectorId) + "' from file '" + hotpixfilename +"'");
695  _inputHotPixFilename = hotpixfilename;
696  string hotpixFiletype(s.value("InputHotPixMaskFiletype","cass").toString().toStdString());
697  if (hotpixFiletype == "cass")
699  else
700  throw invalid_argument("CommonData::loadSettings: HotPixFiletype '" +
701  hotpixFiletype + "' does not exist");
702  }
703 
704  /** setup how and where the gain map will be written to */
705  _outputHotPixFilename = (s.value("OutputHotPixMaskFilename","hotpix").toString().toStdString());
706  string outputhotpixfiletype(s.value("OutputHotPixMaskFiletype","cass").toString().toStdString());
707  if (outputhotpixfiletype == "cass")
709  else
710  throw invalid_argument("CommonData::loadSettings: OutputHotPixMaskFiletype '" +
711  outputhotpixfiletype + "' does not exist");
712 
713  /** create the user mask and generate the correction map */
714  createCASSMask(*this,s);
715  createCorMap();
716 
717  s.endGroup();
718  }
719  _settingsLoaded = true;
720 }
721 
722 void CommonData::generateMaps(const Frame &frame)
723 {
724  _settingsLoaded = false;
725  const size_t allmapsize(offsetMap.size() + noiseMap.size() + mask.size() +
726  hotpixels.size() + gain_cteMap.size() + correctionMap.size());
727  if (allmapsize != 6*frame.data.size())
728  throw runtime_error("CommonData::generateMaps: '" + detectorname +
729  "', at least one of the maps is not resized to fit the " +
730  "frames with '" + toString(frame.columns)+
731  "x" + toString(frame.rows) + "'");
732  MapCreatorBase& generateOffsetNoiseMaps(*_offsetnoiseMapcreator);
733  generateOffsetNoiseMaps(frame);
734  MapCreatorBase& generateGainMap(*_gainCreator);
735  generateGainMap(frame);
736 }
737 
739 {
740  string outname;
741  if (_outputOffsetFilename == "darkcal")
742  outname = "darkcal_"+toString(detectorId) + "_" +
743  QDateTime::currentDateTime().toString("yyyyMMdd_HHmm").toStdString() +
744  ".cal";
745  else
746  outname = _outputOffsetFilename;
747  _saveNoiseOffsetTo(outname,*this);
748  if (_outputOffsetFilename == "darkcal")
749  {
750  string linkname("darkcal_" + toString(detectorId) +".lnk");
751  if (QFile::exists(QString::fromStdString(linkname)))
752  if(!QFile::remove(QString::fromStdString(linkname)))
753  throw runtime_error("CommonData::saveOffsetNoiseMaps: could not remove already existing link '" +
754  linkname +"'");
756  throw runtime_error("CommonData::saveOffsetNoiseMaps: could not create a link named '"+
757  linkname + "' that points to the outputfile '" + outname +"'");
758  }
759 }
760 
762 {
763  string outname;
764  if (_outputGainFilename == "gain")
765  outname = "gain_"+toString(detectorId) + "_" +
766  QDateTime::currentDateTime().toString("yyyyMMdd_HHmm").toStdString() +
767  ".cal";
768  else
769  outname = _outputGainFilename;
770  _saveGainTo(outname,*this);
771  if (_outputGainFilename == "gain")
772  {
773  string linkname("gain_" + toString(detectorId) +".lnk");
774  if (QFile::exists(QString::fromStdString(linkname)))
775  if(!QFile::remove(QString::fromStdString(linkname)))
776  throw runtime_error("CommonData::saveGainMap: could not remove already existing link '" +
777  linkname +"'");
779  throw runtime_error("CommonData::saveGainMap: could not create a link named '"+
780  linkname + "' that points to the outputfile '" + outname +"'");
781  }
782 }
783 
785 {
786  string outname;
787  if (_outputHotPixFilename == "hotpix")
788  outname = "hotpix_"+toString(detectorId) + "_" +
789  QDateTime::currentDateTime().toString("yyyyMMdd_HHmm").toStdString() +
790  ".mask";
791  else
792  outname = _outputHotPixFilename;
793  _saveHotPixTo(outname,*this);
794  if (_outputHotPixFilename == "hotpix")
795  {
796  string linkname("hotpix_" + toString(detectorId) +".lnk");
797  if (QFile::exists(QString::fromStdString(linkname)))
798  if(!QFile::remove(QString::fromStdString(linkname)))
799  throw runtime_error("CommonData::saveGainMap: could not remove already existing link '" +
800  linkname +"'");
802  throw runtime_error("CommonData::saveHotPixMask: could not create a link named '"+
803  linkname + "' that points to the outputfile '" + outname +"'");
804  }
805 }
806 
808 {
809  if (_autoNoiseThreshold && !noiseMap.empty())
810  {
812  calc_t stat(4);
813  Detector::frame_t::const_iterator val(noiseMap.begin());
814  Detector::frame_t::const_iterator End(noiseMap.end());
815  while (val != End)
816  stat.addDatum(*val++);
817  _noiseRange.first = stat.mean() - (_autoMultiplier * stat.stdv());
818  _noiseRange.second = stat.mean() + (_autoMultiplier * stat.stdv());
819  Log::add(Log::INFO, "CommonData::createCorMap(): only noisevalues between '"+
820  toString(_noiseRange.first) + "' and '" + toString(_noiseRange.second) +
821  "' are taken for detector with id '" + toString(detectorId) + "'");
822  }
823  Detector::frame_t::iterator corval(correctionMap.begin());
824  Detector::frame_t::const_iterator corvalMapEnd(correctionMap.end());
825  Detector::frame_t::const_iterator noise(noiseMap.begin());
826  Detector::frame_t::const_iterator gain(gain_cteMap.begin());
827  mask_t::const_iterator Mask(mask.begin());
828  mask_t::const_iterator hotpix(hotpixels.begin());
829  /** reset the correction map before generating the correction values */
830  fill(correctionMap.begin(),correctionMap.end(),1.);
831  while (corval != corvalMapEnd)
832  {
833  *corval = *gain++ * *corval * *Mask++ *
834  (_noiseRange.first < *noise) * (*noise < _noiseRange.second) *
835  (-1 < *hotpix++);
836  ++corval;
837  ++noise;
838  }
839 }
bool _settingsLoaded
switch to tell that load settins for this common data was already running
Definition: common_data.h:353
void createCorMap()
create the correction map
std::string _inputGainFilename
the gain correction input filename
Definition: common_data.h:362
void saveOffsetNoiseMaps()
save offset and noise maps
file contains declaration of the CASSEvent
Settings for CASS.
Definition: cass_settings.h:30
void HLL2CASS(const inputContainerType &HLLMatrix, outputContainerType &CASSMatrix, size_t quadrantColumns, size_t quadrantRows, size_t HLLColumns)
convert a linearised matrix in the hll format to the CASS format
Definition: hlltypes.hpp:322
statistics calculator for a cummulative statistic, removes outliers
contains base class for all correction map creators.
static void controlCalibration(const std::string &command)
issue a command to the map creators of all instances
void saveGainMap()
save gain map
std::string detectorname
the name of the detector whos maps are contained in this class instance
Definition: common_data.h:309
void CASS2HLL(const inputContainerType &CASSMatrix, outputContainerType &HLLMatrix, size_t quadrantColumns, size_t quadrantRows, size_t CASSColumns)
convert a linearised matrix in the CASS format to the hll format
Definition: hlltypes.hpp:235
STL namespace.
contains the layout of the hll data types and conversion to cass data types
std::string _inputOffsetFilename
input filename of the offset and noise map
Definition: common_data.h:350
std::pair< size_t, size_t > shape_t
define a shape of an image columnsxrows
things written only at end of run H5Dump ProcessorSummary size
void readHLLOffsetFile(const string &filename, CommonData &data)
will read the file containing the offset and noise map in the hll format
Definition: common_data.cpp:63
std::tr1::function< void(const std::string &, CommonData &)> _saveHotPixTo
function to write the hot pixel mask
Definition: common_data.h:368
void isSameSize(const Frame &frame, CommonData &data)
check whether the frame has the same size as the maps.
std::vector< char > mask_t
a mask is a vector of bools
Definition: common_data.h:146
bool _autoNoiseThreshold
flag whether the noise threshold should be automatically determined
Definition: common_data.h:380
static void add(Level level, const std::string &line)
add a string to the log
Definition: log.cpp:31
float pixel_t
define a pixel of the pixel detector
static shared_pointer instance(const std::string &type)
create an instance of the requested functor
fromStdString(const std::string &str)
void readHLLGainFile(const string &filename, CommonData &data)
will read the file containing the gain and cte corretion factors in the HLL format ...
std::pair< Detector::pixel_t, Detector::pixel_t > _noiseRange
the range in adu for masking noisy pixels
Definition: common_data.h:377
mask_t hotpixels
the hotpixel mask
Definition: common_data.h:288
Detector::pixel_t _autoMultiplier
the multiplier about which the automatically determined threshold will be defined ...
Definition: common_data.h:383
uint32_t length
the overal length of the frame, if the matrix is linearized
Definition: hlltypes.hpp:147
size_t columns
the width of the maps
Definition: common_data.h:256
void saveHotPixMask()
save hot pixel mask
size_t rows
the height of the maps
Definition: common_data.h:259
static instancesmap_t _instances
the helperclass instances.
Definition: common_data.h:334
void loadSettings(CASSSettings &s)
load the settings of this common object
void saveCASSGainFile(const string &filename, const CommonData &data)
save the gain map to CASS style file
std::vector< pixel_t > frame_t
a frame is a vector of pixels
contains definition of the mask of a pixeldetector
void saveCASSHotPixFile(const string &filename, const CommonData &data)
save the hot pixels to CASS style file
std::tr1::shared_ptr< MapCreatorBase > _gainCreator
functor to create the Maps
Definition: common_data.h:356
uint16_t columns
how many columns
static QMutex _mutex
mutex to lock the creation of an instance
Definition: common_data.h:337
static std::string fromSettings(const CASSSettings &s)
retrieve it from the casssettings
Definition: common_data.h:47
uint32_t rows
the height of the frames
Definition: hlltypes.hpp:144
std::string toString(const Type &t)
convert any type to a string
Definition: cass.h:63
auxiliary data[Processor]
std::string _outputHotPixFilename
the hot pixel mask output filename
Definition: common_data.h:374
Data used commonly for one AdvancedDetector.
Definition: common_data.h:136
void readCASSOffsetFile(const string &filename, CommonData &data)
will read the file containing the offset and noise map in the former CASS format
void readCASSGainFile(const string &filename, CommonData &data)
read the CASS generated gain file
Detector::frame_t offsetMap
the offset map
Definition: common_data.h:266
value(const QString &key, const QVariant &defaultValue=QVariant()
std::tr1::shared_ptr< CommonData > shared_pointer
typedef a shared pointer of this
Definition: common_data.h:140
QReadWriteLock lock
lock to synchronize read and write acces to the common data
Definition: common_data.h:253
contains declarations of statistic calculators
A Frame of an advance Pixel Detector.
void readCASSHotPixFile(const string &filename, CommonData &data)
read the CASS generated hotpixels file
int32_t detectorId
the id of the detector that contains the frames whos maps we have here
Definition: common_data.h:306
Detector::frame_t data
the frame data
void saveCASSOffsetFile(const string &filename, CommonData &data)
will save the file containing the offset and noise map in the former CASS format
contains the common data for one advanced pixeldetector
void saveHLLOffsetFile(const string &filename, CommonData &data)
save the maps to a hll type darkcal file
CommonData()
prevent people from constructing other than using instance().
Definition: common_data.h:313
file contains specialized class that do the settings for cass
Detector::frame_t correctionMap
the correction map
Definition: common_data.h:303
std::tr1::function< void(const std::string &, CommonData &)> _saveGainTo
function to write the gain map
Definition: common_data.h:359
static shared_pointer instance(const instancesmap_t::key_type &detector)
static function creating instance of this.
std::tr1::shared_ptr< MapCreatorBase > _offsetnoiseMapcreator
functor to create the Maps
Definition: common_data.h:341
std::string _inputHotPixFilename
the hot pixel mask input filename
Definition: common_data.h:371
static Detector::shape_t shapeFromName(const std::string &name)
try to retrive the right shape of the detector from the name
std::tr1::function< void(const std::string &, CommonData &)> _saveNoiseOffsetTo
function to write the offset maps
Definition: common_data.h:344
std::string _outputGainFilename
the gain correction output filename
Definition: common_data.h:365
std::string _outputOffsetFilename
output filename for the offset and noise maps
Definition: common_data.h:347
void generateMaps(const Frame &frame)
generate the maps from the frame data with help of the functors
void createCASSMask(CommonData &data, CASSSettings &s)
create the mask
advanced pixeldetectors
std::map< std::string, shared_pointer > instancesmap_t
typedef describing the instances of the helper
Definition: common_data.h:143
Electron detector
Definition: hdf5-input.ini:62
contains a logger for cass
base class for all correction map creators
struct describing the statistics saved in a HLL Darkcal file
Definition: hlltypes.hpp:160
the file header structure of the hll darkcal file format
Definition: hlltypes.hpp:132
Detector::frame_t gain_cteMap
the gain + cte map
Definition: common_data.h:295
mask_t mask
the detector mask
Definition: common_data.h:280
Detector::frame_t noiseMap
the noise map
Definition: common_data.h:273
beginGroup(const QString &prefix)
set up how to create the noise