{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} -- -- Based on the Elm VegaLite GalleryLabel.elm (from development of version -- 1.13.0) -- module Gallery.Label (testSpecs) where import Data.Aeson (Value) import Data.Aeson.QQ.Simple (aesonQQ) import Graphics.Vega.VegaLite import Prelude hiding (filter, lookup, repeat) testSpecs :: [(String, VegaLite)] testSpecs = [ ("label1", label1) , ("label2", label2) , ("label2r", label2r) , ("label3", label3) , ("label4", label4) , ("label5", label5) , ("label6", label6) , ("label7", label7) , ("label8", label8) , ("label9", label9) , ("voyager", voyager) , ("baselines", baselines) ] noStroke :: [ConfigureSpec] -> PropertySpec noStroke = configure . configuration (ViewStyle [ViewNoStroke]) label1 :: VegaLite label1 = let des = description "A simple bar chart with embedded data labels" dvals = dataFromColumns [] . dataColumn "a" (Strings [ "A", "B", "C" ]) . dataColumn "b" (Numbers [ 28, 55, 43 ]) enc = encoding . position X [ PName "b", PmType Quantitative ] . position Y [ PName "a", PmType Ordinal ] specBar = asSpec [ mark Bar [] ] specText = asSpec [ mark Text [ MStyle [ "label" ] ], encoding (text [ TName "b", TmType Quantitative ] []) ] config = configure . configuration (MarkNamedStyles [( "label" , [ MAlign AlignLeft, MBaseline AlignMiddle, MdX 3 ]) ]) in toVegaLite [ des, dvals [], enc [], layer [ specBar, specText ], config [] ] label2Base :: [ScaleConfig] -> VegaLite label2Base opts = let encPosition = encoding . position X [ PName "Cylinders", PmType Ordinal ] . position Y [ PName "Origin", PmType Ordinal ] encRect = encoding . color [ MName "*", MmType Quantitative, MAggregate Count ] specRect = asSpec [ mark Rect [], encRect [] ] encText = encoding . color [ MString "white" ] . text [ TName "*", TmType Quantitative, TAggregate Count ] specText = asSpec [ mark Text [], encText [] ] scOpts = [ SCBandPaddingInner 0, SCBandPaddingOuter 0 ] ++ opts config = configure . configuration (ScaleStyle scOpts) . configuration (TextStyle [ MBaseline AlignMiddle ]) in toVegaLite [ description "Layering text over 'heatmap'" , dataFromUrl "https://vega.github.io/vega-lite/data/cars.json" [] , encPosition [] , layer [ specRect, specText ] , config [] ] label2, label2r :: VegaLite label2 = label2Base [SCXReverse False] label2r = label2Base [SCXReverse True] -- TODO: this has been re-worked in elm label3 :: VegaLite label3 = let des = description "Carbon dioxide in the atmosphere." trans = transform . calculateAs "year(datum.Date)" "year" . calculateAs "month(datum.Date)" "month" . calculateAs "floor(datum.year / 10)" "decade" . calculateAs "(datum.year % 10) + (datum.month / 12)" "scaled_date" encPosition = encoding . position X [ PName "scaled_date" , PmType Quantitative , PAxis [ AxTitle "Year into decade" , AxTickCount 10 , AxValues (Numbers [1, 2, 3, 4, 5, 6, 7, 8, 9]) ] ] . position Y [ PName "CO2" , PmType Quantitative , PScale [ SZero False ] , PAxis [ AxTitle "CO₂ concentration in ppm" ] ] encLine = encoding . color [ MName "decade", MmType Nominal, MLegend [] ] specLine = asSpec [ mark Line [ MOrient Vertical ], encLine [] ] transTextMin = transform . aggregate [ opAs (ArgMin Nothing) "scaled_date" "aggregated" ] [ "decade" ] . calculateAs "datum.aggregated.scaled_date" "scaled_date" . calculateAs "datum.aggregated.CO2" "CO2" encTextMin = encoding . text [ TName "aggregated.year", TmType Nominal ] specTextMin = asSpec [ transTextMin [], mark Text [ MAlign AlignLeft, MBaseline AlignTop, MdX 3, MdY 1 ], encTextMin [] ] transTextMax = transform . aggregate [ opAs (ArgMax Nothing) "scaled_date" "aggregated" ] [ "decade" ] . calculateAs "datum.aggregated.scaled_date" "scaled_date" . calculateAs "datum.aggregated.CO2" "CO2" encTextMax = encoding . text [ TName "aggregated.year", TmType Nominal ] specTextMax = asSpec [ transTextMax [], mark Text [ MAlign AlignLeft, MBaseline AlignBottom, MdX 3, MdY 1 ], encTextMax [] ] in toVegaLite [ des , noStroke [] , width 800 , height 500 , dataFromUrl "https://vega.github.io/vega-lite/data/co2-concentration.csv" [ Parse [ ( "Date", FoUtc "%Y-%m-%d" ) ] ] , trans [] , encPosition [] , layer [ specLine, specTextMin, specTextMax ] ] label4 :: VegaLite label4 = let des = description "Bar chart that highlights values beyond a threshold. The PM2.5 value of Beijing observed 15 days, highlighting the days when PM2.5 level is hazardous to human health. Data source https://chartaccent.github.io/chartaccent.html" dvals = dataFromColumns [] . dataColumn "Day" (Numbers (map fromIntegral [1::Int .. 15])) . dataColumn "Value" (Numbers [ 54.8, 112.1, 63.6, 37.6, 79.7, 137.9, 120.1, 103.3, 394.8, 199.5, 72.3, 51.1, 112.0, 174.5, 130.5 ]) encBar = encoding . position X [ PName "Day", PmType Ordinal, PAxis [ AxLabelAngle 0 ] ] . position Y [ PName "Value", PmType Quantitative ] specBar = asSpec [ mark Bar [], encBar [] ] trans = transform . filter (FExpr "datum.Value >= 300") . calculateAs "300" "baseline" encUpperBar = encoding . position X [ PName "Day", PmType Ordinal, PAxis [ AxLabelAngle 0 ] ] . position Y [ PName "baseline", PmType Quantitative ] . position Y2 [ PName "Value" ] . color [ MString "#e45755" ] specUpperBar = asSpec [ trans [], mark Bar [], encUpperBar [] ] layer0 = asSpec [ dvals [], layer [ specBar, specUpperBar ] ] thresholdData = dataFromRows [] . dataRow [ ( "ThresholdValue", Number 300 ), ( "Threshold", Str "hazardous" ) ] specRule = asSpec [ mark Rule [], encRule [] ] encRule = encoding . position Y [ PName "ThresholdValue", PmType Quantitative ] specText = asSpec [ mark Text [ MAlign AlignRight, MdX (-2), MdY (-4) ], encText [] ] encText = encoding . position X [ PWidth ] . position Y [ PName "ThresholdValue", PmType Quantitative, PAxis [ AxTitle "PM2.5 Value" ] ] . text [ TName "Threshold", TmType Ordinal ] layer1 = asSpec [ thresholdData [], layer [ specRule, specText ] ] in toVegaLite [ des, layer [ layer0, layer1 ] ] label5 :: VegaLite label5 = let des = description "Monthly precipitation with mean value overlay" encBar = encoding . position X [ PName "date", PmType Ordinal, PTimeUnit Month ] . position Y [ PName "precipitation", PmType Quantitative, PAggregate Mean ] specBar = asSpec [ mark Bar [], encBar [] ] encLine = encoding . position Y [ PName "precipitation", PmType Quantitative, PAggregate Mean ] . color [ MString "red" ] . size [ MNumber 3 ] specLine = asSpec [ mark Rule [], encLine [] ] in toVegaLite [ des , dataFromUrl "https://vega.github.io/vega-lite/data/seattle-weather.csv" [] , layer [ specBar, specLine ] ] label6 :: VegaLite label6 = let des = description "Histogram with global mean overlay" encBars = encoding . position X [ PName "IMDB_Rating", PmType Quantitative, PBin [], PAxis [] ] . position Y [ PmType Quantitative, PAggregate Count ] specBars = asSpec [ mark Bar [], encBars [] ] encMean = encoding . position X [ PName "IMDB_Rating", PmType Quantitative, PAggregate Mean ] . color [ MString "red" ] . size [ MNumber 5 ] specMean = asSpec [ mark Rule [], encMean [] ] in toVegaLite [ des , dataFromUrl "https://vega.github.io/vega-lite/data/movies.json" [] , layer [ specBars, specMean ] ] label7 :: VegaLite label7 = let des = description "The population of the German city of Falkensee over time with annotated time periods highlighted" dvals = dataFromColumns [ Parse [ ( "year", FoDate "%Y" ) ] ] . dataColumn "year" (Strings [ "1875", "1890", "1910", "1925", "1933", "1939", "1946", "1950", "1964", "1971", "1981", "1985", "1989", "1990", "1991", "1992", "1993", "1994", "1995", "1996", "1997", "1998", "1999", "2000", "2001", "2002", "2003", "2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014" ]) . dataColumn "population" (Numbers [ 1309, 1558, 4512, 8180, 15915, 24824, 28275, 29189, 29881, 26007, 24029, 23340, 22307, 22087, 22139, 22105, 22242, 22801, 24273, 25640, 27393, 29505, 32124, 33791, 35297, 36179, 36829, 37493, 38376, 39008, 39366, 39821, 40179, 40511, 40465, 40905, 41258, 41777 ]) highlights = dataFromColumns [ Parse [ ( "start", FoDate "%Y" ), ( "end", FoDate "%Y" ) ] ] . dataColumn "start" (Strings [ "1933", "1948" ]) . dataColumn "end" (Strings [ "1945", "1989" ]) . dataColumn "event" (Strings [ "Nazi Rule", "GDR (East Germany)" ]) encRects = encoding . position X [ PName "start", PmType Temporal, PTimeUnit Year, PAxis [] ] . position X2 [ PName "end", PTimeUnit Year ] . color [ MName "event", MmType Nominal ] specRects = asSpec [ highlights [], mark Rect [], encRects [] ] encPopulation = encoding . position X [ PName "year", PmType Temporal, PTimeUnit Year, PAxis [ AxNoTitle ] ] . position Y [ PName "population", PmType Quantitative ] . color [ MString "#333" ] specLine = asSpec [ mark Line [], encPopulation [] ] specPoints = asSpec [ mark Point [], encPopulation [] ] in toVegaLite [ des, width 500, dvals [], layer [ specRects, specLine, specPoints ] ] label8 :: VegaLite label8 = let strColumn n vs = dataColumn n (Strings vs) medians = dataFromColumns [] . strColumn "name" [ "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:" ] . dataColumn "median" (Numbers [ 1.999976, 2, 1.999969, 2.500045, 1.500022, 2.99998, 4.500007 ]) . strColumn "lo" [ "Easy", "Easy", "Toolbar", "Toolbar", "Toolbar", "Toolbar", "Phone" ] . strColumn "hi" [ "Hard", "Hard", "Gesture", "Gesture", "Gesture", "Gesture", "Tablet" ] values = dataFromColumns [] . strColumn "value" [ "P1", "2", "2", "3", "4", "2", "5", "5", "1", "1", "P2", "2", "3", "4", "5", "5", "5", "5", "1", "1", "P3", "2", "2", "2", "1", "2", "1", "5", "1", "0", "P4", "3", "3", "2", "2", "4", "1", "5", "1", "0", "P5", "2", "2", "4", "4", "4", "5", "5", "0", "1", "P6", "1", "3", "3", "4", "4", "4", "4", "0", "1", "P7", "2", "3", "4", "5", "3", "2", "4", "0", "0", "P8", "3", "1", "2", "4", "2", "5", "5", "0", "0", "P9", "2", "3", "2", "4", "1", "4", "4", "1", "1", "P10", "2", "2", "1", "1", "1", "1", "5", "1", "1", "P11", "2", "2", "1", "1", "1", "1", "4", "1", "0", "P12", "1", "3", "2", "3", "1", "3", "3", "0", "1", "P13", "2", "2", "1", "1", "1", "1", "5", "0", "0", "P14", "3", "3", "2", "2", "1", "1", "1", "1", "1", "P15", "4", "5", "1", "1", "1", "1", "5", "1", "0", "P16", "1", "3", "2", "2", "1", "4", "5", "0", "1", "P17", "3", "2", "2", "2", "1", "3", "2", "0", "0" ] . strColumn "name" [ "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First", "Participant ID", "Identify Errors:", "Fix Errors:", "Easier to Fix:", "Faster to Fix:", "Easier on Phone:", "Easier on Tablet:", "Device Preference:", "Tablet_First", "Toolbar_First" ] . strColumn "id" [ "P1", "P1", "P1", "P1", "P1", "P1", "P1", "P1", "P1", "P1", "P2", "P2", "P2", "P2", "P2", "P2", "P2", "P2", "P2", "P2", "P3", "P3", "P3", "P3", "P3", "P3", "P3", "P3", "P3", "P3", "P4", "P4", "P4", "P4", "P4", "P4", "P4", "P4", "P4", "P4", "P5", "P5", "P5", "P5", "P5", "P5", "P5", "P5", "P5", "P5", "P6", "P6", "P6", "P6", "P6", "P6", "P6", "P6", "P6", "P6", "P7", "P7", "P7", "P7", "P7", "P7", "P7", "P7", "P7", "P7", "P8", "P8", "P8", "P8", "P8", "P8", "P8", "P8", "P8", "P8", "P9", "P9", "P9", "P9", "P9", "P9", "P9", "P9", "P9", "P9", "P10", "P10", "P10", "P10", "P10", "P10", "P10", "P10", "P10", "P10", "P11", "P11", "P11", "P11", "P11", "P11", "P11", "P11", "P11", "P11", "P12", "P12", "P12", "P12", "P12", "P12", "P12", "P12", "P12", "P12", "P13", "P13", "P13", "P13", "P13", "P13", "P13", "P13", "P13", "P13", "P14", "P14", "P14", "P14", "P14", "P14", "P14", "P14", "P14", "P14", "P15", "P15", "P15", "P15", "P15", "P15", "P15", "P15", "P15", "P15", "P16", "P16", "P16", "P16", "P16", "P16", "P16", "P16", "P16", "P16", "P17", "P17", "P17", "P17", "P17", "P17", "P17", "P17", "P17", "P17" ] enc = encoding . position Y [ PName "name" , PmType Nominal , PSort [] , PAxis [ AxDomain False , AxOffset 50 , AxLabelFontWeight Bold , AxTicks False , AxGrid True , AxNoTitle ] ] trans = transform . filter (FExpr "datum.name != 'Toolbar_First'") . filter (FExpr "datum.name != 'Tablet_First'") . filter (FExpr "datum.name != 'Participant ID'") encCircle = encoding . position X [ PName "value" , PmType Quantitative , PScale [ SDomain (DNumbers [ 0, 6 ]) ] , PAxis [ AxGrid False, AxValues (Numbers [ 1, 2, 3, 4, 5 ]) ] ] . size [ MAggregate Count , MmType Quantitative , MLegend [ LTitle "Number of Ratings", LOffset 75 ] ] specCircle = asSpec [ dataFromSource "values" [] , trans [] , encCircle [] , mark Circle [ MColor "#6eb4fd" ] ] encTick1 = encoding . position X [ PName "median" , PmType Quantitative , PScale [ SDomain (DNumbers [ 0, 6 ]) ] , PAxis [ AxNoTitle ] ] specTick1 = asSpec [ encTick1 [], mark Tick [ MColor "black" ] ] encTextLo = encoding . text [ TName "lo", TmType Nominal ] specTextLo = asSpec [ encTextLo [], mark Text [ MX (-5), MAlign AlignRight ] ] encTextHi = encoding . text [ TName "hi", TmType Nominal ] specTextHi = asSpec [ encTextHi [], mark Text [ MX 255, MAlign AlignLeft ] ] in toVegaLite [ noStroke [] , datasets [ ( "medians", medians [] ), ( "values", values [] ) ] , dataFromSource "medians" [] , title "Questionnaire Ratings" [] , width 250 , height 175 , enc [] , layer [ specCircle, specTick1, specTextLo, specTextHi ] ] label9 :: VegaLite label9 = let des = description "Comparing Likert scale ratings between two conditions." cfg = noStroke . configuration (MarkNamedStyles [ ( "arrow-label", [ MdY 12, MFontSize 9.5 ] ) , ( "arrow-label2", [ MdY 24, MFontSize 9.5 ] ) ] ) . configuration (TitleStyle [ TFontSize 12 ]) lickertData = dataFromColumns [] . dataColumn "measure" (Strings [ "Open Exploration", "Focused Question Answering", "Open Exploration", "Focused Question Answering" ]) . dataColumn "mean" (Numbers [ 1.81, -1.69, 2.19, -0.06 ]) . dataColumn "lo" (Numbers [ 1.26, -2.33, 1.67, -0.47 ]) . dataColumn "hi" (Numbers [ 2.37, -1.05, 2.71, 0.35 ]) . dataColumn "study" (Strings [ "PoleStar vs Voyager", "PoleStar vs Voyager", "PoleStar vs Voyager 2", "PoleStar vs Voyager 2" ]) labelData = dataFromColumns [] . dataColumn "from" (Numbers [ -0.25, 0.25 ]) . dataColumn "to" (Numbers [ -2.9, 2.9 ]) . dataColumn "label" (Strings [ "PoleStar", "Voyager / Voyager 2" ]) encLickert = encoding . position Y [ PName "study" , PmType Nominal , PAxis [ AxNoTitle , AxLabelPadding 5 , AxDomain False , AxTicks False , AxGrid False ] ] encLickertWhiskers = encoding . position X [ PName "lo" , PmType Quantitative , PScale [ SDomain (DNumbers [ -3, 3 ]) ] , PAxis [ AxNoTitle , AxGridDash [ 3, 3 ] , AxDataCondition (Expr "datum.value === 0") (CAxGridColor "#666" "#ccc") ] ] . position X2 [ PName "hi" ] specLickertWhiskers = asSpec [ encLickertWhiskers [], mark Rule [] ] encLickertMeans = encoding . position X [ PName "mean", PmType Quantitative ] . color [ MName "measure" , MmType Nominal , MScale [ SRange (RStrings [ "black", "white" ]) ] , MLegend [] ] specLickertMeans = asSpec [ encLickertMeans [], mark Circle [ MStroke "black", MOpacity 1 ] ] specLickert = asSpec [ title "Mean of Subject Ratings (95% CIs)" [ TFrame FrBounds ] , encLickert [] , layer [ specLickertWhiskers, specLickertMeans ] ] encLabel1 = encoding . position X [ PName "from", PmType Quantitative, PScale [ SZero False ], PAxis [] ] . position X2 [ PName "to" ] specLabel1 = asSpec [ encLabel1 [], mark Rule [] ] encLabel2 = encoding . position X [ PName "to", PmType Quantitative, PAxis [] ] . shape [ MDataCondition [ ( Expr "datum.to > 0", [ MSymbol SymTriangleRight ] ) ] [ MSymbol SymTriangleLeft ] ] specLabel2 = asSpec [ encLabel2 [], mark Point [ MFilled True, MSize 60, MFill "black" ] ] transLabel3 = transform . filter (FExpr "datum.label === 'PoleStar'") from = position X [ PName "from", PmType Quantitative, PAxis [] ] encLabel3 = encoding . from . text [ TName "label", TmType Nominal ] specLabel3 = asSpec [ transLabel3 [] , encLabel3 [] , mark Text [ MAlign AlignRight, MStyle [ "arrow-label" ] ] ] transLabel4 = transform . filter (FExpr "datum.label !== 'PoleStar'") encLabel4 = encLabel3 specLabel4 = asSpec [ transLabel4 [] , encLabel4 [] , mark Text [ MAlign AlignLeft, MStyle [ "arrow-label" ] ] ] transLabel5 = transLabel3 encLabel5 = encoding . from . text [ TString "more valuable" ] specLabel5 = asSpec [ transLabel5 [] , encLabel5 [] , mark Text [ MAlign AlignRight, MStyle [ "arrow-label2" ] ] ] transLabel6 = transLabel4 encLabel6 = encLabel5 specLabel6 = asSpec [ transLabel6 [] , encLabel6 [] , mark Text [ MAlign AlignLeft, MStyle [ "arrow-label2" ] ] ] specLabels = asSpec [ labelData [] , layer [ specLabel1, specLabel2, specLabel3, specLabel4, specLabel5, specLabel6 ] ] in toVegaLite [ des , cfg [] , lickertData [] , spacing 10 , vConcat [ specLickert, specLabels ] ] -- like label9 but trying to match the current version (Feb 2020) of -- https://vega.github.io/vega-lite/examples/concat_layer_voyager_result.html -- voyagerData :: Value voyagerData = [aesonQQ| [ { "measure": "Open Exploration", "mean": 1.813, "lo": 1.255, "hi": 2.37, "study": "PoleStar vs Voyager" }, { "measure": "Focused Question Answering", "mean": -1.688, "lo": -2.325, "hi": -1.05, "study": "PoleStar vs Voyager" }, { "measure": "Open Exploration", "mean": 2.1875, "lo": 1.665, "hi": 2.71, "study": "PoleStar vs Voyager 2" }, { "measure": "Focused Question Answering", "mean": -0.0625, "lo": -0.474, "hi": 0.349, "study": "PoleStar vs Voyager 2" } ] |] voyager :: VegaLite voyager = let dataPlot = [ title "Mean of Subject Ratings (95% CIs)" [TFrame FrBounds] , encoding . position Y [ PName "study" , PmType Nominal , PAxis [ AxNoTitle , AxLabelPadding 5 , AxDomain False , AxTicks False , AxGrid False ] ] $ [] , layer [asSpec rulePlot, asSpec circlePlot] ] gridColor = AxDataCondition (Expr "datum.value === 0") (CAxGridColor "#666" "#CCC") rulePlot = [ mark Rule [] , encoding . position X [ PName "lo" , PmType Quantitative , PScale [SDomain (DNumbers [-3, 3])] , PAxis [ AxTitle "" , AxGridDash [3, 3] , gridColor ] ] . position X2 [PName "hi"] $ [] ] circlePlot = [ mark Circle [MStroke "black", MOpacity 1] , encoding . position X [PName "mean", PmType Quantitative] . color [ MName "measure" , MmType Nominal , MScale [SRange (RStrings ["black", "white"])] , MLegend [] ] $ [] ] labelPlot = [ dataFromColumns [] . dataColumn "from" (Numbers [-0.25, 0.25]) . dataColumn "to" (Numbers [-2.9, 2.9]) . dataColumn "label" (Strings ["PoleStar", "Voyager / Voyager 2"]) $ [] , layer (map asSpec [linePlot, arrowsPlot, pTextPlot, vTextPlot]) ] linePlot = [ mark Rule [] , encoding . position X [ PName "from" , PmType Quantitative , PScale [SZero False] , PAxis [] ] . position X2 [PName "to"] $ [] ] shapeOpts = MDataCondition [(Expr "datum.to > 0", [MSymbol SymTriangleRight])] [MSymbol SymTriangleLeft] arrowsPlot = [ mark Point [ MFilled True , MFill "black" , MSize 60 ] , encoding . position X [ PName "to" , PmType Quantitative , PAxis [] ] . shape [ shapeOpts ] $ [] ] from = position X [PName "from", PmType Quantitative, PAxis []] pTextPlot = [ mark Text [ MAlign AlignRight , MStyle ["arrow-label"] , MTexts ["Polestar", "More Valuable"] ] , transform . filter (FExpr "datum.label === 'PoleStar'") $ [] , encoding . from $ [] ] vTextPlot = [ mark Text [ MAlign AlignLeft , MStyle ["arrow-label"] , MTexts ["Voyager / Voyager 2", "More Valuable"] ] , transform . filter (FExpr "datum.label !== 'PoleStar'") $ [] , encoding . from $ [] ] styles = MarkNamedStyles [ ("arrow-label", [MdY 12, MFontSize 9.5]) , ("arrow-label2", [MdY 24, MFontSize 9.5]) ] conf = configure . configuration (ViewStyle [ViewStroke "transparent"]) . configuration styles . configuration (TitleStyle [TFontSize 12]) v = [ dataFromJson voyagerData [] , spacing 10 , vConcat [asSpec dataPlot, asSpec labelPlot] , conf [] ] in toVegaLite v baselines :: VegaLite baselines = let dvals = dataFromColumns [] . dataColumn "x" (Numbers [ 5, 30 ]) . dataColumn "y" (Numbers [ 5, 30 ]) ax t n = position t [ PName n , PmType Quantitative , PScale [ SNice (IsNice False) , SDomain (DNumbers [-10, 40]) ] , PAxis [ AxNoTitle ] ] enc = encoding . ax X "x" . ax Y "y" . text [ TStrings ["Xxgq", "qTpP"] ] plot l a = asSpec [ enc [], title l [], mark Text [ MBaseline a ] ] -- plots are ordered left to right, top to bottom plots = vlConcat [ plot "top" AlignTop , plot "line-top" AlignLineTop , plot "middle" AlignMiddle , plot "baseline" AlignBaseline , plot "bottom" AlignBottom , plot "line-bottom" AlignLineBottom ] in toVegaLite [ dvals [] , configure . configuration (MarkStyle [ MFontSize 20 , MFontStyle "italic" , MLineHeight 30 ]) . configuration (TitleStyle [ TFont "Comic Sans MS" ]) $ [] , columns 2 , plots ]