diff --git a/HReg.cabal b/HReg.cabal deleted file mode 100644 index a56309f..0000000 --- a/HReg.cabal +++ /dev/null @@ -1,34 +0,0 @@ -name: HReg -version: 0.1.0.0 --- synopsis: --- description: -homepage: https://github.com/ptrab/linreg -license: GPL-3 -license-file: LICENSE -author: Philipp Traber -maintainer: example@example.com -copyright: 2018 Author name here -category: Numeric -build-type: Simple -cabal-version: >=1.10 -extra-source-files: README.md - -executable HReg - hs-source-dirs: src/app - main-is: HReg.hs - default-language: Haskell2010 - build-depends: base >= 4.7 && < 5, - text >=1.2.2.0, - attoparsec >=0.13.1.0, - HReg -any - -library - hs-source-dirs: src/lib - build-depends: base >=4.7 && <5, - attoparsec >=0.13.1.0, - text >=1.2.2.0, - time >=1.6.0.0 - exposed-modules: HReg.Numeric, - HReg.Types, - HReg.Parser - default-language: Haskell2010 diff --git a/TimeTest b/TimeTest deleted file mode 100644 index e24bb87..0000000 --- a/TimeTest +++ /dev/null @@ -1 +0,0 @@ -(10.0, 1.0) (20.0, 2.0) (30.0, 3.0) diff --git a/input b/input index 5b634d0..f703a90 100644 --- a/input +++ b/input @@ -1,4 +1,11 @@ -0.01 2.46 0.88 2.33 2.28 2.24 2.21 2.17 2.14 2.11 2.08 2.03 2.02 2.04 1.99 1.95 1.91 1.87 -0.02 4.98 1.73 4.6 4.45 4.31 4.15 4.07 3.97 3.86 3.78 3.7 3.62 3.5 3.39 3.29 3.2 3.13 -0.03 7.45 2.49 6.84 6.47 6.2 5.97 5.76 5.56 5.41 5.27 5.13 5 4.81 4.65 4.5 4.37 4.27 -0.04 9.99 3.26 8.88 8.32 7.9 7.53 7.23 6.97 6.75 6.55 6.36 6.21 5.95 5.73 5.55 5.42 5.29 +t 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0 110.0 120.0 +0.01 0.05 0.06 0.06 0.15 0.17 0.23 0.54 1.23 5.32 4.23 5.02 7.03 kappa0=15.0 kappaInf=14.0 +0.02 0.05 0.06 0.06 0.15 0.17 0.23 0.54 1.23 5.32 4.23 5.02 7.03 kappa0=15.0 kappaInf=14.0 +0.03 0.05 0.06 0.06 0.15 0.17 0.23 0.54 1.23 5.32 4.23 5.02 7.03 kappa0=15.0 kappaInf=14.0 +0.04 0.05 0.06 0.06 0.15 0.17 0.23 0.54 1.23 5.32 4.23 5.02 7.03 kappa0=15.0 kappaInf=14.0 + +t 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0 110.0 120.0 +0.01 0.05 0.06 0.06 0.15 0.17 0.23 0.54 1.23 5.32 4.23 5.02 7.03 kappa0=15.0 kappaInf=14.0 +0.02 0.05 0.06 0.06 0.15 0.17 0.23 0.54 1.23 5.32 4.23 5.02 7.03 kappa0=15.0 kappaInf=14.0 +0.03 0.05 0.06 0.06 0.15 0.17 0.23 0.54 1.23 5.32 4.23 5.02 7.03 kappa0=15.0 kappaInf=14.0 +0.04 0.05 0.06 0.06 0.15 0.17 0.23 0.54 1.23 5.32 4.23 5.02 7.03 kappa0=15.0 kappaInf=14.0 diff --git a/linreg.cabal b/linreg.cabal new file mode 100644 index 0000000..37deacf --- /dev/null +++ b/linreg.cabal @@ -0,0 +1,57 @@ +cabal-version: 1.12 + +-- This file has been generated from package.yaml by hpack version 0.31.1. +-- +-- see: https://github.com/sol/hpack +-- +-- hash: fa0bf8bdd10e604d4f1906b3674014839def0801ad2d850159658cec73d30778 + +name: linreg +version: 0.1.0.0 +description: Fitting ester hydrolysis kinetics correctly +homepage: https://github.com/ptrab/linreg#readme +bug-reports: https://github.com/ptrab/linreg/issues +author: Philipp Traber +maintainer: phillip.traber@uni-jena.de +copyright: 2019 Philipp Traber +license: GPL-3 +license-file: LICENSE +build-type: Simple +extra-source-files: + LICENSE + +source-repository head + type: git + location: https://github.com/ptrab/linreg + +library + exposed-modules: + Linreg.Numeric + Linreg.Parser + Linreg.Types + other-modules: + Paths_linreg + hs-source-dirs: + src/lib + ghc-options: -optP-Wno-nonportable-include-path -O2 -Wall -Wno-unused-top-binds -Wno-unused-local-binds -Wno-type-defaults + build-depends: + attoparsec >=0.13.2.2 + , base >=4.7 && <5 + , text >=1.2.3.1 + , time >=1.8.0.2 + default-language: Haskell2010 + +executable exckel + main-is: linreg.hs + other-modules: + Paths_linreg + hs-source-dirs: + src/app + ghc-options: -threaded -rtsopts -with-rtsopts=-N -optP-Wno-nonportable-include-path -O2 -Wall -Wno-unused-top-binds -Wno-unused-local-binds -Wno-type-defaults + build-depends: + attoparsec >=0.13.2.2 + , base >=4.7 && <5 + , linreg + , text >=1.2.3.1 + , time >=1.8.0.2 + default-language: Haskell2010 diff --git a/package.yaml b/package.yaml new file mode 100644 index 0000000..05ef94c --- /dev/null +++ b/package.yaml @@ -0,0 +1,62 @@ +name: linreg +version: 0.1.0.0 +github: "ptrab/linreg" +license: GPL-3 +author: "Philipp Traber" +maintainer: "phillip.traber@uni-jena.de" +copyright: "2019 Philipp Traber" + +extra-source-files: + - LICENSE + +# Metadata used when publishing your package +# synopsis: Short description of your package +# category: Web + +# To avoid duplicated efforts in documentation and dealing with the +# complications of embedding Haddock markup inside cabal files, it is +# common to point users to the README.md file. +description: Fitting ester hydrolysis kinetics correctly + +dependencies: + - base >= 4.7 && < 5 + - text >= 1.2.3.1 + - attoparsec >= 0.13.2.2 + - time >= 1.8.0.2 + +library: + source-dirs: src/lib + ghc-options: + - -optP-Wno-nonportable-include-path + - -O2 + - -Wall + - -Wno-unused-top-binds + - -Wno-unused-local-binds + - -Wno-type-defaults + # - -static + # - -fPIC + # - -optl-static + # - -optl-pthread + #- -optc-static + +executables: + exckel: + main: linreg.hs + source-dirs: src/app + ghc-options: + - -threaded + - -rtsopts + - -with-rtsopts=-N + - -optP-Wno-nonportable-include-path + - -O2 + - -Wall + - -Wno-unused-top-binds + - -Wno-unused-local-binds + - -Wno-type-defaults + # - -static + # - -fPIC + # - -optl-static + # - -optl-pthread + #- -optc-static + dependencies: + - linreg diff --git a/src/app/HReg.hs b/src/app/linreg.hs similarity index 79% rename from src/app/HReg.hs rename to src/app/linreg.hs index 99d7b55..5ea69f9 100644 --- a/src/app/HReg.hs +++ b/src/app/linreg.hs @@ -1,14 +1,14 @@ import Data.Attoparsec.Text.Lazy import qualified Data.Text.IO as T -import HReg.Numeric -import HReg.Parser +import Linreg.Numeric +import Linreg.Parser import System.Environment main :: IO () main = do inputFilePath <- head <$> getArgs rawVals <- T.readFile inputFilePath - let vals = parseOnly (many1 parse_LinRegValues) rawVals + let vals = concat <$> parseOnly (many1 linRegValues) rawVals results = regression <$> vals case results of Right (Just x) -> putStr $ show x diff --git a/src/lib/HReg/Parser.hs b/src/lib/HReg/Parser.hs deleted file mode 100644 index ac72435..0000000 --- a/src/lib/HReg/Parser.hs +++ /dev/null @@ -1,59 +0,0 @@ -module HReg.Parser -( parse_LinRegValues -) where -import Data.Attoparsec.Text.Lazy -import qualified Data.Text as T -import qualified Data.Text.IO as T -import HReg.Types -import Control.Applicative -import Data.Time - --- | Parse the input file. It contains in a very simple format: --- | c (first value in row) --- | kappa0 (second value in row) --- | kappaInf (third value in row) --- | kappaT (many values, possibly associated with a time. If no time is --- | there, than it shall be a whitespace seperated double. --- | If time is there it shall follow the format "(Seconds, kappaT)" -parse_LinRegValues :: Parser LinRegValues -parse_LinRegValues = do - c' <- double - _ <- many1 $ char ' ' <|> char '\t' - - kappa0' <- double - _ <- many1 $ char ' ' <|> char '\t' - - kappaInf' <- double - _ <- many1 $ char ' ' <|> char '\t' - - kappaT' <- many1 parse_kappaT - - endOfLine - - return LinRegValues - { c = c' - , kappa0 = kappa0' - , kappaInf = kappaInf' - , kappaT = kappaT' - } - - where - parse_kappaT :: Parser (Maybe DiffTime, Double) - parse_kappaT = do - hasTime <- option Nothing (Just <$> char '(') - case hasTime of - Nothing -> do - kappaT' <- double - _ <- many' $ char ' ' <|> char '\t' - return (Nothing, kappaT') - Just x -> do - _ <- many' $ char ' ' <|> char '\t' - time' <- secondsToDiffTime <$> decimal - _ <- many' $ char ' ' <|> char '\t' - _ <- many' $ char ',' - _ <- many' $ char ' ' <|> char '\t' - kappaT' <- double - _ <- many' $ char ' ' <|> char '\t' - _ <- char ')' - _ <- many' $ char ' ' <|> char '\t' - return (Just time', kappaT') diff --git a/src/lib/HReg/Numeric.hs b/src/lib/Linreg/Numeric.hs similarity index 87% rename from src/lib/HReg/Numeric.hs rename to src/lib/Linreg/Numeric.hs index 1967bd9..69ba8ae 100644 --- a/src/lib/HReg/Numeric.hs +++ b/src/lib/Linreg/Numeric.hs @@ -1,10 +1,9 @@ -module HReg.Numeric +module Linreg.Numeric ( regression ) where import Data.List -import Data.Maybe import Data.Time -import HReg.Types +import Linreg.Types -------------------------------------------------------------------------------- -- helper functions @@ -31,7 +30,7 @@ genT i -- regression logic -------------------------------------------------------------------------------- -- | calculate c0/c = (kappa0 - kappaInf) / (kappaT - kappaInf) -c0pc :: LinRegValues -> [(Maybe DiffTime, Double)] +c0pc :: LinRegValues -> [(DiffTime, Double)] c0pc vals = [ (fst i, (kappa0' - kappaInf') / (snd i - kappaInf')) | i <- kappaT' @@ -49,17 +48,17 @@ sumY y = sum . concat $ y -- | Calculates the sum over the c*x products -- | sum_i^n sum_j^m c_j x_i sumCX :: (Num a) => [a] -> [a] -> a -sumCX c x = sum $ (*) <$> c <*> x +sumCX c' x = sum $ (*) <$> c' <*> x -- | Sum of all squared c and x values -- | sum_i^n sum_j^m c_j^2 x_i^2 sumC2X2 :: (Num a) => [a] -> [a] -> a -sumC2X2 c x = sum $ (*) <$> map (^2) c <*> map (^2) x +sumC2X2 c' x = sum $ (*) <$> map (^2) c' <*> map (^2) x -- | Zipping products -- | sum_i^n sum_j^m c_j x_i y_ij sumCXY :: (Num a) => [a] -> [a] -> [[a]] -> a -sumCXY c x y = sum $ zipWith (*) ((*) <$> c <*> x) (concat y) +sumCXY c' x y = sum $ zipWith (*) ((*) <$> c' <*> x) (concat y) -- | Mean of a list -- | sum_i^n x_i / n @@ -103,14 +102,10 @@ regression vals -- c' = map c vals mVals = map c0pc vals - t' = nub . map (map $ fmap ((/10^12) . fromIntegral . diffTimeToPicoseconds) . fst) $ mVals + t' = nub . map (map $ (/10^12) . fromIntegral . diffTimeToPicoseconds . fst) $ mVals timesAllTheSame = length t' == 1 t'' = head t' - t''' = - [ fromMaybe (genT i) (t'' !! i) - | i <- [0 .. length t'' - 1] - ] - x' = t''' + x' = t'' y' = map (map snd) mVals sCX = sumCX c' x' sCXY = sumCXY c' x' y' diff --git a/src/lib/Linreg/Parser.hs b/src/lib/Linreg/Parser.hs new file mode 100644 index 0000000..c409438 --- /dev/null +++ b/src/lib/Linreg/Parser.hs @@ -0,0 +1,54 @@ +{-# LANGUAGE OverloadedStrings #-} +module Linreg.Parser +( linRegValues +) where +import Data.Attoparsec.Text.Lazy +import Data.Time +import Linreg.Types +import Prelude hiding (takeWhile) + +-- | Parsing a single block with same "t" as shown in this repository (see "input" file). +linRegValues :: Parser [LinRegValues] +linRegValues = do + -- Parse first line of a block, starting with a "t", followed by many times in seconds + timeSeries <- do + skipSpace + _ <- string "t" + _ <- takeWhile isHorizontalSpace + times <- many1 $ do + time <- double + _ <- takeWhile isHorizontalSpace + return time + endOfLine + return times + -- Parse multiple lines of concentration series. First number is c0, then followed by + -- (length times) concentrations corresponding to the times and then kappa0 and kappaInf + linregSeries <- many1 $ do + _ <- takeWhile isHorizontalSpace + c' <- double + _ <- takeWhile isHorizontalSpace + kappaT' <- count (length timeSeries) $ do + cAtTime <- double + _ <- takeWhile isHorizontalSpace + return cAtTime + _ <- takeWhile isHorizontalSpace + _ <- string "kappa0" + _ <- takeWhile isHorizontalSpace + _ <- string "=" + _ <- takeWhile isHorizontalSpace + kappa0' <- double + _ <- takeWhile isHorizontalSpace + _ <- string "kappaInf" + _ <- takeWhile isHorizontalSpace + _ <- string "=" + _ <- takeWhile isHorizontalSpace + kappaInf' <- double + _ <- takeWhile isHorizontalSpace + endOfLine + return LinRegValues + { c = c' + , kappa0 = kappa0' + , kappaInf = kappaInf' + , kappaT = zip (map (picosecondsToDiffTime . (* 10^12) . round) $ timeSeries) kappaT' + } + return linregSeries diff --git a/src/lib/HReg/Types.hs b/src/lib/Linreg/Types.hs similarity index 84% rename from src/lib/HReg/Types.hs rename to src/lib/Linreg/Types.hs index 6d60895..f4e8b5d 100644 --- a/src/lib/HReg/Types.hs +++ b/src/lib/Linreg/Types.hs @@ -1,9 +1,8 @@ -module HReg.Types +module Linreg.Types ( LinRegValues(..) , RegressionResult(..) ) where import Data.Time -import Data.Text import Text.Printf -- | what we get from the measurements @@ -11,8 +10,7 @@ data LinRegValues = LinRegValues { c :: Double -- concentration of this series , kappa0 :: Double , kappaInf :: Double - , kappaT :: [(Maybe DiffTime, Double)] -- the optional time and corresping - -- kappa_t + , kappaT :: [(DiffTime, Double)] -- the time and corresping kappa_t } -- | what we calculate by regression from the measurements diff --git a/stack.yaml b/stack.yaml index 19b0f4c..c38241c 100644 --- a/stack.yaml +++ b/stack.yaml @@ -18,7 +18,7 @@ # # resolver: ./custom-snapshot.yaml # resolver: https://example.com/snapshots/2018-01-01.yaml -resolver: lts-12.1 +resolver: lts-13.14 # User packages to be built. # Various formats can be used as shown in the example below.