comp.lang.idl-pvwave archive
Messages from Usenet group comp.lang.idl-pvwave, compiled by Paulo Penteado

Home » Public Forums » archive » Re: xyouts with p.multi
Show: Today's Messages :: Show Polls :: Message Navigator
E-mail to friend 
Switch to threaded view of this topic Create a new topic Submit Reply
Re: xyouts with p.multi [message #25191] Fri, 25 May 2001 06:32
Paul van Delst is currently offline  Paul van Delst
Messages: 364
Registered: March 1997
Senior Member
"Christopher W. O'Dell" wrote:
>
> I am plotting six graphs on one page using !p.multi =
> [0,2,3]
> I am trying to put some text in the same place on each
> graph, by using
>
> xyouts, x, y, 'text', /norm
>
> after each graph is plotted. I would think, using /norm,
> that it would put the
> text *in that graph*; but it doesn't, it puts it in some
> crazy place. Does anyone know how
> to make xyouts position the text with respect to the most
> recently plotted graph in the current window?

I smacked together a little procedure to allow me to do exactly that but for legends. It's
probably already been done, and done better (particularly in the braindead way I handle
the symbols). DF's example uses stuff I've never tried before (the !X.WINDOW stuff) so
most of the position calculation gymnastics may be unnecessary. Anyway, the code is
attached to this post (mylegend.pro). Use it, change it, wear it out.

cheers,

paulv


--
Paul van Delst A little learning is a dangerous thing;
CIMSS @ NOAA/NCEP Drink deep, or taste not the Pierian spring;
Ph: (301)763-8000 x7274 There shallow draughts intoxicate the brain,
Fax:(301)763-8545 And drinking largely sobers us again.
Alexander Pope.


;+
;
; NAME:
; mylegend
;
; PURPOSE:
; Procedure to output a plot legend in "PLOT NORMAL" coordinates. Plot normal
; coordinates are defined as coordinates normalised for the plotting region
; bounded by the plot axes, e.g. the bottom left axex vertex corresponds to
; (0,0) and the top right one corresponds to (1,1).
;
; CATEGORY:
; Graphics: Direct
;
; LANGUAGE:
; IDL v5.4
;
; CALLING SEQUENCE:
; mylegend, x_legend_pos, $
; y_legend_pos, $
; legend_text, $
; dx_pos = dx_pos, $
; color = color, $
; psym = psym, $
; symsize = symsize, $
; linestyle = linestyle, $
; charsize = charsize, $
; _extra = extra
;
; INPUTS:
; x_legend_pos: X-coordinate of the legend start position in "PLOT NORMAL"
; coordinates. Plot normal coordinates are coordinates normalised
; for the plotting region bounded by the plot axes.
;
; y_legend_pos: Y-coordinate of the legend start position in "PLOT NORMAL"
; coordinates. Plot normal coordinates are coordinates normalised
; for the plotting region bounded by the plot axes.
;
; legend_text: String array containing the legend text. No zero-length
; elements are permitted.
;
; INPUT KEYWORD PARAMETERS:
; dx_pos: Length of the line in the legend, in normalised units.
;
; color: Array containing the color of the legend text entries.
; If defined, must be the same size as the LEGEND_TEXT argument.
;
; psym: Array containing the symbol code of the legend text entries.
; If defined, must be the same size as the LEGEND_TEXT argument.
;
; symsize: Array containing the symbol size of the legend text entries.
; If defined, must be the same size as the LEGEND_TEXT argument.
;
; linestyle: Array containing the linestyel of the legend text entries.
; If defined, must be the same size as the LEGEND_TEXT argument.
;
; charsize: Character size to use in output of the legend text.
;
; _extra: Any other keywords accepted by both the PLOTS and XYOUTS
; commands.
;
; OUTPUTS:
; None.
;
; OUTPUT KEYWORD PARAMETERS:
; None.
;
; CALLS:
; None.
;
; COMMON BLOCKS:
; None.
;
; INCLUDE FILES:
; None.
;
; SIDE EFFECTS:
; None.
;
; RESTRICTIONS:
; This procedure assumes that the plotting range (transformation?)
; has already been established by a call to PLOT. You'll still get
; output if you haven't but if it's not where you expect it, too bad.
;
; EXAMPLE:
; To plot a legend in the centre of the plot,
;
; mylegend, 0.5, 0.5, $
; [ 'First one', 'Second one' ]
;
; CREATION HISTORY:
; Written by: Paul van Delst, CIMSS/SSEC, 04-Apr-2001
; paul.vandelst@ssec.wisc.edu
;
; Copyright (C) 2001 Paul van Delst, CIMSS/SSEC/UW-Madison
;
; This program is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version 2
; of the License, or (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
;
;-

PRO mylegend, x_legend_pos, $
y_legend_pos, $
legend_text, $
dx_pos = dx_pos, $
color = color, $
psym = psym, $
symsize = symsize, $
linestyle = linestyle, $
charsize = charsize, $
_extra = extra



;----------------------------------------------------------- -------------------
; -- Set up error handler --
;----------------------------------------------------------- -------------------

CATCH, error_status

IF ( error_status NE 0 ) THEN BEGIN
CATCH, /CANCEL
MESSAGE, !ERROR_STATE.MSG, /CONTINUE
HELP, /TRACEBACK
RETURN
ENDIF



;----------------------------------------------------------- -------------------
; -- Check input --
;----------------------------------------------------------- -------------------

n_arguments = 3
IF ( N_PARAMS() LT n_arguments ) THEN $
MESSAGE, 'Invalid number of arguments.', $
/NONAME, /NOPRINT


; -----------------------------------------
; Check that required arguments are defined
; -----------------------------------------

IF ( N_ELEMENTS( x_legend_pos ) EQ 0 ) THEN $
MESSAGE, 'Input X_LEGEND_POS argument not defined!', $
/NONAME, /NOPRINT

IF ( N_ELEMENTS( y_legend_pos ) EQ 0 ) THEN $
MESSAGE, 'Input Y_LEGEND_POS argument not defined!', $
/NONAME, /NOPRINT

n_entries = N_ELEMENTS( legend_text )
IF ( n_entries EQ 0 ) THEN $
MESSAGE, 'Input LEGEND_TEXT argument not defined!', $
/NONAME, /NOPRINT

index = WHERE( STRLEN( legend_text ) EQ 0, count )
IF ( count GT 0 ) THEN $
MESSAGE, 'Input LEGEND_TEXT argument contains empty strings. Norty norty!', $
/NONAME, /NOPRINT


; --------------
; Check keywords
; --------------

; -- Horizontal length of line in legend entry
IF ( N_ELEMENTS( dx_pos ) EQ 0 ) THEN dx_pos = 0.04

; -- Colours
n_colors = N_ELEMENTS( color )
IF ( n_colors EQ 0 ) THEN $
color = MAKE_ARRAY( n_entries, VALUE = !P.COLOR ) $
ELSE $
IF ( n_colors NE n_entries ) THEN $
MESSAGE, 'Keyword COLOR size different from LEGEND_TEXT', $
/NONAME, NOPRINT

; -- Symbols
n_symbols = N_ELEMENTS( psym )
IF ( n_symbols EQ 0 ) THEN $
psym = MAKE_ARRAY( n_entries, VALUE = 0 ) $
ELSE $
IF ( n_symbols NE n_entries ) THEN $
MESSAGE, 'Keyword PSYM size different from LEGEND_TEXT', $
/NONAME, NOPRINT

; -- Symbol size
n_sizes = N_ELEMENTS( symsize )
IF ( n_sizes EQ 0 ) THEN $
symsize = MAKE_ARRAY( n_entries, VALUE = 1.0 ) $
ELSE $
IF ( n_sizes NE n_entries ) THEN $
MESSAGE, 'Keyword SYMSIZE size different from LEGEND_TEXT', $
/NONAME, NOPRINT

; -- Linestyle
n_styles = N_ELEMENTS( linestyle )
IF ( n_styles EQ 0 ) THEN $
linestyle = MAKE_ARRAY( n_entries, VALUE = 0 ) $
ELSE $
IF ( n_styles NE n_entries ) THEN $
MESSAGE, 'Keyword LINESTYLE size different from LEGEND_TEXT', $
/NONAME, NOPRINT

; -- Character size
IF ( N_ELEMENTS( charsize ) EQ 0 ) THEN charsize = 0.75



;----------------------------------------------------------- -------------------
; -- Get the character sizes in normal coordinates --
;----------------------------------------------------------- -------------------

ch_size = CONVERT_COORD( !D.X_CH_SIZE, !D.Y_CH_SIZE, /DEVICE, /TO_NORMAL )
x_ch_size = ch_size[ 0 ] * charsize
y_ch_size = ch_size[ 1 ] * charsize



;----------------------------------------------------------- -------------------
; -- Convert the input "PLOT NORM" coordinates to actual normal coordinates --
;----------------------------------------------------------- -------------------

; -- Assign axis ranges
x1 = !X.CRANGE[0]
x2 = !X.CRANGE[1]

y1 = !Y.CRANGE[0]
y2 = !Y.CRANGE[1]

; -- Apply transformations. Doesn't matter if axes are logarithmic
; -- If they are, transformation is applied to the LOG of the range.
x_data_pos = x1 + ( ( x2 - x1 ) * x_legend_pos )
x_norm_pos = !X.S[0] + ( !X.S[1] * x_data_pos )

y_data_pos = y1 + ( ( y2 - y1 ) * y_legend_pos )
y_norm_pos = !Y.S[0] + ( !Y.S[1] * y_data_pos )



;----------------------------------------------------------- -------------------
; -- Output the legend --
;----------------------------------------------------------- -------------------

; ---------------------------------------------
; Create the array of Y legend text coordinates
;
; DELTA_CHAR defines the vertical separation of
; legend entities in Y_CH_SIZE units.
; ---------------------------------------------

delta_char = 1.5
y_pos = y_norm_pos - ( FINDGEN( n_entries ) * y_ch_size * delta_char )


; -----------------------------------------------
; Loop over the legend text entries
;
; DELTA_CHAR defines the horizontal separation of
; legend entities from it's graphical descriptor
; in X_CH_SIZE units.
; -----------------------------------------------

FOR i = 0, n_entries - 1 DO BEGIN


; ---------------------
; Check the symbol sign
; ---------------------

CASE 1 OF

( psym[ i ] LT 0 ): BEGIN

; -- Symbol and line
PLOTS, [x_norm_pos, x_norm_pos + dx_pos], $
[y_pos[i] , y_pos[i]], $
PSYM = psym[ i ], $
COLOR = color[ i ], $
SYMSIZE = symsize[ i ], $
LINESTYLE = linestyle[ i ], $
/NORM, $
_EXTRA = extra

; -- Legend text
XYOUTS, x_norm_pos + dx_pos + ( delta_char * x_ch_size ), $
y_pos[ i ] - ( y_ch_size/2.0 ), $
legend_text[ i ], $
COLOR = color[ i ], $
CHARSIZE = charsize, $
/NORM, $
_EXTRA = extra
END

( psym[ i ] EQ 0 ): BEGIN

; -- Just a line
PLOTS, [x_norm_pos, x_norm_pos + dx_pos], $
[y_pos[i] , y_pos[i]], $
COLOR = color[ i ], $
SYMSIZE = symsize[ i ], $
LINESTYLE = linestyle[ i ], $
/NORM, $
_EXTRA = extra

; -- Legend text
XYOUTS, x_norm_pos + dx_pos + ( delta_char * x_ch_size ), $
y_pos[ i ] - ( y_ch_size/2.0 ), $
legend_text[ i ], $
COLOR = color[ i ], $
CHARSIZE = charsize, $
/NORM, $
_EXTRA = extra
END

( psym[ i ] GT 0 ): BEGIN

; -- Just a symbol
PLOTS, x_norm_pos, $
y_pos[i], $
PSYM = ABS( psym[ i ] ), $
COLOR = color[ i ], $
SYMSIZE = symsize[ i ], $
/NORM, $
_EXTRA = extra

XYOUTS, x_norm_pos + ( delta_char * x_ch_size ), $
y_pos[ i ] - ( y_ch_size/2.0 ), $
legend_text[ i ], $
COLOR = color[ i ], $
CHARSIZE = charsize, $
/NORM, $
_EXTRA = extra
END

ENDCASE

ENDFOR


;----------------------------------------------------------- -------------------
; -- Done --
;----------------------------------------------------------- -------------------

CATCH, /CANCEL
RETURN

END


;----------------------------------------------------------- --------------------
; -- MODIFICATION HISTORY --
;----------------------------------------------------------- --------------------
;
; $Id:$
;
; $Date:$
;
; $Revision:$
;
; $State:$
;
; $Log:$
;
;
;
Re: xyouts with p.multi [message #25196 is a reply to message #25191] Fri, 25 May 2001 00:19 Go to previous message
Wayne Landsman is currently offline  Wayne Landsman
Messages: 117
Registered: January 1997
Senior Member
> I'm not sure why you would have expected that,
> since I've never heard "normalized" defined by anyone
> with respect to what is *in* a window.

Well, the reason I keep running into the problem is that if you just
have a single window, the distinction between the plot window and the
device area is unimportant. Typically, I will have made, say two
plotting programs 'makeplot1.pro' and 'makeplot2.pro' and they will each
work fine, using, say, XYOUTS,0.2,0.8,'Text',/normal internally. I
will later decide that I want to put both plots on a single page, and so
I naively write

!p.multi = [0,0,2]
makeplot1
makeplot2

and the positioning of the XYOUTS output is completely screwed up.
Now I can compute the correct positioning using !X.window and /NORMAL
coordinates as David suggested, or using !X.CRANGE and /DATA coordinates
as Liam suggested. But it does seem to eliminate most of the
advantages of having access to /Normal coordinates.

--Wayne
Landsman
landsman@mpb.gsfc.nasa.gov
Re: xyouts with p.multi [message #25198 is a reply to message #25196] Thu, 24 May 2001 14:52 Go to previous message
Liam E. Gumley is currently offline  Liam E. Gumley
Messages: 378
Registered: January 2000
Senior Member
"Christopher W. O'Dell" wrote:
>
> I am plotting six graphs on one page using !p.multi =
> [0,2,3]
> I am trying to put some text in the same place on each
> graph, by using
>
> xyouts, x, y, 'text', /norm
>
> after each graph is plotted. I would think, using /norm,
> that it would put the
> text *in that graph*; but it doesn't, it puts it in some
> crazy place. Does anyone know how
> to make xyouts position the text with respect to the most
> recently plotted graph in the current window?

By setting the NORMAL keyword, you are telling XYOUTS that the X and Y
coordinates are normalized, i.e., with respect to the entire display,
not just the current plot. You may have better luck plotting the text in
*data* coordinates, e.g.,

xyouts, x, y, 'text'

where x and y are selected relative to the x- and y-axes.

Cheers,
Liam.
http://cimss.ssec.wisc.edu/~gumley/
Re: xyouts with p.multi [message #25200 is a reply to message #25198] Thu, 24 May 2001 14:50 Go to previous message
davidf is currently offline  davidf
Messages: 2866
Registered: September 1996
Senior Member
Christopher W. O'Dell (odell@cmb.physics.wisc.edu) writes:

> I am plotting six graphs on one page using !p.multi =
> [0,2,3]
> I am trying to put some text in the same place on each
> graph, by using
>
> xyouts, x, y, 'text', /norm
>
> after each graph is plotted. I would think, using /norm,
> that it would put the
> text *in that graph*; but it doesn't, it puts it in some
> crazy place. Does anyone know how
> to make xyouts position the text with respect to the most
> recently plotted graph in the current window?

I'm not sure why you would have expected that,
since I've never heard "normalized" defined by anyone
with respect to what is *in* a window. But you could
use the "normalized" coordinates of the plot axis
endpoints to position text. Here is an example:

PRO Test
!P.Multi=[0, 3, 2]
FOR j=0,5 DO BEGIN
Plot, Findgen(11)
XYOUTS, !X.Window[0] + 0.2 * (!X.Window[1]-!X.Window[0]), $
!Y.Window[1] - 0.2 * (!Y.Window[1]-!Y.Window[0]), $
'This is text', /Normal
ENDFOR
!P.Multi=0
END

Cheers,

David
--
David Fanning, Ph.D.
Fanning Software Consulting
Phone: 970-221-0438 E-Mail: davidf@dfanning.com
Coyote's Guide to IDL Programming: http://www.dfanning.com/
Toll-Free IDL Book Orders: 1-888-461-0155
  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic: Re: read Nexrad level 3 data
Next Topic: Density from scattered points

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ] [ PDF ]

Current Time: Wed Oct 08 11:27:04 PDT 2025

Total time taken to generate the page: 0.00652 seconds