Modifications to scoring and graphics production for the final version of code for the C-LAMP paper in GCB.
1 function taylor_diagram (wks:graphic ,RATIO[*][*]:numeric, CC[*][*]:numeric \
3 ;--------------------------------------------------------------------
4 ; This version of taylor_diagram supports "paneling"
5 ; It requires NCL version 4.2.0.a034 because it uses "gsn_create_legend"
6 ;--------------------------------------------------------------------
9 ; Generate a Taylor Diagram:
10 ; Generate Multiple Aspects of Model Performance in a Single Diagram
11 ; Taylor, K. E., J. Geophys. Res., 106, D7, 7183-7192, 2001
14 ; http://www.grida.no/climate/ipcc_tar/wg1/fig8-4.htm
16 ; This expects one or more datasets. The left dimension
17 ; is the number of datasets. The rightmost is the number of pts.
20 ; http://www.ncl.ucar.edu/Document/Graphics/Resources/gs.shtml
22 ; By default, the function can handle up to 10 variable comparisons..
23 ; To expand ... modify the 'Colors' and 'Markers' attributes.
24 ; The user can change / add some default settings.
26 ; The defaults that the user can modify:
29 ; ; 'made-up' resources
30 ; rOpts@Colors = (/ "blue" , "red", "green", "cyan", "black" \
31 ; , "torquoise", "brown", "yellow"/)
32 ; rOpts@Markers = (/ 2, 3, 6, 14, 9, 12, 7, 4/) ; Marker Indices
33 ; rOpts@markerTxOffset = 0.0175 ; offset for text above marker
34 ; rOpts@stnRad = (/ 1. /) ; (/ 0.50, 0.75, 1.5 /)
35 ; rOpts@centerDiffRMS = False ; True mean draw additional radii from REF
36 ; rOpts@caseLabelsFontHeightF = 0.05
37 ; rOpts@varLabelsFontHeightF = 0.013
38 ; rOpts@varLabelsYloc = 0.65
39 ; rOpts@legendWidth = 0.015
40 ; rOpts@legendHeight = 0.030*nCase
41 ; rOpts@taylorDraw = True
42 ; rOpts@taylorFrame = True
44 ; ; standard NCL resources
45 ; rOpts@tiMainString = "Taylor" ; not using title makes plot bigger
46 ; rOpts@gsMarkerSizeF = 0.0085 ; marker size
47 ; rOpts@gsMarkerThicknessF = 1.0
48 ; rOpts@txFontHeightF = 0.0125 ; text size
49 ; rOpts@tiMainFontHeightF = 0.0225 ; tiMainString size
51 ; It returns to the user a graphic object containing the
52 ; Taylor background and plotted x/y pts.
53 ; This graphic object contains a simple Taylor background appropriate
54 ; for standardized data and the markers for the datasets.
55 ; ==================================================================
56 ; This version allows paneling:
57 ; The 'cumbersome' "dum" variables were added by
58 ; Adam Phillips to allow paneling via "gsn_add_?".
59 ; ==================================================================
61 dimR = dimsizes(RATIO)
62 nCase = dimR(0) ; # of cases [models]
63 nVar = dimR(1) ; # of variables
65 ; x/y coordinates for plotting
66 X = new ( (/nCase,nVar/) , typeof(RATIO) )
67 Y = new ( (/nCase,nVar/) , typeof(RATIO) )
70 angle = acos( CC(nc,:) ) ; array operation
71 X(nc,:) = RATIO(nc,:)*cos( angle )
72 Y(nc,:) = RATIO(nc,:)*sin( angle )
78 xyMax_Panel = xyMax+ 0.10 ; paneling purposes
80 if (rOpts .and. isatt(rOpts,"txFontHeightF")) then
81 FontHeightF = rOpts@txFontHeightF ; user wants to specify size
86 ; ----------------------------------------------------------------
88 ; base plot: Based upon request of Mark Stevens
89 ; basic x-y and draw the 1.0 observed and the outer curve at 1.65
90 ; ----------------------------------------------------------------
97 rxy@tmYLBorderOn = False
98 rxy@tmXBBorderOn = False
100 rxy@tiYAxisString = "Standardized Deviations (Normalized)"
101 rxy@tiYAxisFontHeightF= FontHeightF ; default=0.025
103 rxy@tmXBMode = "Explicit"
104 rxy@tmXBValues = (/0.0,0.25,0.50,0.75,1.00,1.25,1.5/) ; major tm
105 ; default "OBS" or "REF"
106 ;rxy@tmXBLabels = (/"0.00","0.25","0.50","0.75","REF" ,"1.25","1.50"/)
107 rxy@tmXBLabels = (/" ","0.25","0.50","0.75","REF" ,"1.25","1.50"/)
108 if (rOpts .and. isatt(rOpts,"OneX") ) then ; eg: rOpts@OneX="1.00"
109 ;rxy@tmXBLabels = (/"0.00","0.25","0.50","0.75",rOpts@OneX,"1.25","1.50"/)
110 rxy@tmXBLabels = (/" ","0.25","0.50","0.75",rOpts@OneX,"1.25","1.50"/)
113 rxy@tmXBMajorLengthF = 0.015 ; default=0.02 for a vpHeightF=0.6
114 rxy@tmXBLabelFontHeightF = FontHeightF
115 rxy@tmXBMinorOn = False
116 rxy@trXMaxF = xyMax_Panel
118 rxy@tmYLMode = "Manual"
119 rxy@tmYLMinorOn = False
120 rxy@tmYLMajorLengthF = rxy@tmXBMajorLengthF
121 rxy@tmYLLabelFontHeightF = FontHeightF
122 rxy@tmYLMode = "Explicit"
123 rxy@tmYLValues = (/0.0, .25,0.50, 0.75, 1.00, 1.25, 1.5/) ; major tm
124 rxy@tmYLLabels = (/"0.00","0.25","0.50","0.75","1.00","1.25","1.50"/)
125 ;rxy@tmYLLabels = (/" ","0.25","0.50","0.75","1.00","1.25","1.50"/)
126 rxy@trYMaxF = xyMax_Panel
128 rxy@tmYRBorderOn = False
129 rxy@tmYROn = False ; Turn off right tick marks.
131 rxy@tmXTBorderOn = False
132 rxy@tmXTOn = False ; Turn off right tick marks.
134 rxy@xyDashPatterns = (/ 0 /) ; line characteristics (dash,solid)
135 rxy@xyLineThicknesses = (/ 2./) ; choose line thickness
137 rxy@gsnFrame = False ; Don't advance the frame.
139 ; create outer 'correlation axis'
140 npts = 200 ; arbitrary
141 xx = fspan(xyMin,xyMax,npts)
142 yy = sqrt(xyMax^2 - xx^2 ) ; outer correlation line (xyMax)
144 sLabels = (/"0.0","0.1","0.2","0.3","0.4","0.5","0.6" \ ; correlation labels
145 ,"0.7","0.8","0.9","0.95","0.99","1.0" /); also, major tm
146 cLabels = stringtofloat(sLabels)
147 rad = 4.*atan(1.0)/180.
148 angC = acos(cLabels)/rad ; angles: correlation labels
150 if (rOpts .and. isatt(rOpts,"tiMainString")) then
151 rxy@tiMainString = rOpts@tiMainString
152 ;rxy@tiMainOffsetYF = 0.015 ; default 0.0
153 if (isatt(rOpts,"tiMainFontHeightF")) then
154 rxy@tiMainFontHeightF = rOpts@tiMainFontHeightF
156 rxy@tiMainFontHeightF = 0.0225 ; default 0.025
159 ;;if (rOpts .and. isatt(rOpts,"gsnCenterString")) then
160 ;; rxy@gsnCenterString = rOpts@gsnCenterString ; only gsn_csm_xy
163 taylor = gsn_xy(wks,xx,yy,rxy) ; Create and draw XY plot.
166 rsrRes@gsLineThicknessF = rxy@xyLineThicknesses(0) ; line thickness
167 rsrRes@gsLineDashPattern = 0 ; solid line pattern
168 ; draw x and y to xyMax
169 dum0 = gsn_add_polyline(wks,taylor,(/0., 0. /),(/0.,xyMax/), rsrRes)
170 dum1 = gsn_add_polyline(wks,taylor,(/0.,xyMax/),(/0., 0. /), rsrRes)
172 xx = fspan(xyMin, xyOne ,npts) ; draw 1.0 standard radius
173 yy = sqrt(xyOne - xx^2)
174 rsrRes@gsLineDashPattern = 1 ; dashed line pattern
175 rsrRes@gsLineThicknessF = rxy@xyLineThicknesses(0) ; line thickness
176 dum2 = gsn_add_polyline(wks,taylor,xx,yy, rsrRes)
180 if (rOpts .and. isatt(rOpts,"stnRad") ) then
181 rsrRes@gsLineThicknessF = 1 ; rxy@xyLineThicknesses(0)
182 nStnRad = dimsizes(rOpts@stnRad)
184 dum3 = new(nStnRad,graphic)
187 xx = fspan(xyMin, rr ,npts)
188 yy = sqrt(rr^2 - xx^2)
189 dum3(n) = gsn_add_polyline(wks,taylor,xx,yy, rsrRes)
191 taylor@$unique_string("dum")$ = dum3
197 getvalues taylor ; get style info from taylor
198 "tmYLLabelFont" : tmYLLabelFont ; use for correlation axis
199 "tmYLLabelFontHeightF" : tmYLLabelFontHeightF
202 ; ----------------------------------------------------------------
205 ; ----------------------------------------------------------------
206 radC = xyMax ; for correlation labels
207 xC = radC*cos(angC*rad)
208 yC = radC*sin(angC*rad)
209 ; added to get some separation
210 xC = xC + 0.020*cos(rad*angC)
211 yC = yC + 0.060*sin(rad*angC)
213 txRes = True ; text mods desired
214 txRes@txFontHeightF = FontHeightF ; match YL
215 txRes@tmYLLabelFont = tmYLLabelFont ; match YL
216 txRes@txAngleF = -45.
217 if (.not.isatt(rOpts,"drawCorLabel") .or. rOpts@drawCorLabel) then
218 dum4 = gsn_add_text(wks,taylor,"Correlation",1.30,1.30,txRes)
219 taylor@$unique_string("dum")$ = dum4
222 txRes@txFontHeightF = FontHeightF*0.50 ; bit smaller
224 ;;dum0 = gsn_add_text(wks,taylor,"OBSERVED",1.00,0.075,txRes)
227 plRes@gsLineThicknessF = 2.
229 txRes@txJust = "CenterLeft" ; Default="CenterCenter".
230 txRes@txFontHeightF = FontHeightF ; match YL
231 ;txRes@txBackgroundFillColor = "white"
234 radTM = xyMax*tmEnd ; radius end: major TM
235 xTM = new( 2 , "float")
236 yTM = new( 2 , "float")
238 dum5 = new(dimsizes(sLabels),graphic)
241 do i=0,dimsizes(sLabels)-1 ; Loop to draw strings
242 txRes@txAngleF = angC(i)
243 dum5(i) = gsn_add_text(wks, taylor, sLabels(i),xC(i),yC(i),txRes) ; cor label
244 xTM(0) = xyMax*cos(angC(i)*rad) ; major tickmarks at
245 yTM(0) = xyMax*sin(angC(i)*rad) ; correlation labels
246 xTM(1) = radTM*cos(angC(i)*rad)
247 yTM(1) = radTM*sin(angC(i)*rad)
248 dum6(i) = gsn_add_polyline(wks,taylor,xTM,yTM,plRes)
251 mTM = (/0.05,0.15,0.25,0.35,0.45,0.55,0.65 \
252 ,0.75,0.85,0.91,0.92,0.93,0.94,0.96,0.97,0.98 /)
253 angmTM = acos(mTM)/rad ; angles: correlation labels
254 radmTM = xyMax*(1.-(1.-tmEnd)*0.5) ; radius end: minor TM
256 dum7 = new(dimsizes(mTM),graphic)
258 do i=0,dimsizes(mTM)-1 ; manually add tm
259 xTM(0) = xyMax*cos(angmTM(i)*rad) ; minor tickmarks
260 yTM(0) = xyMax*sin(angmTM(i)*rad)
261 xTM(1) = radmTM*cos(angmTM(i)*rad)
262 yTM(1) = radmTM*sin(angmTM(i)*rad)
263 dum7(i) = gsn_add_polyline(wks,taylor,xTM,yTM,plRes)
266 if (rOpts .and. isatt(rOpts,"ccRays") ) then
267 angRL = acos(rOpts@ccRays)/rad ; angles: radial lines
270 rlRes@xyDashPattern = 4 ; line pattern
271 rlRes@xyLineThicknessF = 1 ; choose line thickness
273 dum8 = new(dimsizes(angRL),graphic)
274 do i=0,dimsizes(angRL)-1
275 xRL = xyMax*cos(angRL(i)*rad)
276 yRL = xyMax*sin(angRL(i)*rad)
277 dum8(i) = gsn_add_polyline(wks,taylor,(/0, xRL /),(/0, yRL /),rlRes)
279 taylor@$unique_string("dum")$ = dum8
282 ; ----------------------------------------------------------------
284 ; Concentric about 1.0 on XB axis
285 ; I think this is correct. Still test mode.
286 ; ----------------------------------------------------------------
287 if (rOpts .and. isatt(rOpts,"centerDiffRMS") \
288 .and. rOpts@centerDiffRMS) then
289 respl = True ; polyline mods desired
290 respl@gsLineThicknessF = 1.0 ; line thickness
291 respl@gsLineColor = "Black" ; line color
292 respl@gsLineDashPattern = 2 ; short dash lines
295 ncon = 4 ; 0.75, 0.50, 0.25, 0.0
296 npts = 100 ; arbitrary
297 ang = fspan(180,360,npts)*rad
299 dum9 = new(ncon,graphic)
302 rr = n*dx ; radius from 1.0 [OBS] abscissa
303 xx = 1. + rr*cos(ang)
304 yy = fabs( rr*sin(ang) )
306 dum9(n-1) = gsn_add_polyline(wks,taylor,xx,yy,respl)
309 n3 = floattointeger( 0.77*npts )
310 dum9(n-1) = gsn_add_polyline(wks,taylor,xx(0:n3),yy(0:n3),respl)
313 n4 = floattointeger( 0.61*npts )
314 dum9(n-1) = gsn_add_polyline(wks,taylor,xx(0:n4),yy(0:n4),respl)
320 taylor@$unique_string("dum")$ = dum9
323 ; ---------------------------------------------------------------
325 ; generic resources that will be applied to all users data points
326 ; of course, these can be changed
327 ; http://www.ncl.ucar.edu/Document/Graphics/Resources/gs.shtml
328 ; ---------------------------------------------------------------
329 if (rOpts .and. isatt(rOpts,"Markers")) then
330 Markers = rOpts@Markers
332 Markers = (/ 4, 6, 8, 0, 9, 12, 7, 2, 11, 16/) ; Marker Indices
335 if (rOpts .and. isatt(rOpts,"Colors")) then
336 Colors = rOpts@Colors
338 Colors = (/ "red", "blue", "green", "cyan", "orange" \
339 , "torquoise", "brown", "yellow", "purple", "black"/)
342 if (rOpts .and. isatt(rOpts,"gsMarkerThicknessF")) then
343 gsMarkerThicknessF = rOpts@gsMarkerThicknessF
345 gsMarkerThicknessF = 1.0
348 if (rOpts .and. isatt(rOpts,"gsMarkerSizeF")) then
349 gsMarkerSizeF = rOpts@gsMarkerSizeF
351 gsMarkerSizeF = 0.0085 ; Default: 0.007
355 gsRes@gsMarkerThicknessF = gsMarkerThicknessF ; default=1.0
356 gsRes@gsMarkerSizeF = gsMarkerSizeF ; Default: 0.007
358 ptRes = True ; text options for points
359 ptRes@txJust = "BottomCenter"; Default="CenterCenter".
360 ptRes@txFontThicknessF = 1.2 ; default=1.00
361 ptRes@txFontHeightF = 0.0125 ; default=0.05
362 if (rOpts .and. isatt(rOpts,"txFontHeightF")) then
363 ptRes@txFontHeightF = rOpts@txFontHeightF
366 markerTxYOffset = 0.0175 ; default
367 if (rOpts .and. isatt(rOpts,"markerTxYOffset")) then
368 markerTxYOffset = rOpts@markerTxYOffset ; user defined offset
371 dum10 = new((nCase*nVar),graphic)
375 gsRes@gsMarkerIndex = Markers(n) ; marker style (+)
376 gsRes@gsMarkerColor = Colors(n) ; marker color
377 ptRes@txFontColor = gsRes@gsMarkerColor
379 dum10(n*nVar+i) = gsn_add_polymarker(wks,taylor,X(n,i),Y(n,i),gsRes)
380 dum11(n*nVar+i) = gsn_add_text(wks,taylor,(i+1),X(n,i),Y(n,i)+markerTxYOffset,ptRes)
384 ; ---------------------------------------------------------------
385 ; Part 5: ; add case legend and variable labels
386 ; ---------------------------------------------------------------
388 if (rOpts .and. isatt(rOpts,"caseLabels")) then
390 if (isatt(rOpts,"caseLabelsFontHeightF")) then
391 caseLabelsFontHeightF = rOpts@caseLabelsFontHeightF
393 caseLabelsFontHeightF = 0.05
397 lgres@lgMarkerColors = Colors ; colors of markers
398 lgres@lgMarkerIndexes = Markers ; Markers
399 lgres@lgMarkerSizeF = gsMarkerSizeF ; Marker size
400 lgres@lgItemType = "Markers" ; draw markers only
401 lgres@lgLabelFontHeightF = caseLabelsFontHeightF ; font height of legend case labels
403 if (isatt(rOpts,"legendWidth")) then
404 lgres@vpWidthF = rOpts@legendWidth
406 lgres@vpWidthF = 0.15 ; width of legend (NDC)
409 if (isatt(rOpts,"legendHeight")) then
410 lgres@vpHeightF = rOpts@legendHeight
412 lgres@vpHeightF = 0.030*nCase ; height of legend (NDC)
415 lgres@lgPerimOn = False ; turn off perimeter
416 nModel = dimsizes( rOpts@caseLabels )
417 lbid = gsn_create_legend(wks,nModel,rOpts@caseLabels,lgres)
420 amres@amParallelPosF = 0.35
421 amres@amOrthogonalPosF = -0.35
422 annoid1 = gsn_add_annotation(taylor,lbid,amres) ; add legend to plot
425 if (rOpts .and. isatt(rOpts,"varLabels")) then
426 nVar = dimsizes(rOpts@varLabels)
428 if (isatt(rOpts,"varLabelsFontHeightF")) then
429 varLabelsFontHeightF = rOpts@varLabelsFontHeightF
431 varLabelsFontHeightF = 0.013
435 txres@txFontHeightF = varLabelsFontHeightF
436 txres@txJust = "CenterLeft" ; justify to the center left
440 if (rOpts .and. isatt(rOpts,"varLabelsYloc")) then
441 ys = rOpts@varLabelsYloc ; user specified
443 ys = max( (/nVar*delta_y , 0.30/) )
449 dum12 = new(nVar,graphic)
452 dum12(i-1) = gsn_add_text(wks,taylor,i+" - "+rOpts@varLabels(i-1), .125,ys,txres)
456 taylor@$unique_string("dum")$ = dum12
459 taylor@$unique_string("dum")$ = dum0 ; x-axis
460 taylor@$unique_string("dum")$ = dum1 ; y-axis
461 taylor@$unique_string("dum")$ = dum2 ; 1.0 std curve
462 taylor@$unique_string("dum")$ = dum5 ; labels [COR]
463 taylor@$unique_string("dum")$ = dum6 ; major tm [COR]
464 taylor@$unique_string("dum")$ = dum7 ; minor tm
465 taylor@$unique_string("dum")$ = dum10 ; markers
466 taylor@$unique_string("dum")$ = dum11 ; text
468 if (.not.isatt(rOpts,"taylorDraw") .or. \
469 (isatt(rOpts,"taylorDraw") .and. rOpts@taylorDraw)) then
472 if (.not.isatt(rOpts,"taylorFrame") .or. \
473 (isatt(rOpts,"taylorFrame") .and. rOpts@taylorFrame)) then