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