{-# LANGUAGE OverloadedStrings #-} {-| Module : Graphics.Vega.VegaLite.Scale Copyright : (c) Douglas Burke, 2018-2021 License : BSD3 Maintainer : dburke.gw@gmail.com Stability : unstable Portability : OverloadedStrings Scale-related functionality. -} module Graphics.Vega.VegaLite.Scale ( ScaleDomain(..) , DomainLimits(..) , ScaleRange(..) , ScaleNice(..) , NTimeUnit(..) -- not for external export , scaleDomainProperty , domainLimitsSpec , scaleNiceSpec ) where import qualified Data.Text as T import Data.Aeson ((.=), object, toJSON) import Data.Aeson.Types (Pair) import Graphics.Vega.VegaLite.Foundation ( Channel , FieldName , fromT , channelLabel ) import Graphics.Vega.VegaLite.Specification ( VLSpec , SelectionLabel ) import Graphics.Vega.VegaLite.Time ( DateTime , dateTimeSpec ) {-| Describes the scale domain (type of data in scale). For full details see the <https://vega.github.io/vega-lite/docs/scale.html#domain Vega-Lite documentation>. In @0.11.0.0@ the functionality has been split into 'ScaleDomain' and 'DomainLimits'. -} data ScaleDomain = DMax Double -- ^ Sets the maximum value in the scale domain. -- It is only intended for scales with a continuous domain. -- -- It is supported in Vega-Lite 4.14 and later. -- -- @since 0.11.0.0 | DMaxTime [DateTime] -- ^ 'DMax' for dates. -- -- It is supported in Vega-Lite 4.14 and later. -- -- @since 0.11.0.0 | DMid Double -- ^ Sets the mid-point of a continuous diverging domain. -- -- It replaces 'Graphics.Vega.VegaLite.SDomainMid'. -- -- @since 0.11.0.0 | DMin Double -- ^ Sets the minimum value in the scale domain. -- It is only intended for scales with a continuous domain. -- -- It is supported in Vega-Lite 4.14 and later. -- -- @since 0.11.0.0 | DMinTime [DateTime] -- ^ 'DMin' for dates. -- -- It is supported in Vega-Lite 4.14 and later. -- -- @since 0.11.0.0 | DSelection SelectionLabel -- ^ Scale domain based on a named interactive selection. -- See also 'DSelectionField' and 'DSelectionChannel', which should -- be used when a selection is -- [projected](https://vega.github.io/vega-lite/docs/project.html) -- over multiple fields or encodings. -- -- In @0.7.0.0@ the argument type was changed to @SelectionLabel@ -- (which is a type synonym for @Text@). | DSelectionField SelectionLabel FieldName -- ^ Use the given selection /and/ associated field, when the selection -- is projected over multiple fields or encodings. -- -- @since 0.7.0.0 | DSelectionChannel SelectionLabel Channel -- ^ Use the given selection /and/ associated encoding, when the selection -- is projected over multiple fields or encodings. -- -- @since 0.7.0.0 | DUnionWith DomainLimits -- ^ Combine the domain of the data with the provided domain. -- -- The following example will use a range of at least 0 to 100, -- but this will be increased if the data (either initially or -- via any updates to the Vege-Lite visualization) exceeds this: -- -- @'Graphics.Vega.VegaLite.PScale' ['Graphics.Vega.VegaLite.SDomainOpt' (DUnionWith ('DNumbers' [0, 100]))]@ -- -- @since 0.6.0.0 | Unaggregated -- ^ Indicate that a domain of aggregated data should be scaled to -- the domain of the data prior to aggregation. -- For now we do not include Unaggregated in DomainLimits as the -- documentaiton suggests we should ubt the schema does not: see -- https://github.com/vega/vega-lite/issues/7022 -- {-| Represent the range of the domain, which is used by 'VL.SDomain' and 'DUnionWith'. Prior to @0.11.0.0@ this was part of 'ScaleDomain'. @since 0.11.0.0 -} data DomainLimits = DNumbers [Double] -- ^ Numeric values that define a scale domain. -- -- It is expected that this contains two values (minimum and -- maximum), but more can be given for -- [piecewise quantitative scales](https://vega.github.io/vega-lite/docs/scale.html#piecewise). | DStrings [T.Text] -- ^ String values that define a scale domain | DDateTimes [[DateTime]] -- ^ Date-time values that define a scale domain. scaleDomainProperty :: ScaleDomain -> Pair scaleDomainProperty :: ScaleDomain -> Pair scaleDomainProperty (DMax Double x) = Key "domainMax" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= Double x scaleDomainProperty (DMaxTime [DateTime] dts) = Key "domainMax" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= [DateTime] -> VLSpec dateTimeSpec [DateTime] dts scaleDomainProperty (DMid Double x) = Key "domainMid" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= Double x scaleDomainProperty (DMin Double x) = Key "domainMin" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= Double x scaleDomainProperty (DMinTime [DateTime] dts) = Key "domainMin" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= [DateTime] -> VLSpec dateTimeSpec [DateTime] dts scaleDomainProperty (DSelection Text selName) = Key "domain" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= [Pair] -> VLSpec object [Key "selection" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= Text selName] scaleDomainProperty (DSelectionField Text selName Text field) = Key "domain" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= [Pair] -> VLSpec object [ Key "selection" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= Text selName , Key "field" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= Text field ] scaleDomainProperty (DSelectionChannel Text selName Channel ch) = Key "domain" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= [Pair] -> VLSpec object [ Key "selection" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= Text selName , Key "encoding" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= Channel -> Text channelLabel Channel ch ] scaleDomainProperty (DUnionWith DomainLimits sd) = Key "domain" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= [Pair] -> VLSpec object [Key "unionWith" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= DomainLimits -> VLSpec domainLimitsSpec DomainLimits sd] scaleDomainProperty ScaleDomain Unaggregated = Key "domain" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= Text -> VLSpec fromT Text "unaggregated" domainLimitsSpec :: DomainLimits -> VLSpec domainLimitsSpec :: DomainLimits -> VLSpec domainLimitsSpec (DNumbers [Double] nums) = forall a. ToJSON a => a -> VLSpec toJSON (forall a b. (a -> b) -> [a] -> [b] map forall a. ToJSON a => a -> VLSpec toJSON [Double] nums) domainLimitsSpec (DDateTimes [[DateTime]] dts) = forall a. ToJSON a => a -> VLSpec toJSON (forall a b. (a -> b) -> [a] -> [b] map [DateTime] -> VLSpec dateTimeSpec [[DateTime]] dts) domainLimitsSpec (DStrings [Text] cats) = forall a. ToJSON a => a -> VLSpec toJSON (forall a b. (a -> b) -> [a] -> [b] map forall a. ToJSON a => a -> VLSpec toJSON [Text] cats) {-| Describes the way a scale can be rounded to \"nice\" numbers. For full details see the <https://vega.github.io/vega-lite/docs/scale.html#continuous Vega-Lite documentation>. Prior to version @0.10.0.0@ the time units were included in the constructors for @ScaleNice@. -} data ScaleNice = NTU NTimeUnit -- ^ Time range. | NInterval NTimeUnit Int -- ^ \"Nice\" temporal interval values when scaling. | IsNice Bool -- ^ Enable or disable nice scaling. | NTickCount Int -- ^ Desired number of tick marks in a \"nice\" scaling. {-| The time intervals that can be rounded to \"nice\" numbers. Prior to @0.10.0.0@ these were part of 'ScaleNice'. -} data NTimeUnit = NMillisecond -- ^ Nice time intervals that try to align with rounded milliseconds. | NSecond -- ^ Nice time intervals that try to align with whole or rounded seconds. | NMinute -- ^ Nice time intervals that try to align with whole or rounded minutes. | NHour -- ^ Nice time intervals that try to align with whole or rounded hours. | NDay -- ^ Nice time intervals that try to align with whole or rounded days. | NWeek -- ^ Nice time intervals that try to align with whole or rounded weeks. | NMonth -- ^ Nice time intervals that try to align with whole or rounded months. | NYear -- ^ Nice time intervals that try to align with whole or rounded years. nTimeUnitSpec :: NTimeUnit -> VLSpec nTimeUnitSpec :: NTimeUnit -> VLSpec nTimeUnitSpec NTimeUnit NMillisecond = Text -> VLSpec fromT Text "millisecond" nTimeUnitSpec NTimeUnit NSecond = Text -> VLSpec fromT Text "second" nTimeUnitSpec NTimeUnit NMinute = Text -> VLSpec fromT Text "minute" nTimeUnitSpec NTimeUnit NHour = Text -> VLSpec fromT Text "hour" nTimeUnitSpec NTimeUnit NDay = Text -> VLSpec fromT Text "day" nTimeUnitSpec NTimeUnit NWeek = Text -> VLSpec fromT Text "week" nTimeUnitSpec NTimeUnit NMonth = Text -> VLSpec fromT Text "month" nTimeUnitSpec NTimeUnit NYear = Text -> VLSpec fromT Text "year" scaleNiceSpec :: ScaleNice -> VLSpec scaleNiceSpec :: ScaleNice -> VLSpec scaleNiceSpec (NTU NTimeUnit tu) = NTimeUnit -> VLSpec nTimeUnitSpec NTimeUnit tu scaleNiceSpec (NInterval NTimeUnit tu Int step) = [Pair] -> VLSpec object [Key "interval" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= NTimeUnit -> VLSpec nTimeUnitSpec NTimeUnit tu, Key "step" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= Int step] scaleNiceSpec (IsNice Bool b) = forall a. ToJSON a => a -> VLSpec toJSON Bool b scaleNiceSpec (NTickCount Int n) = forall a. ToJSON a => a -> VLSpec toJSON Int n {-| Describes a scale range of scale output values. For full details see the <https://vega.github.io/vega-lite/docs/scale.html#range Vega-Lite documentation>. For color scales you can also specify a color [scheme](https://vega.github.io/vega-lite/docs/scale.html#scheme) instead of range. Any directly specified range for @x@ and @y@ channels will be ignored. Range can be customized via the view's corresponding [size](https://vega.github.io/vega-lite/docs/size.html) ('Graphics.Vega.VegaLite.width' and 'Graphics.Vega.VegaLite.height') or via range steps and paddings properties (e.g. 'Graphics.Vega.VegaLite.SCRangeStep') for band and point scales. -} data ScaleRange = RField FieldName -- ^ For [discrete](https://vega.github.io/vega-lite/docs/scale.html#discrete) -- and [discretizing](https://vega.github.io/vega-lite/docs/scale.html#discretizing) -- scales, the name if the field to use. -- -- For example. if the field \"color\" contains CSS color names, we can say -- @RField \"color\"@. -- -- It is supported in Vega-Lite 4.14 and later. -- -- @since 0.11.0.0 | RMax Double -- ^ Sets the maximum value in the scale range. -- It is only intended for scales with a continuous range. -- -- It is supported in Vega-Lite 4.14 and later. -- -- @since 0.11.0.0 | RMin Double -- ^ Sets the minimum value in the scale range. -- It is only intended for scales with a continuous range. -- -- It is supported in Vega-Lite 4.14 and later. -- -- @since 0.11.0.0 | RPair Double Double -- ^ The minimum and maximum values. -- -- @since 0.9.0.0 | RHeight Double -- ^ Specify the width as a number and height as the string @"height"@. -- -- @since 0.9.0.0 | RWidth Double -- ^ Specify the height as a number and width as the string @"width"@. -- -- @since 0.9.0.0 | RNumbers [Double] -- ^ For [continuous scales](https://vega.github.io/vega-lite/docs/scale.html#continuous), -- a two-element array indicating minimum and maximum values, or an array with more than -- two entries for specifying a -- [piecewise scale](https://vega.github.io/vega-lite/docs/scale.html#piecewise). -- -- Support for the two-element version may be removed (ie this left only -- for piecewise scales). | RNumberLists [[Double]] -- ^ A scale range comprising of numeric lists, such as custom dash styles for -- the 'Graphics.Vega.VegaLite.strokeDash' channel encoding. -- -- @since 0.6.0.0 | RStrings [T.Text] -- ^ Text scale range for discrete scales. | RName T.Text -- ^ Name of a [pre-defined named scale range](https://vega.github.io/vega-lite/docs/scale.html#range-config) -- (e.g. \"symbol\" or \"diverging\"). {- TODO: * TickCount accepts number or TimeInterval but this is a subset of ScaleNice -}