1 #ifndef RSPEC_H
2 
3 /*
4  * Argyll Color Correction System
5  *
6  * Author: Graeme W. Gill
7  * Date:   20015
8  *
9  * Copyright 2006 - 2015 Graeme W. Gill
10  * All rights reserved.
11  *
12  * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
13  * see the License2.txt file for licencing details.
14  *
15  * Derived from i1pro_imp.c & munki_imp.c
16  */
17 
18 /*
19  * A library for processing raw spectrometer values.
20  *
21  * Currently this is setup for the EX1 spectrometer,
22  * but the longer term plan is to expand the functionality
23  * so that it becomes more generic, and can replace a lot
24  * of common code in i1pro_imp.c & munki_imp.c.
25  */
26 
27 #ifdef __cplusplus
28 	extern "C" {
29 #endif
30 
31 #define RSPEC_MAXSAMP 2048
32 
33 /* - - - - - - - - - - - - - */
34 /* Collection of raw samples */
35 typedef enum {
36 	rspec_sensor,		/* Includes shielded/temperature values */
37 	rspec_raw,			/* Potential light values */
38 	rspec_wav			/* Valid wavelength values */
39 } rspec_type;
40 
41 /* The order the state is changed in, is device workflow dependent */
42 typedef enum {
43 	rspec_none = 0x0000,	/* No processing */
44 	rspec_shld = 0x0002,	/* Shielded cell corrected */
45 	rspec_dcal = 0x0004,	/* Dark calibration subtracted */
46 	rspec_lin  = 0x0010,	/* Linearized */
47 	rspec_int  = 0x0020,	/* Integration time adjusted */
48 	rspec_temp = 0x0001,	/* Temperature corrected */
49 	rspec_cal  = 0x0040		/* Calibrated */
50 } rspec_state;
51 
52 struct _rspec {
53 	struct _rspec_inf *inf;		/* Base information */
54 
55 	rspec_type     stype;	/* Spectral type - sensor, raw, cooked */
56 	inst_meas_type mtype;	/* Measurement type (emis, ambient, reflective etc.) */
57 	rspec_state    state;	/* Processing state */
58 
59 	double inttime;		/* Integration time */
60 
61 	int nmeas;			/* Number of measurements */
62 	int nsamp;			/* Number of sensor/wavelength samples */
63 	double **samp;		/* [mesa][samples] allocated using numlib. */
64 
65 }; typedef struct _rspec rspec;
66 
67 
68 /* - - - - - - - - - - - - - */
69 /* Base information about characteristics in a given mode */
70 
71 /* Wavelength resample kernel type */
72 typedef enum {
73 	rspec_triangle,
74 	rspec_gausian,
75 	rspec_lanczos2,
76 	rspec_lanczos3,
77 	rspec_cubicspline
78 } rspec_kernel;
79 
80 /* Group of values */
81 typedef struct {
82 	int off;		/* Offset to start of group */
83 	int num;		/* Number in group */
84 } rspec_group;
85 
86 struct _rspec_inf {
87 	a1log *log;
88 
89 	int nsen;					/* Number of sensor values */
90 	int nshgrps;				/* Number of shielded sensor groups */
91 	rspec_group shgrps[2];		/* Shielded group definition */
92 
93 	int nilltkgrps;				/* Number of illuminant level tracking groups */
94 	rspec_group illtkgrps[2];	/* illuminant level tracking groups definition */
95 
96 	rspec_group lightrange;		/* Range of sensor potential light values transferred to raw */
97 
98 	int nraw;					/* Number of raw light sensor values */
99 	rspec_group rawrange;		/* Valid range of raw values for filter to wav */
100 
101 	rspec_kernel ktype;			/* Re-sampling kernel type */
102 	int nwav;					/* Cooked spectrum bands */
103 	double wl_space;			/* Wavelength spacing */
104 	double wl_short;			/* Cooked spectrum bands short wavelength nm */
105 	double wl_long;				/* Cooked spectrum bands short wavelength nm */
106 
107 
108 								/* (Stray light is not currently implemented) */
109 	rspec_type straytype;		/* Stray light spectral type - sensor, raw, cooked */
110 	double **straylight;		/* [][] Stray light convolution matrix (size ??) */
111 
112 	/* raw index to wavelength polynomial */
113 	unsigned int nwlcal;		/* Number in array */
114 	double *wlcal;				/* Array of wavelenght cal polinomial factors. */
115 
116 	/* raw index to wavelength re-sampling filters */
117 	int *findex;				/* [nwav] raw starting index for each out wavelength */
118 	int *fnocoef; 				/* [nwav] Number of matrix cooeficients for each out wavelength */
119 	double *fcoef;				/* [nwav * nocoef] Packed cooeficients to compute each wavelength */
120 
121 	unsigned int nlin;			/* Number in array */
122 	double *lin;				/* Array of linearisation polinomial factors. */
123 	int lindiv;					/* nz if polinomial result should be divided */
124 
125 	/* Black calibration */
126 	rspec *idark[2];			/* Adaptive dark cal for two integration times */
127 
128 	/* Emission calibration */
129 	rspec_type ecaltype;		/* Emissioni calibration type - sensor, raw, cooked */
130 	double *ecal;				/* Emission calibration values */
131 
132 }; typedef struct _rspec_inf rspec_inf;
133 
134 /* - - - - - - - - - - - - - */
135 
136 /* Completely clear an rspec_inf. */
137 void clear_rspec_inf(rspec_inf *inf);
138 
139 /* Completely free contents of rspec_inf. */
140 void free_rspec_inf(rspec_inf *inf);
141 
142 /* return the number of samples for the given spectral type */
143 int rspec_typesize(rspec_inf *inf, rspec_type ty);
144 
145 /* Compute the valid raw range from the calibration information */
146 void rspec_comp_raw_range_from_ecal(rspec_inf *inf);
147 
148 /* Convert a raw index to nm */
149 double rspec_raw2nm(rspec_inf *inf, double rix);
150 
151 /* Convert a cooked index to nm */
152 double rspec_wav2nm(rspec_inf *inf, double ix);
153 
154 /* Create the wavelength resampling filters */
155 void rspec_make_resample_filters(rspec_inf *inf);
156 
157 
158 /* Plot the first rspec */
159 void plot_rspec1(rspec *p);
160 
161 /* Plot the first rspec of 2 */
162 void plot_rspec2(rspec *p1, rspec *p2);
163 
164 /* Plot the wave resampling filters */
165 void plot_resample_filters(rspec_inf *inf);
166 
167 /* Plot the calibration curves */
168 void plot_ecal(rspec_inf *inf);
169 
170 /* - - - - - - - - - - - - - */
171 
172 /* Create a new rspec from scratch */
173 /* This always succeeds (i.e. application bombs if malloc fails) */
174 rspec *new_rspec(rspec_inf *inf, rspec_type ty, int nmeas);
175 
176 /* Create a new rspec based on an existing prototype */
177 /* If nmes == 0, create space for the same number or measurements */
178 rspec *new_rspec_proto(rspec *rs, int nmeas);
179 
180 /* Create a new rspec by cloning an existing one */
181 rspec *new_rspec_clone(rspec *rs);
182 
183 /* Free a rspec */
184 void del_rspec(rspec *rs);
185 
186 /* - - - - - - - - - - - - - */
187 /* Return the largest value */
188 double largest_val_rspec(int *pmix, int *psix, rspec *raw);
189 
190 /* return a raw rspec from a sensor rspec */
191 rspec *extract_raw_from_sensor_rspec(rspec *sens);
192 
193 /* Return an interpolated dark reference value from idark */
194 double ex1_interp_idark_val(rspec_inf *inf, int mix, int six, double inttime);
195 
196 /* Return an interpolated dark reference from idark */
197 rspec *ex1_interp_idark(rspec_inf *inf, double inttime);
198 
199 /* Subtract the adaptive black */
200 void subtract_idark_rspec(rspec *raw);
201 
202 /* Apply non-linearity to a single value */
203 double linearize_val_rspec(rspec_inf *inf, double ival);
204 
205 /* Invert non-linearity of a single value */
206 double inv_linearize_val_rspec(rspec_inf *inf, double targv);
207 
208 /* Correct non-linearity */
209 void linearize_rspec(rspec *raw);
210 
211 /* Apply the emsissive calibration */
212 void emis_calibrate_rspec(rspec *sens);
213 
214 /* Scale to the integration time */
215 void inttime_calibrate_rspec(rspec *sens);
216 
217 /* return a wav rspec from a raw rspec */
218 rspec *convert_wav_from_raw_rspec(rspec *sens);
219 
220 
221 /* - - - - - - - - - - - - - */
222 /* Calibration file support */
223 
224 typedef struct {
225 	a1log *log;
226 	int lo_secs;			/* Seconds since last opened (from file mod time) */
227 	FILE *fp;
228 	int rd;					/* 0 = dummy read, 1 = real read */
229 	int ef;					/* Error flag, 1 = write failed, 2 = close failed */
230 	unsigned int chsum;		/* Checksum */
231 	int nbytes;				/* Number of bytes checksummed */
232 
233 	char *buf;				/* Dummy read buffer */
234 	size_t bufsz;			/* Size of dumy read buffer */
235 } calf;
236 
237 int calf_open(calf *x, a1log *log, char *fname, int wr);
238 void calf_rewind(calf *x);
239 int calf_touch(a1log *log, char *fname);
240 int calf_done(calf *x);
241 
242 void calf_wints(calf *x, int *dp, int n);
243 void calf_wdoubles(calf *x, double *dp, int n);
244 void calf_wtime_ts(calf *x, time_t *dp, int n);
245 void calf_wstrz(calf *x, char *dp);
246 
247 void calf_rints(calf *x, int *dp, int n);
248 void calf_rints2(calf *x, int *dp, int n);
249 void calf_rdoubles(calf *x, double *dp, int n);
250 void calf_rtime_ts(calf *x, time_t *dp, int n);
251 void calf_rstrz(calf *x, char **dp);
252 void calf_rstrz2(calf *x, char **dp);
253 
254 /* Save a rspec to a calibration file */
255 void calf_wrspec(calf *x, rspec *dp);
256 
257 /* Restore a rspec from a calibration file */
258 void calf_rrspec(calf *x, rspec **dp, rspec_inf *inf);
259 
260 #ifdef __cplusplus
261 	}
262 #endif
263 
264 #define RSPEC_H
265 #endif /* RSPEC_H */
266