Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upRuntime exception from gampleman/elm-visualization #806
Comments
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
process-bot
Jan 14, 2017
Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it!
Here is what to expect next, and if anyone wants to comment, keep these things in mind.
process-bot
commented
Jan 14, 2017
|
Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it! Here is what to expect next, and if anyone wants to comment, keep these things in mind. |
rtfeldman
changed the title from
Runtime exception
to
Runtime exception from gampleman/elm-visualization
Jan 15, 2017
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
|
@gampleman - any ideas on how to narrow this down? |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jackalcooper
Jan 16, 2017
This should reproduce the error:
module LineChart exposing (..)
import Visualization.Scale as Scale exposing (ContinuousScale, ContinuousTimeScale)
import Visualization.Axis as Axis
import Visualization.List as List
import Visualization.Shape as Shape
import Date
import Date.Extra exposing (..)
import Svg exposing (..)
import Svg.Attributes exposing (..)
import Date exposing (Date)
import String
w : Float
w =
900
h : Float
h =
450
padding : Float
padding =
30
view : List ( Date, Float ) -> Svg msg
view model =
let
_ =
Debug.log "data breaks line chart" model
xScale : ContinuousTimeScale
xScale =
let
start =
Date.fromTime 1448928000000
end =
Date.fromTime 1456790400000
( start_, _ ) =
Maybe.withDefault ( start, 0 ) (List.head model)
( end_, _ ) =
Maybe.withDefault ( start, 0 ) (List.reverse model |> List.head)
in
Scale.time ( add Day -1 start_, add Day 1 end_ ) ( 0, w - 2 * padding )
yScale : ContinuousScale
yScale =
Scale.linear ( 0, 5 ) ( h - 2 * padding, 0 )
opts : Axis.Options a
opts =
Axis.defaultOptions
xAxis : Svg msg
xAxis =
Axis.axis { opts | orientation = Axis.Bottom, tickCount = List.length model } xScale
yAxis : Svg msg
yAxis =
Axis.axis { opts | orientation = Axis.Left, tickCount = 5 } yScale
areaGenerator : ( Date, Float ) -> Maybe ( ( Float, Float ), ( Float, Float ) )
areaGenerator ( x, y ) =
Just ( ( Scale.convert xScale x, Tuple.first (Scale.rangeExtent yScale) ), ( Scale.convert xScale x, Scale.convert yScale y ) )
lineGenerator : ( Date, Float ) -> Maybe ( Float, Float )
lineGenerator ( x, y ) =
Just ( Scale.convert xScale x, Scale.convert yScale y )
area : String
area =
List.map areaGenerator model
|> Shape.area Shape.monotoneInXCurve
line : String
line =
List.map lineGenerator model
|> Shape.line Shape.monotoneInXCurve
in
svg [ width (toString w ++ "px"), height (toString h ++ "px") ]
[ g [ transform ("translate(" ++ toString (padding - 1) ++ ", " ++ toString (h - padding) ++ ")") ]
[ xAxis ]
, g [ transform ("translate(" ++ toString (padding - 1) ++ ", " ++ toString padding ++ ")") ]
[ yAxis ]
, g [ transform ("translate(" ++ toString padding ++ ", " ++ toString padding ++ ")"), class "series" ]
[ Svg.path [ d area, stroke "none", strokeWidth "3px", fill "rgba(255, 0, 0, 0.54)" ] []
, Svg.path [ d line, stroke "red", strokeWidth "3px", fill "none" ] []
]
]
-- From here onwards this is simply example boilerplate.
-- In a real app you would load the data from a server and parse it, perhaps in
-- a separate module.
main =
view model
-- Here we simply define the data inline. The examples don't include logic for fetching and parsing this data.
model =
[ ( Date.fromTime 1483521850, 0.107 )
, ( Date.fromTime 1483521850, 0.266 )
, ( Date.fromTime 1483521850, 0.285 )
, ( Date.fromTime 1483521827, 0.084 )
, ( Date.fromTime 1483521751, 0.081 )
, ( Date.fromTime 1483521649, 0.073 )
, ( Date.fromTime 1483521635, 0.049 )
, ( Date.fromTime 1483521699, 0.359 )
, ( Date.fromTime 1483521698, 0.089 )
, ( Date.fromTime 1483521688, 0.146 )
, ( Date.fromTime 1483521658, 0.112 )
, ( Date.fromTime 1483521657, 0.055 )
, ( Date.fromTime 1483521858, 0.069 )
, ( Date.fromTime 1483521842, 0.049 )
, ( Date.fromTime 1483521750, 0.126 )
, ( Date.fromTime 1483521747, 0.1 )
, ( Date.fromTime 1483521746, 0.132 )
, ( Date.fromTime 1483521650, 0.063 )
, ( Date.fromTime 1483521646, 0.059 )
, ( Date.fromTime 1483521659, 0.078 )
, ( Date.fromTime 1483521881, 0.054 )
, ( Date.fromTime 1483521820, 0.057 )
, ( Date.fromTime 1483521729, 0.167 )
, ( Date.fromTime 1483521753, 0.063 )
, ( Date.fromTime 1483521661, 0.057 )
, ( Date.fromTime 1483521863, 0.061 )
, ( Date.fromTime 1483521750, 0.07 )
, ( Date.fromTime 1483521745, 0.126 )
, ( Date.fromTime 1483521722, 0.126 )
, ( Date.fromTime 1483521642, 0.436 )
, ( Date.fromTime 1483521628, 0.068 )
, ( Date.fromTime 1483521679, 0.067 )
]
jackalcooper
commented
Jan 16, 2017
|
This should reproduce the error: module LineChart exposing (..)
import Visualization.Scale as Scale exposing (ContinuousScale, ContinuousTimeScale)
import Visualization.Axis as Axis
import Visualization.List as List
import Visualization.Shape as Shape
import Date
import Date.Extra exposing (..)
import Svg exposing (..)
import Svg.Attributes exposing (..)
import Date exposing (Date)
import String
w : Float
w =
900
h : Float
h =
450
padding : Float
padding =
30
view : List ( Date, Float ) -> Svg msg
view model =
let
_ =
Debug.log "data breaks line chart" model
xScale : ContinuousTimeScale
xScale =
let
start =
Date.fromTime 1448928000000
end =
Date.fromTime 1456790400000
( start_, _ ) =
Maybe.withDefault ( start, 0 ) (List.head model)
( end_, _ ) =
Maybe.withDefault ( start, 0 ) (List.reverse model |> List.head)
in
Scale.time ( add Day -1 start_, add Day 1 end_ ) ( 0, w - 2 * padding )
yScale : ContinuousScale
yScale =
Scale.linear ( 0, 5 ) ( h - 2 * padding, 0 )
opts : Axis.Options a
opts =
Axis.defaultOptions
xAxis : Svg msg
xAxis =
Axis.axis { opts | orientation = Axis.Bottom, tickCount = List.length model } xScale
yAxis : Svg msg
yAxis =
Axis.axis { opts | orientation = Axis.Left, tickCount = 5 } yScale
areaGenerator : ( Date, Float ) -> Maybe ( ( Float, Float ), ( Float, Float ) )
areaGenerator ( x, y ) =
Just ( ( Scale.convert xScale x, Tuple.first (Scale.rangeExtent yScale) ), ( Scale.convert xScale x, Scale.convert yScale y ) )
lineGenerator : ( Date, Float ) -> Maybe ( Float, Float )
lineGenerator ( x, y ) =
Just ( Scale.convert xScale x, Scale.convert yScale y )
area : String
area =
List.map areaGenerator model
|> Shape.area Shape.monotoneInXCurve
line : String
line =
List.map lineGenerator model
|> Shape.line Shape.monotoneInXCurve
in
svg [ width (toString w ++ "px"), height (toString h ++ "px") ]
[ g [ transform ("translate(" ++ toString (padding - 1) ++ ", " ++ toString (h - padding) ++ ")") ]
[ xAxis ]
, g [ transform ("translate(" ++ toString (padding - 1) ++ ", " ++ toString padding ++ ")") ]
[ yAxis ]
, g [ transform ("translate(" ++ toString padding ++ ", " ++ toString padding ++ ")"), class "series" ]
[ Svg.path [ d area, stroke "none", strokeWidth "3px", fill "rgba(255, 0, 0, 0.54)" ] []
, Svg.path [ d line, stroke "red", strokeWidth "3px", fill "none" ] []
]
]
-- From here onwards this is simply example boilerplate.
-- In a real app you would load the data from a server and parse it, perhaps in
-- a separate module.
main =
view model
-- Here we simply define the data inline. The examples don't include logic for fetching and parsing this data.
model =
[ ( Date.fromTime 1483521850, 0.107 )
, ( Date.fromTime 1483521850, 0.266 )
, ( Date.fromTime 1483521850, 0.285 )
, ( Date.fromTime 1483521827, 0.084 )
, ( Date.fromTime 1483521751, 0.081 )
, ( Date.fromTime 1483521649, 0.073 )
, ( Date.fromTime 1483521635, 0.049 )
, ( Date.fromTime 1483521699, 0.359 )
, ( Date.fromTime 1483521698, 0.089 )
, ( Date.fromTime 1483521688, 0.146 )
, ( Date.fromTime 1483521658, 0.112 )
, ( Date.fromTime 1483521657, 0.055 )
, ( Date.fromTime 1483521858, 0.069 )
, ( Date.fromTime 1483521842, 0.049 )
, ( Date.fromTime 1483521750, 0.126 )
, ( Date.fromTime 1483521747, 0.1 )
, ( Date.fromTime 1483521746, 0.132 )
, ( Date.fromTime 1483521650, 0.063 )
, ( Date.fromTime 1483521646, 0.059 )
, ( Date.fromTime 1483521659, 0.078 )
, ( Date.fromTime 1483521881, 0.054 )
, ( Date.fromTime 1483521820, 0.057 )
, ( Date.fromTime 1483521729, 0.167 )
, ( Date.fromTime 1483521753, 0.063 )
, ( Date.fromTime 1483521661, 0.057 )
, ( Date.fromTime 1483521863, 0.061 )
, ( Date.fromTime 1483521750, 0.07 )
, ( Date.fromTime 1483521745, 0.126 )
, ( Date.fromTime 1483521722, 0.126 )
, ( Date.fromTime 1483521642, 0.436 )
, ( Date.fromTime 1483521628, 0.068 )
, ( Date.fromTime 1483521679, 0.067 )
] |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
|
Yikes, that's...a lot. Could you get that down to a SSCCE? |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
mgold
Jan 16, 2017
Contributor
The SVG path says it's expecting a number but given a string. This is odd, because paths are supposed to be strings. But what's even more interesting is that NaN appears in the string. I've gotten DOM errors in D3 (a JS library) when doing the same thing, so that's likely something to focus on. You can obtain NaN in Elm with 0/0 (verify with isNaN).
|
The SVG path says it's expecting a number but given a string. This is odd, because paths are supposed to be strings. But what's even more interesting is that |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jackalcooper
Jan 16, 2017
@rtfeldman Sorry, probably not. Because this is based on the example @gampleman wrote. So to reproduce the error it requires the boilerplate of the visualization library. The only difference between his and mine is the model = [...] part. Anyway I would try to downsize it for you.
jackalcooper
commented
Jan 16, 2017
•
|
@rtfeldman Sorry, probably not. Because this is based on the example @gampleman wrote. So to reproduce the error it requires the boilerplate of the visualization library. The only difference between his and mine is the |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jackalcooper
Jan 16, 2017
@mgold @gampleman I found that the exception seems to appear when there are three same dates back to back in a row. Like this one:
( Date.fromTime 1483521850, 0.107 )
, ( Date.fromTime 1483521850, 0.266 )
, ( Date.fromTime 1483521850, 0.285 )
jackalcooper
commented
Jan 16, 2017
•
|
@mgold @gampleman I found that the exception seems to appear when there are three same dates back to back in a row. Like this one:
|
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
gampleman
Jan 16, 2017
So there are three things going on here:
-
The SVG library throws a runtime exception when passed an invalid parameter to the
dattribute. This violates the "no-runtime exceptions" promise. AFAIK there is no easy solution to this problem, but I'm trying to get some momentum going for a more type safe SVG library (see elm-dev for that, although the current proposal wouldn't solve this problem). -
elm-visualization produces this invalid data. Let's tackle that in gampleman/elm-visualization#3.
-
The underlying cause is that float math is unsafe for this purpose and can produce NaN values. Some of this is tracked in https://github.com/elm-lang/core/issues/721.
gampleman
commented
Jan 16, 2017
•
|
So there are three things going on here:
|
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jackalcooper
Jan 16, 2017
Thank you @gampleman . I'm going to close this issue since elm-visualization produces the invalid data.
jackalcooper
commented
Jan 16, 2017
|
Thank you @gampleman . I'm going to close this issue since elm-visualization produces the invalid data. |
jackalcooper commentedJan 14, 2017
•
edited
Edited 1 time
-
jackalcooper
edited Jan 14, 2017 (most recent)
I am not sure what this has anything to do with particular library. It happened when I'm using
gampleman/elm-visualizationpkg. It seems to have something to do with Date converted from Unix timestamp or overwhelming amount of DOM element(I'm using it to render a line chart with data sent through Phoenix Channel).