SlsDetectorEiger.h 8.97 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//###########################################################################
// This file is part of LImA, a Library for Image Acquisition
//
// Copyright (C) : 2009-2011
// European Synchrotron Radiation Facility
// BP 220, Grenoble 38043
// FRANCE
//
// This is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
//###########################################################################

#ifndef __SLS_DETECTOR_EIGER_H
#define __SLS_DETECTOR_EIGER_H

#include "SlsDetectorCamera.h"

#include "processlib/LinkTask.h"


namespace lima 
{

namespace SlsDetector
{

#define EIGER_PACKET_DATA_LEN	(4 * 1024)

39
class Eiger : public Model
40
41
42
43
44
45
46
47
{
	DEB_CLASS_NAMESPC(DebModCamera, "Eiger", "SlsDetector");

 public:
	typedef unsigned char Byte;
	typedef unsigned short Word;
	typedef unsigned int Long;

48
49
	typedef Defs::ClockDiv ClockDiv;

50
51
52
53
	enum ParallelMode {
		NonParallel, Parallel, Safe,
	};

54
55
56
57
58
59
60
61
62
	class Correction : public LinkTask
	{
		DEB_CLASS_NAMESPC(DebModCamera, "Eiger::Correction", 
				  "SlsDetector");
	public:
		Correction(Eiger *eiger);

		virtual Data process(Data& data);
	private:
63
		Eiger *m_eiger;
64
65
66
67
68
69
70
71
72
73
	};

	Eiger(Camera *cam);
	~Eiger();
	
	virtual void getFrameDim(FrameDim& frame_dim, bool raw = false);

	virtual std::string getName();
	virtual void getPixelSize(double& x_size, double& y_size);

74
75
	virtual void getDACInfo(NameList& name_list, IntList& idx_list,
				IntList& milli_volt_list);
76
77
78
	virtual void getADCInfo(NameList& name_list, IntList& idx_list,
				FloatList& factor_list, 
				FloatList& min_val_list);
79

80
	virtual void getTimeRanges(TimeRanges& time_ranges);
81

82
83
84
	// the returned object must be deleted by the caller
	Correction *createCorrectionTask();

85
86
87
	void setParallelMode(ParallelMode  mode);
	void getParallelMode(ParallelMode& mode);

88
89
90
91
92
93
94
95
96
97
98
99
100
	void setClockDiv(ClockDiv  clock_div);
	void getClockDiv(ClockDiv& clock_div);

	void setAllTrimBits(int sub_mod_idx, int  val);
	void getAllTrimBits(int sub_mod_idx, int& val);
	void getAllTrimBitsList(IntList& val_list);

	void setHighVoltage(int  hvolt);
	void getHighVoltage(int& hvolt);

	void setThresholdEnergy(int  thres);
	void getThresholdEnergy(int& thres);

101
 protected:
102
103
	virtual void updateImageSize();

104
105
106
107
108
	virtual bool checkSettings(Settings settings);

	virtual int getRecvPorts();

	virtual void prepareAcq();
109
110
111
	virtual void processRecvFileStart(int port_idx, uint32_t dsize);
	virtual void processRecvPort(int port_idx, FrameType frame, char *dptr,
				     uint32_t dsize, char *bptr);
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

 private:
	friend class Correction;
	friend class CorrBase;

	class RecvPortGeometry
	{
		DEB_CLASS_NAMESPC(DebModCamera, "Eiger::RecvPortGeometry", 
				  "SlsDetector");
	public:
		RecvPortGeometry(Eiger *eiger, int recv_idx, int port);

		void prepareAcq();
		void processRecvFileStart(uint32_t dsize);
		void processRecvPort(FrameType frame, char *dptr, char *bptr);
127
128
129

		void expandPixelDepth4(FrameType frame, char *ptr);

130
131
132
133
134
135
136
137
	private:
		Eiger *m_eiger;
		int m_port;
		bool m_top_half_recv;
		bool m_port_idx;
		bool m_raw;
		int m_recv_idx;
		int m_port_offset;
138
139
140
		int m_ilw;			// image line width
		int m_scw;			// source chip width
		int m_dcw;			// dest chip width
141
142
143
144
145
		int m_pchips;
	};

	typedef std::vector<AutoPtr<RecvPortGeometry> > PortGeometryList;

146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
	class CorrBase
	{
		DEB_CLASS_NAMESPC(DebModCamera, "Eiger::CorrBase", 
				  "SlsDetector");
	public:
		CorrBase(Eiger *eiger);
		virtual ~CorrBase();

		int getNbEigerModules()
		{ return m_nb_eiger_modules; }

		virtual void prepareAcq();
		virtual void correctFrame(FrameType frame, void *ptr) = 0;

	protected:
		friend class Eiger;
		Eiger *m_eiger;
		int m_nb_eiger_modules;
		FrameDim m_mod_frame_dim;
		Size m_frame_size;
		std::vector<int> m_inter_lines;
		// TODO: add ref count
	};

	typedef std::vector<CorrBase *> CorrList;

172
173
174
175
176
177
178
	class BadRecvFrameCorr : public CorrBase
	{
		DEB_CLASS_NAMESPC(DebModCamera, "Eiger::BadRecvFrameCorr", 
				  "SlsDetector");
	public:
		BadRecvFrameCorr(Eiger *eiger);

179
		virtual void prepareAcq();
180
		virtual void correctFrame(FrameType frame, void *ptr);
181
182
183
184
185
186
187
188
189
190
191

	protected:
		struct BadFrameData {
			int last_idx;
			IntList bad_frame_list;
			void reset();
		};

		Camera *m_cam;
		int m_nb_ports;
		std::vector<BadFrameData> m_bfd_list;
192
193
	};

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
	class PixelDepth4Corr : public CorrBase
	{
		DEB_CLASS_NAMESPC(DebModCamera, "Eiger::PixelDepth4Corr", 
				  "SlsDetector");
	public:
		PixelDepth4Corr(Eiger *eiger);

		virtual void correctFrame(FrameType frame, void *ptr);

	protected:
		PortGeometryList& m_port_geom_list;
	};

	class InterModGapCorr : public CorrBase
	{
		DEB_CLASS_NAMESPC(DebModCamera, "Eiger::InterModGapCorr", 
				  "SlsDetector");
	public:
		InterModGapCorr(Eiger *eiger);

		virtual void prepareAcq();
		virtual void correctFrame(FrameType frame, void *ptr);

	protected:
		typedef std::pair<int, int> Block;
		typedef std::vector<Block> BlockList;
		BlockList m_gap_list;
	};

223
224
225
226
227
	template <class T>
	class ChipBorderCorr : public CorrBase
	{
	public:
		ChipBorderCorr(Eiger *eiger)
228
			: CorrBase(eiger)
229
230
231
232
233
234
		{}
		
		virtual void prepareAcq()
		{
			CorrBase::prepareAcq();

235
			m_f.resize(m_nb_eiger_modules);
236
			std::vector<BorderFactor>::iterator it = m_f.begin();
237
			for (int i = 0; i < m_nb_eiger_modules; ++i, ++it) {
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
				it->resize(2);
				(*it)[0] = m_eiger->getBorderCorrFactor(i, 0);
				(*it)[1] = m_eiger->getBorderCorrFactor(i, 1);
			}
		}

		virtual void correctFrame(FrameType frame, void *ptr)
		{
			correctBorderCols(ptr);
			correctBorderRows(ptr);
			correctInterChipCols(ptr);
			correctInterChipRows(ptr);
		}

	private:
		typedef std::vector<double> BorderFactor;

		static void correctInterChipLine(T *d, int offset, int nb_iter, 
						 int step) 
		{
			for (int i = 0; i < nb_iter; ++i, d += step)
				d[0] = d[offset] /= 2;
		}

		static void correctBorderLine(T *d, int nb_iter, int step,
					      double f) 
		{
			for (int i = 0; i < nb_iter; ++i, d += step)
				d[0] /= f;
		}

		void correctInterChipCols(void *ptr)
		{
			int width = m_frame_size.getWidth();
			int height= m_frame_size.getHeight();
			T *d = static_cast<T *>(ptr);
			for (int i = 0; i < HalfModuleChips - 1; ++i) {
				d += ChipSize;
				correctInterChipLine(d++, -1, height, width);
				correctInterChipLine(d++, 1, height, width);
			}
		}

		void correctInterChipRows(void *ptr)
		{
			int width = m_frame_size.getWidth();
			int mod_height = m_mod_frame_dim.getSize().getHeight();
			T *p = static_cast<T *>(ptr);
286
			for (int i = 0; i < m_nb_eiger_modules; ++i) {
287
288
289
290
				T *d = p + ChipSize * width;
				correctInterChipLine(d, -width, width, 1);
				d += width;
				correctInterChipLine(d, width, width, 1);
291
				if (i == m_nb_eiger_modules - 1)
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
					continue;
				p += (mod_height + m_inter_lines[i]) * width;
			}
		}

		void correctBorderCols(void *ptr)
		{
			int width = m_frame_size.getWidth();
			int height= m_frame_size.getHeight();
			T *d = static_cast<T *>(ptr);
			correctBorderLine(d, height, width, 2);
			d += width - 1;
			correctBorderLine(d, height, width, 2);
		}

		void correctBorderRows(void *ptr)
		{
			int width = m_frame_size.getWidth();
			int mod_height = m_mod_frame_dim.getSize().getHeight();
			T *p = static_cast<T *>(ptr);
312
			for (int i = 0; i < m_nb_eiger_modules; ++i) {
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
				double f0 = m_f[i][0], f1 = m_f[i][1];
				T *d = p;
				correctBorderLine(d, width, 1, f0);
				d += width;
				correctBorderLine(d, width, 1, f1);
				d += (mod_height - 1 - 2) * width;
				correctBorderLine(d, width, 1, f1);
				d += width;
				correctBorderLine(d, width, 1, f0);
				p += (mod_height + m_inter_lines[i]) * width;
			}
		}

		std::vector<BorderFactor> m_f;
	};

329
330
	bool isPixelDepth4()
	{
331
		PixelDepth pixel_depth;
332
		getCamera()->getPixelDepth(pixel_depth);
333
		return (pixel_depth == PixelDepth4);
334
335
336
	}

	int getNbEigerModules()
337
	{ return getNbDetModules() / 2; }
338

339
340
341
	static double KiloHzPeriod(double f)
	{ return 1e6 / (f * 1e3); }

342
343
	void getRecvFrameDim(FrameDim& frame_dim, bool raw, bool geom);

344
	CorrBase *createBadRecvFrameCorr();
345
	CorrBase *createPixelDepth4Corr();
346
347
348
349
350
	CorrBase *createChipBorderCorr(ImageType image_type);
	CorrBase *createInterModGapCorr();

	void addCorr(CorrBase *corr);
	void removeCorr(CorrBase *corr);
351
	void removeAllCorr();
352
353
354
355
356
357
358
359
360
361

	double getBorderCorrFactor(int det, int line);
	int getInterModuleGap(int det);

	static const int ChipSize;
	static const int ChipGap;
	static const int HalfModuleChips;
	static const int RecvPorts;

	FrameDim m_recv_frame_dim;
362
	CorrList m_corr_list;
363
364
365
	PortGeometryList m_port_geom_list;
};

366
std::ostream& operator <<(std::ostream& os, Eiger::ParallelMode mode);
367
368
369
370
371
372
373
374

} // namespace SlsDetector

} // namespace lima



#endif // __SLS_DETECTOR_EIGER_H