1+ """
2+ Segment(args...)
3+
4+ Represent a Segment line with given arguments.
5+
6+ $(print_doc (SEGMENT_DEFAULT))
7+ """
8+ mutable struct Segment <: SGMarks
9+ opts
10+ function Segment (;opts... )
11+ optsd = val_opts (opts)
12+ cp_SEGMENT_DEFAULT = update_default_opts! (deepcopy (SEGMENT_DEFAULT), optsd)
13+ if (cp_SEGMENT_DEFAULT[:x ] == 0 && cp_SEGMENT_DEFAULT[:y ] == 0 ) || ((cp_SEGMENT_DEFAULT[:lower ] isa Integer && cp_SEGMENT_DEFAULT[:lower ] == 0 ) || (cp_SEGMENT_DEFAULT[:upper ] isa Integer && cp_SEGMENT_DEFAULT[:upper ] == 0 )) || (cp_SEGMENT_DEFAULT[:lower ] isa Float64 && cp_SEGMENT_DEFAULT[:upper ] isa Float64)
14+ throw (ArgumentError (" Segment plot needs one of x and y keyword arguments and both lower and upper keyword arguments" ))
15+ end
16+ new (cp_SEGMENT_DEFAULT)
17+ end
18+ end
19+
20+ # Segment graphic produce a simple 2D Segment line
21+ # It requires three keyword arguments; one of x and y + lower and upper
22+ # It needs the input data set to be passed dirctly to vega
23+ function _push_plots! (vspec,plt:: Segment , all_args; idx= 1 )
24+ # check if the required arguments are passed
25+ _check_and_normalize! (plt, all_args)
26+ _add_legends! (plt, all_args, idx)
27+ opts = plt. opts
28+
29+ s_spec = Dict {Symbol,Any} ()
30+ s_spec[:type ] = " group"
31+ s_spec[:clip ] = something (opts[:clip ], all_args. opts[:clip ])
32+ s_spec_marks = Dict {Symbol,Any} ()
33+ s_spec_marks[:type ] = " rect"
34+ s_spec_marks[:from ] = Dict (:data => " source_0_$idx " )
35+ s_spec_marks[:encode ] = Dict {Symbol,Any} ()
36+ s_spec_marks[:encode ][:enter ] = Dict {Symbol,Any} ()
37+ s_spec_marks[:encode ][:enter ][:opacity ] = Dict (:value => opts[:opacity ])
38+ s_spec_marks[:encode ][:enter ][:strokeWidth ] = Dict (:value => opts[:thickness ])
39+
40+ s_spec_marks[:encode ][:enter ][:stroke ] = Dict {Symbol,Any} ()
41+
42+ # group in all plots uses the same scale
43+ if opts[:group ] === nothing
44+ s_spec_marks[:encode ][:enter ][:stroke ][:value ] = opts[:color ]
45+ else
46+ s_spec[:from ] = Dict {Symbol,Any} ()
47+ s_spec[:from ][:facet ] = Dict {Symbol,Any} ()
48+ s_spec[:from ][:facet ][:name ] = " group_facet_source"
49+ s_spec[:from ][:facet ][:data ] = " source_0_$idx "
50+ s_spec[:from ][:facet ][:groupby ] = opts[:group ]
51+ s_spec_marks[:from ][:data ] = " group_facet_source"
52+ s_spec_marks[:encode ][:enter ][:stroke ][:scale ] = " group_scale"
53+ s_spec_marks[:encode ][:enter ][:stroke ][:field ] = opts[:group ]
54+ # group is the 5th element of scales
55+ addto_group_scale! (vspec[:scales ][5 ], " source_0_$idx " , opts[:group ], all_args)
56+ end
57+ if opts[:x ] != 0
58+ # vertical
59+ s_spec_marks[:encode ][:enter ][:x ] = Dict {Symbol,Any} ()
60+ if opts[:x2axis ]
61+ s_spec_marks[:encode ][:enter ][:x ][:scale ] = " x2"
62+ addto_scale! (all_args, 2 , all_args. ds, opts[:x ])
63+ addto_axis! (vspec[:axes ][2 ], all_args. axes[2 ], opts[:x ])
64+ else
65+ s_spec_marks[:encode ][:enter ][:x ][:scale ] = " x1"
66+ addto_scale! (all_args, 1 , all_args. ds, opts[:x ])
67+ addto_axis! (vspec[:axes ][1 ], all_args. axes[1 ], opts[:x ])
68+ end
69+ s_spec_marks[:encode ][:enter ][:x ][:field ] = opts[:x ]
70+ s_spec_marks[:encode ][:enter ][:y ] = Dict {Symbol,Any} ()
71+ s_spec_marks[:encode ][:enter ][:y2 ] = Dict {Symbol,Any} ()
72+
73+ l_val = false
74+ u_val = false
75+ if opts[:lower ] isa Float64
76+ lower_value = opts[:lower ]
77+ opts[:lower ] = opts[:upper ]
78+ l_val = true
79+ end
80+ if opts[:upper ] isa Float64
81+ upper_value = opts[:upper ]
82+ opts[:upper ] = opts[:lower ]
83+ u_val = true
84+ end
85+
86+ if opts[:y2axis ]
87+ s_spec_marks[:encode ][:enter ][:y ][:scale ] = " y2"
88+ addto_scale! (all_args, 4 , all_args. ds, opts[:lower ])
89+ addto_axis! (vspec[:axes ][4 ], all_args. axes[4 ], opts[:lower ])
90+ s_spec_marks[:encode ][:enter ][:y2 ][:scale ] = " y2"
91+ addto_scale! (all_args, 4 , all_args. ds, opts[:upper ])
92+ else
93+ s_spec_marks[:encode ][:enter ][:y ][:scale ] = " y1"
94+ addto_scale! (all_args, 3 , all_args. ds, opts[:lower ])
95+ addto_axis! (vspec[:axes ][3 ], all_args. axes[3 ], opts[:lower ])
96+ s_spec_marks[:encode ][:enter ][:y2 ][:scale ] = " y1"
97+ addto_scale! (all_args, 3 , all_args. ds, opts[:upper ])
98+ end
99+ l_val ? s_spec_marks[:encode ][:enter ][:y ][:value ] = lower_value : s_spec_marks[:encode ][:enter ][:y ][:field ] = opts[:lower ]
100+ u_val ? s_spec_marks[:encode ][:enter ][:y2 ][:value ] = upper_value : s_spec_marks[:encode ][:enter ][:y2 ][:field ] = opts[:upper ]
101+
102+ else
103+ # horizontal
104+ s_spec_marks[:encode ][:enter ][:y ] = Dict {Symbol,Any} ()
105+ if opts[:y2axis ]
106+ s_spec_marks[:encode ][:enter ][:y ][:scale ] = " y2"
107+ addto_scale! (all_args, 4 , all_args. ds, opts[:y ])
108+ addto_axis! (vspec[:axes ][4 ], all_args. axes[4 ], opts[:y ])
109+ else
110+ s_spec_marks[:encode ][:enter ][:y ][:scale ] = " y1"
111+ addto_scale! (all_args, 3 , all_args. ds, opts[:y ])
112+ addto_axis! (vspec[:axes ][3 ], all_args. axes[3 ], opts[:y ])
113+ end
114+ s_spec_marks[:encode ][:enter ][:y ][:field ] = opts[:y ]
115+ s_spec_marks[:encode ][:enter ][:x ] = Dict {Symbol,Any} ()
116+ s_spec_marks[:encode ][:enter ][:x2 ] = Dict {Symbol,Any} ()
117+ l_val = false
118+ u_val = false
119+ if opts[:lower ] isa Float64
120+ lower_value = opts[:lower ]
121+ opts[:lower ] = opts[:upper ]
122+ l_val = true
123+ end
124+ if opts[:upper ] isa Float64
125+ upper_value = opts[:upper ]
126+ opts[:upper ] = opts[:lower ]
127+ u_val = true
128+ end
129+
130+ if opts[:x2axis ]
131+ s_spec_marks[:encode ][:enter ][:x ][:scale ] = " x2"
132+ addto_scale! (all_args, 2 , all_args. ds, opts[:lower ])
133+ addto_axis! (vspec[:axes ][2 ], all_args. axes[2 ], opts[:lower ])
134+ s_spec_marks[:encode ][:enter ][:x2 ][:scale ] = " x2"
135+ addto_scale! (all_args, 2 , all_args. ds, opts[:upper ])
136+ else
137+ s_spec_marks[:encode ][:enter ][:x ][:scale ] = " x1"
138+ addto_scale! (all_args, 1 , all_args. ds, opts[:lower ])
139+ addto_axis! (vspec[:axes ][1 ], all_args. axes[1 ], opts[:lower ])
140+ s_spec_marks[:encode ][:enter ][:x2 ][:scale ] = " x1"
141+ addto_scale! (all_args, 1 , all_args. ds, opts[:upper ])
142+ end
143+ l_val ? s_spec_marks[:encode ][:enter ][:x ][:value ] = lower_value : s_spec_marks[:encode ][:enter ][:x ][:field ] = opts[:lower ]
144+ u_val ? s_spec_marks[:encode ][:enter ][:x2 ][:value ] = upper_value : s_spec_marks[:encode ][:enter ][:x2 ][:field ] = opts[:upper ]
145+ end
146+ filter_data = Dict {Symbol,Any} ()
147+ filter_data[:name ] = " source_0_$idx "
148+ filter_data[:source ] = " source_0"
149+ filter_data[:transform ] = [Dict {Symbol,Any} (:type => :filter , :expr => " (isValid(datum['$(opts[:x ]) ']) || isValid(datum['$(opts[:y ]) '])) && isValid(datum['$(opts[:lower ]) ']) && isValid(datum['$(opts[:upper ]) '])" )]
150+
151+ push! (vspec[:data ], filter_data)
152+ s_spec[:marks ] = [s_spec_marks]
153+ push! (vspec[:marks ], s_spec)
154+ end
155+
156+
157+ # converts all column names to string, also check if the required arguments are passed
158+ # TODO use macro to generate repeated code
159+ function _check_and_normalize! (plt:: Segment , all_args)
160+ opts = plt. opts
161+ ds = all_args. ds
162+ cols = all_args. referred_cols
163+ if opts[:x ] != 0 && length (IMD. index (ds)[opts[:x ]]) == 1
164+ append! (cols, IMD. index (ds)[opts[:x ]])
165+ opts[:x ] = _colname_as_string (ds, opts[:x ])
166+ elseif opts[:x ] != 0
167+ @goto argerr
168+ end
169+ if opts[:y ] != 0 && length (IMD. index (ds)[opts[:y ]]) == 1
170+ append! (cols, IMD. index (ds)[opts[:y ]])
171+ opts[:y ] = _colname_as_string (ds, opts[:y ])
172+ elseif opts[:y ] != 0
173+ @goto argerr
174+ end
175+ if ! isa (opts[:lower ], Float64) && length (IMD. index (ds)[opts[:lower ]]) == 1
176+ append! (cols, IMD. index (ds)[opts[:lower ]])
177+ opts[:lower ] = _colname_as_string (ds, opts[:lower ])
178+ elseif ! isa (opts[:lower ], Float64)
179+ @goto argerr
180+ end
181+ if ! isa (opts[:upper ], Float64) && length (IMD. index (ds)[opts[:upper ]]) == 1
182+ append! (cols, IMD. index (ds)[opts[:upper ]])
183+ opts[:upper ] = _colname_as_string (ds, opts[:upper ])
184+ elseif ! isa (opts[:upper ], Float64)
185+ @goto argerr
186+ end
187+ if opts[:group ] != = nothing
188+ if length (IMD. index (ds)[opts[:group ]]) == 1
189+ append! (cols, IMD. index (ds)[opts[:group ]])
190+ opts[:group ] = _colname_as_string (ds, opts[:group ])
191+ else
192+ @goto argerr
193+ end
194+ end
195+ return plt
196+ @label argerr
197+ throw (ArgumentError (" only a single column must be selected" ))
198+ end
199+
200+
201+ function _add_legends! (plt:: Segment , all_args, idx)
202+ opts = plt. opts
203+ # find the suitable scales for the legend
204+ # group, color, symbol, angle, ...
205+ which_scale = [opts[:group ]]
206+
207+ if opts[:legend ] === nothing
208+ legend_id = " __internal__name__for__legend__$idx "
209+ else
210+ legend_id = opts[:legend ]
211+ end
212+ if all_args. legends isa Vector
213+ loc_of_leg = findfirst (x-> x. opts[:name ] == legend_id, all_args. legends)
214+ else
215+ loc_of_leg = nothing
216+ end
217+ if loc_of_leg != = nothing # user provided some customisation
218+ leg_spec = all_args. legends[loc_of_leg]
219+ else
220+ leg_spec = Legend (name = legend_id)
221+ end
222+
223+ leg_spec_cp = Dict {Symbol, Any} ()
224+ if which_scale[1 ] != = nothing
225+ _title = which_scale[1 ]
226+ leg_spec_cp[:fill ] = " group_scale"
227+ _build_legen! (leg_spec_cp, leg_spec. opts, " square" , _title, " $(legend_id) _group_scale_legend_$idx " , all_args)
228+ push! (all_args. out_legends, leg_spec_cp)
229+ end
230+ end
0 commit comments