42 #include "sinfo_function_1d.h"
43 #include "sinfo_fit_curve.h"
44 #include "sinfo_median.h"
61 #define HALF_CENTROID_DOMAIN 5
65 static double * function1d_generate_smooth_kernel(
int filt_type,
int hw);
68 function1d_search_value(
95 sinfo_function1d_new(
int nsamples)
97 if (nsamples<1)
return NULL ;
98 return cpl_calloc(nsamples,
sizeof(pixelvalue)) ;
112 sinfo_function1d_del(pixelvalue * s)
136 sinfo_function1d_dup(pixelvalue * arr,
int ns)
140 n_arr = sinfo_function1d_new(ns);
141 memcpy(n_arr, arr, ns *
sizeof(pixelvalue));
161 sinfo_function1d_find_centroid(
177 for (i=1 ; i<npix ; i++) {
191 for (i=maxpos-HALF_CENTROID_DOMAIN;
192 i<=maxpos+HALF_CENTROID_DOMAIN; i++) {
193 centroid += (double)line[i] * (
double)i ;
194 weights += (double)line[i] ;
197 centroid /= weights ;
224 sinfo_function1d_find_locmax(
237 if ((where<hs) || (where>(npix-hs-1))) {
238 return (
double)-1.0 ;
246 for (i=-hs ; i<=hs ; i++) {
247 if (line[where+i]>max) {
248 max = line[where+i] ;
260 for (i=maxpos-hs; i<=maxpos+hs; i++) {
261 centroid += (double)line[i] * (
double)i ;
262 weights += (double)line[i] ;
264 if (fabs(weights)>1e-6) {
265 centroid /= weights ;
297 sinfo_function1d_filter_lowpass(
298 pixelvalue * input_sig,
304 pixelvalue * out_sig ;
310 out_sig = sinfo_function1d_new(samples);
313 kernel = function1d_generate_smooth_kernel(filter_type, hw) ;
316 for (i=0 ; i<hw ; i++) {
318 for (j=-hw ; j<=hw ; j++) {
320 replace += kernel[hw+j] * (double)input_sig[0] ;
322 replace += kernel[hw+j] * (double)input_sig[i+j] ;
325 out_sig[i] = (pixelvalue)replace ;
329 for (i=samples-hw ; i<samples ; i++) {
331 for (j=-hw ; j<=hw ; j++) {
333 replace += kernel[hw+j] * (double)input_sig[samples-1] ;
335 replace += kernel[hw+j] * (double)input_sig[i+j] ;
338 out_sig[i] = (pixelvalue)replace ;
342 for (i=hw ; i<samples-hw ; i++) {
344 for (j=-hw ; j<=hw ; j++) {
345 replace += kernel[hw+j] * (double)input_sig[i+j] ;
347 out_sig[i] = (pixelvalue)replace ;
372 function1d_generate_smooth_kernel(
int filt_type,
int hw)
378 kernel = (
double*)cpl_calloc(2*hw+1,
sizeof(
double)) ;
382 case LOW_PASS_LINEAR:
383 for (i=-hw ; i<=hw ; i++) {
385 kernel[hw+i] = 1.0 / (double)(2*hw+1) ;
389 case LOW_PASS_GAUSSIAN:
391 for (i=-hw ; i<=hw ; i++) {
393 kernel[hw+i] = exp(-(
double)(i*i)) ;
394 norm += kernel[hw+i] ;
396 for (i=0 ; i<2*hw+1 ; i++) {
403 "cannot generate kernel") ;
404 return (
double*)NULL ;
430 sinfo_function1d_median_smooth(
437 pixelvalue * smoothed ;
440 smoothed = sinfo_function1d_new(np);
441 for (i=0 ; i<hw ; i++) {
442 smoothed[i] = list[i] ;
444 for (i=np-hw ; i<np ; i++) {
445 smoothed[i] = list[i] ;
449 row = sinfo_function1d_new(2*hw+1);
450 for (i=hw ; i<np-hw ; i++) {
451 for (j=-hw ; j<=hw ; j++) {
452 row[j+hw] = list[i+j] ;
454 smoothed[i] = sinfo_median_pixelvalue(row, 2*hw+1) ;
456 sinfo_function1d_del(row) ;
476 #define LOWFREQ_PASSES 5
479 sinfo_function1d_remove_lowfreq(
480 pixelvalue * pixel_signal,
483 pixelvalue * sig_in ;
484 pixelvalue * smooth ;
489 sig_in = sinfo_function1d_dup(pixel_signal, ns);
490 for (i=0 ; i<LOWFREQ_PASSES ; i++) {
491 smooth = sinfo_function1d_filter_lowpass( sig_in, ns,
498 for (i=0 ; i<ns ; i++) {
499 smooth[i] = pixel_signal[i] - smooth[i];
504 #undef LOWFREQ_PASSES
527 #define SAMPLE_BORDER 10
530 sinfo_function1d_remove_thermalbg(
531 pixelvalue * pixel_signal,
534 pixelvalue * smooth ;
538 pixelvalue lef[2], rig[2];
551 x = sinfo_function1d_new(ns);
552 y = sinfo_function1d_new(ns);
554 for (i=SAMPLE_BORDER ; i<(ns-SAMPLE_BORDER) ; i++) {
555 lef[0] = pixel_signal[i-2];
556 lef[1] = pixel_signal[i-1];
557 rig[0] = pixel_signal[i+1];
558 rig[1] = pixel_signal[i+2];
560 if ( (pixel_signal[i] < lef[0]) &&
561 (pixel_signal[i] < lef[1]) &&
562 (pixel_signal[i] < rig[0]) &&
563 (pixel_signal[i] < rig[1])) {
564 x[nmin] = (pixelvalue)i ;
565 y[nmin] = pixel_signal[i];
572 spl_x = sinfo_function1d_new(ns);
573 spl_y = sinfo_function1d_new(ns);
574 for (i=0 ; i<ns ; i++) {
575 spl_x[i] = (pixelvalue)i ;
577 sinfo_function1d_interpolate_linear(x, y, nmin, spl_x, spl_y, ns);
579 sinfo_function1d_del(x) ;
580 sinfo_function1d_del(y) ;
581 sinfo_function1d_del(spl_x);
584 med_y = (double)sinfo_median_pixelvalue(pixel_signal, ns);
586 for (i=0 ; i<ns ; i++) {
587 avg2med += fabs((
double)pixel_signal[i] - med_y) ;
589 avg2med /= (double)ns ;
592 for (i=0 ; i<ns ; i++) {
593 dist = fabs((
double)pixel_signal[i] - med_y);
594 if (dist > (2.0*avg2med)) {
595 spl_y[i] = (pixelvalue)0 ;
600 smooth = sinfo_function1d_new(ns);
601 for (i=0 ; i<ns ; i++) {
603 smooth[i] = pixel_signal[i] - spl_y[i];
608 sinfo_function1d_del(spl_y);
612 #undef LOWFREQ_PASSES
636 sinfo_function1d_interpolate_linear(
649 for (i=0 ; i<spl_len ; i++) {
652 for (j=0 ; j<(len-1) ; j++) {
653 if ((spl_x[i]>=x[j]) && (spl_x[i]<=x[j+1])) {
661 a = ((double)y[j+1]-(
double)y[j]) /
662 ((
double)x[j+1]-(double)x[j]);
663 b = (double)y[j] - a * (
double)x[j] ;
664 spl_y[i] = (pixelvalue)(a * (
double)spl_x[i] + b) ;
687 function1d_search_value(
701 while (high >= low) {
702 middle = (high + low) / 2;
703 if (key > x[middle]) {
705 }
else if (key < x[middle]) {
742 sinfo_function1d_natural_spline(
770 a = cpl_malloc(
sizeof(
double) * splLen * 9) ;
780 for (i = 0; i < len; i++) {
785 for (i = 0; i < end; i++) {
786 h[i] = (double)x[i + 1] - (
double)x[i];
794 for (n = 0, i = 1; i < end; i++, n++) {
796 alpha[i] = 3.0 * ((a[i+1] / h[i]) - (a[i] / h[n]) - (a[i] / h[i]) +
802 mu[0] = mu[end] = 0.0;
807 for (n = 0, i = 1; i < end; i++, n++) {
809 l[i] = 2 * (h[i] + h[n]) - h[n] * mu[n];
811 z[i] = (alpha[i] - h[n] * z[n]) / l[i];
813 for (n = end, j = end - 1; j >= 0; j--, n--) {
815 c[j] = z[j] - mu[j] * c[n];
816 b[j] = (a[n] - a[j]) / h[j] - h[j] * (c[n] + 2.0 * c[j]) / 3.0;
817 d[j] = (c[n] - c[j]) / (3.0 * h[j]);
821 for (j = 0; j < splLen; j++) {
823 splY[j] = (pixelvalue)0;
826 if ((v < (
double)x[0]) || (v > (
double)x[end])) {
830 loc = function1d_search_value(x, len, (pixelvalue)v, &found);
836 splY[j] = (pixelvalue)( a[loc] +
865 sinfo_function1d_average_reject(
871 pixelvalue * sorted ;
876 if ((line==NULL) || (npix<1))
return (pixelvalue)0 ;
877 if ((pix_low+pix_high)>=npix)
return (pixelvalue)0 ;
880 sorted = cpl_malloc(npix *
sizeof(pixelvalue)) ;
881 memcpy(sorted, line, npix *
sizeof(pixelvalue)) ;
882 sinfo_pixel_qsort(sorted, npix);
886 for (i=pix_low+1 ; i<(npix-pix_high) ; i++) {
887 avg += (double)sorted[i] ;
890 avg /= (double)(npix - pix_high - pix_low) ;
892 return (pixelvalue)avg ;
920 #define STEP_MIN (-half_search)
921 #define STEP_MAX (half_search)
924 sinfo_function1d_xcorrelate(
935 double mean_i, mean_t ;
936 double rms_i, rms_t ;
948 for (i=0 ; i<width_i ; i++) {
949 sum += (double)line_i[i] ;
950 sqsum += (double)line_i[i] * (
double)line_i[i];
952 mean_i = sum / (double)width_i ;
953 sqsum /= (double)width_i ;
954 rms_i = sqsum - mean_i*mean_i ;
957 for (i=0 ; i<width_t ; i++) {
958 sum += (double)line_t[i] ;
959 sqsum += (double)line_t[i] * (
double)line_t[i];
961 mean_t = sum / (double)width_t ;
962 sqsum /= (double)width_t ;
963 rms_t = sqsum - mean_t*mean_t ;
965 norm = 1.00 / sqrt(rms_i * rms_t);
967 nsteps = (STEP_MAX - STEP_MIN) +1 ;
968 xcorr = cpl_malloc(nsteps *
sizeof(
double));
969 for (step=STEP_MIN ; step<=STEP_MAX ; step++) {
970 xcorr[step-STEP_MIN] = 0.00 ;
972 for (i=0 ; i<width_t ; i++) {
974 (i+step < width_i)) {
975 xcorr[step-STEP_MIN] += ((double)line_t[i] - mean_t) *
976 ((double)line_i[i+step] - mean_i) *
981 xcorr[step-STEP_MIN] /= (double)nval ;
983 xcorr_max = xcorr[0] ;
985 for (i=0 ; i<nsteps ; i++) {
986 if (xcorr[i]>xcorr_max) {
988 xcorr_max = xcorr[i];
992 (*delta) = + ((double)STEP_MIN + (
double)maxpos);