Viewing contents of file '../idllib/contrib/fanning/xplot.pro'
;+
; NAME:
; XPLOT
;
; PURPOSE:
; The purpose of this program is to demonstrate how to
; create a line plot with axes and a title in the
; new IDL 5 object graphics.
;
; AUTHOR:
; FANNING SOFTWARE CONSULTING
; David Fanning, Ph.D.
; 2642 Bradbury Court
; Fort Collins, CO 80521 USA
; Phone: 970-221-0438
; E-mail: davidf@dfanning.com
; Coyote's Guide to IDL Programming: http://www.dfanning.com
;
; CATEGORY:
; Widgets, IDL 5 Object Graphics.
;
; CALLING SEQUENCE:
; XPlot, x, y
;
; REQUIRED INPUTS:
; x: A vector of input values used as the dependent data.
;
; OPTIONAL INPUTS
; y: A vector of input values used as the dependent data.
; If both x and y parameters are present, x is the independent data.
;
; OPTIONAL KEYWORD PARAMETERS:
;
; _EXTRA: This keyword collects otherwise undefined keywords that are
; passed to new Plot command. To some extent these are similar to the
; old IDL Plot command. For example: Linestyle=2, Thick=3,
; XRange=[-100,100], etc.
;
; GROUP_LEADER: The group leader for this program. When the group leader
; is destroyed, this program will be destroyed.
;
; PSYM: The index of a plotting symbol to use on the plot. Integers 0-7
; are valid values.
;
; TITLE: A string used as the title of the plot.
;
; XTITLE: A string used as the X title of the plot.
;
; YTITLE: A string used as the Y title of the plot.
;
; COMMON BLOCKS:
; None.
;
; SIDE EFFECTS:
; None.
;
; RESTRICTIONS:
; Axes are always drawn with the Exact keyword set.
;
; EXAMPLE:
; To use this program, pass a 1D vector or vectors, like this:
;
; IDL> XPlot, RandomU(seed, 11) * 9, YRange=[0, 10]
;
; MODIFICATION HISTORY:
; Written by David Fanning, 13 June 97.
; Modified axis font handling. 17 Sept 97. DWF.
; Was not destroying all objects on exit. 12 Feb 98. DWF.
; Changed IDLgrContainer to IDL_Container to fix 5.1 problems. 20 May 98. DWF.
;-
FUNCTION Normalize, range, Position=position
; This is a utility routine to calculate the scaling vector
; required to position a vector of specified range at a
; specific position given in normalized coordinates. The
; scaling vector is given as a two-element array like this:
;
; scalingVector = [translationFactor, scalingFactor]
;
; The scaling vector should be used with the [XYZ]COORD_CONV
; keywords of a graphics object or model. For example, if you
; wanted to scale an X axis into the data range of -0.5 to 0.5,
; you might type something like this:
;
; xAxis->GetProperty, Range=xRange
; xScale = Normalize(xRange, Position=[-0.5, 0.5])
; xAxis, XCoord_Conv=xScale
IF (N_Elements(position) EQ 0) THEN position = [0.0, 1.0] ELSE $
position=Float(position)
range = Float(range)
scale = [((position[0]*range[1])-(position[1]*range[0])) / $
(range[1]-range[0]), (position[1]-position[0])/(range[1]-range[0])]
RETURN, scale
END
;-------------------------------------------------------------------------
PRO XPlot_Output, event
; This event handler creates GIF and JPEG files.
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Get a snapshop of window contents. (TVRD equivalent.)
info.thisWindow->GetProperty, Image_Data=snapshot
; JPEG or GIF file wanted?
Widget_Control, event.id, Get_UValue=whichFileType
CASE whichFileType OF
'GIF': BEGIN
; Because we are using a window set up for RGB color,
; snapshot contains a 3xMxN array. Use Color_Quan to
; create a 2D image and appropriate color tables for
; the GIF file.
image2D = Color_Quan(snapshot, 1, r, g, b)
filename = Dialog_Pickfile(/Write, File='idl.gif')
IF filename NE '' THEN Write_GIF, filename, image2d, r, g, b
END
'JPEG': BEGIN
filename = Dialog_Pickfile(/Write, File='idl.jpg')
IF filename NE '' THEN Write_JPEG, filename, snapshot, True=1
END
ENDCASE
;Put the info structure back.
Widget_Control, event.top, Set_UValue=info, /No_Copy
END
;-------------------------------------------------------------------
PRO XPlot_Exit, event
; Exit the program.
Widget_Control, event.top, /Destroy
END
;-------------------------------------------------------------------
PRO XPlot_Printing, event
; PostScript printing and printer setup handled here.
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Which button?
Widget_Control, event.id, Get_UValue=ButtonValue
CASE buttonValue OF
'PRINT': BEGIN
result = Dialog_PrintJob(info.thisPrinter)
IF result EQ 1 THEN BEGIN
info.thisPrinter->Draw, info.plotView
info.thisPrinter->NewDocument
ENDIF
END
'SETUP': BEGIN
result = Dialog_PrinterSetup(info.thisPrinter)
IF result EQ 1 THEN BEGIN
info.thisPrinter->Draw, info.plotView
info.thisPrinter->NewDocument
ENDIF
END
ENDCASE
; Put the info structure back.
Widget_Control, event.top, Set_UValue=info, /No_Copy
END
;-------------------------------------------------------------------
PRO Xplot_Cleanup, id
; Come here when the widget dies. Free all the program
; objects, pointers, pixmaps, etc. and release memory.
Widget_Control, id, Get_UValue=info
IF N_Elements(info) NE 0 THEN Obj_Destroy, info.thisContainer
END
;---------------------------------------------------------------------
PRO XPlot_Draw_Widget_Events, event
; This event handler handles draw widget expose events.
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Draw the graphic.
info.thisWindow->Draw, info.plotView
;Put the info structure back.
Widget_Control, event.top, Set_UValue=info, /No_Copy
END
;------------------------------------------------------------------------
PRO XPlot_Resize_Events, event
; This event handler handles TLB resize events.
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Resize the draw widget.
info.thisWindow->SetProperty, Dimension=[event.x, event.y]
; Redisplay the graphic.
info.thisWindow->Draw, info.plotView
;Put the info structure back.
Widget_Control, event.top, Set_UValue=info, /No_Copy
END
;------------------------------------------------------------------------
PRO XPlot, x, y, _Extra=extra, PSym=psym, Title=title, $
Group_Leader=group, XTitle=xtitle, YTitle=ytitle
; Check to be sure at least one parameter is present.
np = N_Params()
CASE np OF
0: BEGIN
Print, 'Using fake data in XPLOT...'
y = FIndGen(101)
y = Sin(y/5) / Exp(y/50)
x = IndGen(N_Elements(y))
END
1: BEGIN
y = x
x = IndGen(N_Elements(y))
END
ELSE:
ENDCASE
; Check keyword parameters. Make symbols red.
IF N_Elements(psym) EQ 0 THEN psym = Obj_New() ELSE $
psym = Obj_New('IDLgrSymbol', psym, Color=[255,0,0], Size=0.5)
IF N_Elements(title) EQ 0 THEN title = 'Example Object Graphics Line Plot'
IF N_Elements(xtitle) EQ 0 THEN xtitle = 'X Axis'
IF N_Elements(ytitle) EQ 0 THEN ytitle = 'Y Axis'
; Create a plot object. The plot will be in the coordinate
; space 0->1. The view will be in the range -0.35->1.25 so
; that the plot axis annotation will be visable. Make the plot
; a green color.
thisPlot = Obj_New('IDLgrPLOT', x, y, _Extra=extra, $
Color=[0,255,0], Symbol=psym, Thick=2)
; Get the data ranges from the Plot Object.
thisPlot->GetProperty, XRange=xrange, YRange=yrange
; Set up the scaling so that the axes for the plot and the
; plot data extends from 0->1 in the X and Y directions.
xs = Normalize(xrange)
ys = Normalize(yrange)
; Scale the plot data into 0->1.
thisPlot->SetProperty, XCoord_Conv=xs, YCoord_Conv=ys
; Create a plot title. Center it at a location above the plot.
helvetica14pt = Obj_New('IDLgrFont', 'Helvetica', Size=14)
plotTitle = Obj_New('IDLgrText', title, Color=[255,255,0], $
Location=[0.5, 1.05, 0.0], Alignment=0.5, Font=helvetica14pt)
; Create titles objects for the axes. Color them yellow.
xTitle = Obj_New('IDLgrText', xtitle, Color=[255,255,0])
yTitle = Obj_New('IDLgrText', ytitle, Color=[255,255,0])
; Create plot box style axes. Make the axes yellow.
; The large values in the LOCATION keyword indicates which
; values are NOT used. The axes text is set to Helvetica
; 10 point font.
xAxis1 = Obj_New("IDLgrAxis", 0, Color=[255,255,0], Ticklen=0.025, $
Minor=4, Range=xrange, Title=xtitle, XCoord_Conv=xs, $
Location=[1000, 0 ,0], /Exact)
xAxis1->GetProperty, Ticktext=xAxisText
helvetica10pt = Obj_New('IDLgrFont', 'Helvetica', Size=10)
xAxisText->SetProperty, Font=helvetica10pt
xAxis2 = Obj_New("IDLgrAxis", 0, Color=[255,255,0], Ticklen=0.025, $
Minor=4, /NoText, Range=xrange, TickDir=1, XCoord_Conv=xs, $
Location=[1000, 1, 0], /Exact)
yAxis1 = Obj_New("IDLgrAxis", 1, Color=[255,255,0], Ticklen=0.025, $
Minor=4, Title=ytitle, Range=yrange, YCoord_conv=ys, $
Location=[0, 1000, 0], /Exact)
yAxis1->GetProperty, Ticktext=yAxisText
yAxisText->SetProperty, Font=helvetica10pt
yAxis2 = Obj_New("IDLgrAxis", 1, Color=[255,255,0], Ticklen=0.025, $
Minor=4, /NoText, Range=yrange, TickDir=1, YCoord_conv=ys, $
Location=[1, 1000, 0], /Exact)
; Create a plot model and add axes, plot, and plot title to it.
plotModel = Obj_New('IDLgrModel')
plotModel->Add, thisPlot
plotModel->Add, xAxis1
plotModel->Add, xAxis2
plotModel->Add, yAxis1
plotModel->Add, yAxis2
plotModel->Add, plotTitle
; Create a view and add the plot model to it. Notice that the view
; is larger than the 0->1 plot area to accomodate axis annotation.
; The view will have a gray background.
plotView = Obj_New('IDLgrView', Viewplane_Rect=[-.35, -.35, 1.6, 1.6], $
Location=[0,0], Color=[80,80,80])
plotView->Add, plotModel
; Create the widgets for this program.
tlb = Widget_Base(Column=1, Title='Resizeable Line Plot Example', $
TLB_Size_Events=1, MBar=menubase)
; Create FILE menu buttons for printing and exiting.
filer = Widget_Button(menubase, Value='File', /Menu)
b = Widget_Button(filer, Value='Print', $
Event_Pro='XPlot_Printing', UValue='PRINT')
b = Widget_Button(filer, Value='Print Setup', $
Event_Pro='XPlot_Printing', UValue='SETUP')
b = Widget_Button(filer, /Separator, Value='Exit', $
Event_Pro='XPlot_Exit')
; Create OUTPUT menu buttons for formatted output files.
output = Widget_Button(menubase, Value='Output')
b = Widget_Button(output, Value='GIF File', $
UValue='GIF', Event_Pro='XPlot_Output')
b = Widget_Button(output, Value='JPEG File', $
UValue='JPEG', Event_Pro='XPlot_Output')
; Create the draw widget. Use RGB color model. Be sure to set
; the Expose_Events keyword so that graphics are redisplayed
; properly. (This implies that RETAIN=0. The Graphics_Level
; keyword makes it a window object.
drawID = Widget_Draw(tlb, XSize=400, YSize=400, Color_Model=0, $
Graphics_Level=2, Expose_Events=1, Retain=0, $
Event_Pro='XPlot_Draw_Widget_Events')
; Realize the widgets and get the window object.
Widget_Control, tlb, /Realize
Widget_Control, drawID, Get_Value=thisWindow
; Display the plot in the window.
thisWindow->Draw, plotView
; Get a printer object for this graphic.
thisPrinter = Obj_New('IDLgrPrinter')
; Create a container object to hold all the other
; objects. This will make it easy to free all the
; objects when we are finished with the program.
thisContainer = Obj_New('IDL_Container')
thisContainer->Add, thisWindow
thisContainer->Add, plotView
thisContainer->Add, thisPrinter
thisContainer->Add, helvetica10pt
thisContainer->Add, helvetica14pt
thisContainer->Add, xaxis1
thisContainer->Add, xaxis2
thisContainer->Add, yaxis1
thisContainer->Add, yaxis2
thisContainer->Add, plotTitle
thisContainer->Add, xTitle
thisContainer->Add, yTitle
; Create an info structure to hold program information.
info = { thisContainer:thisContainer, $ ; The container object.
thisWindow:thisWindow, $ ; The window object.
plotView:plotView, $ ; The view that will be rendered.
thisPrinter:thisPrinter } ; The printer object.
; Put the info stucture in the TLB.
Widget_Control, tlb, Set_UValue=info, /No_Copy
; Start the event loop.
XManager, 'xplot', tlb, Cleanup='XPlot_Cleanup', Group_Leader=group, $
Event_Handler='XPlot_Resize_Events', /No_Block
END
;------------------------------------------------------------------------