OPERA
1.0
Open source echelle spectrograph reduction pipeline
|
00001 #ifndef LIBOPERASTATS_H 00002 #define LIBOPERASTATS_H 00003 /******************************************************************* 00004 **** LIBRARY FOR OPERA v1.0 **** 00005 ******************************************************************* 00006 Library name: operaStats 00007 Version: 1.0 00008 Description: ThisC library implements basic statistics routines.. 00009 Author(s): CFHT OPERA team 00010 Affiliation: Canada France Hawaii Telescope 00011 Location: Hawaii USA 00012 Date: Aug/2011 00013 Contact: eder@cfht.hawaii.edu 00014 00015 Copyright (C) 2011 Opera Pipeline team, Canada France Hawaii Telescope 00016 00017 This program is free software: you can redistribute it and/or modify 00018 it under the terms of the GNU General Public License as published by 00019 the Free Software Foundation, either version 3 of the License, or 00020 (at your option) any later version. 00021 00022 This program is distributed in the hope that it will be useful, 00023 but WITHOUT ANY WARRANTY; without even the implied warranty of 00024 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00025 GNU General Public License for more details. 00026 00027 You should have received a copy of the GNU General Public License 00028 along with this program. If not, see: 00029 http://software.cfht.hawaii.edu/licenses 00030 -or- 00031 http://www.gnu.org/licenses/gpl-3.0.html 00032 ********************************************************************/ 00033 00034 // $Date$ 00035 // $Id$ 00036 // $Revision$ 00037 // $Locker$ 00038 // $Log$ 00039 00040 /* 00041 * Image routines. 00042 * 00043 */ 00044 #include <stdio.h> 00045 #include <stdlib.h> 00046 #include <math.h> 00047 00048 #include "operaError.h" 00049 00050 // for Linux... 00051 #ifndef M_PI 00052 #define M_PI 3.14159265358979323846264338327950288 00053 #endif 00054 00055 #define ELEM_SWAP(a,b) {register float t=(a);(a)=(b);(b)=t;} 00056 00057 float operaArrayMean(unsigned np, const float *array); 00058 float operaArrayWeightedMean(unsigned np, const float *array, const float *weigh); 00059 float operaArrayAvgSigClip(unsigned np, const float *array, unsigned nsig); 00060 float operaArraySig(unsigned np, const float *array); 00061 float operaArrayWeightedSig(unsigned np, const float *array, const float *weigh); 00062 float operaArrayMedian(unsigned np, const float *array); 00063 float operaArrayMedSig(unsigned np, const float *array, float median); 00064 float operaArrayMaxValue(unsigned np, const float *array); 00065 float operaArrayMinValue(unsigned np, const float *array); 00066 void operaArrayHeapSort(unsigned np, float *arr); 00067 void operaArrayIndexSort(unsigned np, const float *array, unsigned *sindex); 00068 float operaUniformRand(float xcen, float xmax, float xmin); 00069 float operaGaussRand(float xcen, float sig); 00070 unsigned operaCountPixels(unsigned np, const float *array, float minvalue, float maxvalue); 00071 00072 00081 inline void operaArrayIndexedMeanQuick(unsigned np, const float *array, const float *indexmask, unsigned nb, float *meanbin) { 00082 00083 float *sumbin = (float *)malloc(sizeof(float)*nb); 00084 00085 memset(sumbin, 0, sizeof(float)*nb); 00086 memset(meanbin, 0, sizeof(float)*nb); 00087 00088 while (np--){ 00089 if(*indexmask) { 00090 meanbin[(unsigned)*indexmask-1] += *array; 00091 sumbin[(unsigned)*indexmask-1]++; 00092 } 00093 indexmask++; 00094 array++; 00095 } 00096 while(nb--) { 00097 *meanbin++ /= *sumbin++; 00098 } 00099 } 00100 00109 inline void operaArrayIndexedSigQuick(unsigned np, const float *array, const float *indexmask, unsigned nb, float *sigbin) { 00110 00111 float *sumbin = (float *)malloc(sizeof(float)*nb); 00112 float *meanbin = (float *)malloc(sizeof(float)*nb); 00113 unsigned i=np; 00114 unsigned j=0; 00115 00116 memset(sumbin, 0, sizeof(float)*nb); 00117 memset(meanbin, 0, sizeof(float)*nb); 00118 memset(sigbin, 0, sizeof(float)*nb); 00119 00120 if(np){ 00121 00122 while (i--){ 00123 if(*indexmask) { 00124 j = (unsigned)*indexmask-1; 00125 meanbin[j] += *array; 00126 sumbin[j]++; 00127 } 00128 indexmask++; 00129 array++; 00130 } 00131 00132 j=nb; 00133 while(j--) { 00134 meanbin[j] /= sumbin[j]; 00135 } 00136 00137 i=np; 00138 while(i--) { 00139 array--; 00140 indexmask--; 00141 if(*indexmask) { 00142 j = (unsigned)*indexmask-1; 00143 sigbin[j] += (*array - meanbin[j])*(*array - meanbin[j]); 00144 } 00145 } 00146 j=nb; 00147 while(j--) { 00148 sigbin[j] = sqrt(sigbin[j]/sumbin[j]); 00149 } 00150 } 00151 } 00152 00153 00161 inline float operaArrayMeanQuick(unsigned np, const float *array) { 00162 float xmean = 0.0; 00163 unsigned i=np; 00164 while (i--) xmean += *array++; 00165 if (!np) 00166 return 0.0; 00167 else 00168 return xmean/(float)np; 00169 } 00170 00179 inline float operaArrayWeightedMeanQuick(unsigned np, const float *array, const float *weigh) { 00180 double xmean = 0.0; 00181 float npf = 0.0; 00182 00183 while (np--){ 00184 xmean += (*array++)*(*weigh); 00185 npf += *weigh++; 00186 } 00187 if (npf == 0.0) 00188 return 0.0; 00189 else 00190 return xmean/npf; 00191 } 00192 00200 inline float operaArraySigQuick(unsigned np, const float *array) { 00201 00202 float xsig = 0.0; 00203 float xmean = 0.0; 00204 unsigned i=np; 00205 00206 if(np){ 00207 while (i--) xmean += *array++; 00208 xmean/=(float)np; 00209 i=np; 00210 while (i--) { 00211 array--; 00212 xsig += (*array - xmean)*(*array - xmean); 00213 } 00214 xsig/=(float)np; 00215 } 00216 return sqrt(xsig); 00217 } 00218 00227 inline float operaArrayWeightedSigQuick(unsigned np, const float *array, const float *weigh) { 00228 float xmean = 0.0; 00229 float xsig = 0.0; 00230 float npf = 0.0; 00231 unsigned i=np; 00232 00233 if (np) { 00234 while (i--){ 00235 xmean += (*array)*(*weigh); 00236 npf += *weigh; 00237 array++; 00238 weigh++; 00239 } 00240 xmean /= npf; // NOTE: This may throw a floating point exception if weigh is all zeroes 00241 i=np; 00242 while (i--){ 00243 array--; 00244 weigh--; 00245 xsig += (*weigh)*(*array - xmean)*(*array - xmean); 00246 } 00247 xsig /= npf; 00248 } 00249 return sqrt(xsig); 00250 } 00259 inline float operaArrayAvgSigClipQuick(unsigned np, const float *array, unsigned nsig) 00260 { 00261 float xsig = 0.0; 00262 float xmean = 0.0; 00263 float clipedmean = 0.0; 00264 unsigned clipednp = 0; 00265 unsigned i=np; 00266 00267 if(np){ 00268 while (i--) xmean += *array++; 00269 xmean/=(float)np; 00270 i=np; 00271 while (i--) { 00272 array--; 00273 xsig += (*array - xmean)*(*array - xmean); 00274 } 00275 xsig = sqrt(xsig/(float)np); 00276 00277 i=np; 00278 while (i--) { 00279 if((*array > xmean - (float)nsig*xsig) && (*array < xmean + (float)nsig*xsig)) { 00280 clipedmean += *array; 00281 clipednp++; 00282 } 00283 array++; 00284 } 00285 } 00286 return(clipedmean/(float)clipednp); 00287 } 00288 00296 inline float operaArrayMedianQuick(unsigned np, /*MODIFIED!!!*/float *arr) { 00297 unsigned low = 0, high = np-1; 00298 unsigned median = (low + high) / 2; 00299 unsigned odd = (np & 1); 00300 unsigned middle, ll, hh; 00301 00302 while (1) { 00303 00304 if (high <= low) {/* One element only */ 00305 return arr[median] ; 00306 } 00307 if (high == low + 1) { /* Two elements only */ 00308 if (arr[low] > arr[high]) 00309 ELEM_SWAP(arr[low], arr[high]) ; 00310 if (odd) 00311 return arr[median] ; 00312 else 00313 return (arr[low] + arr[high]) / 2.0; 00314 } 00315 00316 /* Find median of low, middle and high items; swap into position low */ 00317 middle = (low + high) / 2; 00318 if (arr[middle] > arr[high]) 00319 ELEM_SWAP(arr[middle], arr[high]) 00320 if (arr[low] > arr[high]) 00321 ELEM_SWAP(arr[low], arr[high]) 00322 if (arr[middle] > arr[low]) 00323 ELEM_SWAP(arr[middle], arr[low]) 00324 00325 /* Swap low item (now in position middle) into position (low+1) */ 00326 ELEM_SWAP(arr[middle], arr[low+1]) ; 00327 00328 /* Nibble from each end towards middle, swapping items when stuck */ 00329 ll = low + 1; 00330 hh = high; 00331 for (;;) { 00332 do ll++; while (arr[low] > arr[ll]) ; 00333 do hh--; while (arr[hh] > arr[low]) ; 00334 00335 if (hh < ll) 00336 break; 00337 ELEM_SWAP(arr[ll], arr[hh]) 00338 } 00339 00340 /* Swap middle item (in position low) back into correct position */ 00341 ELEM_SWAP(arr[low], arr[hh]) 00342 00343 /* Re-set active partition */ 00344 if (hh <= median) low = ll; 00345 if (hh >= median) high = hh - 1; 00346 } 00347 } 00348 00356 inline unsigned short operaArrayMedianQuickUSHORT(unsigned np, /*MODIFIED!!!*/unsigned short *arr) { 00357 unsigned low = 0, high = np-1; 00358 unsigned median = (low + high) / 2; 00359 unsigned odd = (np & 1); 00360 unsigned middle, ll, hh; 00361 00362 while (1) { 00363 00364 if (high <= low) {/* One element only */ 00365 return arr[median] ; 00366 } 00367 if (high == low + 1) { /* Two elements only */ 00368 if (arr[low] > arr[high]) 00369 ELEM_SWAP(arr[low], arr[high]) ; 00370 if (odd) 00371 return arr[median] ; 00372 else 00373 return (arr[low] + arr[high]) / 2.0; 00374 } 00375 00376 /* Find median of low, middle and high items; swap into position low */ 00377 middle = (low + high) / 2; 00378 if (arr[middle] > arr[high]) 00379 ELEM_SWAP(arr[middle], arr[high]) 00380 if (arr[low] > arr[high]) 00381 ELEM_SWAP(arr[low], arr[high]) 00382 if (arr[middle] > arr[low]) 00383 ELEM_SWAP(arr[middle], arr[low]) 00384 00385 /* Swap low item (now in position middle) into position (low+1) */ 00386 ELEM_SWAP(arr[middle], arr[low+1]) ; 00387 00388 /* Nibble from each end towards middle, swapping items when stuck */ 00389 ll = low + 1; 00390 hh = high; 00391 for (;;) { 00392 do ll++; while (arr[low] > arr[ll]) ; 00393 do hh--; while (arr[hh] > arr[low]) ; 00394 00395 if (hh < ll) 00396 break; 00397 ELEM_SWAP(arr[ll], arr[hh]) 00398 } 00399 00400 /* Swap middle item (in position low) back into correct position */ 00401 ELEM_SWAP(arr[low], arr[hh]) 00402 00403 /* Re-set active partition */ 00404 if (hh <= median) low = ll; 00405 if (hh >= median) high = hh - 1; 00406 } 00407 } 00408 00409 00410 #endif 00411