-- | Beautiful and practical color schemes, taken from
--
--  * Mathematica: https://www.wolfram.com/mathematica/
--  * Color Brewer 2: https://colorbrewer2.org/
--
-- +-----------------+--------------------------------------------------------------+---------+
-- | Name            |                                                              | Domain  |
-- +=================+==============================================================+=========+
-- | 'mma'           | <<docs/colors/schemes/discrete/mathematica/ColorData97.svg>> | [0..∞)  |
-- +-----------------+--------------------------------------------------------------+---------+
-- | 'accent'        | <<docs/colors/schemes/discrete/colorbrewer2/accent.svg>>     | [0..7]  |
-- +-----------------+--------------------------------------------------------------+---------+
-- | 'dark2'         | <<docs/colors/schemes/discrete/colorbrewer2/dark2.svg>>      | [0..7]  |
-- +-----------------+--------------------------------------------------------------+---------+
-- | 'paired'        | <<docs/colors/schemes/discrete/colorbrewer2/paired.svg>>     | [0..11] |
-- +-----------------+--------------------------------------------------------------+---------+
-- | 'pastel1'       | <<docs/colors/schemes/discrete/colorbrewer2/pastel1.svg>>    | [0..8]  |
-- +-----------------+--------------------------------------------------------------+---------+
-- | 'pastel2'       | <<docs/colors/schemes/discrete/colorbrewer2/pastel2.svg>>    | [0..7]  |
-- +-----------------+--------------------------------------------------------------+---------+
-- | 'set1'          | <<docs/colors/schemes/discrete/colorbrewer2/set1.svg>>       | [0..8]  |
-- +-----------------+--------------------------------------------------------------+---------+
-- | 'set2'          | <<docs/colors/schemes/discrete/colorbrewer2/set2.svg>>       | [0..7]  |
-- +-----------------+--------------------------------------------------------------+---------+
-- | 'set3'          | <<docs/colors/schemes/discrete/colorbrewer2/set3.svg>>       | [0..11] |
-- +-----------------+--------------------------------------------------------------+---------+
module Draw.Color.Schemes.Discrete (
    -- * Mathematica
      mma
    , mathematica97

    -- * Color Brewer 2
    , accent
    , dark2
    , paired
    , pastel1
    , pastel2
    , set1
    , set2
    , set3
) where



import           Data.Vector (Vector, (!), (!?))
import qualified Data.Vector as V

import Draw.Color
import Draw.Color.Schemes.Internal.Common

import qualified Draw.Color.Schemes.Internal.ColorBrewer2 as ColorBrewer2



-- | Mathematica’s ColorData[97] scheme, which I find really nice. Please don’t sue
-- me Steven o:-)
--
-- <<docs/colors/schemes/discrete/mathematica/ColorData97.svg>>
mma :: Int -> Color Double
mma :: Int -> Color Double
mma Int
i = case Vector (Color Double)
mma97cache Vector (Color Double) -> Int -> Maybe (Color Double)
forall a. Vector a -> Int -> Maybe a
!? Int
i of
    Just Color Double
cached -> Color Double
cached
    Maybe (Color Double)
Nothing -> RGB -> Color Double
toColor (Int -> RGB
generateMathematica97 Int
i)

{-# DEPRECATED mathematica97 "Renamed to mma" #-}
mathematica97 :: Int -> Color Double
mathematica97 :: Int -> Color Double
mathematica97 = Int -> Color Double
mma

-- Taken straight out of mathematica, translated to Haskell: @ColorData[97] // FullForm@
generateMathematica97 :: Int -> RGB
generateMathematica97 :: Int -> RGB
generateMathematica97 Int
i
    -- Note that Mathematica *does* allow values of 0, yielding a red-orange
    -- color out of the interpolated section! It starts plots with 1 though.
    | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = [Char] -> RGB
forall a. HasCallStack => [Char] -> a
error ([Char]
"mathematica97 color index out of bounds: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
i)
generateMathematica97 Int
i
    | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
10 = Vector RGB
mma97_constantBeginning Vector RGB -> Int -> RGB
forall a. Vector a -> Int -> a
! Int
i
         -- MMA uses 1-based indexing, hence < instead of <= here.
generateMathematica97 Int
i =
    let (Integer
_, Double
i') = Double -> (Integer, Double)
forall b. Integral b => Double -> (b, Double)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
10) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
goldenRatio)
                ------------------------------- ^^^^
                -- Offset of -1 missing because of Haskell’s 0-based
                -- vs. Mathematica’s 1-based indexing.
        goldenRatio :: Double
goldenRatio = (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double -> Double
forall a. Floating a => a -> a
sqrt Double
5)Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2
    in Vector RGB -> Double -> RGB
cyclic Vector RGB
mma97_interpolating Double
i'

-- For frequent access, we cache the first entries. If later entries are needed,
-- chances are they’re not reused anyway, so why cache them?
mma97cache :: Vector (Color Double)
mma97cache :: Vector (Color Double)
mma97cache = Int -> (Int -> Color Double) -> Vector (Color Double)
forall a. Int -> (Int -> a) -> Vector a
V.generate Int
32 (\Int
i -> RGB -> Color Double
toColor (Int -> RGB
generateMathematica97 Int
i))

-- | The first 10 color values are hardcoded and not interpolated
mma97_constantBeginning :: Vector RGB
mma97_constantBeginning :: Vector RGB
mma97_constantBeginning = [RGB] -> Vector RGB
forall a. [a] -> Vector a
V.fromList
    [ Double -> Double -> Double -> RGB
RGB Double
0.368417 Double
0.506779 Double
0.709798
    , Double -> Double -> Double -> RGB
RGB Double
0.880722 Double
0.611041 Double
0.142051
    , Double -> Double -> Double -> RGB
RGB Double
0.560181 Double
0.691569 Double
0.194885
    , Double -> Double -> Double -> RGB
RGB Double
0.922526 Double
0.385626 Double
0.209179
    , Double -> Double -> Double -> RGB
RGB Double
0.528488 Double
0.470624 Double
0.701351
    , Double -> Double -> Double -> RGB
RGB Double
0.772079 Double
0.431554 Double
0.102387
    , Double -> Double -> Double -> RGB
RGB Double
0.363898 Double
0.618501 Double
0.782349
    , Double -> Double -> Double -> RGB
RGB Double
1        Double
0.75     Double
0
    , Double -> Double -> Double -> RGB
RGB Double
0.647624 Double
0.37816  Double
0.614037
    , Double -> Double -> Double -> RGB
RGB Double
0.571589 Double
0.586483 Double
0
    ]

-- Starting at the 11th value, Mathematica starts picking intermediate colors
-- between a short lookup table
mma97_interpolating :: Vector RGB
mma97_interpolating :: Vector RGB
mma97_interpolating = [RGB] -> Vector RGB
forall a. [a] -> Vector a
V.fromList
    [ Double -> Double -> Double -> RGB
RGB Double
0.915  Double
0.3325 Double
0.2125
    , Double -> Double -> Double -> RGB
RGB Double
0.83   Double
0.46   Double
0
    , Double -> Double -> Double -> RGB
RGB Double
0.9575 Double
0.545  Double
0.11475
    , Double -> Double -> Double -> RGB
RGB Double
1      Double
0.7575 Double
0
    , Double -> Double -> Double -> RGB
RGB Double
0.6175 Double
0.715  Double
0
    , Double -> Double -> Double -> RGB
RGB Double
0.15   Double
0.715  Double
0.595
    , Double -> Double -> Double -> RGB
RGB Double
0.3625 Double
0.545  Double
0.85
    , Double -> Double -> Double -> RGB
RGB Double
0.575  Double
0.4175 Double
0.85
    , Double -> Double -> Double -> RGB
RGB Double
0.677  Double
0.358  Double
0.595
    , Double -> Double -> Double -> RGB
RGB Double
0.7875 Double
0.358  Double
0.425
    , Double -> Double -> Double -> RGB
RGB Double
0.915  Double
0.3325 Double
0.2125
    ]

-- | <<docs/colors/schemes/discrete/colorbrewer2/accent.svg>>
accent :: Int -> Color Double
accent :: Int -> Color Double
accent = RGB -> Color Double
toColor (RGB -> Color Double) -> (Int -> RGB) -> Int -> Color Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector RGB -> Int -> RGB
discreteCyclic Vector RGB
ColorBrewer2.qualitative_Accent

-- | <<docs/colors/schemes/discrete/colorbrewer2/set1.svg>>
set1 :: Int -> Color Double
set1 :: Int -> Color Double
set1 = RGB -> Color Double
toColor (RGB -> Color Double) -> (Int -> RGB) -> Int -> Color Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector RGB -> Int -> RGB
discreteCyclic Vector RGB
ColorBrewer2.qualitative_Set1

-- | <<docs/colors/schemes/discrete/colorbrewer2/set2.svg>>
set2 :: Int -> Color Double
set2 :: Int -> Color Double
set2 = RGB -> Color Double
toColor (RGB -> Color Double) -> (Int -> RGB) -> Int -> Color Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector RGB -> Int -> RGB
discreteCyclic Vector RGB
ColorBrewer2.qualitative_Set2

-- | <<docs/colors/schemes/discrete/colorbrewer2/set3.svg>>
set3 :: Int -> Color Double
set3 :: Int -> Color Double
set3 = RGB -> Color Double
toColor (RGB -> Color Double) -> (Int -> RGB) -> Int -> Color Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector RGB -> Int -> RGB
discreteCyclic Vector RGB
ColorBrewer2.qualitative_Set3

-- | <<docs/colors/schemes/discrete/colorbrewer2/dark2.svg>>
dark2 :: Int -> Color Double
dark2 :: Int -> Color Double
dark2 = RGB -> Color Double
toColor (RGB -> Color Double) -> (Int -> RGB) -> Int -> Color Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector RGB -> Int -> RGB
discreteCyclic Vector RGB
ColorBrewer2.qualitative_Dark2

-- | <<docs/colors/schemes/discrete/colorbrewer2/paired.svg>>
paired :: Int -> Color Double
paired :: Int -> Color Double
paired = RGB -> Color Double
toColor (RGB -> Color Double) -> (Int -> RGB) -> Int -> Color Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector RGB -> Int -> RGB
discreteCyclic Vector RGB
ColorBrewer2.qualitative_Paired

-- | <<docs/colors/schemes/discrete/colorbrewer2/pastel2.svg>>
pastel2 :: Int -> Color Double
pastel2 :: Int -> Color Double
pastel2 = RGB -> Color Double
toColor (RGB -> Color Double) -> (Int -> RGB) -> Int -> Color Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector RGB -> Int -> RGB
discreteCyclic Vector RGB
ColorBrewer2.qualitative_Pastel2

-- | <<docs/colors/schemes/discrete/colorbrewer2/pastel1.svg>>
pastel1 :: Int -> Color Double
pastel1 :: Int -> Color Double
pastel1 = RGB -> Color Double
toColor (RGB -> Color Double) -> (Int -> RGB) -> Int -> Color Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector RGB -> Int -> RGB
discreteCyclic Vector RGB
ColorBrewer2.qualitative_Pastel1