-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpostplot.f90
345 lines (306 loc) · 10.8 KB
/
postplot.f90
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
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
! Copyright (C) 2003-2018 John Young, Matthew Worsley
!
! This file is part of mfit.
!
! Mfit is free software: you can redistribute it and/or modify it
! under the terms of the GNU General Public License as published by
! the Free Software Foundation, either version 3 of the License, or
! (at your option) any later version.
!
! This program is distributed in the hope that it will be useful, but
! WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
! General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with this program. If not, see http://www.gnu.org/licenses/ .
module Postplot
use Plot
use Bayes
use Wrap
use Model
use Marginalise
implicit none
public
!public subroutines contained:
!
!plot_post1d - plot 1d cut through -ln(posterior) or
!-ln(marginalised posterior)
!
!plot_post2d - plot 2d slice through -ln(posterior) or
!-ln(marginalised posterior)
contains
!============================================================================
!! Plot 1d cut through -ln(posterior) or -ln(marginalised posterior)
subroutine plot_post1d(plotmargd, nlevidence, inpar, indx, &
x_title, y_title, top_title, uxmin, uxmax, device)
!subroutine arguments
logical, intent(in) :: plotmargd
double precision, intent(in) :: nlevidence
!! Model parameters (variable and non-variable)
type(allparam), intent(in) :: inpar
!! Index into variable parameters, specifying x-axis
integer, intent(in) :: indx
character(len=*), intent(in) :: x_title, y_title, top_title
double precision, intent(in) :: uxmin, uxmax
character(len=*), intent(in), optional :: device
!local variables
type(allparam) :: plotpar
logical :: mg_marg(inpar%nvar)
real, allocatable :: post_points(:, :), mpost_points(:, :)
double precision :: val, lhd, pri, lxbound, uxbound
integer :: nvar, num_points, i, istat
real :: xmin, xmax, ymin, ymax, pmin
character(len=128) :: info
!functions
integer :: pgopen
!return if nothing to plot
nvar = inpar%nvar
if (indx < 1 .or. indx > nvar) return
lxbound = model_limits(inpar%var_pos(indx, 1), inpar%var_pos(indx, 2), 1)
uxbound = model_limits(inpar%var_pos(indx, 1), inpar%var_pos(indx, 2), 2)
if (uxmax < lxbound) return
if (uxmin > uxbound) return
!adjust x range if necessary - need to keep within bound limits
if (uxmin < lxbound) then
xmin = lxbound
else
xmin = uxmin
end if
if (uxmax > uxbound) then
xmax = uxbound
else
xmax = uxmax
end if
!copy model parameters
call allparam_copy(inpar, plotpar)
!calculate grid of points
if (plotmargd) then
num_points = 20
allocate(mpost_points(num_points, 2))
mg_marg = .true.
mg_marg(indx) = .false.
else
num_points = 50
end if
allocate(post_points(num_points, 2))
do i = 1, num_points
val = xmin + ((i-1.)/(num_points-1.))*(xmax-xmin)
post_points(i, 1) = val
call allparam_setone(plotpar, indx, val)
if (plotmargd) then
mpost_points(i, 1) = val
mpost_points(i, 2) = marg_post(info, plotpar, mg_marg)
if (info /= '') print *, trim(info)
end if
lhd = likelihood(vis_data, triple_data, model_spec, plotpar%param)
pri = prior(plotpar%var_pos, plotpar%param, model_param, model_prior)
post_points(i, 2) = lhd + pri - nlevidence !fix normalisation later
end do
!calculate y range
if (plotmargd) then
ymin = minval(mpost_points(:, 2))
ymax = maxval(mpost_points(:, 2))
pmin = minval(post_points(:, 2))
post_points(:, 2) = post_points(:, 2) + (ymin - pmin)
else
ymin = minval(post_points(:, 2))
ymax = maxval(post_points(:, 2))
end if
!plot posterior
if (present(device)) then
istat = pgopen(device)
if (istat <= 0) return
end if
call pgsci(1)
call pgenv(xmin, xmax, ymin, ymax, 0, 1)
call pglab(trim(x_title), trim(y_title), trim(top_title))
if (.not. plotmargd) then
call pgsci(1)
else
call pgsci(7)
call pgsls(2)
end if
call plot_pts(x_title, '-ln(postprob)', num_points, post_points, -1, &
'post1d.dat')
call pgsci(1)
call pgsls(1)
if (plotmargd) &
call plot_pts(x_title, y_title, num_points, mpost_points, -1, &
'mpost1d.dat')
call allparam_free(plotpar)
if (allocated(post_points)) deallocate(post_points)
if (allocated(mpost_points)) deallocate(mpost_points)
end subroutine plot_post1d
!============================================================================
!! Plot 2d slice through -ln(posterior) or -ln(marginalised posterior)
subroutine plot_post2d(plotmargd, nlposterior, inpar, indx, &
x_title, y_title, top_title, uxmin, uxmax, uymin, uymax, device)
!subroutine arguments
logical, intent(in) :: plotmargd
!! Minimum of negative log posterior (in case this is not
!! sufficiently close to a grid point), needed to plot correct n-sigma
!! contours in unmarginalised case
double precision, intent(in) :: nlposterior
!! Model parameters (variable and non-variable)
type(allparam), intent(in) :: inpar
!! Indices into variable parameters, specifying axes for plot
integer, intent(in) :: indx(2)
character(len=*), intent(in) :: x_title, y_title, top_title
double precision, intent(in) :: uxmin, uxmax
double precision, intent(in) :: uymin, uymax
character(len=*), intent(in), optional :: device
!local variables
type(allparam) :: plotpar
logical :: mg_marg(inpar%nvar)
integer, parameter :: iunit = 12
character(len=20) :: save_filename
real, allocatable :: post_points(:, :)
double precision :: xval, yval, lhd, pri
double precision :: lxbound, uxbound, lybound, uybound
double precision :: sol(2)
integer :: nvar, num_points, i, j, istat
real :: xmin, xmax, ymin, ymax
character(len=128) :: info
logical :: invgray
real :: tr(6)
real :: fg, bg
integer, parameter :: nlevs_max = 3
!delta (chi^2)/2 values for 2-parameter 1-, 2-, 3-sigma confidence regions
real :: levs(nlevs_max) = (/1.15,3.08,5.90/)
!functions
integer :: pgopen
!return if nothing to plot
nvar = inpar%nvar
if (indx(1) < 1 .or. indx(1) > nvar) return
if (indx(2) < 1 .or. indx(2) > nvar) return
lxbound = &
model_limits(inpar%var_pos(indx(1), 1), inpar%var_pos(indx(1), 2), 1)
uxbound = &
model_limits(inpar%var_pos(indx(1), 1), inpar%var_pos(indx(1), 2), 2)
if (uxmax < lxbound) return
if (uxmin > uxbound) return
lybound = &
model_limits(inpar%var_pos(indx(2), 1), inpar%var_pos(indx(2), 2), 1)
uybound = &
model_limits(inpar%var_pos(indx(2), 1), inpar%var_pos(indx(2), 2), 2)
if (uymax < lybound) return
if (uymin > uybound) return
!adjust ranges if necessary - need to keep within bound limits
if (uxmin < lxbound) then
xmin = lxbound
else
xmin = uxmin
end if
if (uxmax > uxbound) then
xmax = uxbound
else
xmax = uxmax
end if
if (uymin < lybound) then
ymin = lybound
else
ymin = uymin
end if
if (uymax > uybound) then
ymax = uybound
else
ymax = uymax
end if
!copy model parameters
call allparam_copy(inpar, plotpar)
if (plotmargd) then
mg_marg = .true.
mg_marg(indx(1)) = .false.
mg_marg(indx(2)) = .false.
end if
sol(1) = inpar%param(inpar%var_pos(indx(1),1), inpar%var_pos(indx(1),2))
sol(2) = inpar%param(inpar%var_pos(indx(2),1), inpar%var_pos(indx(2),2))
!calculate grid of points
if (plotmargd) then
num_points = 20
save_filename = 'mpost2d.dat'
else
num_points = 40
save_filename = 'post2d.dat'
end if
allocate(post_points(num_points, num_points))
do i = 1, num_points
xval = xmin + ((i-1.)/(num_points-1.))*(xmax-xmin)
call allparam_setone(plotpar, indx(1), xval)
do j = 1, num_points
yval = ymin + ((j-1.)/(num_points-1.))*(ymax-ymin)
call allparam_setone(plotpar, indx(2), yval)
if (plotmargd) then
post_points(i, j) = marg_post(info, plotpar, mg_marg)
if (info /= '') print *, trim(info)
else
lhd = likelihood(vis_data, triple_data, model_spec, plotpar%param)
pri = prior(plotpar%var_pos, plotpar%param, &
model_param, model_prior)
post_points(i, j) = lhd + pri - nlposterior
end if
end do
end do
!plot posterior
if (present(device)) then
istat = pgopen(device)
if (istat <= 0) return
end if
call pgsci(1)
call pgenv(xmin, xmax, ymin, ymax, 0, -2)
call pglab(trim(x_title), trim(y_title), trim(top_title))
call pgsci(1)
!mapping from array elements to sky coordinates
tr(2) = (xmax-xmin)/real(num_points-1)
tr(6) = (ymax-ymin)/real(num_points-1)
tr(1) = xmin - tr(2)
tr(4) = ymin - tr(6)
tr(3) = 0.
tr(5) = 0.
print *, minval(post_points)
if (plotmargd) then
!(marginalisation can shift minimum)
post_points = post_points - minval(post_points)
end if
invgray = .true. !make minimum bright
if (invgray) then
fg = minval(post_points)
bg = 0.6*maxval(post_points)
else
fg = maxval(post_points)
bg = minval(post_points)
endif
call pggray(post_points, num_points, num_points, &
1, num_points, 1, num_points, fg, bg, tr)
write (51, *) (levs(i), i=1, size(levs,1))
call pgsci(2)
call pgcont(post_points, num_points, num_points, &
1, num_points, 1, num_points, levs, size(levs,1), tr)
call pgsci(1)
call pgbox('ABCNST', 0., 0, 'ABCNST', 0., 0)
call pgsci(3)
call pgpt1(real(sol(1)), real(sol(2)), 12) !mark pos'n found by minimiser
!write plotted points to text file
open (unit=iunit, file=save_filename, status='replace', action='write', &
err=91)
write (iunit, '(a)') &
'# -ln(norm. posterior probability) points from last such mfit plot'
write (iunit, '(a, 3a25)') '# ', trim(x_title), trim(y_title), &
trim(top_title)
do j = 1, num_points
yval = ymin + ((j-1.)/(num_points-1.))*(ymax-ymin)
do i = 1, num_points
xval = xmin + ((i-1.)/(num_points-1.))*(xmax-xmin)
write (iunit, '(2x, 3f25.6)') xval, yval, post_points(i,j)
end do
write (iunit, *)
end do
close (iunit)
call allparam_free(plotpar)
if (allocated(post_points)) deallocate(post_points)
return
91 print *, 'Cannot open file '//trim(save_filename)
end subroutine plot_post2d
!============================================================================
end module Postplot