92 cpl_image *filt_image;
97 cpl_vector *line_filt;
99 double median, stdev, max, mean;
103 cpl_apertures *aperts;
112 if (orient != 0 && orient != 1)
117 loc_ima = cpl_image_duplicate(in);
118 cpl_image_flip(loc_ima, 1);
121 loc_ima = cpl_image_duplicate(in);
125 mask = cpl_mask_new(3, 3);
127 filt_image = cpl_image_new(cpl_image_get_size_x(loc_ima),
128 cpl_image_get_size_y(loc_ima),
129 cpl_image_get_type(loc_ima));
130 if (cpl_image_filter_mask(filt_image, loc_ima, mask, CPL_FILTER_MEDIAN,
131 CPL_BORDER_FILTER) != CPL_ERROR_NONE) {
132 cpl_msg_error(__func__,
"Cannot filter the image");
133 cpl_mask_delete(mask);
134 cpl_image_delete(filt_image);
137 cpl_mask_delete(mask);
138 cpl_image_delete(loc_ima);
141 if ((collapsed = cpl_image_collapse_median_create(filt_image, 1, 0, 0)) ==
143 cpl_msg_error(cpl_func,
144 "collapsing image: aborting spectrum detection");
145 cpl_image_delete(filt_image);
148 cpl_image_delete(filt_image);
151 line = cpl_vector_new_from_image_column(collapsed, 1);
152 cpl_image_delete(collapsed);
153 line_filt = cpl_vector_filter_median_create(line, SPECTRUM_HW);
154 cpl_vector_subtract(line, line_filt);
155 cpl_vector_delete(line_filt);
158 median = cpl_vector_get_median_const(line);
159 stdev = cpl_vector_get_stdev(line);
160 max = cpl_vector_get_max(line);
161 mean = cpl_vector_get_mean(line);
164 threshold = median + stdev;
165 if (threshold > MIN_THRESH_FACT * max)
166 threshold = MIN_THRESH_FACT * max;
167 if (threshold < MAX_THRESH_FACT * mean)
168 threshold = MAX_THRESH_FACT * mean;
171 collapsed = cpl_image_new(1, cpl_vector_get_size(line), CPL_TYPE_FLOAT);
172 pcollapsed = cpl_image_get_data_float(collapsed);
173 pline = cpl_vector_get_data(line);
174 for (i = 0; i < cpl_vector_get_size(line); i++)
175 pcollapsed[i] = (
float)pline[i];
176 cpl_vector_delete(line);
179 if ((mask = cpl_mask_threshold_image_create(collapsed, threshold,
181 cpl_msg_error(cpl_func,
"cannot binarise");
182 cpl_image_delete(collapsed);
185 if (cpl_mask_count(mask) < 1) {
186 cpl_msg_error(cpl_func,
"not enough signal to detect spectra");
187 cpl_image_delete(collapsed);
188 cpl_mask_delete(mask);
192 if ((labels = cpl_image_labelise_mask_create(mask, &nlabels)) == NULL) {
193 cpl_msg_error(cpl_func,
"cannot labelise");
194 cpl_image_delete(collapsed);
195 cpl_mask_delete(mask);
198 cpl_mask_delete(mask);
201 if ((aperts = cpl_apertures_new_from_image(collapsed, labels)) == NULL) {
202 cpl_msg_error(cpl_func,
"cannot compute apertures");
203 cpl_image_delete(collapsed);
204 cpl_image_delete(labels);
207 cpl_image_delete(labels);
210 if (select_valid_spectra(collapsed, aperts, offset, shadows, SPEC_MAXWIDTH,
211 &n_valid_specs, &valid_specs) == -1) {
214 "Could not select valid spectra from the %" CPL_SIZE_FORMAT
215 " apertures in %" CPL_SIZE_FORMAT
"-col 1D-image, offset=%d"
217 cpl_apertures_get_size(aperts), cpl_image_get_size_y(collapsed),
218 offset, SPEC_MAXWIDTH);
219 if (cpl_msg_get_level() <= CPL_MSG_DEBUG)
220 cpl_apertures_dump(aperts, stderr);
221 cpl_image_delete(collapsed);
222 cpl_apertures_delete(aperts);
225 cpl_image_delete(collapsed);
226 if (n_valid_specs < 1) {
227 cpl_msg_error(cpl_func,
"no valid spectrum detected");
228 cpl_free(valid_specs);
229 cpl_apertures_delete(aperts);
234 *pos = cpl_apertures_get_centroid_y(aperts, valid_specs[0] + 1);
235 brightness = cpl_apertures_get_flux(aperts, valid_specs[0] + 1);
236 for (i = 0; i < n_valid_specs; i++) {
237 if (cpl_apertures_get_flux(aperts, valid_specs[i] + 1) > brightness) {
238 *pos = cpl_apertures_get_centroid_y(aperts, valid_specs[i] + 1);
239 brightness = cpl_apertures_get_flux(aperts, valid_specs[i] + 1);
242 cpl_apertures_delete(aperts);
243 cpl_free(valid_specs);
246 if (brightness < min_bright) {
247 cpl_msg_error(cpl_func,
"brightness %f too low <%f", brightness,
274 cpl_vector **fwhms_out,
275 cpl_vector **areas_out)
277 cpl_vector *filtered;
278 cpl_vector *spec_clean;
279 cpl_vector *spec_convolved;
280 double *pspec_convolved;
282 cpl_vector *big_detected;
283 cpl_vector *big_fwhms;
284 cpl_vector *big_area;
285 double *pbig_detected;
288 cpl_vector *detected;
291 double max, med, stdev;
292 double x0, sig, norm, offset;
293 int nb_det, nb_samples, hwidth, start, stop;
301 nb_samples = cpl_vector_get_size(in);
306 cpl_msg_debug(__func__,
"Low Frequency signal removal");
307 if ((filtered = cpl_vector_filter_median_create(in, filt_size)) == NULL) {
308 cpl_msg_error(__func__,
"Cannot filter the spectrum");
311 spec_clean = cpl_vector_duplicate(in);
312 cpl_vector_subtract(spec_clean, filtered);
313 cpl_vector_delete(filtered);
317 cpl_plot_vector(
"set grid;set xlabel 'Position (pixels)';set ylabel "
318 "'Intensity (ADU)';",
319 "t 'Filtered extracted spectrum' w lines",
"",
324 spec_convolved = cpl_vector_duplicate(spec_clean);
326 cpl_vector *conv_kernel;
327 cpl_msg_debug(__func__,
"Spectrum convolution");
329 if ((conv_kernel = irplib_wlxcorr_convolve_create_kernel(fwhm, fwhm)) ==
331 cpl_msg_error(cpl_func,
"Cannot create convolution kernel");
332 cpl_vector_delete(spec_clean);
333 cpl_vector_delete(spec_convolved);
338 if (irplib_wlxcorr_convolve(spec_convolved, conv_kernel)) {
339 cpl_msg_error(cpl_func,
"Cannot smoothe the signal");
340 cpl_vector_delete(spec_clean);
341 cpl_vector_delete(spec_convolved);
342 cpl_vector_delete(conv_kernel);
345 cpl_vector_delete(conv_kernel);
349 cpl_plot_vector(
"set grid;set xlabel 'Position (pixels)';set "
350 "ylabel 'Intensity (ADU)';",
351 "t 'Convolved extracted spectrum' w lines",
"",
357 big_detected = cpl_vector_duplicate(spec_convolved);
358 big_fwhms = cpl_vector_duplicate(spec_convolved);
359 big_area = cpl_vector_duplicate(spec_convolved);
360 pbig_detected = cpl_vector_get_data(big_detected);
361 pbig_fwhms = cpl_vector_get_data(big_fwhms);
362 pbig_area = cpl_vector_get_data(big_area);
364 pspec_convolved = cpl_vector_get_data(spec_convolved);
367 pspec_convolved[0] = pspec_convolved[nb_samples - 1] = 0.0;
370 max = cpl_vector_get_max(spec_convolved);
371 stdev = cpl_vector_get_stdev(spec_convolved);
372 med = cpl_vector_get_median_const(spec_convolved);
376 while (max > med + stdev * sigma) {
378 cpl_vector *extract_x;
383 while (pspec_convolved[i] < max)
385 if (i <= 0 || i >= nb_samples - 1)
393 if (i + hwidth <= nb_samples - 1)
396 stop = nb_samples - 1;
397 extract = cpl_vector_extract(spec_clean, start, stop, 1);
398 extract_x = cpl_vector_duplicate(extract);
399 for (j = 0; j < cpl_vector_get_size(extract_x); j++) {
400 cpl_vector_set(extract_x, j, (
double)j + 1);
403 if (cpl_vector_fit_gaussian(extract_x, NULL, extract, NULL, CPL_FIT_ALL,
404 &x0, &sig, &norm, &offset, NULL, NULL,
405 NULL) != CPL_ERROR_NONE) {
406 cpl_msg_debug(__func__,
"Cannot fit a gaussian at [%d, %d]", start,
411 pbig_detected[nb_det] = x0 + start;
412 pbig_area[nb_det] = norm;
413 pbig_fwhms[nb_det] = 2 * sig * sqrt(2 * log(2));
414 cpl_msg_debug(__func__,
"Line nb %d at position %g", nb_det + 1,
415 pbig_detected[nb_det]);
418 cpl_vector_delete(extract);
419 cpl_vector_delete(extract_x);
423 cur_val = pspec_convolved[i];
424 while (j >= 0 && pspec_convolved[j] < cur_val) {
425 cur_val = pspec_convolved[j];
426 pspec_convolved[j] = 0.0;
431 cur_val = pspec_convolved[i];
432 while (j <= nb_samples - 1 && pspec_convolved[j] < cur_val) {
433 cur_val = pspec_convolved[j];
434 pspec_convolved[j] = 0.0;
438 pspec_convolved[i] = 0.0;
441 max = cpl_vector_get_max(spec_convolved);
442 stdev = cpl_vector_get_stdev(spec_convolved);
443 med = cpl_vector_get_median_const(spec_convolved);
445 cpl_vector_delete(spec_convolved);
446 cpl_vector_delete(spec_clean);
458 detected = cpl_vector_new(nb_det);
459 area = cpl_vector_new(nb_det);
460 fwhms = cpl_vector_new(nb_det);
461 pdetected = cpl_vector_get_data(detected);
462 parea = cpl_vector_get_data(area);
463 pfwhms = cpl_vector_get_data(fwhms);
464 for (i = 0; i < nb_det; i++) {
465 pdetected[i] = pbig_detected[i];
466 parea[i] = pbig_area[i];
467 pfwhms[i] = pbig_fwhms[i];
470 cpl_vector_delete(big_detected);
471 cpl_vector_delete(big_area);
472 cpl_vector_delete(big_fwhms);
475 if (fwhms_out == NULL)
476 cpl_vector_delete(fwhms);
479 if (areas_out == NULL)
480 cpl_vector_delete(area);