// ----------------------------------------------------------------------- // Statistics.cc: Member functions for the templated StatsContainer // class. // ----------------------------------------------------------------------- // Copyright (C) 2006, Matthew Whiting, ATNF // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your // option) any later version. // // Duchamp is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License // along with Duchamp; if not, write to the Free Software Foundation, // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA // // Correspondence concerning Duchamp may be directed to: // Internet email: Matthew.Whiting [at] atnf.csiro.au // Postal address: Dr. Matthew Whiting // Australia Telescope National Facility, CSIRO // PO Box 76 // Epping NSW 1710 // AUSTRALIA // ----------------------------------------------------------------------- #include #include #include namespace Statistics { template float madfmToSigma(T madfm){ return float(madfm)/correctionFactor; } template float madfmToSigma(int madfm); template float madfmToSigma(long madfm); template float madfmToSigma(float madfm); template float madfmToSigma(double madfm); //-------------------------------------------------------------------- float sigmaToMADFM(float sigma){ return float(sigma)*correctionFactor; } //-------------------------------------------------------------------- //-------------------------------------------------------------------- template StatsContainer::StatsContainer(const StatsContainer& s) { /// @details /// The copy constructor for the StatsContainer class. Just uses /// the assignment operator. operator=(s); } template StatsContainer::StatsContainer(const StatsContainer& s); template StatsContainer::StatsContainer(const StatsContainer& s); template StatsContainer::StatsContainer(const StatsContainer& s); template StatsContainer::StatsContainer(const StatsContainer& s); //-------------------------------------------------------------------- template StatsContainer& StatsContainer::operator= (const StatsContainer& s) { /// The assignment operator for the StatsContainer class. if(this == &s) return *this; this->defined = s.defined; this->mean = s.mean; this->stddev = s.stddev; this->median = s.median; this->madfm = s.madfm; this->threshold = s.threshold; this->pThreshold = s.pThreshold; this->useRobust = s.useRobust; this->useFDR = s.useFDR; return *this; } template StatsContainer& StatsContainer::operator= (const StatsContainer& s); template StatsContainer& StatsContainer::operator= (const StatsContainer& s); template StatsContainer& StatsContainer::operator= (const StatsContainer& s); template StatsContainer& StatsContainer::operator= (const StatsContainer& s); //-------------------------------------------------------------------- template float StatsContainer::getThresholdSNR() { /// @details /// The SNR is defined in terms of excess over the middle estimator /// in units of the spread estimator. return (threshold - this->getMiddle())/this->getSpread(); } template float StatsContainer::getThresholdSNR(); template float StatsContainer::getThresholdSNR(); template float StatsContainer::getThresholdSNR(); template float StatsContainer::getThresholdSNR(); //-------------------------------------------------------------------- template void StatsContainer::setThresholdSNR(float snr) { /// @details /// The SNR is defined in terms of excess over the middle estimator /// in units of the spread estimator. threshold=this->getMiddle() + snr*this->getSpread(); } template void StatsContainer::setThresholdSNR(float snr); template void StatsContainer::setThresholdSNR(float snr); template void StatsContainer::setThresholdSNR(float snr); template void StatsContainer::setThresholdSNR(float snr); //-------------------------------------------------------------------- template float StatsContainer::valueToSNR(float value) { /// @details /// The SNR is defined in terms of excess over the middle estimator /// in units of the spread estimator. return (value - this->getMiddle())/this->getSpread(); } template float StatsContainer::valueToSNR(float value); template float StatsContainer::valueToSNR(float value); template float StatsContainer::valueToSNR(float value); template float StatsContainer::valueToSNR(float value); //-------------------------------------------------------------------- template float StatsContainer::snrToValue(float snr) { /// @details /// The SNR is defined in terms of excess over the middle estimator /// in units of the spread estimator. return snr * this->getSpread() + this->getMiddle(); } template float StatsContainer::snrToValue(float value); template float StatsContainer::snrToValue(float value); template float StatsContainer::snrToValue(float value); template float StatsContainer::snrToValue(float value); //-------------------------------------------------------------------- template void StatsContainer::setMiddle(float middle) { /// @details /// The middle value is determined by the StatsContainer::useRobust /// flag -- it will be either the median (if true), or the mean (if /// false). if(useRobust) this->median = Type(middle); else this->mean = middle; } template void StatsContainer::setMiddle(float middle); template void StatsContainer::setMiddle(float middle); template void StatsContainer::setMiddle(float middle); template void StatsContainer::setMiddle(float middle); //-------------------------------------------------------------------- template float StatsContainer::getMiddle() { /// @details /// The middle value is determined by the StatsContainer::useRobust /// flag -- it will be either the median (if true), or the mean (if /// false). if(useRobust) return float(this->median); else return this->mean; } template float StatsContainer::getMiddle(); template float StatsContainer::getMiddle(); template float StatsContainer::getMiddle(); template float StatsContainer::getMiddle(); //-------------------------------------------------------------------- template void StatsContainer::setSpread(float spread) { /// @details /// The spread value is set according to the /// StatsContainer::useRobust flag -- it will be either the madfm /// (if true), or the rms (if false). If robust, the spread value will be /// converted to a madfm from an equivalent rms under the assumption of /// Gaussianity, using the Statistics::sigmaToMADFM function. if(useRobust) this->madfm = Type(sigmaToMADFM(spread)); else this->stddev = spread; } template void StatsContainer::setSpread(float spread); template void StatsContainer::setSpread(float spread); template void StatsContainer::setSpread(float spread); template void StatsContainer::setSpread(float spread); //-------------------------------------------------------------------- template float StatsContainer::getSpread() { /// @details /// The spread value returned is determined by the /// StatsContainer::useRobust flag -- it will be either the madfm /// (if true), or the rms (if false). If robust, the madfm will be /// converted to an equivalent rms under the assumption of /// Gaussianity, using the Statistics::madfmToSigma function. if(useRobust) return madfmToSigma(this->madfm); else return this->stddev; } template float StatsContainer::getSpread(); template float StatsContainer::getSpread(); template float StatsContainer::getSpread(); template float StatsContainer::getSpread(); //-------------------------------------------------------------------- template void StatsContainer::scaleNoise(float scale) { /// @details /// Multiply the noise parameters (stddev & madfm) by a given /// factor, and adjust the threshold. float snr = (threshold - this->getMiddle())/this->getSpread(); this->madfm = Type(this->madfm*scale); this->stddev *= scale; this->threshold = this->getMiddle() + snr*this->getSpread(); } template void StatsContainer::scaleNoise(float scale); template void StatsContainer::scaleNoise(float scale); template void StatsContainer::scaleNoise(float scale); template void StatsContainer::scaleNoise(float scale); //-------------------------------------------------------------------- template float StatsContainer::getPValue(float value) { /// @details /// Get the "probability", under the assumption of normality, of a /// value occuring. /// /// It is defined by \f$0.5 \operatorname{erfc}(z/\sqrt{2})\f$, where /// \f$z=(x-\mu)/\sigma\f$. We need the factor of 0.5 here, as we are /// only considering the positive tail of the distribution -- we /// don't care about negative detections. float zStat = (value - this->getMiddle()) / this->getSpread(); return 0.5 * erfc( zStat / M_SQRT2 ); } template float StatsContainer::getPValue(float value); template float StatsContainer::getPValue(float value); template float StatsContainer::getPValue(float value); template float StatsContainer::getPValue(float value); //-------------------------------------------------------------------- template bool StatsContainer::isDetection(float value) { /// @details /// Compares the value given to the correct threshold, depending on /// the value of the StatsContainer::useFDR flag. if(useFDR) return (this->getPValue(value) < this->pThreshold); else return (value > this->threshold); } template bool StatsContainer::isDetection(float value); template bool StatsContainer::isDetection(float value); template bool StatsContainer::isDetection(float value); template bool StatsContainer::isDetection(float value); //-------------------------------------------------------------------- template void StatsContainer::calculate(Type *array, long size) { /// @details /// Calculate all four statistics for all elements of a given /// array. /// /// \param array The input data array. /// \param size The length of the input array // findNormalStats(array, size, this->mean, this->stddev); // findMedianStats(array, size, this->median, this->madfm); findAllStats(array,size,this->mean,this->stddev,this->median,this->madfm); this->defined = true; } template void StatsContainer::calculate(int *array, long size); template void StatsContainer::calculate(long *array, long size); template void StatsContainer::calculate(float *array, long size); template void StatsContainer::calculate(double *array, long size); //-------------------------------------------------------------------- template void StatsContainer::calculate(Type *array, long size, bool *mask) { /// @details /// Calculate all four statistics for a subset of a given /// array. The subset is defined by an array of bool /// variables. /// /// \param array The input data array. /// \param size The length of the input array /// \param mask An array of the same length that says whether to /// include each member of the array in the calculations. Use a /// value if mask=true. // findNormalStats(array, size, mask, this->mean, this->stddev); // findMedianStats(array, size, mask, this->median, this->madfm); findAllStats(array, size, mask, this->mean, this->stddev, this->median, this->madfm); this->defined = true; } template void StatsContainer::calculate(int *array, long size, bool *mask); template void StatsContainer::calculate(long *array, long size, bool *mask); template void StatsContainer::calculate(float *array, long size, bool *mask); template void StatsContainer::calculate(double *array, long size, bool *mask); //-------------------------------------------------------------------- template std::ostream& operator<< (std::ostream& theStream, StatsContainer &s) { /// Prints out the four key statistics to the requested stream. theStream << "Mean = " << s.mean << "\t" << "Std.Dev. = " << s.stddev << "\n" << "Median = " << s.median << "\t" << "MADFM = " << s.madfm << " (= " << madfmToSigma(s.madfm) << " as std.dev.)\n"; return theStream; } template std::ostream& operator<< (std::ostream& theStream, StatsContainer &s); template std::ostream& operator<< (std::ostream& theStream, StatsContainer &s); template std::ostream& operator<< (std::ostream& theStream, StatsContainer &s); template std::ostream& operator<< (std::ostream& theStream, StatsContainer &s); } // matches: namespace Statistics {