; docformat = 'rst'
;+
; Plot 1- and 2-sigma contours for covariance matrix
;-
;+
; Plot 1- and 2-sigma contours for covariance matrix
; :Params:
; cov_mat : in, required
; [n, n] covariance matrix (symmetric)
; :Keywords:
; means : in, optional, default=0
; [n] mean of each parameter
; labels : in, optional, type=strarr
; [n] label for plot axes
; reverse : in, optional
; [n] Reverse parameters: 1 for yes, 0 for no
; true_means : in, optional
; [n] "True" values to show on plots
; plotfile : in, optional
; See ajs_plot_start
; show_plot : in, optional
; See ajs_plot_start
; :History:
; 31 Mar 2008 Written, Anthony Smith
;
; 14 May 2008 Added true_means
;-
PRO ajs_cov_mat_plot, cov_mat, means=means, labels=labels, reverse=reverse, $
true_means=true_means, plotfile=plotfile, $
show_plot=show_plot
compile_opt idl2
;; Check dimensions of covariance matrix
dims_mat = size(cov_mat, /dimensions)
IF n_elements(dims_mat) NE 2 THEN $
message, 'Wrong number of dimensions for covariance matrix [n, n]' $
ELSE IF dims_mat[0] NE dims_mat[1] THEN $
message, 'Inconsistent dimensions for covariance matrix [n, n]'
n_vars = dims_mat[0]
;; Means and labels
IF n_elements(means) GT 0 AND n_elements(means) NE n_vars THEN $
message, 'Incorrect number of elements for means' $
ELSE IF n_elements(means) EQ 0 THEN $
means = intarr(n_vars)
IF n_elements(labels) GT 0 AND n_elements(labels) NE n_vars THEN $
message, 'Incorrect number of elements for labels' $
ELSE IF n_elements(labels) EQ 0 THEN $
labels = strarr(n_vars)
IF n_elements(reverse) GT 0 AND n_elements(reverse) NE n_vars THEN $
message, 'Incorrect number of elements for reverse' $
ELSE IF n_elements(reverse) EQ 0 THEN $
reverse = intarr(n_vars)
IF NOT array_equal(cov_mat, transpose(cov_mat)) THEN $
message, 'Covariance matrix not symmetrical'
;; Clear plot
IF !d.name EQ 'X' THEN $
erase
IF n_vars GT 3 THEN $
csize = 0.3 $
ELSE $
csize = 0.5
ygap = csize / 30.
;; Start plot
IF n_elements(plotfile) GT 0 OR keyword_set(show_plot) THEN BEGIN
open = 1
ajs_ellipse_plot, plotfile=plotfile, open=open
thick = 2
ENDIF ELSE BEGIN
open = 0
thick = 1
csize = csize * 1.5
ENDELSE
;; Disable Gaussian plots (all identical - unnecessary!)
FOR i = 1, n_vars - 1 DO BEGIN ; Row, counting from top
FOR j = 0, n_vars - 2 DO BEGIN ; Column, counting from left
IF (i GT 0 OR j LT n_vars - 1) AND (i - j LT 2) THEN BEGIN
;; Plot something (else leave blank space)
;; Axis labels
IF i - j EQ 1 THEN BEGIN
xtitle = labels[j + 1]
ytitle = labels[i - 1]
doxaxis = 1
doyaxis = 1
ENDIF ELSE BEGIN
xtitle = ''
ytitle = ''
doxaxis = 0
doyaxis = 0
ENDELSE
;; Next multiplot subplot (goes left then down)
IF i EQ 1 AND j EQ 0 THEN $
multiplot, [n_vars - 1, n_vars - 1], doxaxis=doxaxis, $
doyaxis=doyaxis, ygap=ygap $
ELSE $
multiplot, doxaxis=doxaxis, doyaxis=doyaxis
IF i EQ 0 OR j EQ n_vars - 1 THEN BEGIN
;; Gaussian (disabled: check FOR loops)
;; IF i EQ 0 THEN BEGIN
;; ;; Upright Gaussian
;; mean = means[j + 1]
;; sigma = sqrt(cov_mat[j + 1, j + 1])
;; x = ajs_linspace(mean - 3 * sigma, mean + 3 * sigma, 101)
;; gauss = exp(- (x - mean) ^ 2 / 2 / sigma ^ 2) $
;; / sigma / sqrt(2 * !PI)
;; plot, x, gauss / max(gauss), /xstyle, /ystyle, $
;; xtitle=xtitle, ytitle=ytitle
;; ENDIF ELSE BEGIN
;; ;; Sideways Gaussian
;; mean = means[i - 1]
;; sigma = sqrt(cov_mat[i - 1, i - 1])
;; x = ajs_linspace(mean - 3 * sigma, mean + 3 * sigma, 101)
;; gauss = exp(- (x - mean) ^ 2 / 2 / sigma ^ 2) $
;; / sigma / sqrt(2 * !PI)
;; plot, gauss / max(gauss), x, /xstyle, /ystyle, $
;; xtitle=xtitle, ytitle=ytitle
;; ENDELSE
ENDIF ELSE BEGIN
;; 1- and 2-sigma contour plot
;; Correlation
sigma_x = sqrt(cov_mat[j + 1, j + 1])
sigma_y = sqrt(cov_mat[i - 1, i - 1])
rho = cov_mat[i - 1, j + 1] / sigma_x / sigma_y
xrange = [means[j + 1] - 2 * sigma_x, $
means[j + 1] + 2 * sigma_x]
yrange = [means[i - 1] - 2 * sigma_y, $
means[i - 1] + 2 * sigma_y]
IF n_elements(true_means) GT 1 THEN BEGIN
;; Plot '+' symbol for "true" values
xrange[0] = min([xrange[0], true_means[j + 1] $
- abs(true_means[j + 1]) * 1e-6])
xrange[1] = max([xrange[1], true_means[j + 1] $
+ abs(true_means[j + 1]) * 1e-6])
yrange[0] = min([yrange[0], true_means[i - 1] $
- abs(true_means[i - 1]) * 1e-6])
yrange[1] = max([yrange[1], true_means[i - 1] $
+ abs(true_means[i - 1]) * 1e-6])
ENDIF
IF reverse[j + 1] THEN $
xrange = reverse(xrange)
IF reverse[i - 1] THEN $
yrange = reverse(yrange)
ajs_ellipse_plot, sigma_x, sigma_y, $
means[j + 1], means[i - 1], $
rho=rho, n_sigma=[1, 2], $
xrange=xrange, yrange=yrange, $
;;/xstyle, /ystyle, $
xtitle=xtitle, ytitle=ytitle, $
charsize=csize, xthick=thick, $
ythick=thick, charthick=thick
IF n_elements(true_means) GT 1 THEN $
;; Plot '+' symbol for "true" values
oplot, [true_means[j + 1]], [true_means[i - 1]], psym=1
ENDELSE
ENDIF ELSE BEGIN
;; Next subplot (leave blank)
IF i EQ 0 AND j EQ 0 THEN $
multiplot, [n_vars, n_vars], gap=0 $
ELSE $
multiplot
ENDELSE
ENDFOR
ENDFOR
;; Close plot (if necessary)
IF open EQ 1 THEN $
ajs_ellipse_plot, plotfile=plotfile, /close, show_plot=show_plot
;; Reset multiplot options
;; IF n_vars GT 2 THEN $
;; !P.charsize = charsizetemp
multiplot, /default
END
;+
; Test ajs_cov_mat_plot
;-
PRO ajs_cov_mat_plot_test
means = [-23.042634, -0.38052661, 0.017801707, 17.324397, 0.58152665, 0.24535320]
reverse = [1, 0, 0, 1, 0, 0]
labels = ['M*', '!4a!3', '!4u!3*', '!4l!3*', '!4r!Dl!U!3', '!4b!3']
cov_mat = [[0.00011233944, 0.00012717791, 1.5205410e-06, 2.5459600e-05, 4.4394161e-06, 5.2019502e-06], $
[0.00012717791, 0.00020450268, 1.5074665e-06, 2.4230836e-05, 3.2560968e-07, -4.1112576e-06], $
[1.5205410e-06, 1.5074665e-06, 3.4861713e-08, 4.4584887e-07, 6.8802010e-08, 1.0825542e-07], $
[2.5459600e-05, 2.4230836e-05, 4.4584887e-07, 2.5795079e-05, 2.0363024e-06, 1.1370081e-05], $
[4.4394161e-06, 3.2560968e-07, 6.8802010e-08, 2.0363024e-06, 4.6717352e-06, 1.4206954e-06], $
[5.2019502e-06, -4.1112576e-06, 1.0825542e-07, 1.1370081e-05, 1.4206954e-06, 1.5966081e-05]]
ajs_cov_mat_plot, cov_mat, means=means, reverse=reverse, labels=labels, $
/show_plot
END