00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033
00034 #include <math.h>
00035 #include <string.h>
00036 #include <cpl.h>
00037 #include <cxtypes.h>
00038
00039 #include "vircam_stats.h"
00040 #include "vircam_utils.h"
00041
00042
00043
00044 static float kselect(float *a, int n, int k);
00045 static double dkselect(double *a, int n, int k);
00046 static float histexam(int *histo, int nhist, int level);
00047
00061
00087
00088
00089 extern float vircam_med(float *data, unsigned char *bpm, long npts) {
00090 int i,j,is_even,ilevel;
00091 float *buf,value;
00092
00093
00094
00095 buf = cpl_malloc(npts*sizeof(*buf));
00096 if (bpm == NULL) {
00097 is_even = !(npts & 1);
00098 memmove((char *)buf,(char *)data,npts*sizeof(float));
00099 if (is_even) {
00100 ilevel = npts/2 - 1;
00101 value = kselect(buf,npts,ilevel);
00102 ilevel = npts/2;
00103 value = 0.5*(value + kselect(buf,npts,ilevel));
00104 } else {
00105 ilevel = npts/2;
00106 value = kselect(buf,npts,ilevel);
00107 }
00108
00109
00110
00111 } else {
00112 j = 0;
00113 for (i = 0; i < npts; i++) {
00114 if (bpm[i] == 0)
00115 buf[j++] = data[i];
00116 }
00117 if (j == 0) {
00118 cpl_free(buf);
00119 value = CX_MAXFLOAT;
00120 return(value);
00121 }
00122 is_even = !(j & 1);
00123 if (is_even) {
00124 ilevel = j/2 - 1;
00125 value = kselect(buf,j,ilevel);
00126 ilevel = j/2;
00127 value = 0.5*(value + kselect(buf,j,ilevel));
00128 } else {
00129 ilevel = j/2;
00130 value = kselect(buf,j,ilevel);
00131 }
00132 }
00133 cpl_free(buf);
00134 return(value);
00135 }
00136
00137
00163
00164
00165 extern double vircam_dmed(double *data, unsigned char *bpm, long npts) {
00166 int i,j,is_even,ilevel;
00167 double *buf,value;
00168
00169
00170
00171 buf = cpl_malloc(npts*sizeof(*buf));
00172 if (bpm == NULL) {
00173 is_even = !(npts & 1);
00174 memmove((char *)buf,(char *)data,npts*sizeof(double));
00175 if (is_even) {
00176 ilevel = npts/2 - 1;
00177 value = dkselect(buf,npts,ilevel);
00178 ilevel = npts/2;
00179 value = 0.5*(value + dkselect(buf,npts,ilevel));
00180 } else {
00181 ilevel = npts/2;
00182 value = dkselect(buf,npts,ilevel);
00183 }
00184
00185
00186
00187 } else {
00188 j = 0;
00189 for (i = 0; i < npts; i++) {
00190 if (bpm[i] == 0)
00191 buf[j++] = data[i];
00192 }
00193 if (j == 0) {
00194 cpl_free(buf);
00195 value = CX_MAXDOUBLE;
00196 return(value);
00197 }
00198 is_even = !(j & 1);
00199 if (is_even) {
00200 ilevel = j/2 - 1;
00201 value = dkselect(buf,j,ilevel);
00202 ilevel = j/2;
00203 value = 0.5*(value + dkselect(buf,j,ilevel));
00204 } else {
00205 ilevel = j/2;
00206 value = dkselect(buf,j,ilevel);
00207 }
00208 }
00209 cpl_free(buf);
00210 return(value);
00211 }
00212
00213
00239
00240
00241 extern float vircam_mean(float *data, unsigned char *bpm, long npts) {
00242 int i,n;
00243 float sum,value;
00244
00245
00246
00247 sum = 0.0;
00248 if (bpm == NULL) {
00249 n = npts;
00250 for (i = 0; i < npts; i++)
00251 sum += data[i];
00252 } else {
00253 n = 0;
00254 for (i = 0; i < npts; i++) {
00255 if (bpm[i] == 0) {
00256 sum += data[i];
00257 n++;
00258 }
00259 }
00260 }
00261 if (n > 0)
00262 value = sum/(float)n;
00263 else
00264 value = CX_MAXFLOAT;
00265 return(value);
00266 }
00267
00268
00294
00295
00296 extern double vircam_dmean(double *data, unsigned char *bpm, long npts) {
00297 int i,n;
00298 double sum,value;
00299
00300
00301
00302 sum = 0.0;
00303 if (bpm == NULL) {
00304 n = npts;
00305 for (i = 0; i < npts; i++)
00306 sum += data[i];
00307 } else {
00308 n = 0;
00309 for (i = 0; i < npts; i++) {
00310 if (bpm[i] == 0) {
00311 sum += data[i];
00312 n++;
00313 }
00314 }
00315 }
00316 if (n > 0)
00317 value = sum/(float)n;
00318 else
00319 value = CX_MAXDOUBLE;
00320 return(value);
00321 }
00322
00323
00355
00356
00357 extern int vircam_meansig(float *data, unsigned char *bpm, long npts,
00358 float *mean, float *sig) {
00359 int i,n;
00360 double sum,sum2,d;
00361 const char *fctid = "vircam_meansig";
00362
00363
00364
00365 sum = 0.0;
00366 sum2 = 0.0;
00367 if (bpm == NULL) {
00368 n = npts;
00369 for (i = 0; i < npts; i++) {
00370 d = (double)(data[i]);
00371 sum += d;
00372 sum2 += d*d;
00373 }
00374 } else {
00375 n = 0;
00376 for (i = 0; i < npts; i++) {
00377 if (bpm[i] == 0) {
00378 d = (double)(data[i]);
00379 sum += d;
00380 sum2 += d*d;
00381 n++;
00382 }
00383 }
00384 }
00385
00386
00387
00388 switch (n) {
00389 case 0:
00390 *mean = CX_MAXFLOAT;
00391 *sig = CX_MAXFLOAT;
00392 cpl_msg_warning(fctid,"All values flagged as bad\n");
00393 return(VIR_WARN);
00394 case 1:
00395 *mean = (float)sum;
00396 *sig = 0.0;
00397 return(VIR_OK);
00398 default:
00399 sum /= (double)n;
00400 *mean = (float)sum;
00401 sum2 = sum2/(double)n - sum*sum;
00402 *sig = (float)sqrt(max(1.0e-12,sum2));
00403 return(VIR_OK);
00404 }
00405 }
00406
00407
00444
00445
00446 extern int vircam_meansigcut(float *data, unsigned char *bpm, long npts,
00447 float lcut, float hcut, float *mean, float *sig) {
00448 int i,n;
00449 double sum,sum2;
00450 const char *fctid = "vircam_meansigcut";
00451
00452
00453
00454 sum = 0.0;
00455 sum2 = 0.0;
00456 if (bpm == NULL) {
00457 n = 0;
00458 for (i = 0; i < npts; i++) {
00459 if (data[i] > lcut && data[i] < hcut) {
00460 sum += data[i];
00461 sum2 += data[i]*data[i];
00462 n++;
00463 }
00464 }
00465 } else {
00466 n = 0;
00467 for (i = 0; i < npts; i++) {
00468 if (bpm[i] == 0 && data[i] > lcut && data[i] < hcut) {
00469 sum += data[i];
00470 sum2 += data[i]*data[i];
00471 n++;
00472 }
00473 }
00474 }
00475
00476
00477
00478 switch (n) {
00479 case 0:
00480 *mean = CX_MAXFLOAT;
00481 *sig = CX_MAXFLOAT;
00482 cpl_msg_warning(fctid,"All values flagged as bad\n");
00483 return(VIR_WARN);
00484 case 1:
00485 *mean = (float)sum;
00486 *sig = 0.0;
00487 return(VIR_OK);
00488 default:
00489 sum /= (double)n;
00490 *mean = (float)sum;
00491 sum2 = sum2/(double)n - sum*sum;
00492 *sig = (float)sqrt(max(1.0e-12,sum2));
00493 return(VIR_OK);
00494 }
00495 }
00496
00497
00535
00536
00537 extern void vircam_qmedsig(float *data, unsigned char *bpm, long npts,
00538 float thresh, int niter, float lowv, float highv,
00539 float *median, float *sigma) {
00540 int *histo,nbins,nhist,ilev,iclip,nhist2,halflev,quartlev;
00541 int irej,jst,j;
00542 long i;
00543 float mlev,qlev;
00544 unsigned char *b;
00545
00546
00547
00548
00549 if (bpm == NULL)
00550 b = cpl_calloc(npts,sizeof(unsigned char));
00551 else
00552 b = bpm;
00553 nbins = vircam_nint(highv - lowv + 1.0);
00554 histo = cpl_calloc(nbins,sizeof(*histo));
00555 nhist = 0;
00556 for (i = 0; i < npts; i++) {
00557 if (b[i] || data[i] < lowv || data[i] > highv)
00558 continue;
00559 ilev = vircam_nint(data[i] - lowv);
00560 ilev = max(0,min(nbins-1,ilev));
00561 histo[ilev] += 1;
00562 nhist += 1;
00563 }
00564 if (bpm == NULL)
00565 freespace(b);
00566
00567
00568
00569 iclip = nbins - 1;
00570 nhist2 = nhist;
00571 for (i = 0; i <= niter; i++) {
00572 halflev = (nhist2 + 1)/2;
00573 quartlev = (nhist2 + 3)/4;
00574 mlev = histexam(histo,nbins,halflev);
00575 *median = mlev + lowv;
00576 qlev = histexam(histo,nbins,quartlev);
00577 *sigma = (mlev - qlev)*1.48;
00578 if (i == niter)
00579 break;
00580 irej = 0;
00581 jst = vircam_nint(mlev + thresh*(*sigma));
00582 for (j = jst; j <= iclip; j++)
00583 irej += histo[j];
00584 if (irej == 0)
00585 break;
00586 iclip = jst - 1;
00587 nhist2 -= irej;
00588 }
00589 cpl_free(histo);
00590 }
00591
00592
00618
00619
00620 extern void vircam_medmad(float *data, unsigned char *bpm, long np, float *med,
00621 float *mad) {
00622 int i;
00623 float *work;
00624
00625
00626
00627 *med = vircam_med(data,bpm,np);
00628
00629
00630
00631
00632 work = cpl_malloc(np*sizeof(*work));
00633 for (i = 0; i < np; i++)
00634 work[i] = (float)fabs((double)(data[i] - *med));
00635
00636
00637
00638 *mad = vircam_med(work,bpm,np);
00639
00640
00641
00642 cpl_free(work);
00643 }
00644
00645
00677
00678
00679 extern void vircam_medmadcut(float *data, unsigned char *bpm, long np,
00680 float lcut, float hcut, float *med, float *mad) {
00681 int i;
00682 float *work;
00683 unsigned char *bad;
00684
00685
00686
00687 bad = cpl_calloc(np,sizeof(*bad));
00688 if (bpm != NULL) {
00689 for (i = 0; i < np; i++)
00690 if (bpm[i] != 0 || data[i] < lcut || data[i] > hcut)
00691 bad[i] = 1;
00692 } else {
00693 for (i = 0; i < np; i++)
00694 if (data[i] < lcut || data[i] > hcut)
00695 bad[i] = 1;
00696 }
00697
00698
00699
00700 *med = vircam_med(data,bad,np);
00701
00702
00703
00704
00705 work = cpl_malloc(np*sizeof(*work));
00706 for (i = 0; i < np; i++)
00707 work[i] = (float)fabs((double)(data[i] - *med));
00708
00709
00710
00711 *mad = vircam_med(work,bad,np);
00712
00713
00714
00715 cpl_free(work);
00716 cpl_free(bad);
00717 }
00718
00719
00744
00745
00746 extern void vircam_medsig(float *data, unsigned char *bpm, long np, float *med,
00747 float *sig) {
00748 int i,n;
00749 float sum,resid;
00750
00751
00752
00753 *med = vircam_med(data,bpm,np);
00754
00755
00756
00757 if (bpm == NULL) {
00758 sum = 0.0;
00759 for (i = 0; i < np; i++) {
00760 resid = data[i] - *med;
00761 sum += resid*resid;
00762 }
00763 *sig = sqrt(sum/(float)np);
00764
00765
00766
00767 } else {
00768 sum = 0.0;
00769 n = 0;
00770 for (i = 0; i < np; i++) {
00771 if (bpm[i] == 0) {
00772 n++;
00773 resid = data[i] - *med;
00774 sum += resid*resid;
00775 }
00776 }
00777 if (n > 0)
00778 *sig = sqrt(sum/(float)n);
00779 else
00780 *sig = 0.0;
00781 }
00782 }
00783
00784
00806
00807
00808 extern int vircam_sumbpm(unsigned char *bpm, int npts, int *sumb) {
00809 int j;
00810
00811 *sumb = 0;
00812 for (j = 0; j < npts; j++)
00813 *sumb += bpm[j];
00814 return(VIR_OK);
00815 }
00816
00819 static float histexam(int *histo, int nhist, int level) {
00820 int ilev,ii;
00821 float value;
00822
00823 ii = 0;
00824 ilev = -1;
00825 while (ii < level && ilev < nhist-1)
00826 ii += histo[++ilev];
00827 value = (float)ilev - (float)(ii - level)/(float)histo[ilev] + 0.5;
00828 return(value);
00829 }
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842 static float kselect(float *a, int n, int k) {
00843 while (n > 1) {
00844 int i = 0, j = n - 1;
00845 float x = a[j/2], w;
00846
00847 do {
00848 while (a[i] < x) i++;
00849 while (a[j] > x) j--;
00850 if (i < j) {
00851 w = a[i]; a[i] = a[j]; a[j] = w;
00852 } else {
00853 if (i == j) i++;
00854 break;
00855 }
00856 } while (++i <= --j);
00857
00858 if (k < i)
00859 n = i;
00860 else {
00861 a += i; n -= i; k -= i;
00862 }
00863 }
00864
00865 return a[0];
00866 }
00867
00868 static double dkselect(double *a, int n, int k) {
00869 while (n > 1) {
00870 int i = 0, j = n - 1;
00871 double x = a[j/2], w;
00872
00873 do {
00874 while (a[i] < x) i++;
00875 while (a[j] > x) j--;
00876 if (i < j) {
00877 w = a[i]; a[i] = a[j]; a[j] = w;
00878 } else {
00879 if (i == j) i++;
00880 break;
00881 }
00882 } while (++i <= --j);
00883
00884 if (k < i)
00885 n = i;
00886 else {
00887 a += i; n -= i; k -= i;
00888 }
00889 }
00890
00891 return a[0];
00892 }
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944