packages feed

isotope 0.4.0.0 → 0.5.0.0

raw patch · 7 files changed

+145/−6 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Isotope: charge :: ToElementalComposition a => a -> Maybe Charge
+ Isotope.Ion: Deprotonated :: a -> Deprotonated a
+ Isotope.Ion: Mz :: Double -> Mz
+ Isotope.Ion: Negative :: Polarity
+ Isotope.Ion: Positive :: Polarity
+ Isotope.Ion: Protonated :: a -> Protonated a
+ Isotope.Ion: [getMz] :: Mz -> Double
+ Isotope.Ion: class ToElementalComposition a => Ion a where mz a = Mz . abs $ monoisotopicMass' / charge' where monoisotopicMass' = getMonoisotopicMass $ monoisotopicMass a charge' = let charge'' = fromMaybe 0 (charge a) in if charge'' /= 0 then fromIntegral charge'' else error "An ion can't have a charge of 0!" polarity a = polarity' $ fromMaybe 0 (charge a) where polarity' c | c > 0 = Positive | c < 0 = Negative | c == 0 = error "An ion can't have a charge of 0!"
+ Isotope.Ion: data Polarity
+ Isotope.Ion: doublyDeprotonated :: a -> Deprotonated (Deprotonated a)
+ Isotope.Ion: doublyProtonated :: a -> Protonated (Protonated a)
+ Isotope.Ion: instance GHC.Classes.Eq Isotope.Ion.Mz
+ Isotope.Ion: instance GHC.Classes.Eq Isotope.Ion.Polarity
+ Isotope.Ion: instance GHC.Classes.Eq a => GHC.Classes.Eq (Isotope.Ion.Deprotonated a)
+ Isotope.Ion: instance GHC.Classes.Eq a => GHC.Classes.Eq (Isotope.Ion.Protonated a)
+ Isotope.Ion: instance GHC.Classes.Ord Isotope.Ion.Mz
+ Isotope.Ion: instance GHC.Classes.Ord Isotope.Ion.Polarity
+ Isotope.Ion: instance GHC.Classes.Ord a => GHC.Classes.Ord (Isotope.Ion.Deprotonated a)
+ Isotope.Ion: instance GHC.Classes.Ord a => GHC.Classes.Ord (Isotope.Ion.Protonated a)
+ Isotope.Ion: instance GHC.Read.Read Isotope.Ion.Mz
+ Isotope.Ion: instance GHC.Read.Read Isotope.Ion.Polarity
+ Isotope.Ion: instance GHC.Read.Read a => GHC.Read.Read (Isotope.Ion.Deprotonated a)
+ Isotope.Ion: instance GHC.Read.Read a => GHC.Read.Read (Isotope.Ion.Protonated a)
+ Isotope.Ion: instance GHC.Show.Show Isotope.Ion.Mz
+ Isotope.Ion: instance GHC.Show.Show Isotope.Ion.Polarity
+ Isotope.Ion: instance GHC.Show.Show a => GHC.Show.Show (Isotope.Ion.Deprotonated a)
+ Isotope.Ion: instance GHC.Show.Show a => GHC.Show.Show (Isotope.Ion.Protonated a)
+ Isotope.Ion: instance Isotope.Base.ToElementalComposition a => Isotope.Base.ToElementalComposition (Isotope.Ion.Deprotonated a)
+ Isotope.Ion: instance Isotope.Base.ToElementalComposition a => Isotope.Base.ToElementalComposition (Isotope.Ion.Protonated a)
+ Isotope.Ion: instance Isotope.Base.ToElementalComposition a => Isotope.Ion.Ion (Isotope.Ion.Deprotonated a)
+ Isotope.Ion: instance Isotope.Base.ToElementalComposition a => Isotope.Ion.Ion (Isotope.Ion.Protonated a)
+ Isotope.Ion: mz :: Ion a => a -> Mz
+ Isotope.Ion: newtype Deprotonated a
+ Isotope.Ion: newtype Mz
+ Isotope.Ion: newtype Protonated a
+ Isotope.Ion: polarity :: Ion a => a -> Polarity

Files

README.md view
@@ -1,5 +1,5 @@ [![Build Status](https://travis-ci.org/Michaelt293/isotope.svg?branch=master)](https://travis-ci.org/Michaelt293/isotope)-[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/Michaelt293/isotope)+[![Gitter](https://badges.gitter.im/Michaelt293/isotope.svg)](https://gitter.im/Michaelt293/isotope)  ![alt tag](https://github.com/Michaelt293/isotope/blob/master/isotope_jpeg.jpg) @@ -13,6 +13,7 @@     * [ToElementalComposition type class](#elementalcomposition-type-class)     * [Behaviour of ElementalComposition, MolecularFormula, CondensedFormula and EmpiricalFormula data types](#behaviour-of-elementalcomposition-molecularformula-condensedformula-and-empiricalformula-data-types)     * [Additional functions accepting an ElementSymbol as input](#additional-functions-accepting-an-elementsymbol-as-input)+    * [Representing ions in Isotope](#representing-ions-in-isotope) * [Comparison to other chemistry libraries](#comparison-to-other-chemistry-libraries)     * [Radium](#radium)     * [Ouch](#ouch)@@ -108,13 +109,13 @@  ### `ToElementalComposition` type class -`ToElementalComposition` is a superclass of `ToMolecularFormula`, `ToCondensedFormula` and `ToEmpiricalFormula`. In addition to the `toElementalComposition` method, the `ToElementalComposition` type class has three other methods; `monoisotopicMass`, `nominalMass` and `averageMass`. (`toElementalComposition` is the minimal complete definition.) `ElementSymbol`, `ElementalComposition`, `MolecularFormula`, `CondensedFormula` and `EmpiricalFormula` all have instances of `ToElementalComposition`. This provides a uniform approach to working with elements, elemental compositions, molecular formulae, condensed formulae and empirical formulae.+`ToElementalComposition` is a superclass of `ToMolecularFormula`, `ToCondensedFormula` and `ToEmpiricalFormula`. In addition to the `toElementalComposition` method, the `ToElementalComposition` type class has four other methods; `charge`, `monoisotopicMass`, `nominalMass` and `averageMass`. (`toElementalComposition` and `charge` is the minimal complete definition.) `ElementSymbol`, `ElementalComposition`, `MolecularFormula`, `CondensedFormula` and `EmpiricalFormula` all have instances of `ToElementalComposition`. This provides a uniform approach to working with elements, elemental compositions, molecular formulae, condensed formulae and empirical formulae. ```haskell ghci> nominalMass C NominalMass {getNominalMass = 12} ghci> averageMass [mol|CH4|] AverageMass {getAverageMass = 16.042498912958358}-ghci> monoisotopicMass [mol|N(CH3)3|]+ghci> monoisotopicMass [con|N(CH3)3|] MonoisotopicMass {getMonoisotopicMass = 59.073499294499996} ``` @@ -156,6 +157,36 @@ ```haskell ghci> isotopicMasses Ti [IsotopicMass {getIsotopicMass = 45.95262772},IsotopicMass {getIsotopicMass = 46.95175879},IsotopicMass {getIsotopicMass = 47.94794198},IsotopicMass {getIsotopicMass = 48.94786568},IsotopicMass {getIsotopicMass = 49.94478689}]+```++### Representing ions in Isotope++Ions are represented in `Isotope` using the `Ion` type class. The `Ion` type class has two methods, `mz` and `polarity`; where `mz` is mass-to-charge ratio and `polarity` is either `Positive` or `Negative`. Any type with an `ToElementalComposition` instance can have an `Ion` instance if charge is not equal to zero. If charge is equal to zero, a runtime exception will occur! Ideally, the type system should be put better use to catch this error at compile-time.++```haskell+data Ammonium = Ammonium deriving Show++instance ToElementalComposition Ammonium where+  toElementalComposition _ = mkElementalComposition [(N, 1), (H, 4)]+  charge _ = 1++instance Ion Ammonium++ghci> mz Ammonium+Mz {getMz = 18.03437413335}+```++`Protonated` and `Deprotonated` types, with `Ion` instances, are provided to represent protonated and deprotonated ions, respectively.++```haskell+ghci> mz . Protonated $ mkMolecularFormula [(H, 2), (O, 1)]+Mz {getMz = 19.01838971626}+ghci> mz . Deprotonated $ mkMolecularFormula [(H, 2), (O, 1)]+Mz {getMz = 17.0027396518}+ghci> polarity . Protonated $ mkMolecularFormula [(H, 2), (O, 1)]+Positive+ghci> polarity . Deprotonated $ mkMolecularFormula [(H, 2), (O, 1)]+Negative ```  ## Comparison to other chemistry libraries
isotope.cabal view
@@ -1,5 +1,5 @@ name:                isotope-version:             0.4.0.0+version:             0.5.0.0 synopsis:            Isotopic masses and relative abundances. description:         Please see README.md homepage:            https://github.com/Michaelt293/Element-isotopes/blob/master/README.md@@ -18,6 +18,7 @@   exposed-modules:     Isotope                      , Isotope.Base                      , Isotope.Parsers+                     , Isotope.Ion   build-depends:       base >= 4.7 && < 5                      , containers >= 0.5 && < 0.6                      , megaparsec >= 5 && < 6@@ -37,5 +38,6 @@                      , megaparsec   other-modules:       Isotope.BaseSpec                      , Isotope.ParsersSpec+                     , Isotope.IonSpec   ghc-options:         -threaded -rtsopts -with-rtsopts=-N   default-language:    Haskell2010
src/Isotope/Base.hs view
@@ -189,6 +189,8 @@ -- neutron number) for an isotope. type MassNumber        = Int +type Charge            = Int+ --------------------------------------------------------------------------------  -- 'Isotope' and 'Element' data types@@ -638,13 +640,14 @@ -- 'monoisotopicMass', 'nominalMass' and 'averageMass'. class ToElementalComposition a where      toElementalComposition :: a -> ElementalComposition+     charge                 :: a -> Maybe Charge      monoisotopicMass       :: a -> MonoisotopicMass      nominalMass            :: a -> NominalMass      averageMass            :: a -> AverageMass      monoisotopicMass = getFormulaSum elementMonoisotopicMass      nominalMass      = getFormulaSum elementNominalMass      averageMass      = getFormulaSum elementAverageMass-     {-# MINIMAL (toElementalComposition) #-}+     {-# MINIMAL (toElementalComposition, charge) #-}  -- Helper function for the calculating monoistopic masses, average mass and -- nominal masses for molecular formulae.@@ -672,9 +675,11 @@  instance ToElementalComposition ElementSymbol where     toElementalComposition sym = mkElementalComposition [(sym, 1)]+    charge _ = Nothing  instance ToElementalComposition ElementalComposition where   toElementalComposition = id+  charge _ = Nothing  instance Formula ElementalComposition where    renderFormula f = foldMap renderFoldfunc@@ -742,6 +747,7 @@  instance ToElementalComposition MolecularFormula where     toElementalComposition (MolecularFormula m) = ElementalComposition m+    charge _ = Nothing  instance Formula MolecularFormula where    renderFormula f = foldMap renderFoldfunc@@ -766,6 +772,7 @@ instance ToElementalComposition CondensedFormula where     toElementalComposition =       ElementalComposition . getMolecularFormula . toMolecularFormula+    charge _ = Nothing  instance ToMolecularFormula CondensedFormula where     toMolecularFormula c = foldMap foldFunc (getCondensedFormula c)@@ -814,6 +821,7 @@  instance ToElementalComposition EmpiricalFormula where   toElementalComposition (EmpiricalFormula a) = ElementalComposition a+  charge _ = Nothing  instance Formula EmpiricalFormula where    renderFormula f = foldMap renderFoldfunc
+ src/Isotope/Ion.hs view
@@ -0,0 +1,70 @@+{-|+Module      : Isotope.Ion+Description : Provides support for ions.+Copyright   : Michael Thomas+License     : GPL-3+Maintainer  : Michael Thomas <Michaelt293@gmail.com>+Stability   : Experimental++This module allows the mass-to-charge ratio and polarity of ions to be+calculated.+-}+module Isotope.Ion where++import Isotope.Base+import Data.Maybe (fromMaybe)+import Data.Monoid++-- | The polarity of a charge. A charge can be either `Positive` or `Negative`.+data Polarity = Positive | Negative+  deriving (Show, Read, Eq, Ord)++-- | The mass-to-charge ratio of an ion.+newtype Mz = Mz { getMz :: Double }+  deriving (Show, Read, Eq, Ord)++-- | The `Ion` type class. This type class has two methods: `mz` and `polarity`.+class ToElementalComposition a => Ion a where+  mz :: a -> Mz+  polarity :: a -> Polarity+  mz a = Mz . abs $ monoisotopicMass' / charge'+   where+     monoisotopicMass' = getMonoisotopicMass $ monoisotopicMass a+     charge' = let charge'' = fromMaybe 0 (charge a)+               in if charge'' /= 0+                 then fromIntegral charge''+                 else error "An ion can't have a charge of 0!"+  polarity a = polarity' $ fromMaybe 0 (charge a)+    where+      polarity' c+        | c > 0 = Positive+        | c < 0 = Negative+        | c == 0 = error "An ion can't have a charge of 0!"++-- | Protonated represents a protonated ion.+newtype Protonated a = Protonated a deriving (Show, Read, Eq, Ord)++instance ToElementalComposition a => ToElementalComposition (Protonated a) where+  toElementalComposition (Protonated a) = toElementalComposition a |+|+                                          mkElementalComposition [(H, 1)]+  charge (Protonated a) = getSum <$> Just (Sum 1) <> (Sum <$> charge a)++instance ToElementalComposition a => Ion (Protonated a)++-- | `doublyProtonated` takes a type and returns a doubly `Protonated` ion.+doublyProtonated :: a -> Protonated (Protonated a)+doublyProtonated = Protonated . Protonated++-- | `Deprotonated` represents a deprotonated ion.+newtype Deprotonated a = Deprotonated a deriving (Show, Read, Eq, Ord)++instance ToElementalComposition a => ToElementalComposition (Deprotonated a) where+  toElementalComposition (Deprotonated a) = toElementalComposition a |-|+                                            mkElementalComposition [(H, 1)]+  charge (Deprotonated a) = getSum <$> Just (Sum (-1)) <> (Sum <$> charge a)++instance ToElementalComposition a => Ion (Deprotonated a)++-- | `doublyDeprotonated` takes a type and returns a doubly `Deprotonated` ion.+doublyDeprotonated :: a -> Deprotonated (Deprotonated a)+doublyDeprotonated = Deprotonated . Deprotonated
test/Isotope/BaseSpec.hs view
@@ -115,6 +115,8 @@     describe "ToElementalComposition - ElementalComposition instance" $ do       it "toElementalComposition" . property $         \ec -> toElementalComposition ec == (ec :: ElementalComposition)+      it "charge of an elemental composition should Just 0" . property $+        \ec -> charge (ec :: ElementalComposition) == Nothing       it "monoisotopic mass of ethanol" $         withinTolerance (getMonoisotopicMass (monoisotopicMass [ele|C2H6O|])) 46.04186 0.0001         `shouldBe` True@@ -130,9 +132,11 @@       it "should give the correct formula" $         mkElementalComposition [(C, 2), (H, 6), (O, 1)] `shouldBe` [ele|C2H6O|] -    describe "ToElementalComposition - ElementSymbol instance" .+    describe "ToElementalComposition - ElementSymbol instance" $ do       it "monoisotopicMass" . property $         \sym -> monoisotopicMass sym == monoisotopicMass (mkElementalComposition [(sym, 1)])+      it "charge of a symbol should be Just 0" . property $+        \sym -> charge (sym :: ElementSymbol) == Nothing      describe "Monoid instance for MolecularFormula" $ do       it "associativity" . property $
+ test/Isotope/IonSpec.hs view
@@ -0,0 +1,22 @@+module Isotope.IonSpec (spec) where++import Isotope+import Isotope.Ion+import Test.Hspec++spec :: Spec+spec = do+  describe "mz" $ do+    it "The mass-to-charge ratio of protonated water should be 19.01838971626" $+      mz (Protonated water) `shouldBe` Mz {getMz = 19.01838971626}+    it "The mass-to-charge ratio of deprotonated water should be 17.0027396518" $+      mz (Deprotonated water) `shouldBe` Mz {getMz = 17.0027396518}++  describe "polarity" $ do+    it "The polarity of protonated water should be Positive" $+      polarity (Protonated water) `shouldBe` Positive+    it "The polarity of deprotonated water should be Negative" $+      polarity (Deprotonated water) `shouldBe` Negative++water :: MolecularFormula+water = mkMolecularFormula [(H, 2), (O, 1)]
test/Spec.hs view
@@ -4,8 +4,10 @@ import Test.QuickCheck import Isotope.BaseSpec import Isotope.ParsersSpec+import Isotope.IonSpec  main :: IO () main = hspec $ do   describe "Base" Isotope.BaseSpec.spec   describe "Parsers" Isotope.ParsersSpec.spec+  describe "Ion" Isotope.IonSpec.spec