Commit 93b46661 authored by Alejandro Homs Puron's avatar Alejandro Homs Puron Committed by operator for beamline
Browse files

Jungfrau: add GainPed calibration

* Add 16 & 32 bit gain & pedestal correction with calibration maps
  export using GainPedImgProc task
* Move double buffer read code to ReadHelper
parent 529345be
...@@ -28,12 +28,17 @@ ...@@ -28,12 +28,17 @@
#include "processlib/SinkTask.h" #include "processlib/SinkTask.h"
#include <array>
#include <variant>
namespace lima namespace lima
{ {
namespace SlsDetector namespace SlsDetector
{ {
typedef std::array<Data, 3> JungfrauGainDataSet;
class Jungfrau : public Model class Jungfrau : public Model
{ {
DEB_CLASS_NAMESPC(DebModCamera, "Jungfrau", "SlsDetector"); DEB_CLASS_NAMESPC(DebModCamera, "Jungfrau", "SlsDetector");
...@@ -43,6 +48,87 @@ class Jungfrau : public Model ...@@ -43,6 +48,87 @@ class Jungfrau : public Model
typedef unsigned short Word; typedef unsigned short Word;
typedef unsigned int Long; typedef unsigned int Long;
class GainPed
{
DEB_CLASS_NAMESPC(DebModCamera, "Jungfrau::GainPed",
"SlsDetector");
public:
struct Calib {
JungfrauGainDataSet gain_map;
JungfrauGainDataSet ped_map;
void clear() {
for (auto& d: gain_map) clearData(d);
for (auto& d: ped_map) clearData(d);
}
};
enum MapType { Map16, Map32 };
struct Map16Data {
static constexpr MapType Type = Map16;
static constexpr double DefaultCoeffs[3][2] = {
{ 0.011555, 965.5},
{-0.302124, 5519.0},
{-4.254403, 64882.8},
};
static constexpr Data::TYPE DataType = Data::UINT16;
using Pixel = unsigned short;
};
struct Map32Data {
static constexpr MapType Type = Map32;
static constexpr double DefaultCoeffs[3][2] = {
{ 0.999952, 0.4}, // effectively {1, 0}
{ -26.144935, 394047.3}, // G0 x16
{-368.163215, 5531211.9}, // G1 x14
};
static constexpr Data::TYPE DataType = Data::UINT32;
using Pixel = unsigned int;
};
GainPed(Jungfrau *jungfrau);
void setMapType(MapType map_type);
void getMapType(MapType& map_type);
void updateImageSize(Size size, bool raw);
void getDefaultCalib(Calib& calib);
Data::TYPE getDataType();
void processFrame(Data& data, Data& proc);
void setCalib(const Calib& calib);
void getCalib(Calib& calib);
private:
template <class M> struct Impl {
DEB_CLASS_NAMESPC(DebModCamera,
"Jungfrau::GainPed::Impl",
"SlsDetector");
public:
using Map = M;
Impl(Jungfrau *j) : m_jungfrau(j) {}
void updateImageSize(Size size, bool raw);
void getDefaultCalib(Calib& calib);
void setDefaultCalib() { getDefaultCalib(m_calib); }
void processFrame(Data& data, Data& proc);
Jungfrau *m_jungfrau;
Size m_size;
bool m_raw;
int m_pixels{0};
Calib m_calib;
};
using AnyImpl = std::variant<Impl<Map16Data>, Impl<Map32Data>>;
Jungfrau *m_jungfrau;
AnyImpl m_impl;
Size m_size;
bool m_raw;
};
class ImgProcTask : public SinkTaskBase class ImgProcTask : public SinkTaskBase
{ {
DEB_CLASS_NAMESPC(DebModCamera, "Jungfrau::ImgProcTask", DEB_CLASS_NAMESPC(DebModCamera, "Jungfrau::ImgProcTask",
...@@ -90,6 +176,9 @@ class Jungfrau : public Model ...@@ -90,6 +176,9 @@ class Jungfrau : public Model
void readGainADCMaps(Data& gain_map, Data& adc_map, FrameType& frame); void readGainADCMaps(Data& gain_map, Data& adc_map, FrameType& frame);
GainPed& getGainPed() { return m_gain_ped_img_proc->m_gain_ped; }
void readGainPedProcMap(Data& proc_map, FrameType& frame);
virtual bool isXferActive(); virtual bool isXferActive();
protected: protected:
...@@ -109,6 +198,8 @@ class Jungfrau : public Model ...@@ -109,6 +198,8 @@ class Jungfrau : public Model
virtual void stopAcq(); virtual void stopAcq();
private: private:
friend class GainPed;
class Recv class Recv
{ {
DEB_CLASS_NAMESPC(DebModCamera, "Jungfrau::Recv", "SlsDetector"); DEB_CLASS_NAMESPC(DebModCamera, "Jungfrau::Recv", "SlsDetector");
...@@ -214,6 +305,54 @@ class Jungfrau : public Model ...@@ -214,6 +305,54 @@ class Jungfrau : public Model
typedef std::vector<ImgProcBase *> ImgProcList; typedef std::vector<ImgProcBase *> ImgProcList;
template <class T>
class ReaderHelper : public Buffer::Callback {
DEB_CLASS_NAMESPC(DebModCamera, "Jungfrau::ReaderHelper",
"SlsDetector");
public:
typedef DoubleBuffer<T> DBuffer;
T& addRead(DBuffer& b, FrameType& frame) {
DEB_MEMBER_FUNCT();
if (m_reader)
THROW_HW_ERROR(Error)
<< "A reader is already active";
m_reader = new Reader(b, frame);
frame = m_reader->getCounter();
return m_reader->getBuffer();
}
void addData(Data& src, Data& ref) {
DEB_MEMBER_FUNCT();
makeDataRef(src, ref, this);
m_buffer_list.insert(ref.data());
DEB_TRACE() << DEB_VAR1(m_buffer_list.size());
}
protected:
virtual void destroy(void *buffer) {
DEB_MEMBER_FUNCT();
DEB_PARAM() << DEB_VAR1(m_buffer_list.size());
if (m_buffer_list.empty() || !m_reader)
DEB_ERROR() << "Unexpected "
<< DEB_VAR1(buffer);
BufferList::iterator it, end = m_buffer_list.end();
it = find(m_buffer_list.begin(), end, buffer);
if (it == end)
DEB_ERROR() << "Bad " << DEB_VAR1(buffer);
m_buffer_list.erase(it);
if (m_buffer_list.empty())
m_reader = NULL;
}
private:
typedef DoubleBufferReader<T> Reader;
typedef std::set<void *> BufferList;
AutoPtr<Reader> m_reader;
BufferList m_buffer_list;
};
class GainADCMapImgProc : public ImgProcBase class GainADCMapImgProc : public ImgProcBase
{ {
DEB_CLASS_NAMESPC(DebModCamera, "Jungfrau::GainADCMapImgProc", DEB_CLASS_NAMESPC(DebModCamera, "Jungfrau::GainADCMapImgProc",
...@@ -247,56 +386,45 @@ class Jungfrau : public Model ...@@ -247,56 +386,45 @@ class Jungfrau : public Model
} }
}; };
typedef DoubleBuffer<MapData> DBuffer; typedef ReaderHelper<MapData> Reader;
typedef typename Reader::DBuffer DBuffer;
class ReaderHelper : public Buffer::Callback { DBuffer m_buffer;
DEB_CLASS_NAMESPC(DebModCamera, "Jungfrau::" AutoPtr<Reader> m_reader;
"GainADCMapImgProc::ReaderHelper", };
class GainPedImgProc : public ImgProcBase
{
DEB_CLASS_NAMESPC(DebModCamera, "Jungfrau::GainPedImgProc",
"SlsDetector"); "SlsDetector");
public: public:
void addRead(DBuffer& b, Data& gain_map, Data& adc_map, GainPedImgProc(Jungfrau *jungfrau);
FrameType frame) {
DEB_MEMBER_FUNCT();
if (m_reader)
THROW_HW_ERROR(Error)
<< "A reader is already active";
m_reader = new Reader(b, frame);
MapData& m = m_reader->getBuffer();
DEB_TRACE() << DEB_VAR1(&m);
makeDataRef(m.gain_map, gain_map, this); virtual void updateImageSize(Size size, bool raw);
++m_count; virtual void prepareAcq();
makeDataRef(m.adc_map, adc_map, this); virtual void processFrame(Data& data);
++m_count;
DEB_TRACE() << DEB_VAR1(m_count);
frame = m_reader->getCounter(); void readProcMap(Data& proc_map, FrameType& frame);
}
protected: GainPed m_gain_ped;
virtual void destroy(void *buffer) {
DEB_MEMBER_FUNCT();
DEB_PARAM() << DEB_VAR1(m_count);
if ((m_count == 0) || !m_reader)
DEB_ERROR() << DEB_VAR1(m_count);
MapData& m = m_reader->getBuffer();
if ((buffer != m.gain_map.data()) &&
(buffer != m.adc_map.data()))
THROW_HW_ERROR(Error)
<< "Bad buffer";
if (--m_count == 0)
m_reader = NULL;
}
private: private:
typedef DoubleBufferReader<MapData> Reader; struct MapData {
Data proc_map;
AutoPtr<Reader> m_reader; MapData() { proc_map.type = Data::UINT16; }
int m_count{0};
void updateSize(Size size) {
updateDataSize(proc_map, size);
};
void clear() { clearData(proc_map); }
}; };
typedef ReaderHelper<MapData> Reader;
typedef typename Reader::DBuffer DBuffer;
DBuffer m_buffer; DBuffer m_buffer;
AutoPtr<ReaderHelper> m_reader; AutoPtr<Reader> m_reader;
}; };
bool getRawMode() { bool getRawMode() {
...@@ -309,7 +437,10 @@ class Jungfrau : public Model ...@@ -309,7 +437,10 @@ class Jungfrau : public Model
std::vector<int> data_dims{size.getWidth(), size.getHeight()}; std::vector<int> data_dims{size.getWidth(), size.getHeight()};
if (d.empty() || (d.dimensions != data_dims)) { if (d.empty() || (d.dimensions != data_dims)) {
d.dimensions = data_dims; d.dimensions = data_dims;
d.setBuffer(new Buffer(d.size())); Buffer *b = new Buffer(d.size());
d.setBuffer(b);
b->unref();
clearData(d);
} }
} }
...@@ -339,6 +470,7 @@ class Jungfrau : public Model ...@@ -339,6 +470,7 @@ class Jungfrau : public Model
Buffer *b = new Buffer(d.size()); Buffer *b = new Buffer(d.size());
d.setBuffer(b); d.setBuffer(b);
b->unref(); b->unref();
clearData(d);
} }
} }
...@@ -346,8 +478,6 @@ class Jungfrau : public Model ...@@ -346,8 +478,6 @@ class Jungfrau : public Model
void removeImgProc(ImgProcBase *img_proc); void removeImgProc(ImgProcBase *img_proc);
void removeAllImgProc(); void removeAllImgProc();
ImgProcBase *createGainADCMapImgProc();
int getNbJungfrauModules() int getNbJungfrauModules()
{ return getNbDetModules(); } { return getNbDetModules(); }
...@@ -375,6 +505,8 @@ class Jungfrau : public Model ...@@ -375,6 +505,8 @@ class Jungfrau : public Model
void processOneFrame(AutoMutex& l); void processOneFrame(AutoMutex& l);
Cond m_cond; Cond m_cond;
AutoPtr<GainPedImgProc> m_gain_ped_img_proc;
AutoPtr<GainADCMapImgProc> m_gain_adc_map_img_proc;
std::string m_img_proc_config; std::string m_img_proc_config;
ImgProcList m_img_proc_list; ImgProcList m_img_proc_list;
RecvList m_recv_list; RecvList m_recv_list;
...@@ -386,6 +518,8 @@ class Jungfrau : public Model ...@@ -386,6 +518,8 @@ class Jungfrau : public Model
ThreadList m_thread_list; ThreadList m_thread_list;
}; };
std::ostream& operator <<(std::ostream& os, Jungfrau::GainPed::MapType map_type);
} // namespace SlsDetector } // namespace SlsDetector
} // namespace lima } // namespace lima
......
...@@ -20,6 +20,77 @@ ...@@ -20,6 +20,77 @@
// along with this program; if not, see <http://www.gnu.org/licenses/>. // along with this program; if not, see <http://www.gnu.org/licenses/>.
//########################################################################### //###########################################################################
// namespace SlsDetector
// {
// typedef std::array<Data, 3> JungfrauGainDataSet;
// };
%MappedType SlsDetector::JungfrauGainDataSet
{
%TypeHeaderCode
#include "SlsDetectorJungfrau.h"
#include <array>
using namespace lima;
%End
%ConvertToTypeCode
constexpr int S = 3;
using cppType = std::array<Data, S>;
auto sipElemType = sipFindType("Data");
if (sipIsErr == NULL) {
bool is_ok = (PySequence_Check(sipPy) && (PySequence_Size(sipPy) == S));
for (int i = 0; is_ok && i < S; ++i) {
PyObject *p = PySequence_Fast_GET_ITEM(sipPy, i);
is_ok = sipCanConvertToType(p, sipElemType, SIP_NOT_NONE);
}
return is_ok;
}
std::unique_ptr<cppType> a(new cppType);
for (int i = 0; i < S; ++i) {
PyObject *py_d = PySequence_Fast_GET_ITEM(sipPy, i);
int state;
void *p = sipConvertToType(py_d, sipElemType, 0, SIP_NOT_NONE, &state,
sipIsErr);
auto deleter = [=](Data *d) { sipReleaseType(d, sipElemType, state); };
using Ptr = std::unique_ptr<Data, std::function<void(Data *)>>;
Ptr d(reinterpret_cast<Data *>(p), deleter);
if (*sipIsErr)
return 0;
(*a)[i] = *d;
}
*sipCppPtr = a.release();
return sipGetState(sipTransferObj);
%End
%ConvertFromTypeCode
constexpr int S = 3;
auto deleter = [](PyObject *o) { Py_DECREF(o); };
using Ptr = std::unique_ptr<PyObject, std::function<void(PyObject *)>>;
auto sipElemType = sipFindType("Data");
// Create the Python list of the correct length.
Ptr l(PyList_New(S), deleter);
if (!l)
return NULL;
for (int i = 0; i < S; ++i) {
auto cppData = std::make_unique<Data>((*sipCpp)[i]);
PyObject *d = sipConvertFromNewType(cppData.get(), sipElemType, NULL);
if (!d)
return NULL;
cppData.release();
PyList_SET_ITEM(l.get(), i, d);
}
// Return the Python list.
return l.release();
%End
};
namespace SlsDetector namespace SlsDetector
{ {
...@@ -36,6 +107,37 @@ class Jungfrau : public SlsDetector::Model ...@@ -36,6 +107,37 @@ class Jungfrau : public SlsDetector::Model
%End %End
public: public:
class GainPed
{
public:
struct Calib {
SlsDetector::JungfrauGainDataSet gain_map;
SlsDetector::JungfrauGainDataSet ped_map;
void clear();
};
enum MapType { Map16, Map32 };
GainPed(SlsDetector::Jungfrau *jungfrau);
void setMapType(
SlsDetector::Jungfrau::GainPed::MapType map_type);
void getMapType(
SlsDetector::Jungfrau::GainPed::MapType& map_type);
void updateImageSize(Size size, bool raw);
void getDefaultCalib(
SlsDetector::Jungfrau::GainPed::Calib& calib /Out/);
void setCalib(
const SlsDetector::Jungfrau::GainPed::Calib& calib);
void getCalib(
SlsDetector::Jungfrau::GainPed::Calib& calib /Out/);
void processFrame(Data& data, Data& proc /In,Out/);
};
class ImgProcTask : public SinkTaskBase class ImgProcTask : public SinkTaskBase
{ {
public: public:
...@@ -80,6 +182,10 @@ class Jungfrau : public SlsDetector::Model ...@@ -80,6 +182,10 @@ class Jungfrau : public SlsDetector::Model
void readGainADCMaps(Data& gain_map /Out/, Data& adc_map /Out/, void readGainADCMaps(Data& gain_map /Out/, Data& adc_map /Out/,
unsigned long& frame /In,Out/); unsigned long& frame /In,Out/);
SlsDetector::Jungfrau::GainPed& getGainPed();
void readGainPedProcMap(Data& proc_map /Out/,
unsigned long& frame /In,Out/);
virtual bool isXferActive(); virtual bool isXferActive();
protected: protected:
......
Subproject commit 942f599edfda51283f162edd75808367a960056e Subproject commit b2fda94b915626fd17e05791467f68c870adb7ea
...@@ -52,6 +52,187 @@ using namespace lima::SlsDetector::Defs; ...@@ -52,6 +52,187 @@ using namespace lima::SlsDetector::Defs;
}, any_geom); \ }, any_geom); \
}, any_nb_ifaces); }, any_nb_ifaces);
/*
* Jungfrau::GainPed::Impl class
*/
template <class M>
void Jungfrau::GainPed::GainPed::Impl<M>::updateImageSize(Size size, bool raw)
{
m_size = size;
m_raw = raw;
m_pixels = Point(m_size).getArea();
std::vector<int> dims = {m_size.getWidth(), m_size.getHeight()};
if (m_calib.gain_map[0].dimensions != dims)
setDefaultCalib();
}
template <class M>
void Jungfrau::GainPed::Impl<M>::getDefaultCalib(Calib& calib)
{
DEB_MEMBER_FUNCT();
auto init = [&](auto& d) {
initData(d, m_size, Data::DOUBLE);
// gap pixels are set to 0
if (!m_raw)
memset(d.data(), 0, d.size());
};
double *p[3][2];
for (int g = 0; g < 3; ++g) {
init(calib.gain_map[g]);
p[g][0] = (double *) calib.gain_map[g].data();
init(calib.ped_map[g]);
p[g][1] = (double *) calib.ped_map[g].data();
}
auto f = [&](auto det_geom) {
using namespace sls::Geom;
det_for_each_mod(det_geom, mod, mod_geom,
mod_for_each_recv(mod_geom, recv, recv_geom,
recv_for_each_iface(recv_geom, iface, iface_geom,
iface_for_each_chip(iface_geom, chip, chip_view,
view_for_each_pixel(chip_view, pixel,
int i = chip_view.calcMapPixelIndex(pixel);
for (int g = 0; g < 3; ++g) {
p[g][0][i] = M::DefaultCoeffs[g][0];
p[g][1][i] = M::DefaultCoeffs[g][1];
}
);
);
);
);
);
};
applyDetGeom(m_jungfrau, f, m_raw);
}
template <class M>
void Jungfrau::GainPed::Impl<M>::processFrame(Data& data, Data& proc)
{
DEB_MEMBER_FUNCT();
auto calib_coeff = [&](auto gain, auto type) {
Data& d = (type == 0) ? m_calib.gain_map[gain] :
m_calib.ped_map[gain];
return (double *) d.data();
};
double *coeffs[3][2] = {{calib_coeff(0, 0), calib_coeff(0, 1)},
{calib_coeff(1, 0), calib_coeff(1, 1)},
{calib_coeff(2, 0), calib_coeff(2, 1)}};
{
unsigned short *src;
src = reinterpret_cast<unsigned short *>(data.data());
using P = typename M::Pixel;
P *dst = reinterpret_cast<P *>(proc.data());
for (int i = 0; i < m_pixels; ++i, ++src, ++dst) {
int gain = *src >> 14;
int adc = *src & 0x3fff;
DEB_TRACE() << DEB_VAR3(i, gain, adc);
if (gain == 3)
gain = 2;
else if (gain == 2) {
*dst = std::numeric_limits<P>::max() - 0x10;
continue;
}
*dst = coeffs[gain][0][i] * adc + coeffs[gain][1][i];
DEB_TRACE() << DEB_VAR1(*dst);
}
}
}
/*
* Jungfrau::GainPed class
*/
Jungfrau::GainPed::GainPed(Jungfrau *jungfrau)
: m_jungfrau(jungfrau), m_impl(std::in_place_index_t<1>(), jungfrau)
{
DEB_MEMBER_FUNCT();
setMapType(Map16);
}
void Jungfrau::GainPed::setMapType(MapType map_type)
{
DEB_MEMBER_FUNCT();
DEB_PARAM() << DEB_VAR1(map_type);
MapType curr_type;
<