-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplot.lisp
More file actions
274 lines (239 loc) · 10.4 KB
/
plot.lisp
File metadata and controls
274 lines (239 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
(in-package #:bayesian-analysis)
;;; api
(defgeneric plot-result (optimization-result &key))
(defgeneric plot-result-models (input-model result-model data &key))
(defgeneric plot-iteration-values (mcmc-result &key (params-to-plot) (start) end (every)))
(defgeneric get-iteration-value (mcmc-result parameter &key (start) end (every)))
(defgeneric plot-data (data &key))
(defgeneric plot-likelihood (mcmc-result &key (start) end (every)))
;;; implementation
(defun %get-mgl-data (data x-slot other-slots)
(let+ (((&values min-x max-x)
(iter
(for x in-sequence (slot-value data x-slot))
(minimize x into min-x)
(maximize x into max-x)
(finally (return (values min-x max-x)))))
(len (length (slot-value data x-slot)))
(offset (+ min-x (/ (- max-x min-x) 2))))
(values
(iter
(for i from 0 below len)
(collect
(append (list (- (aref (slot-value data x-slot) i) offset))
(iter
(for slot in other-slots)
(collect (aref (slot-value data slot) i))))))
min-x max-x offset)))
(defun %get-gnuplot-labels-for-1x/1y-and-title (x-slot y-slot title xlabel ylabel offset)
(labels ((cmd (fmt-str &rest args)
(apply #'format t fmt-str args)
(mgl-gnuplot:command (apply #'format nil fmt-str args)))
(iff (obj else) (if obj obj else)))
(let+ ((x (iff xlabel x-slot))
(xx (format nil "~a - ~f" x offset))
(y (iff ylabel y-slot)))
(values xx y
(iff title (format nil "~a_i[~a_i - ~f]" y x offset))))))
(defun get-plot-mgl-plot-data (data independent-parameter other-parameters
plot-type style title xlabel ylabel)
(labels ((cmd (fmt-str &rest args)
(apply #'format t fmt-str args)
(mgl-gnuplot:command (apply #'format nil fmt-str args))))
(let+ (((&values plot-data min-x max-x offset)
(%get-mgl-data data
independent-parameter
other-parameters))
((&values x y title) (%get-gnuplot-labels-for-1x/1y-and-title
independent-parameter (first other-parameters) title xlabel ylabel offset))
(options (format nil "with ~a ~a title '~a'"
plot-type style title)))
(values
(mgl-gnuplot:data* plot-data options) x y min-x max-x offset))))
(defparameter *data-transparency* 0.2)
(defparameter *2d-data-circle-size* 1)
(defun get-plot-mgl-data-depending-on-type (data style title xlabel ylabel)
(labels ((f (slot) (first (slot-value data slot))))
(cond
((= 1 (no-independent-parameters data)
(no-dependent-parameters data)
(no-error-parameters data))
(get-plot-mgl-plot-data data
(f 'independent-parameters)
(list (f 'dependent-parameters)
(f 'error-parameters))
"errorbars" style
title xlabel ylabel))
((and (= 1 (no-independent-parameters data) (no-dependent-parameters data))
(= 0 (no-error-parameters data)))
(get-plot-mgl-plot-data data
(f 'independent-parameters)
(list (f 'dependent-parameters))
"points" style title xlabel ylabel))
((and (= 2 (no-independent-parameters data))
(= (no-error-parameters data)
(no-dependent-parameters data)
0))
(mgl-gnuplot:command
(format nil "set style fill transparent solid ~,2f noborder" *data-transparency*))
(mgl-gnuplot:command
(format nil "set style circle radius ~,2f transparent solid 0.1 noborder" *2d-data-circle-size*))
(get-plot-mgl-plot-data data
(f 'independent-parameters)
(cdr (slot-value data 'independent-parameters))
"circles" style title xlabel ylabel))
(t (error "plotting of given data not supported.")))))
(defmethod plot-data ((data data) &key (style "lc 7 pt 7 lw 1 pw 1")
title xlabel ylabel)
(labels ((cmd (fmt-str &rest args)
(apply #'format t fmt-str args)
(mgl-gnuplot:command (apply #'format nil fmt-str args))))
(let+ (((&values plot-data x y min-x max-x offset)
(get-plot-mgl-data-depending-on-type data style title xlabel ylabel)))
(unless (= min-x max-x)
(cmd "set xrange [~f:~f]" (- min-x offset) (- max-x offset)))
(cmd "set xlabel '~a'" x)
(cmd "set ylabel '~a'" y)
(mgl-gnuplot:plot* (list plot-data)))))
(defmethod plot-result ((result optimized-parameters)
&key (no-steps 1000)
(style-options/data "pt 7")
(style-options/input "with lines lt 3 lw 0.3 lc 0 title 'input input-model'")
(style-options/result "with lines lw 1.5 lc 7 title 'result input-model'")
(enclose-in-plot t)
(overwrite-xlabel))
(let+ (((&slots model data algorithm-result) result)
((&slots input-model) algorithm-result))
(plot-result-models input-model model data
:no-steps no-steps
:style-options/data style-options/data
:style-options/input style-options/input
:style-options/result style-options/result
:enclose-in-plot enclose-in-plot
:overwrite-xlabel overwrite-xlabel)))
(defmethod plot-result-models ((input-model model) (result-model model) data
&key (no-steps 1000)
(style-options/data "pt 7")
(style-options/input "with lines lt 3 lw 0.3 lc 0 title 'input input-model'")
(style-options/result "with lines lw 1.5 lc 7 title 'result input-model'")
(include-input-model t)
(include-data t)
(enclose-in-plot t)
(overwrite-xlabel))
(let+ ((input-fun (ba:get-1d-plot-function input-model))
(result-fun (ba:get-1d-plot-function result-model))
((&values plot-data x-label y-label min-x max-x offset)
(get-plot-mgl-data-depending-on-type data style-options/data "" nil nil))
((&values model-input-data model-results-data)
(if (= min-x max-x)
(values `((,(- min-x offset) ,(funcall input-fun min-x)))
`((,(- min-x offset) ,(funcall result-fun min-x))))
(iter
(for x from min-x to max-x by (/ (- max-x min-x) no-steps))
(collect (list (- x offset) (funcall input-fun x)) into id)
(collect (list (- x offset) (funcall result-fun x)) into rd)
(finally (return (values id rd)))))))
(labels ((cmd (fmt-str &rest args)
(apply #'format t fmt-str args)
(mgl-gnuplot:command (apply #'format nil fmt-str args))))
(cmd "set xrange [~f:~f]" (- min-x offset) (- max-x offset))
(cmd "set xlabel '~a'" (if overwrite-xlabel overwrite-xlabel x-label))
(cmd "set ylabel '~a'" y-label))
(let ((d `(,@(if include-data (list plot-data))
,@(if include-input-model (list (mgl-gnuplot:data* model-input-data style-options/input)))
,(mgl-gnuplot:data* model-results-data style-options/result))))
(if enclose-in-plot (mgl-gnuplot:plot* d) d))))
(defmethod get-iteration-value-data ((result mcmc-optimization-result) parameter &key (start 0) (end) (every 1))
(let+ (((&slots iteration-accumulator) result)
((&slots marginalized-parameters parameter-array no-iterations) iteration-accumulator)
(end (if end end no-iterations))
(index-param (position parameter marginalized-parameters)))
(unless index-param (error "Unknown parameter: ~a" parameter))
(iter
(for i from start below end)
(if (= (mod i every) 0)
(collect (list i (aref parameter-array index-param i)))))))
(defmethod plot-iteration-values ((result mcmc-optimization-result)
&key (params-to-plot) (start 0) (end) (every 1)
(other-plot-options ""))
(let+ (((&slots iteration-accumulator) result)
((&slots marginalized-parameters parameter-array no-iterations) iteration-accumulator))
(alexandria:if-let (diff (set-difference params-to-plot marginalized-parameters))
(error "Unknown parameters: ~{~a~^, ~}" diff))
(mgl-gnuplot:plot*
(iter
(for p in (if params-to-plot params-to-plot marginalized-parameters))
(for index-param = (position p marginalized-parameters))
(collect
(get-iteration-value-data ))))))
(defmethod plot-parameter-distribution ((result optimized-parameters) parameter
&key title
(offset-around-median t)
(offset-around)
(fn-on-x #'identity)
(return-mgl-data nil)
(boxes-fun
(constantly
"u 1:2 with boxes lc 7 fs solid 0.3 noborder title ''")))
(let+ ((parameter-info (get-parameter-infos result parameter))
((&slots binned-data median confidence-min confidence-max max-counts absolute-error) parameter-info)
(median (funcall fn-on-x median))
(confidence-min (funcall fn-on-x confidence-min))
(confidence-max (funcall fn-on-x confidence-max))
(offset (cond
(offset-around offset-around)
(offset-around-median median)
(t 0d0)))
(binned-data
(iter
(for d in binned-data)
(collect (list (- (funcall fn-on-x (first d)) offset)
(second d)))))
(mgl-data
(list
(mgl-gnuplot:data* (iter
(for (x c) in binned-data)
(if (<= (- confidence-min offset) x (- confidence-max offset))
(collect (list x c))))
(format nil (funcall boxes-fun)))
(mgl-gnuplot:data* binned-data (format nil "u 1:2 with histeps lc 0 title '~a'"
(cond
((stringp title) title)
((functionp title) (funcall title median))
(t (let ((digits (max 2 (1+ (ceiling
(- (log median 10)))))))
(format nil
(format nil "~~a, median: ~~,~Df +/- ~~,~Df"
digits digits)
parameter median
(/ (- confidence-max confidence-min) 2d0))))))))))
(if return-mgl-data
mgl-data
(labels ((cmd (fmt-str &rest args)
(apply #'format t fmt-str args)
(mgl-gnuplot:command (apply #'format nil fmt-str args))))
(cmd "unset arrow")
(cmd "set arrow from ~,10f,0 to ~,10f,~,10f nohead front lt 1 lw 2 lc 7"
(- median offset)
(- median offset)
(* 1.05 max-counts))
(mgl-gnuplot:plot* mgl-data)))))
(defmethod plot-likelihood ((result mcmc-optimization-result) &key (start 0) (end) (every 1))
(let+ (((&slots iteration-accumulator input-model data) result)
(new-model (copy-object input-model))
(likelihood (initialize-likelihood new-model data))
((&slots marginalized-parameters parameter-array no-iterations) iteration-accumulator)
(end (if end end no-iterations)))
(mgl-gnuplot:plot*
(list
(mgl-gnuplot:data*
(iter outer
(for i from start below end)
(when (= (mod i every) 0)
(collect
(iter
(for p in marginalized-parameters)
(for index-param = (position p marginalized-parameters))
(setf (slot-value new-model p) (aref parameter-array index-param i))
(finally (return (list i (funcall (varying/log-of-likelihood likelihood)))))))))
(format nil "with steps title 'likelihood'"))))))