Viewing contents of file '../idllib/contrib/tappin/graffer/graff_add.pro'
pro Graff_add, file, a1, a2, a3, errors=errors, $
               funcx=funcx, funcy=funcy, polar=polar, rescale=rescale, $
               display=display, style=style, psym=psym, join=join, $
               symsize=symsize, colour=colour, thick=thick, $
               neval=neval, description=description, frange=frange, $
               sort=sort, graffer=graffer, errtype=errtype, $
               funcz=funcz, ascii=ascii, noclip=noclip, mouse=mouse

;+
; GRAFF_ADD
;	User-callable interface to add a dataset to a graffer file.
;
; Usage:
;	graff_add, file, [[[z], x,] y, errors=errors, funcx=funcx, $
;		funcy=funcy, errtype=errtype, funcz=funcz, $
;               polar=polar, rescale=rescale, /display, join=join, $
;               style=style, psym=psym, symsize=symsize, colour=colour, $
;               thick=thick, neval=neval, description=description, $
;               frange=frange, /graffer, /ascii, /noclip, $
;               mouse=mouse]
;
; Arguments:
;	file	string	input	The graffer file to modify.
;	z	float	input	The Z values for a 2-D dataset (If
;				only 2 arguments are present, then
;				they are treated as X & Y)
;	x	float	input	The x values to add.
;	y	float	input	The y values to add.
;
; Keywords:
;	errors	float	input	Array with errors, 1-d or (m,n).
;	errtype string	input	Specify error types as code
;				(e.g. "XXY" for asymmetrical errors in
;				X and symmetric errors in Y)
;	funcx	string	input	Function specification for x = f(y) or
;				x = f(t)
;	funcy	string	input	Function specification for y = f(x) or
;				y = f(t)
;	funcz	string	input	Function specification for z = f(x,y)
;	frange  float	input	The range of x, y or t over which to
;				plot a function
;	polar	int	input	If unset or 0 rectangular, 1 = polar
;				in radians, 2 = polar in degrees.
;	rescale 	input	If set, then reset the scaling of the
;				plot with the autoscale routine.
;	display		input	If set, then display the plot on the
;				current device.
;	style	int	input	The standard IDL linestyle codes
;	psym	int	input	The GRAFFER symbol code - extended IDL
;                                                         symbol
;                                                         codes.
;	join	int	input	The style of joining: 0 - none
;					 	      1 - sloping lines
;						      2 - histogram
;	symsize float	input	The size for the symbols (relative to
;				standard)
;	colour	int	input	Colour number - standard GRAFFER
;                                               colours (which may
;                                               well not work on
;                                               current device).
;	thick	int	input	Line thickness.
;	neval	int	input	The number of times to evaluate a
;				function. (2-elements for funcz)
;	description str input	A description of the data set.
;	sort		input	Whether to sort the values on the X
;				axis.
;	graffer		input	If set, then invoke GRAFFER after
;				adding the dataset.
;	ascii		input	If set, then save as an ASCII GRAFFER
;				file (by default a binary graffer file
;				is generated).
;	noclip		input	If  set, then disable clipping to the
;				axis box. 
;	mouse	int	input	If explicitly set to zero then
;				disable mouse-editing of the dataset.
;
; Restrictions:
;	The func<xyz> keys and the x,y,z arguments are exclusive.
;	The GRAFFER key overrides the DISPLAY key and the ASCII key.
;	The setting of display options for 2-D data & functions is not
;	yet suppported
;
; Side Effects:
;	A graffer file is updated or created.
;	The DISPLAY option will cause your device colour table to be
;	changed.
;
; History:
;	Original: 13/8/96; SJT
;	Fix counting problem for new file: 13/9/96; SJT
;	Add GRAFFER key: 18/9/96; SJT
;	Add support for 2-D datasets: 20/12/96; SJT
;	Support index for X (i.e. filename & 1 arg): 9/1/97; SJT
;	Add ascii key: 15/1/97; SJT
;	Add mouse-editing default option: 13/8/97; SJT
;-

;	Check that the necessary inputs are present

on_error, 2                     ; Return to caller on error

if (n_params() ge 3 and (keyword_set(funcx) or keyword_set(funcy) or $
                         keyword_set(funcz))) $
  then message, "May not specify both data and a function"

if ((keyword_set(funcx) or keyword_set(funcy)) and keyword_set(funcz)) $
  then message, "May not mix 1 & 2 D function specifiers"

case (n_params()) of
    0: message, "Must specify a GRAFFER file"
    1: if (not keyword_set(funcx) and $
           not keyword_set(funcy) and $
           not keyword_set(funcz)) then $
      message, "Must give data arrays or a function specification"
    2: begin
        y = a1
        x = findgen(n_elements(y))
    end
    3: begin                    ; 1-D dataset
        x = a1
        y = a2
    end
    4: begin                    ; 2-D dataset
        z = a1
        x = a2
        y = a3
    end
endcase

;	Open the file

version = [2, 2]

f0 = file
graff_init, pdefs, f0, version = version
igot = graff_get(pdefs, f0, /no_set, /no_warn)

handle_value, pdefs.data, data, /no_copy

if (pdefs.nsets gt 1 or data(0).ndata ne 0) then begin
    data = [data, {graff_data, $
                   Ndata:    0l, $
                   Ndata2:   0l, $ ; ONly used in 2D Dss
                   Type:     0, $
                   Mode:     0, $
                   Xydata:   handle_create(), $
                   Descript: "", $
                   Pline:    1, $
                   Psym:     0, $
                   Symsize:  1., $
                   Line:     0, $
                   Colour:   1, $
                   Thick:    1, $
                   Zopts:    {graff_2d, $
                              Format:    0, $
                              N_levels:  -6, $
                              Levels:    fltarr(30), $
                              N_cols:    1, $
                              Colours:   intarr(30)+1, $
                              N_sty:	  1, $
                              Style:     intarr(30), $
                              N_thick:   1, $
                              Thick:     intarr(30)+1, $
                              Range:     fltarr(2), $
                              Pxsize:    0.5, $
                              Label:     0, $
                              Fill:      0b}, $
                   Sort:     0b, $
                   Noclip:   0b, $
                   Medit:    pdefs.opts.mouse}]
    
    pdefs.nsets = pdefs.nsets+1
endif

pdefs.cset = pdefs.nsets-1

if (n_params() eq 3 or n_params() eq 2) then begin ; Ordinary data
    
    nx = n_elements(x)
    ny = n_elements(y)
    if (nx ne ny) then message, 'X & Y must be the same size'
    
    if (keyword_set(errors)) then begin
        se = size(errors)
        if (se(0) eq 1) then begin
            nt = 3
            nerr = se(1)
            errs = transpose(errors)
        endif else if (se(0) eq 2 and se(1) le 6) then begin
            nt = se(1)+2
            nerr = se(2)
            errs = errors
        endif else message, "Invalid dimensions for ERRORS"
        if (nerr ne nx) then message, 'Must have the same number of ' + $
          'errors as X-values'
    endif else nt = 2

    xydata = fltarr(nt, nx)
    xydata(0, *) = x
    xydata(1, *) = y
    if (nt ge 3) then xydata(2, 0) = errs
    
    defety = [0, 1, 2, 6, 8]
    if (keyword_set(errtype)) then begin
        set = size(errtype)
        if (set(set(0)+1) eq 7) then case strupcase(errtype) of
            'XY': ety = 0
            'XYE': ety = 1
            'XYEE': ety = 2
            'XYF': ety = 3
            'XYFF': ety = 4
            'XYFE': ety = 5
            'XYFEE': ety = 6
            'XYFFE': ety = 7
            'XYFFEE': ety = 8
        endcase else ety = fix(errtype)
        
        ntet = [2, 3, 4, 3, 4, 4, 5, 5, 6]
        if (ntet(ety) ne nt) then begin
            print, "Requested error mapping does not match the number " + $
              "of error limits"
            print, "Using the default for ", nt-2, " errors"
            ety = defety(nt-2)
        endif
    endif else ety = defety(nt-2)
            
       
    handle_value, data(pdefs.cset).xydata, xydata, /set
    data(pdefs.cset).type = ety
    data(pdefs.cset).ndata = nx
    
endif else if (n_params() eq 4) then begin ; 2-D dataset
    
    sz = size(z)
    if (sz(0) ne 2) then message, "Z array must be 2-D"
    nx = sz(1)
    ny = sz(2)
    if (n_elements(x) ne sz(1)) then message, "X-array doesn't match " + $
      "X-size of Z-array"
    if (n_elements(y) ne sz(2)) then message, "Y-array doesn't match " + $
      "Y-size of Z-array"
    
    xydata = {graff_zdata, $
              Z: handle_create(), $
              X: handle_create(), $
              Y: handle_create()}

    data(pdefs.cset).ndata = nx
    data(pdefs.cset).ndata2 = ny

    handle_value, xydata.x, x, /no_copy, /set
    handle_value, xydata.y, y, /no_copy, /set
    handle_value, xydata.z, z, /no_copy, /set

    handle_value, data(pdefs.cset).xydata, xydata, /no_copy, /set
    data(pdefs.cset).type = 9

endif else begin                ; function
    if (keyword_set(funcz)) then begin
        if (not keyword_set(frange)) then frange = fltarr(2, 2)
        xydata = {graff_zfunct,  $
                  Range: frange,  $
                  Funct: funcz}
        data(pdefs.cset).type = -4
        if (keyword_set(neval)) then data(pdefs.cset).ndata2 = neval(1) $
        else data(pdefs.cset).ndata2 = 25
        
    endif else if (keyword_set(funcx) and keyword_set(funcy)) then begin ;
                                ; parametric
        if (not keyword_set(frange)) then frange = findgen(2)
        xydata = {graff_pfunct,  $
                  Range:frange,  $
                  Funct:[funcx, funcy]}
        data(pdefs.cset).type = -3
        
    endif else if keyword_set(funcy) then begin
        if (not keyword_set(frange)) then frange = fltarr(2)
        xydata = {graff_funct,  $
                  Range:frange,  $
                  Funct:funcy}
        data(pdefs.cset).type = -1
        
    endif else begin
        if (not keyword_set(frange)) then frange = fltarr(2)
        xydata = {graff_funct,  $
                  Range:frange,  $
                  Funct:funcx}
        data(pdefs.cset).type = -2
        
    endelse
    handle_value, data(pdefs.cset).xydata, xydata, /set
    
    if (keyword_set(neval)) then data(pdefs.cset).ndata = neval(0) $
    else data(pdefs.cset).ndata = 25
    
endelse

if (keyword_set(polar) and (data(pdefs.cset).type ge -3 and $
                            data(pdefs.cset).type le 8)) then $
    data(pdefs.cset).mode = polar
if (n_elements(psym) ne 0) then  data(pdefs.cset).psym = psym
if (n_elements(join) ne 0) then data(pdefs.cset).pline = join
if (n_elements(symsize) ne 0) then  data(pdefs.cset).symsize = symsize
if (n_elements(style) ne 0) then data(pdefs.cset).line = style
if (n_elements(colour) ne 0) then  data(pdefs.cset).colour = colour
if (n_elements(thick) ne 0) then  data(pdefs.cset).thick = thick
if (keyword_set(sort)) then data(pdefs.cset).sort = 1
if (n_elements(description) ne 0) then  data(pdefs.cset).descript = description
if (n_elements(noclip)  ne 0) then data(pdefs.cset).noclip = noclip
if (n_elements(mouse) ne 0) then data(pdefs.cset).medit = mouse

handle_value, pdefs.data, data, /no_copy, /set

if (keyword_set(rescale)) then begin
    gr_autoscale, pdefs, /xaxis, /ignore
    gr_autoscale, pdefs, /yaxis, /ignore
endif

if (keyword_set(graffer)) then begin
    gr_bin_save, pdefs
    graffer, file
    return
endif else if (keyword_set(display)) then begin
    graff_colours, pdefs
    gr_plot_object, pdefs
endif

if (keyword_set(ascii)) then gr_asc_save, pdefs $
else gr_bin_save, pdefs

end