@@ -3,16 +3,12 @@ use plotters::prelude::*;
3
3
use std:: fs:: File ;
4
4
use std:: io:: BufReader ;
5
5
6
- use chrono:: NaiveDate ;
7
- use std:: str:: FromStr ;
8
-
9
6
#[ derive( serde_derive:: Deserialize ) ]
10
7
struct DailyData {
11
- date : String ,
12
8
#[ serde( default ) ]
13
- new_cases_smoothed_per_million : f64 ,
9
+ new_cases : f64 ,
14
10
#[ serde( default ) ]
15
- total_cases_per_million : f64 ,
11
+ total_cases : f64 ,
16
12
}
17
13
18
14
#[ derive( serde_derive:: Deserialize ) ]
@@ -22,68 +18,70 @@ struct CountryData {
22
18
23
19
fn main ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
24
20
let root =
25
- BitMapBackend :: gif ( "/tmp/tick_control.gif" , ( 800 , 600 ) , 100 ) ?. into_drawing_area ( ) ;
26
-
27
- for a in 0 ..200 {
28
-
29
- root. fill ( & WHITE ) ?;
21
+ SVGBackend :: new ( "plotters-doc-data/tick_control.svg" , ( 1024 , 768 ) ) . into_drawing_area ( ) ;
30
22
23
+ root. fill ( & WHITE ) ?;
31
24
32
- let mut chart = ChartBuilder :: on ( & root)
33
- . set_label_area_size ( LabelAreaPosition :: Left , ( 8 ) . percent ( ) )
34
- . set_label_area_size ( LabelAreaPosition :: Bottom , ( 6 ) . percent ( ) )
35
- . margin ( ( 1 ) . percent ( ) )
36
- . build_cartesian_3d (
37
- ( 20u32 ..10_0000u32 )
38
- . log_scale ( )
39
- . with_key_points ( vec ! [ 50 , 100 , 200 , 500 , 1000 , 10000 ] ) ,
40
- ( 0u32 ..1000u32 )
41
- . log_scale ( )
42
- . with_key_points ( vec ! [ 2 , 5 , 10 , 20 , 50 , 100 , 200 ] ) ,
43
- NaiveDate :: from_ymd ( 2020 , 1 , 1 ) ..NaiveDate :: from_ymd ( 2020 , 9 , 5 ) ,
44
- ) ?;
25
+ let ( upper, lower) = root. split_vertically ( 750 ) ;
45
26
46
- chart. with_projection ( |mut pb| {
47
- pb. yaw = ( 1.57 - a as f64 / 100.0 * 1.57 ) . abs ( ) ;
48
- pb. into_matrix ( )
49
- } ) ;
50
-
51
- chart
52
- . configure_axes ( )
53
- . draw ( ) ?;
27
+ lower. titled (
28
+ "Data Source: https://covid.ourworldindata.org/data/owid-covid-data.json" ,
29
+ ( "sans-serif" , 10 ) . into_font ( ) . color ( & BLACK . mix ( 0.5 ) ) ,
30
+ ) ?;
54
31
55
- let data: std:: collections:: HashMap < String , CountryData > = serde_json:: from_reader (
56
- BufReader :: new ( File :: open ( "plotters-doc-data/covid-data.json" ) ?) ,
32
+ let mut chart = ChartBuilder :: on ( & upper)
33
+ . caption ( "World COVID-19 Cases" , ( "sans-serif" , ( 5 ) . percent_height ( ) ) )
34
+ . set_label_area_size ( LabelAreaPosition :: Left , ( 8 ) . percent ( ) )
35
+ . set_label_area_size ( LabelAreaPosition :: Bottom , ( 4 ) . percent ( ) )
36
+ . margin ( ( 1 ) . percent ( ) )
37
+ . build_cartesian_2d (
38
+ ( 20u32 ..5000_0000u32 )
39
+ . log_scale ( )
40
+ . with_key_points ( vec ! [ 50 , 100 , 1000 , 10000 , 100000 , 1000000 , 10000000 ] ) ,
41
+ ( 0u32 ..50_0000u32 )
42
+ . log_scale ( )
43
+ . with_key_points ( vec ! [ 10 , 50 , 100 , 1000 , 10000 , 100000 , 200000 ] ) ,
57
44
) ?;
58
45
59
- for ( idx, & series) in [ "USA" , "CHN" ]
60
- . iter ( )
61
- . enumerate ( )
62
- {
63
- let color = Palette99 :: pick ( idx) . mix ( 1.0 ) ;
64
- chart
65
- . draw_series ( LineSeries :: new (
66
- data[ series] . data . iter ( ) . map (
67
- |DailyData {
68
- date,
69
- new_cases_smoothed_per_million,
70
- total_cases_per_million,
71
- ..
72
- } | ( * total_cases_per_million as u32 , * new_cases_smoothed_per_million as u32 , chrono:: NaiveDate :: from_str ( date) . unwrap ( ) , ) ,
73
- ) ,
74
- color. stroke_width ( 1 ) ,
75
- ) ) ?
76
- . label ( series)
77
- . legend ( move |( x, y) | Rectangle :: new ( [ ( x, y - 5 ) , ( x + 10 , y + 5 ) ] , color. filled ( ) ) ) ;
78
- }
46
+ chart
47
+ . configure_mesh ( )
48
+ . x_desc ( "Total Cases" )
49
+ . y_desc ( "New Cases" )
50
+ . draw ( ) ?;
79
51
80
- chart
81
- . configure_series_labels ( )
82
- . border_style ( & BLACK )
83
- . draw ( ) ?;
52
+ let data: std:: collections:: HashMap < String , CountryData > = serde_json:: from_reader (
53
+ BufReader :: new ( File :: open ( "plotters-doc-data/covid-data.json" ) ?) ,
54
+ ) ?;
84
55
85
- root. present ( ) ?;
56
+ for ( idx, & series) in [ "CHN" , "USA" , "RUS" , "JPN" , "DEU" , "IND" , "OWID_WRL" ]
57
+ . iter ( )
58
+ . enumerate ( )
59
+ {
60
+ let color = Palette99 :: pick ( idx) . mix ( 0.9 ) ;
61
+ chart
62
+ . draw_series ( LineSeries :: new (
63
+ data[ series] . data . iter ( ) . map (
64
+ |& DailyData {
65
+ new_cases,
66
+ total_cases,
67
+ ..
68
+ } | ( total_cases as u32 , new_cases as u32 ) ,
69
+ ) ,
70
+ color. stroke_width ( 3 ) ,
71
+ ) ) ?
72
+ . label ( series)
73
+ . legend ( move |( x, y) | Rectangle :: new ( [ ( x, y - 5 ) , ( x + 10 , y + 5 ) ] , color. filled ( ) ) ) ;
86
74
}
87
75
76
+ chart
77
+ . configure_series_labels ( )
78
+ . border_style ( & BLACK )
79
+ . draw ( ) ?;
80
+
88
81
Ok ( ( ) )
89
82
}
83
+
84
+ #[ test]
85
+ fn entry_point ( ) {
86
+ main ( ) . unwrap ( ) ;
87
+ }
0 commit comments