OPERA  1.0
Open source echelle spectrograph reduction pipeline
operaStats.h
Go to the documentation of this file.
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