Giter VIP home page Giter VIP logo

almanac's Introduction

Almanac

Utilities for processing pre-calculated Ephemeris data (see swiss-ephemeris.) Given an interval and a set of queries, it will efficiently traverse precalculated ephemeris in daily increments, or do faster interpolation of regular ephemeris data for certain queries like moon events and eclipses, and return a Seq of Events. One can then choose to inspect the extracted events to calculate when exactly they happen -- this is recommended as an extra step, only on demand, since the exactitude calculation needs to do some numerical interpolation, vs. simple fast daily perusal.

Since the main use case is to get a sequence of events and presumably examine them, Lenses and Traversals are provided in the Almanac.Optics module to help in the otherwise tiresome deep pattern matching that could ensue. Note that there's no dependency on any actual lens-like library, so you'll have to bring your own to actually do "lens stuff" with the provided optics. To illustrate how the provided optics can be brought to life with a lens library, the tests use microlens. I have only added the most obvious lenses and traversals (no Prisms, since I don't foresee any "construction" happening and thus Traversals do the job nicely and that obviates the need for a dependency on profunctors.)

To use this library, you'll have to get ahold of ephemeris files; you'll also need precalculated ephemeris, which are not officially distributed by astro.com, but I've put a couple of centuries of precalculated ephemeris in this project's test/ephe/ directory that you can just copy (they're tiny files.) Functions to generate precalculated ephemeris are also provided by swiss-ephemeris, here's some example usage from laboratorium, which can be run as a CLI.

With those in place, here's some example usage:

import Almanac
import Almanac.Optics
import Control.Applicative 
import Data.Time 
-- You can use any `lens`-compatible library here.
import Lens.Micro
import System.Directory (makeAbsolute)

lunarPhasesAndEclipses :: IO [(String, UTCTime)]
lunarPhasesAndEclipses = do
  let nov2021 = UTCTime (fromGregorian 2021 11 1) 0
      dec2021 = UTCTime (fromGregorian 2021 12 1) 0
      q = mundane
            (Interval nov2021 dec2021)
            [QueryLunarPhase, QueryEclipse] 

  -- Get events, then calculate the exact moment they happen
  exactEvents <- runQuery q >>= eventsWithExactitude

  -- For each event, get the phase name (if it's a lunar phase,)
  -- or the eclipse type (only when it's a lunar eclipse,) as well
  -- as the moment of exactitude. Using optics to deal with the
  -- annoying pattern matching that would ensue.
  let digest = (summarize <$> exactEvents) ^.. traversed . _Just
      summarize evt = 
        let phaseName = show <$> evt ^? eventL._LunarPhaseInfo.lunarPhaseNameL
            eclType   = show <$> evt ^? eventL._EclipseInfo._LunarEclipseType
            exactAt   = evt ^? exactitudeMomentsL._head
        in liftA2 (,) (phaseName <|> eclType) exactAt
  pure digest  

-- NOTE: as mentioned in @swiss-ephemeris@, in a production application
-- you're better off setting environment variables with the location of the
-- ephemeris directory --  it's unnecessary and potentially thread-unsafe
-- in the presence of laziness to set them programmatically.
main :: IO ()
  fullEphePath <- makeAbsolute "./my-ephe"
  -- location of ephe data
  setEphemeridesPath fullEphePath
  -- location of precalculated ephe
  setEphe4Path fullEphePath

  lunarPhasesAndEclipses >>= print
  
{- 
  Would print something like 
[
  ("WaningCrescent","2021-11-01T13:28:27.314121723175Z"),
  ("NewMoon","2021-11-04T21:14:36.684200763702Z"),
  ("WaxingCrescent","2021-11-08T02:31:28.868464529514Z"),
  ("FirstQuarter","2021-11-11T12:46:02.566146254539Z"),
  ("WaxingGibbous","2021-11-15T07:27:48.519482016563Z"),
  ("FullMoon","2021-11-19T08:57:27.984892129898Z"),
  ("PartialLunarEclipse","2021-11-19T09:02:55.849740207195Z")
  ("WaningGibbous","2021-11-23T12:50:27.58442312479Z"),
  ("LastQuarter","2021-11-27T12:27:40.648325085639Z")
]
-}

See the test directory for more examples: planetary ingresses, changes of direction, transits and queries relevant to a "natal" reference event are provided.

This library was incubated in my laboratorium, with some further refinements.

almanac's People

Contributors

lfborjas avatar

Stargazers

Jared Ramirez avatar Jason avatar mattsee avatar kaplan avatar

Watchers

 avatar James Cloos avatar

almanac's Issues

consider adding lenses and traversals

Would make traversing events easier, though we probably want monomorphic lenses/traversals|prisms -- need to think about it more to provide an ergonomic interface.

some exploratory code:

{-#LANGUAGE TemplateHaskell #-}

module Almanac.Lens where
import Lens.Micro.TH
import Lens.Micro

data FooInfo =
  FooInfo {_a :: Int, _b :: String}
  deriving (Show)

makeLenses ''FooInfo

data BarInfo =
  BarInfo {_x :: Double, _y :: Double, _z :: Double}
  deriving (Show)
  
makeLenses ''BarInfo

data FooBar
  = Foo FooInfo
  | Bar BarInfo
  deriving (Show)
  
_Foo :: Traversal' FooBar FooInfo
_Foo f (Foo info) = Foo <$> f info
_Foo _ (Bar info) = pure $ Bar info

_Bar :: Traversal' FooBar BarInfo 
_Bar _ (Foo info) = pure $ Foo info
_Bar f (Bar info) = Bar <$> f info

 
makeLenses ''FooBar 
  
  
{-
example ^.. each._Bar.y
[2.0]
-}
example :: [FooBar]
example = [Foo (FooInfo 1 "2"), Bar (BarInfo 1 2 3)]

{-
example2 ^.. each._1._Foo.b
-}
example2 :: [(FooBar, Int)]
example2 = zip example [1,2]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.