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") ;
405 return (
double*)NULL ;
431 sinfo_function1d_median_smooth(
438 pixelvalue * smoothed ;
441 smoothed = sinfo_function1d_new(np);
442 for (i=0 ; i<hw ; i++) {
443 smoothed[i] = list[i] ;
445 for (i=np-hw ; i<np ; i++) {
446 smoothed[i] = list[i] ;
450 row = sinfo_function1d_new(2*hw+1);
451 for (i=hw ; i<np-hw ; i++) {
452 for (j=-hw ; j<=hw ; j++) {
453 row[j+hw] = list[i+j] ;
455 smoothed[i] = sinfo_median_pixelvalue(row, 2*hw+1) ;
457 sinfo_function1d_del(row) ;
477 #define LOWFREQ_PASSES 5
480 sinfo_function1d_remove_lowfreq(
481 pixelvalue * pixel_signal,
484 pixelvalue * sig_in ;
485 pixelvalue * smooth ;
490 sig_in = sinfo_function1d_dup(pixel_signal, ns);
491 for (i=0 ; i<LOWFREQ_PASSES ; i++) {
492 smooth = sinfo_function1d_filter_lowpass( sig_in, ns,
499 for (i=0 ; i<ns ; i++) {
500 smooth[i] = pixel_signal[i] - smooth[i];
505 #undef LOWFREQ_PASSES
528 #define SAMPLE_BORDER 10
531 sinfo_function1d_remove_thermalbg(
532 pixelvalue * pixel_signal,
535 pixelvalue * smooth ;
539 pixelvalue lef[2], rig[2];
552 x = sinfo_function1d_new(ns);
553 y = sinfo_function1d_new(ns);
555 for (i=SAMPLE_BORDER ; i<(ns-SAMPLE_BORDER) ; i++) {
556 lef[0] = pixel_signal[i-2];
557 lef[1] = pixel_signal[i-1];
558 rig[0] = pixel_signal[i+1];
559 rig[1] = pixel_signal[i+2];
561 if ( (pixel_signal[i] < lef[0]) &&
562 (pixel_signal[i] < lef[1]) &&
563 (pixel_signal[i] < rig[0]) &&
564 (pixel_signal[i] < rig[1])) {
565 x[nmin] = (pixelvalue)i ;
566 y[nmin] = pixel_signal[i];
573 spl_x = sinfo_function1d_new(ns);
574 spl_y = sinfo_function1d_new(ns);
575 for (i=0 ; i<ns ; i++) {
576 spl_x[i] = (pixelvalue)i ;
578 sinfo_function1d_interpolate_linear(x, y, nmin, spl_x, spl_y, ns);
580 sinfo_function1d_del(x) ;
581 sinfo_function1d_del(y) ;
582 sinfo_function1d_del(spl_x);
585 med_y = (double)sinfo_median_pixelvalue(pixel_signal, ns);
587 for (i=0 ; i<ns ; i++) {
588 avg2med += fabs((
double)pixel_signal[i] - med_y) ;
590 avg2med /= (double)ns ;
593 for (i=0 ; i<ns ; i++) {
594 double dist = fabs((
double)pixel_signal[i] - med_y);
595 if (dist > (2.0*avg2med)) {
596 spl_y[i] = (pixelvalue)0 ;
601 smooth = sinfo_function1d_new(ns);
602 for (i=0 ; i<ns ; i++) {
604 smooth[i] = pixel_signal[i] - spl_y[i];
609 sinfo_function1d_del(spl_y);
613 #undef LOWFREQ_PASSES
637 sinfo_function1d_interpolate_linear(
650 for (i=0 ; i<spl_len ; i++) {
653 for (j=0 ; j<(len-1) ; j++) {
654 if ((spl_x[i]>=x[j]) && (spl_x[i]<=x[j+1])) {
662 a = ((double)y[j+1]-(
double)y[j]) /
663 ((
double)x[j+1]-(double)x[j]);
664 b = (double)y[j] - a * (
double)x[j] ;
665 spl_y[i] = (pixelvalue)(a * (
double)spl_x[i] + b) ;
688 function1d_search_value(
700 while (high >= low) {
701 int middle = (high + low) / 2;
702 if (key > x[middle]) {
704 }
else if (key < x[middle]) {
741 sinfo_function1d_natural_spline(
768 a = cpl_malloc(
sizeof(
double) * splLen * 9) ;
778 for (i = 0; i < len; i++) {
783 for (i = 0; i < end; i++) {
784 h[i] = (double)x[i + 1] - (
double)x[i];
792 for (n = 0, i = 1; i < end; i++, n++) {
794 alpha[i] = 3.0 * ((a[i+1] / h[i]) - (a[i] / h[n]) - (a[i] / h[i]) +
800 mu[0] = mu[end] = 0.0;
805 for (n = 0, i = 1; i < end; i++, n++) {
807 l[i] = 2 * (h[i] + h[n]) - h[n] * mu[n];
809 z[i] = (alpha[i] - h[n] * z[n]) / l[i];
811 for (n = end, j = end - 1; j >= 0; j--, n--) {
813 c[j] = z[j] - mu[j] * c[n];
814 b[j] = (a[n] - a[j]) / h[j] - h[j] * (c[n] + 2.0 * c[j]) / 3.0;
815 d[j] = (c[n] - c[j]) / (3.0 * h[j]);
819 for (j = 0; j < splLen; j++) {
820 double v = (double)splX[j];
821 splY[j] = (pixelvalue)0;
824 if ((v < (
double)x[0]) || (v > (
double)x[end])) {
828 loc = function1d_search_value(x, len, (pixelvalue)v, &found);
834 splY[j] = (pixelvalue)( a[loc] +
863 sinfo_function1d_average_reject(
869 pixelvalue * sorted ;
874 if ((line==NULL) || (npix<1))
return (pixelvalue)0 ;
875 if ((pix_low+pix_high)>=npix)
return (pixelvalue)0 ;
878 sorted = cpl_malloc(npix *
sizeof(pixelvalue)) ;
879 memcpy(sorted, line, npix *
sizeof(pixelvalue)) ;
880 sinfo_pixel_qsort(sorted, npix);
884 for (i=pix_low+1 ; i<(npix-pix_high) ; i++) {
885 avg += (double)sorted[i] ;
888 avg /= (double)(npix - pix_high - pix_low) ;
890 return (pixelvalue)avg ;
918 #define STEP_MIN (-half_search)
919 #define STEP_MAX (half_search)
922 sinfo_function1d_xcorrelate(
933 double mean_i, mean_t ;
934 double rms_i, rms_t ;
946 for (i=0 ; i<width_i ; i++) {
947 sum += (double)line_i[i] ;
948 sqsum += (double)line_i[i] * (
double)line_i[i];
950 mean_i = sum / (double)width_i ;
951 sqsum /= (double)width_i ;
952 rms_i = sqsum - mean_i*mean_i ;
955 for (i=0 ; i<width_t ; i++) {
956 sum += (double)line_t[i] ;
957 sqsum += (double)line_t[i] * (
double)line_t[i];
959 mean_t = sum / (double)width_t ;
960 sqsum /= (double)width_t ;
961 rms_t = sqsum - mean_t*mean_t ;
963 norm = 1.00 / sqrt(rms_i * rms_t);
965 nsteps = (STEP_MAX - STEP_MIN) +1 ;
966 xcorr = cpl_malloc(nsteps *
sizeof(
double));
967 for (step=STEP_MIN ; step<=STEP_MAX ; step++) {
968 xcorr[step-STEP_MIN] = 0.00 ;
970 for (i=0 ; i<width_t ; i++) {
972 (i+step < width_i)) {
973 xcorr[step-STEP_MIN] += ((double)line_t[i] - mean_t) *
974 ((double)line_i[i+step] - mean_i) *
979 xcorr[step-STEP_MIN] /= (double)nval ;
981 xcorr_max = xcorr[0] ;
983 for (i=0 ; i<nsteps ; i++) {
984 if (xcorr[i]>xcorr_max) {
986 xcorr_max = xcorr[i];
990 (*delta) = + ((double)STEP_MIN + (
double)maxpos);
#define sinfo_msg_error(...)
Print an error message.