;+ ; NAME: ; PlotCurve ; PURPOSE: ; (Over)plot two arrays x, y. Connect only `valid' points. ; CALLING SEQUENCE: PRO PlotCurve, xin, y, nvalid, $ sigma = sigma , $ oplotx = oplotx , $ xrange = xrange , $ newyaxis = newyaxis , $ yaxis = yaxis , $ ynozero = ynozero , $ ylog = ylog , $ yrange = yrange , $ ystyle = ystyle , $ color = color , $ changecolor = changecolor, $ _extra = _extra , $ silent = silent , $ bar = bar , $ shade = shade , $ hatch = hatch , $ noline = noline ; INPUTS: ; x,y one-dimensional arrays; must have the same size ; nvalid identifies the array elements to be plotted as: ; - an array of indices e.g. [0,1,2,7,8,9,10] ; - a boolean array (containing only values 0 or 1) ; of same size as x and y, e.g. [1,1,1,0,0,0,0,1,1,1,1] ; if nvalid is absent, all finite function values are plotted ; OPTIONAL INPUT PARAMETERS: ; /oplot if not set, then a new plot (with a new x-axis) is started) ; (implicitly /newaxis is set and yaxis=-1, i.e. a y-axis ; will be drawn on the left) ; if set, then the arrays are overplotted on a previous plot ; (the keywords /newyaxis and yaxis=yaxis can be used to add ; additional y axes, if necessary) ; /newyaxis ; adds a new yaxis (if /oplot is NOT set, then /newaxis is assumed set) ; yaxis=yaxis controls the position of a new y axis; yaxis is used only if /newaxis is set ; yaxis=-1 : y-axis on left (default) ; yaxis=0 : y-axis on right ; 0 Only valid data points are connected by the type of line specified ; by the linestyle keyword. ;> Valid data points are identified in the nvalid array either by their ; array index or by a boolean value of 1. ; MODIFICATION HISTORY: ; APR-1996, Paul Hick (UCSD/CASS) ; OCT-1999, Paul Hick (UCSD/CASS) ; if nvalid is not specified only finite y-values (finite(y) = 1) are ; plotted, instead of all points ; FEB-2001, Paul Hick (UCSD/CASS) ; Fixed minor bug in handling of invalid data points. ; FEB-2004, Paul Hick (UCSD/CASS) ; Fixed bug for call with a time array as x-array when the time ; origin is not yet defined ; SEP-2007, Paul Hick (UCSD/CASS) ; Added keywords bar, hatch and shade for plotting bar graphs ; JUL-2008, Paul Hick (UCSD/CASS; pphick@ucsd.edu) ; Added xrange keyword to allo ;- InitVar, silent , /key InitVar, ylog , /key InitVar, ynozero , /key InitVar, changecolor, /key InitVar, oplotx , /key InitVar, newyaxis , /key InitVar, bar , /key InitVar, noline , /key newyaxis = NOT oplotx OR newyaxis ; torigin and tunit must be set by a previous call to TimeAxis SWITCH 1 OF IsType(xin,/string): xin = TimeSet(xin) IsTime(xin): BEGIN ;IF NOT IsTime(torigin) THEN TimeXAxis, xin IF NOT oplotx THEN BEGIN InitVar, xrange, xin IF IsType(xrange,/string) THEN xrange = TimeSet(xrange) TimeXAxis, xrange, _extra=_extra oplotx = 1 newyaxis = 1 ENDIF x = TimeOp(/subtract, xin, torigin, tunit) break END ELSE: BEGIN x = xin break END ENDSWITCH ;IF NOT oplotx OR n_elements(yaxis) EQ 0 THEN yaxis=-1 InitVar, yaxis, -1 nx = n_elements(x) bsigma = n_elements(sigma) EQ nx n = n_elements(nvalid) IF n EQ 0 THEN BEGIN ; nvalid absent: plot finite fnc values nv = where( finite(y) NE 0, n) ENDIF ELSE IF nvalid[0] EQ -1 THEN BEGIN; nvalid = -1: no valid points n = 0 ENDIF ELSE IF n EQ nx THEN BEGIN ; nvalid is boolean or nvalid=indgen(nx) nv = nvalid m = where(nv EQ indgen(nx),i) IF i NE nx THEN nv = where(nv EQ 1,n) ; it's a boolean array ENDIF ELSE $ nv = nvalid IF NOT silent THEN message, /info, 'plotting'+strcompress(n)+' out of'+strcompress(nx)+' points' IF NOT oplotx THEN BEGIN ; Draw new x-axis CASE 1 OF n EQ 0 : xp = x ; No data points, use full range for x-axis changecolor : xp = x ; /change set, use full range for x-axis ELSE : xp = x[nv] ; Otherwise restrict to valid data points ENDCASE plot, [xp], 0*[xp], $ /nodata, $ ; Don't plot any data ystyle = 4, $ ; Don't plot y axis xrange = xrange, $ _extra = _extra ENDIF IF newyaxis THEN BEGIN ; New y-axis (always if /oplot NOT set) IF yaxis EQ -1 THEN $ ; First y-axis (always if /oplot NOT set) xp = !x.crange[0] $ ; Y-axis on left side with tickmarks pointing left ELSE BEGIN xp = convert_coord(!x.crange[1],0.,/data,/to_normal) xp = xp+yaxis*(1-xp) ; Y-axis on right with tickmarks pointing right xp = (convert_coord(xp,0.,/normal,/to_data))[0] ENDELSE IF n EQ 0 THEN BEGIN ; No data IF yaxis EQ -1 THEN oplot, [xp,xp],[!y.crange[0],!y.crange[1]] ; Plot vertical line on left if y-axis on left ENDIF ELSE BEGIN IF n_elements(yrange) EQ 0 THEN BEGIN CASE changecolor OF 0: BEGIN CASE min(y[nv])*max(y[nv]) LT 0 OR ynozero OF 0: yrange = [(min(y[nv]) LT 0)*min(y[nv]),(min(y[nv]) GE 0)*max(y[nv])] 1: yrange = [min(y[nv]),max(y[nv])] ENDCASE END 1: BEGIN CASE min(y)*max(y) LT 0 OR ynozero OF 0: yrange = [(min(y) LT 0)*min(y),(min(y) GE 0)*max(y)] 1: yrange = [min(y),max(y)] ENDCASE END ENDCASE ENDIF IF yrange[0] EQ yrange[1] THEN $ yrange = [yrange[0]-1,yrange[1]+1] axis, xp, $ ; Plot y axis yaxis = yaxis NE -1, $ yrange = yrange, $ ynozero= ynozero, $ ystyle = ystyle, $ ylog = ylog, $ /save, $ ; Save the y-scaling (needed to plot data points) _extra = _extra ENDELSE IF yaxis EQ -1 THEN BEGIN ; If y-axis on left is plotted, !p.clip[2] += 1 ; Fixes IDL - bug with clip window CASE ylog OF ; .. then plot vertical line on right 0: oplot, !x.crange[1]*[1,1], [!y.crange[0],!y.crange[1]] 1: oplot, !x.crange[1]*[1,1], 10^[!y.crange[0],!y.crange[1]] ENDCASE ENDIF ENDIF goodcolor = !p.color badcolor = !d.n_colors/2 IF IsType(color,/defined) THEN BEGIN goodcolor = color[0] IF n_elements(color) GT 1 THEN badcolor = color[1] ENDIF IF bar THEN BEGIN xedge = (shift(x,-1)+x)*0.5 xedge = [x[0],xedge[0:nx-2],x[nx-1]] shading = IsType(shade,/defined) IF shading THEN BEGIN goodshade = shade[0] badshade = shade[n_elements(shade)-1] ENDIF hatching = IsType(hatch,/defined) IF hatching THEN BEGIN goodhatch = hatch[0] badhatch = hatch[n_elements(hatch)-1] ENDIF ENDIF m = 0 ; Add data points dlast = 0 WHILE m LT n DO BEGIN ; Pick up next string of valid points d = where ( nv[m:n-1] EQ nv[m]+indgen(n-m), i ) d = nv[m+d] ; Indices of string of valid points ; Note that d is a list of indices into x,y without gaps CASE bar OF 0: BEGIN ; If there were invalid points between this string of valid ; points and the previous one, then plot them with badcolor if ; keyword /changecolor was set IF changecolor AND dlast NE d[0] THEN BEGIN oplot, [x[dlast:d[0]]],[y[dlast:d[0]]], _extra=_extra, color=badcolor IF bsigma THEN FOR j=dlast+1,d[0]-1 DO IF sigma[j] GT 0 THEN oplot, x[j]*[1,1], y[j]+sigma[j]*[-1,1] ENDIF ; Plot the string of valid points oplot, [x[d]],[y[d]], _extra=_extra, color=goodcolor IF bsigma THEN FOR j=d[0],d[i-1] DO IF sigma[j] GT 0 THEN oplot, x[j]*[1,1], y[j]+sigma[j]*[-1,1] END 1: BEGIN IF changecolor AND dlast NE d[0] THEN BEGIN FOR j=dlast+(dlast NE 0),d[0]-1 DO BEGIN p = [xedge[j]*[1,1],xedge[j+1]*[1,1]] q = [!y.crange[0],y[j],y[j],!y.crange[0]] qq = q IF dlast NE 0 THEN IF y[j] GT y[j-1] THEN qq[0] = y[j-1] IF NOT noline THEN BEGIN oplot, p,qq, noclip=0, _extra=_extra, color=badcolor IF bsigma THEN oplot, x[j]*[1,1], y[j]+sigma[j]*[-1,1] ENDIF IF y[j] NE !y.crange[0] THEN BEGIN IF shading THEN polyfill, p,q, noclip=0, color=badshade IF hatching THEN polyfill, p,q, noclip=0, spacing=badhatch,orientation=([45,-45])[j mod 2] ENDIF ENDFOR ENDIF ; Plot the string of valid points as vertical bars FOR j=d[0],d[i-1] DO BEGIN p = [xedge[j]*[1,1],xedge[j+1]*[1,1]] q = [!y.crange[0],y[j],y[j],!y.crange[0]] IF NOT noline THEN BEGIN oplot, p,q, noclip=0, _extra=_extra, color=goodcolor IF bsigma THEN oplot, x[j]*[1,1], y[j]+sigma[j]*[-1,1] ENDIF IF y[j] NE !y.crange[0] THEN BEGIN IF shading THEN polyfill, p,q, noclip=0, color=goodshade IF hatching THEN polyfill, p,q, noclip=0, spacing=goodhatch,orientation=([45,-45])[j mod 2] ENDIF ENDFOR END ENDCASE m = m+i dlast = d[i-1] ENDWHILE IF changecolor AND n NE 0 THEN BEGIN IF nv[n-1] NE nx-1 THEN BEGIN ; Still bad points left after last good point CASE bar OF 0: BEGIN oplot, [x[nv[n-1]:*]],[y[nv[n-1]:*]], _extra=_extra, color=badcolor IF bsigma THEN FOR j=nv[n-1]+1,nx-1 DO IF sigma[j] GT 0 THEN oplot, x[j]*[1,1], y[j]+sigma[j]*[-1,1] END 1: BEGIN FOR j=nv[n-1]+1,nx-1 DO BEGIN p = [xedge[j]*[1,1],xedge[j+1]*[1,1]] q = [!y.crange[0],y[j],y[j],!y.crange[0]] qq = q IF dlast NE 0 THEN IF y[j] GT y[j-1] THEN qq[0] = y[j-1] IF NOT noline THEN BEGIN oplot, p,qq, noclip=0, _extra=_extra, color=badcolor IF bsigma THEN oplot, x[j]*[1,1], y[j]+sigma[j]*[-1,1] ENDIF IF y[j] NE !y.crange[0] THEN BEGIN IF IsType(shade,/defined) THEN polyfill, p,q, noclip=0, color=badshade IF IsType(hatch,/defined) THEN polyfill, p,q, noclip=0, spacing=badhatch,orientation=([45,-45])[j mod 2] ENDIF ENDFOR END ENDCASE ENDIF ENDIF RETURN & END