Article: 421 of comp.lang.idl-pvwave Newsgroups: comp.lang.idl-pvwave Path: acs.ucalgary.ca!kakwa.ucs.ualberta.ca!unixg.ubc.ca!ubc-cs!utcsri!rpi!gatech!ukma!nsisrv!stars.gsfc.nasa.gov!thompson From: thompson@stars.gsfc.nasa.gov (William Thompson, code 682.1, x2040) Subject: Re: IDL and X and PS Message-ID: <15SEP199217204994@stars.gsfc.nasa.gov> News-Software: VAX/VMS VNEWS 1.4-b1 Keywords: idl X PostScript Sender: usenet@nsisrv.gsfc.nasa.gov (Usenet) Nntp-Posting-Host: stars.gsfc.nasa.gov Organization: NASA/GSFC-Laboratory for Astronomy and Solar Physics References: <1992Sep14.204750.8612@sunspot.noao.edu> Distribution: na Date: Tue, 15 Sep 1992 21:20:00 GMT In article <1992Sep14.204750.8612@sunspot.noao.edu>, mcgraw@sunspot.sunspot.noao.edu (Robert McGraw) writes... >I am looking for any information and/or procedures that make it >eash to stay with the same coordinates system when going from >set_plot,'x to/from set_plot,'ps' in IDL. > >For example, it seems that tv and xyouts uses a different coordinate >system in PostScript then when in the X environment. > >Is there a way to make a procedure work the same when in X or PS >without having to make a lot of changes? It is true that TV works differently for X-windows displays and PostScript files. However, XYOUTS should normally work the same for both displays. You can run into a problem if you try to mix and match plots and overplots. For instance, the following should work without problems: SET_PLOT,'X' PLOT,INDGEN(10) OPLOT,INDGEN(10),PSYM=2 SET_PLOT,'PS' PLOT,INDGEN(10) OPLOT,INDGEN(10),PSYM=2 and the output should appear more or less the same on the screen and in the PostScript file. However, the following will not work properly: SET_PLOT,'X' PLOT,INDGEN(10) SET_PLOT,'PS' PLOT,INDGEN(10) SET_PLOT,'X' OPLOT,INDGEN(10),PSYM=2 SET_PLOT,'PS' OPLOT,INDGEN(10),PSYM=2 (Although it may *ALMOST* work.) The reason for this is that the PLOT command defines certain system variables (e.g. !X.S, !Y.S) which describe the transformation between data coordinates and device coordinates. These system variables will be different for the two different devices, and IDL does not keep track of them as a function of device. Therefore, when the PLOT command is executed on the PostScript file, the coordinate information for the X-windows display is lost. The same thing happens when switching between windows, or between plots generated with !P.MULTI. However, the following routine called SETPLOT can be used to replace SET_PLOT to overcome this difficulty. I use this myself, and it fits my needs. It may work okay for you to. It simply stores some of the most used system variables in a common block as a function of plotting device and window. The issue of TV working differently in PostScript files as opposed to X-windows files is because PostScript uses scalable pixels. The only way to control the size of the image in a PostScript file (as I understand it) is to use the XSIZE and YSIZE keywords. X-windows on the other hand always maps image pixels directly into screen pixels, and the XSIZE, YSIZE keywords are ignored. The way I achieve device independence between PostScript files and other devices such as X-windows is to use a separate routine to display images rather than using TVSCL directly. I calculate how big I can scale the image to fit within the page, or section of the page, and I express this in device coordinates: NX, NY. I also calculate the position IX,IY to place the image to center it within the selected region, again in device coordinates. Then, if the device is a PostScript printer, I use the command TVSCL,ARRAY,IX,IY,XSIZE=NX,YSIZE=NY,/DEVICE Otherwise I use the function CONGRID to rescale ARRAY to size XSIZE, i.e. TVSCL,CONGRID(ARRAY,NX,NY),IX,IY Because of the IF statements involved, it's better to put this into a routine rather than call these statements directly. Bill Thompson P.S. The file SETPLOT.PRO, which contains several procedures, follows. =============================================================================== PRO ADD_DEVICE, NAME, SV ; ; Called from SETPLOT. Used to add devices to the PLOTFILE common block. ; Also used to set default values for the various devices. ; ON_ERROR,1 COMMON PLOTFILE,NAMES,SAVE ; ; Define some of the defaults for various devices. ; ;****************************************************************************** ; These represent my own personal preferences. You can change these, or ; omit this section entirely. I make these settings take effect by ; putting the command SETPLOT,!D.NAME in my IDL startup file. ;****************************************************************************** ; IF NAME EQ 'QMS' THEN BEGIN SV.THICK = 3 SV.CHARTHICK = 3 SV.XTHICK = 3 SV.YTHICK = 3 ENDIF IF NAME EQ 'REGIS' THEN BEGIN SV.COLOR = 3 SV.FONT = 0 ENDIF IF NAME EQ 'TEK' THEN SV.FONT = 0 ; ; Check to see if the common block variables have been initialized. Either ; initialize the common block with this device, or add this device to the ; common block. ; IF N_ELEMENTS(NAMES) EQ 0 THEN BEGIN NAMES = NAME SAVE = SV END ELSE BEGIN NAMES = [NAMES,NAME] SAVE = [SAVE,SV] ENDELSE ; RETURN END ;****************************************************************************** ; **** **** **** **** **** **** **** **** **** **** ;****************************************************************************** PRO STORE_INTO_SV, SV ; ; Called from SETPLOT. Used to initialize SV, and to store the various system ; variables in it. ; SV = {SV_PLT, CHARSIZE: !P.CHARSIZE, $ FONT: !P.FONT, $ COLOR: !P.COLOR, $ BACKGROUND: !P.BACKGROUND, $ REGION: !P.REGION, $ CLIP: !P.CLIP, $ POSITION: !P.POSITION, $ THICK: !P.THICK, $ CHARTHICK: !P.CHARTHICK, $ XTYPE: !X.TYPE, $ XCRANGE: !X.CRANGE, $ XS: !X.S, $ XMARGIN: !X.MARGIN, $ XWINDOW: !X.WINDOW, $ XREGION: !X.REGION, $ XTHICK: !X.THICK, $ YTYPE: !Y.TYPE, $ YCRANGE: !Y.CRANGE, $ YS: !Y.S, $ YMARGIN: !Y.MARGIN, $ YWINDOW: !Y.WINDOW, $ YREGION: !Y.REGION, $ YTHICK: !Y.THICK, $ ZTYPE: !Z.TYPE, $ ZCRANGE: !Z.CRANGE, $ ZS: !Z.S, $ ZMARGIN: !Z.MARGIN, $ ZWINDOW: !Z.WINDOW, $ ZREGION: !Z.REGION} ; RETURN END ;****************************************************************************** ; **** **** **** **** **** **** **** **** **** **** ;****************************************************************************** PRO SETPLOT,DEVICE ;+ ; NAME: ; SETPLOT ; PURPOSE: ; Switches among the various available plotting devices. The plotting ; variables for each device are saved in a common block so that the user ; retains the ability to reset to a previously used device and do over- ; plots, even if plots were produced on another device in the meantime. ; ; Calling SETPLOT with the name of the currently selected device resets ; the system variables to either default values, or those from the last ; time SETPLOT was called. ; ; CALLING SEQUENCE: ; SETPLOT, DEVICE ; INPUTS: ; DEVICE - Name of the plotting device one is changing to. ; OPTIONAL INPUT PARAMETERS: ; None. ; OUTPUTS: ; None. ; OPTIONAL OUTPUT PARAMETERS: ; None. ; COMMON BLOCKS: ; PLOTFILE - Saves system variables for later retrieval. Not to be used ; by other routines. ; SIDE EFFECTS: ; Many system variables are manipulated by this routine--in particular ; !P.CHARSIZE and !P.FONT. ; ; The first time the routine is called, SET_PLOT is called in turn for ; each plotting device and the results saved in the common block. ; ; RESTRICTIONS: ; The procedure will not work correctly unless it is used exclusively to ; change the plotting device. ; PROCEDURE: ; Many system variables that would be changed by the command SET_PLOT ; are saved in a common block. SET_PLOT is called, and then the saved ; values are restored. ; MODIFICATION HISTORY: ; W.T.T., Sept. 1987. ; William Thompson, February, 1990. ;- ; ON_ERROR,1 COMMON PLOTFILE,NAMES,SAVE ; ; Check the number of parameters. ; IF N_PARAMS(0) EQ 0 THEN BEGIN PRINT,'*** SETPLOT must be called with one parameter:' PRINT,' DEVICE' RETURN ENDIF ; ; Define the structure. ; STORE_INTO_SV, SV ; ; Check to see if the common block variables have been initialized. ; IF N_ELEMENTS(NAMES) EQ 0 THEN ADD_DEVICE,!D.NAME,SV ; ; Get the number of the current plot device. ; I_DEVICE = WHERE(NAMES EQ !D.NAME, N_FOUND) IF N_FOUND EQ 0 THEN BEGIN ADD_DEVICE,!D.NAME,SV I_DEVICE = WHERE(NAMES EQ !D.NAME) ENDIF I_DEVICE = I_DEVICE(0) ; ; If the device is being changed, then store the current system variables. ; IF STRUPCASE(DEVICE) NE !D.NAME THEN BEGIN SAVE(I_DEVICE) = SV ; ; Change the plotting device. ; SET_PLOT,DEVICE ; ; Get the number of the new plotting device. ; I_DEVICE = WHERE(NAMES EQ !D.NAME,N_FOUND) IF N_FOUND EQ 0 THEN BEGIN STORE_INTO_SV, SV ADD_DEVICE,!D.NAME,SV I_DEVICE = WHERE(NAMES EQ !D.NAME) ENDIF I_DEVICE = I_DEVICE(0) ENDIF ; ; Restore the system variables from the saved arrays. This is done even if ; the plotting device is not changed. By using SETPLOT on the device one is ; already set to, one can reinitialize the system variables. ; SV = SAVE(I_DEVICE) !P.CHARSIZE = SV.CHARSIZE !P.FONT = SV.FONT !P.COLOR = SV.COLOR !P.BACKGROUND = SV.BACKGROUND !P.REGION = SV.REGION !P.CLIP = SV.CLIP !P.POSITION = SV.POSITION !P.THICK = SV.THICK !P.CHARTHICK = SV.CHARTHICK !X.TYPE = SV.XTYPE !X.CRANGE = SV.XCRANGE !X.S = SV.XS !X.MARGIN = SV.XMARGIN !X.WINDOW = SV.XWINDOW !X.REGION = SV.XREGION !X.THICK = SV.XTHICK !Y.TYPE = SV.YTYPE !Y.CRANGE = SV.YCRANGE !Y.S = SV.YS !Y.MARGIN = SV.YMARGIN !Y.WINDOW = SV.YWINDOW !Y.REGION = SV.YREGION !Y.THICK = SV.YTHICK !Z.TYPE = SV.ZTYPE !Z.CRANGE = SV.ZCRANGE !Z.S = SV.ZS !Z.MARGIN = SV.ZMARGIN !Z.WINDOW = SV.ZWINDOW !Z.REGION = SV.ZREGION ; RETURN END