Commits

Bryan O'Sullivan  committed 21fa4d7

Add support for loading and saving analysis info as JSON.

  • Participants
  • Parent commits 2b08b32

Comments (0)

Files changed (3)

File Criterion/Analysis.hs

     ) where
 
 import Control.Monad (when)
+import Criterion.Analysis.Types
 import Criterion.IO (note)
 import Criterion.Measurement (secs)
 import Criterion.Monad (Criterion)
-import Data.Data (Data)
 import Data.Int (Int64)
 import Data.Monoid (Monoid(..))
-import Data.Typeable (Typeable)
 import Statistics.Function (sort)
 import Statistics.Quantile (weightedAvg)
 import Statistics.Resampling (Resample, resample)
 import qualified Data.Vector.Unboxed as U
 import qualified Statistics.Resampling.Bootstrap as B
 
--- | Outliers from sample data, calculated using the boxplot
--- technique.
-data Outliers = Outliers {
-      samplesSeen :: {-# UNPACK #-} !Int64
-    , lowSevere   :: {-# UNPACK #-} !Int64
-    -- ^ More than 3 times the IQR below the first quartile.
-    , lowMild     :: {-# UNPACK #-} !Int64
-    -- ^ Between 1.5 and 3 times the IQR below the first quartile.
-    , highMild    :: {-# UNPACK #-} !Int64
-    -- ^ Between 1.5 and 3 times the IQR above the third quartile.
-    , highSevere  :: {-# UNPACK #-} !Int64
-    -- ^ More than 3 times the IQR above the third quartile.
-    } deriving (Eq, Read, Show, Typeable, Data)
-
--- | A description of the extent to which outliers in the sample data
--- affect the sample mean and standard deviation.
-data OutlierEffect = Unaffected -- ^ Less than 1% effect.
-                   | Slight     -- ^ Between 1% and 10%.
-                   | Moderate   -- ^ Between 10% and 50%.
-                   | Severe     -- ^ Above 50% (i.e. measurements
-                                -- are useless).
-                     deriving (Eq, Ord, Read, Show, Typeable, Data)
-
-instance Monoid Outliers where
-    mempty  = Outliers 0 0 0 0 0
-    mappend = addOutliers
-
-addOutliers :: Outliers -> Outliers -> Outliers
-addOutliers (Outliers s a b c d) (Outliers t w x y z) =
-    Outliers (s+t) (a+w) (b+x) (c+y) (d+z)
-{-# INLINE addOutliers #-}
-
 -- | Classify outliers in a data set, using the boxplot technique.
 classifyOutliers :: Sample -> Outliers
 classifyOutliers sa = U.foldl' ((. outlier) . mappend) mempty ssa
           iqr = q3 - q1
 {-# INLINE classifyOutliers #-}
 
--- | Analysis of the extent to which outliers in a sample affect its
--- mean and standard deviation.
-data OutlierVariance = OutlierVariance {
-      ovEffect   :: OutlierEffect
-    -- ^ Qualitative description of effect.
-    , ovFraction :: Double
-    -- ^ Quantitative description of effect (a fraction between 0 and 1).
-    } deriving (Eq, Read, Show, Typeable, Data)
-
 -- | Compute the extent to which outliers in the sample data affect
 -- the sample mean and standard deviation.
 outlierVariance :: B.Estimate  -- ^ Bootstrap estimate of sample mean.
   noteOutliers . classifyOutliers $ a
   return µ
 
--- | Result of a bootstrap analysis of a non-parametric sample.
-data SampleAnalysis = SampleAnalysis {
-      anMean :: B.Estimate
-    , anStdDev :: B.Estimate
-    , anOutliers :: OutlierVariance
-    } deriving (Eq, Show, Typeable, Data)
-
 -- | Multiply the 'Estimate's in an analysis by the given value, using
 -- 'B.scale'.
 scale :: Double                 -- ^ Value to multiply by.

File Criterion/Analysis/Types.hs

+{-# LANGUAGE DeriveDataTypeable, OverloadedStrings, RecordWildCards #-}
+-- |
+-- Module      : Criterion.Analysis.Types
+-- Copyright   : (c) 2011 Bryan O'Sullivan
+--
+-- License     : BSD-style
+-- Maintainer  : bos@serpentine.com
+-- Stability   : experimental
+-- Portability : GHC
+--
+-- Analysis types.
+
+module Criterion.Analysis.Types
+    (
+      Outliers (..)
+    , OutlierEffect(..)
+    , OutlierVariance(..)
+    , SampleAnalysis(..)
+    ) where
+
+import Control.Applicative ((<$>), (<*>), empty, pure)
+import Data.Aeson.Types
+import Data.Data (Data)
+import Data.Int (Int64)
+import Data.Monoid (Monoid(..))
+import Data.Typeable (Typeable)
+import qualified Statistics.Resampling.Bootstrap as B
+
+-- | Outliers from sample data, calculated using the boxplot
+-- technique.
+data Outliers = Outliers {
+      samplesSeen :: {-# UNPACK #-} !Int64
+    , lowSevere   :: {-# UNPACK #-} !Int64
+    -- ^ More than 3 times the interquartile range (IQR) below the
+    -- first quartile.
+    , lowMild     :: {-# UNPACK #-} !Int64
+    -- ^ Between 1.5 and 3 times the IQR below the first quartile.
+    , highMild    :: {-# UNPACK #-} !Int64
+    -- ^ Between 1.5 and 3 times the IQR above the third quartile.
+    , highSevere  :: {-# UNPACK #-} !Int64
+    -- ^ More than 3 times the IQR above the third quartile.
+    } deriving (Eq, Read, Show, Typeable, Data)
+
+instance ToJSON Outliers where
+    toJSON Outliers{..} = object [
+                            "samplesSeen" .= samplesSeen
+                          , "lowSevere" .= lowSevere
+                          , "lowMild" .= lowMild
+                          , "highMild" .= highMild
+                          , "highSevere" .= highSevere
+                          ]
+
+instance FromJSON Outliers where
+    parseJSON (Object v) = Outliers <$>
+                           v .: "samplesSeen" <*>
+                           v .: "lowSevere" <*>
+                           v .: "lowMild" <*>
+                           v .: "highMild" <*>
+                           v .: "highSevere"
+    parseJSON _ = empty
+
+-- | A description of the extent to which outliers in the sample data
+-- affect the sample mean and standard deviation.
+data OutlierEffect = Unaffected -- ^ Less than 1% effect.
+                   | Slight     -- ^ Between 1% and 10%.
+                   | Moderate   -- ^ Between 10% and 50%.
+                   | Severe     -- ^ Above 50% (i.e. measurements
+                                -- are useless).
+                     deriving (Eq, Ord, Read, Show, Typeable, Data)
+
+instance ToJSON OutlierEffect where
+    toJSON Unaffected = "unaffected"
+    toJSON Slight     = "slight"
+    toJSON Moderate   = "moderate"
+    toJSON Severe     = "severe"
+
+instance FromJSON OutlierEffect where
+    parseJSON (String t) = case t of
+                             _| t== "unaffected" -> pure Unaffected
+                             _| t== "slight"     -> pure Slight
+                             _| t== "moderate"   -> pure Moderate
+                             _| t== "severe"     -> pure Severe
+                              | otherwise        -> empty
+    parseJSON _ = empty
+
+instance Monoid Outliers where
+    mempty  = Outliers 0 0 0 0 0
+    mappend = addOutliers
+
+addOutliers :: Outliers -> Outliers -> Outliers
+addOutliers (Outliers s a b c d) (Outliers t w x y z) =
+    Outliers (s+t) (a+w) (b+x) (c+y) (d+z)
+{-# INLINE addOutliers #-}
+
+-- | Analysis of the extent to which outliers in a sample affect its
+-- mean and standard deviation.
+data OutlierVariance = OutlierVariance {
+      ovEffect   :: OutlierEffect
+    -- ^ Qualitative description of effect.
+    , ovFraction :: Double
+    -- ^ Quantitative description of effect (a fraction between 0 and 1).
+    } deriving (Eq, Read, Show, Typeable, Data)
+
+instance ToJSON OutlierVariance where
+    toJSON OutlierVariance{..} = object [
+                                   "effect" .= ovEffect
+                                 , "fraction" .= ovFraction
+                                 ]
+
+instance FromJSON OutlierVariance where
+    parseJSON (Object v) = OutlierVariance <$>
+                           v .: "effect" <*>
+                           v .: "fraction"
+    parseJSON _ = empty
+
+-- | Result of a bootstrap analysis of a non-parametric sample.
+data SampleAnalysis = SampleAnalysis {
+      anMean :: B.Estimate
+    , anStdDev :: B.Estimate
+    , anOutliers :: OutlierVariance
+    } deriving (Eq, Show, Typeable, Data)
+
+instance ToJSON SampleAnalysis where
+    toJSON SampleAnalysis{..} = object [
+                                  "mean" .= anMean
+                                , "stdDev" .= anStdDev
+                                , "outliers" .= anOutliers
+                                ]
+
+instance FromJSON SampleAnalysis where
+    parseJSON (Object v) = SampleAnalysis <$>
+                           v .: "mean" <*>
+                           v .: "stdDev" <*>
+                           v .: "outliers"
+    parseJSON _ = empty

File criterion.cabal

   exposed-modules:
     Criterion
     Criterion.Analysis
+    Criterion.Analysis.Types
     Criterion.Config
     Criterion.Environment
     Criterion.IO
     Criterion.Types
 
   build-depends:
+    aeson,
     base < 5,
     bytestring >= 0.9 && < 1.0,
     containers,