SUBROUTINE SPLOT( STATUS )
*+
*  Name:
*     SPLOT

*  Purpose:
*     Generates plot of spectra with overlaid fits

*  Language:
*     Starlink Fortran

*  Type of Module:
*     ASTERIX task

*  Invocation:
*     CALL SPLOT( STATUS )

*  Arguments:
*     STATUS = INTEGER (Given and Returned)
*        The global status.

*  Description:
*     Obtains observed data (with instrument response if present) and fit
*     model from the environment, and produces a GRAFIX dataset of data with
*     model overlaid. This can be done rigorously in the data space, or (in
*     the case where model and data spaces are distict; i.e. instrument folding
*     has taken place) with some approximation in the model space, or both,
*     according to the plot mode selected:
*         Mode D/C...........................  data/channel space plot
*         Mode P ............................  photon space plot
*         Mode DP ...........................  both data and model plots
*         Mode DPR......... .................  data and model with residuals
*         Mode R.............................  data space residuals (only)
*     If multiple datasets are entered then all are displayed.
*     For the spectral fitting case, a redshift may be included. The model is
*     then interpreted as applying in the source frame, but the model space
*     spectrum displayed is that observed in the earth frame (i.e. flux from
*     blue shifted source energy bins is mapped onto the corresponding
*     unshifted rest frame bins.
*     Note - no special treatment is required for data which has been
*     likelihood fitted - it is assumed that the dataset given is
*     b/g-subtracted, so plotting is unaffected.

*  Usage:
*     splot {parameter_usage}

*  Environment Parameters:
*     INP = CHAR (read)
*        Input data (either a single dataset or a file of references).
*     Z = REAL (read)
*        Redshift of source spectrum
*     MODEL = CHAR (read)
*        Data object containing model specification
*     MODE = LITERAL(R)
*        Plot mode
*     OUT = CHAR (read)
*        Output plot file

*  Examples:
*     {routine_example_text}
*        {routine_example_description}

*  Pitfalls:
*     {pitfall_description}...

*  Notes:
*     {routine_notes}...

*  Prior Requirements:
*     {routine_prior_requirements}...

*  Side Effects:
*     {routine_side_effects}...

*  Algorithm:
*     Model space dataset values are generated by an approximate method
*     (unavoidably), explained in SPLOT_TRANSFM. Note that the
*     transformation is only valid if the model is a good fit.
*     Formatting of plotted output is expressed in terms of 'plot zones'
*      'plots' and 'graphs'. A 'plot' is a set of axes with one or more
*     'graphs' plotted on it (i.e. overlaying allows several graphs per plot).
*     A 'plot zone' is just the collection of plots for a single input
*     dataset. The total graphical output from the program consists of one
*     p.z. for each dataset.
*     Note that the base axes in each plot are set by the observed data. This
*     may mean that some of an overlaid fit will disappear off the graph.
*     Graph legends and axis labels etc are propagated from the input datasets
*     into the plots produced.

*  Accuracy:
*     {routine_accuracy}

*  Timing:
*     {routine_timing}

*  Implementation Status:
*     {routine_implementation_status}

*  External Routines Used:
*     {name_of_facility_or_package}:
*        {routine_used}...

*  Implementation Deficiencies:
*     Assumes that either ALL or NO datasets are folded.
*     Residual plotting not yet implemented.

*  References:
*     {task_references}...

*  Keywords:
*     splot, usage:public

*  Copyright:
*     Copyright (C) University of Birmingham, 1995

*  Authors:
*     TJP: Trevor Ponman (University of Birmingham)
*     RJV: Bob Vallance (ROSAT, University of Birmingham)
*     {enter_new_authors_here}

*  History:
*     26 Aug 88: Converted to FIT_MODEL, model space plotting working (TJP)
*      1 Dec 88: Residual plotting implemented + various minor bug fixes (TJP)
*     24 Jan 89: QUALITY copied into residual plot (TJP)
*     17 May 89: Safeguarded against undefined returns from MATH_LINTERP (TJP)
*     13 Jun 89: Converted to ASTERIX88 (RJV)
*     21 Jun 89: Final mods and redshifting (TJP)
*     12 Jul 89: Final final mods to deal with spectral sets (RJV/TJP)
*     17 Nov 89: Warning if no response found in spectral case (TJP)
*      5 Dec 89: Photon space residuals expressed as significances (TJP)
*     18 May 90: Trap missing quality in model space resid case (TJP)
*      6 Dec 90: Doesn't copy input quality if not present (DJA)
*      5 Aug 90: QUALITY copied to residuals plot! (TJP)
*     22 Jun 92: Handle case when photon space model (& its variance) = 0 (TJP)
*      3 Jul 92: Change to FIT_DATINGET & _PREDDAT interfaces (l-fitting) (TJP)
*      8 Jul 92: Legend change in plots (TJP)
*      9 Aug 92: Bug in handling Quality for spectral sets fixed (TJP)
*     25 Jun 87: V0.6-1 Original (BHVAD::TJP)
*     23 Aug 88: V0.6-2 Major reorganisation, FIT_PLOT introduced (TJP)
*     28 Nov 88: V0.6-3 Residual plotting option implemented (TJP)
*     21 Jun 89: V1.0-1 ASTERIX88 release, incorporates redshifting (TJP/RJV)
*      7 Dec 90: V1.4-1 Bug with multiple spectra and model compts fixed (TJP)
*      5 Aug 91: V1.5-1 Quality arrays copied to resids plots, INIT added (TJP)
*     24 Jun 92: V1.6-1 FIT_PLOT adapted to call l-fit routines + bug fix (TJP)
*        Feb 93: V1.7-0 FIT_PLOT got rid of - interactive plotting (RJV)
*      4 Mar 93: V1.7-1 Use new SFIT_ subroutines (DJA)
*      6 May 93: V1.7-2 Divide by bin width (RJV)
*      8 Sep 93: V1.7-3 Added SPEC_INIT call and removed reference to
*                       SPEC_CMN_RZ (DJA)
*        Nov 93: V1.7-4 Complete rebuild and new features (RJV)
*     19 Mar 94: V1.7-5 Model component plot (RJV)
*     24 Nov 94 : V1.8-0 Now use USI for user interface (DJA)
*     24 Apr 95 : V1.8-1 Updated input and model data interfaces. Use
*                        ADI style response matrices (DJA)
*     30 Nov 1995 V2.0-0 (DJA):
*        Full ADI port
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
      
*  Type Definitions:
      IMPLICIT NONE              ! No implicit typing

*  Global Constants:
      INCLUDE 'SAE_PAR'          ! Standard SAE constants
      INCLUDE 'FIT_PAR'
      INCLUDE 'ADI_PAR'

*  Structure Definitions:
      INCLUDE 'FIT_STRUC'

*  Global Variables:
      INCLUDE 'SPLOT_CMN'
*        {global_name}[dimensions] = {data_type} ({global_access_mode})
*           [global_variable_purpose]

*  Status:
      INTEGER			STATUS             	! Global status

*  Local Constants:
      CHARACTER*30		VERSION
        PARAMETER		( VERSION = 'SPLOT Version V2.0-0' )

*  Local Variables:
      RECORD /DATASET/ 		OBDAT(NDSMAX)		! Observed datasets
      RECORD /INSTR_RESP/ 	INSTR(NDSMAX)   	! Instrument responses
      RECORD /PREDICTION/ 	PREDDAT(NDSMAX) 	! Data predicted by model
      RECORD /MODEL_SPEC/ 	MODEL			! Model specification
      RECORD /MODEL_SPEC/ 	TMODEL			! Term model spec

      CHARACTER*80 		MODSPEC			! Model spec (for title)
      CHARACTER*80 		TITLE(2)		! Text specifying dataset and model
      CHARACTER*20 		DEV			! Graphics device
      CHARACTER*20 		COMPSPEC(MAXCOMP)	! spec for individual components

      REAL 			PARAM(NPAMAX)		! Model parameters
      REAL 			LB(NPAMAX)		! Parameter lower bounds
      REAL 			UB(NPAMAX)		! Parameter upper bounds
      REAL 			LE(NPAMAX)	        ! Lower parameter errors
      REAL 			UE(NPAMAX)		! Upper parameter errors
      REAL 			XMIN,XMAX		! Min/max x for current p.z. (NDC)
      REAL 			YMIN,YMAX		! Min/max y for current p.z. (NDC)
      REAL 			ELOW,EUPP		! energy bounds for model plot
      REAL 			EWID			! channel width for model plot
      REAL 			Z			! Redshift [ Eobs/Esource=1/(1+z) ]

      INTEGER			IERR			! First VEC_ error
      INTEGER			IFID			! Input dataset id
      INTEGER 			IG			! Current graph number
      INTEGER 			IP			! Current plot number
      INTEGER 			ITERM			! Loop over terms
      INTEGER 			IUX			! Current x posn (in plot zone)
      INTEGER 			IUY			! Current y posn (in plot zone)
      INTEGER 			LDIM(2),UDIM(2)         ! Slice specification
      INTEGER			MFID			! Model spec dataset id
      INTEGER			MOBJ			! O/p multi-graph
      INTEGER 			NCHAN			! # energy channels for model plot
      INTEGER			NERR			! # VEC_ errors
      INTEGER 			N			! Dataset index
      INTEGER 			NDMAX,NFMAX
      INTEGER 			NMAX,NEL
      INTEGER 			NGOOD			! # good data points
      INTEGER 			NNDF			! Total # NDFs (curves)
      INTEGER 			NPAR			! No of parameters
      INTEGER 			NPZ			! # plots per plot zone
      INTEGER 			NGZ			! # graphs per plot zone
      INTEGER 			NSET			! # spectra in set
      INTEGER 			NTERM			! # additive terms 
      INTEGER 			NZX,NZY			! x,y layout of plot zones
      INTEGER			OFID			! Output dataset
      INTEGER			QPTR			! I/p quality pointer
      INTEGER 			SIGNS(MAXCOMP)		! Sign of each term
      INTEGER 			SSCALE			! Statistic scaling
      INTEGER 			TERMS(MAXCOMP,MAXCOMP)	! Individual terms

      LOGICAL 			ACTIVE			! Graphics device active
      LOGICAL 			CHANGE			! Plot mode has changed
      LOGICAL 			COMPLEX                 ! Complex plot (>1 per page)
      LOGICAL 			FROZEN(NPAMAX)		! Parameter frozen?
      LOGICAL 			SAVE			! Save data to file?
*.

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

*  Version id
      CALL MSG_PRNT( VERSION )

*  Initialise ASTERIX
      CALL AST_INIT()
      CALL SPEC_INIT( STATUS )

*  Set up genus in MODEL structure
      MODEL.GENUS = 'SPEC'

*  Set plot mode flags in common
      CALL SPLOT_PLOTMODE( 'MODE', CHANGE, COMPLEX, STATUS )

*  Model only plot?
      IF ( MPLOT ) THEN

        CALL USI_GET0R( 'ELOW', ELOW, STATUS ) 
        CALL USI_GET0R( 'EUPP', EUPP, STATUS )
        CALL USI_GET0I( 'NCHAN', NCHAN, STATUS )

      ELSE

*    Get observed data and response
        CALL USI_ASSOC( 'INP', 'FileSet|BinDS', 'READ', IFID, STATUS )
        CALL FIT_GETDAT( ADI__NULLID, IFID, 'SPEC', 1, .FALSE., 
     :                   .FALSE., NDS, OBDAT,
     :                   NGOOD, SSCALE, PREDDAT, INSTR, STATUS )
        NDMAX = OBDAT(1).NDAT
        NFMAX = PREDDAT(1).NMDAT

      END IF

*  Get model specification
      CALL USI_ASSOC( 'MODEL', '*', 'READ', MFID, STATUS )
      CALL FIT_MODGET( MFID, MODEL, NPAR, PARAM, LB, UB, LE, UE, FROZEN,
     :                 STATUS )
      MODSPEC = MODEL.SPEC

*  Look for redshift
      CALL SFIT_GETZ( Z, STATUS )

      IF ( MPLOT ) THEN

*    Apply redshift
        CALL SFIT_APPRED(Z,1,ELOW,EUPP,STATUS)
        EWID = (EUPP-ELOW)/REAL(NCHAN)

      ELSE

*    Apply red-shift and check data structures
        CALL SFIT_PRECHK( NDS, Z, PREDDAT, STATUS )
 
*    Loop through input datasets to find maximum data and predicted data sizes
        DO N = 1, NDS
          NDMAX = MAX(NDMAX,OBDAT(N).NDAT)
          NFMAX = MAX(NFMAX,PREDDAT(N).NMDAT)
        END DO

*    Get dynamic storage
        CALL SPLOT_GET_DYN( NDMAX, NFMAX, STATUS )

      END IF

*  Set up workspace for model stack
      IF ( MPLOT ) THEN
        CALL DYN_MAPR(1,NCHAN*MAXSTACK,MODEL.STACKPTR,STATUS)
      ELSE
        NMAX = MAX(NDMAX,NFMAX)
        CALL DYN_MAPR(1,NMAX*MAXSTACK,MODEL.STACKPTR,STATUS)
      END IF
      IF ( STATUS .NE. SAI__OK ) GOTO 9000

      IF ( MPLOT ) THEN

*    Break up model into additive components
        CALL FIT_MSPECFLAT( MODEL, MAXCOMP, NTERM, TERMS, SIGNS, 
     :                      STATUS )

*    Dynamic storage
        CALL SPLOT_MPLOT_GET_DYN( NCHAN, NTERM, STATUS )
        CALL ARR_INIT1R( 0.0, NCHAN, %val(MTDPTR), STATUS )

*    Get channel boundaries and centres
        CALL SPLOT_MPLOT_EAXIS( NCHAN, ELOW, EUPP, %VAL(ELPTR),
     :                      %VAL(EUPTR), %VAL(MCXPTR), STATUS )

*    Get data values for each term
        DO ITERM = 1, NTERM

*      Calculate values in a term
          CALL FIT_MCALCTERM( MODEL, NTERM, TERMS, SIGNS, ITERM,
     :                        PARAM, 1, 1, NCHAN, NCHAN, NCHAN+1,
     :                        %VAL(ELPTR), %VAL(EUPTR),
     :                        %VAL(MODEL.STACKPTR), TMODEL,
     :                        %VAL(MCDPTR(ITERM)), STATUS )

*      Store term model spec for labelling
          COMPSPEC(ITERM) = TMODEL.SPEC

*      Normalise
          CALL SPLOT_DIVWID2( NCHAN, EWID, %VAL(MCDPTR(ITERM)), STATUS )

*      Add to total model (what about -ve)
          CALL SPLOT_MPLOT_ADDCOMP( NCHAN, %VAL(MCDPTR(ITERM)),
     :                                   %VAL(MTDPTR), STATUS )

*    Next term
        END DO

      ELSE

*    Loop through input datasets getting predicted data values
        DO N = 1, NDS
          CALL FIT_PREDDAT( 1, NDS, OBDAT, INSTR, PREDDAT, MODEL,
     :                      PARAM, N, %VAL(PREDDAT(N).DPTR), STATUS )
        END DO

*    If no convolution is involved, plot mode 'P' is unavailable
        IF ( PPLOT .AND. .NOT. (PREDDAT(1).CONVOLVE) ) THEN
          CALL MSG_PRNT('No convolution available - '//
     :                         'cannot plot in photon space')
          PPLOT = .FALSE.
          PRPLOT = .FALSE.
        END IF

      END IF
      IF ( STATUS .NE. SAI__OK ) GOTO 9000

*  Set up layout parameters
      CALL SPLOT_LAYOUT( NPZ, NGZ, NZX, NZY, STATUS )

*  Get number of NDFs to store data
      IF ( MPLOT ) THEN
        NNDF = NTERM + 1
      ELSE
        NNDF = NGZ * NDS
      END IF

*  Interactive or save mode
      CALL USI_GET0L( 'SAVE', SAVE, STATUS )
      IF ( STATUS .NE. SAI__OK ) GOTO 9000

*  Output is multi-graph 
      CALL ADI_NEW0( 'MultiGraph', MOBJ, STATUS )

*  Create file in save mode
      IF ( SAVE ) THEN

        CALL USI_CREAT( 'OUT', MOBJ, OFID, STATUS )
        CALL MSG_PRNT('Creating multiple dataset...')

*  Otherwise write to graphics device
      ELSE

*    Temporary internal file
        CALL ADI_TEMP( OFID, STATUS )
        CALL ADI_SETLNK( MOBJ, OFID, STATUS )
        OFID = MOBJ

*    Open device if not already open
        CALL GDV_STATUS( ACTIVE, STATUS )
        IF ( .NOT. ACTIVE ) THEN
          CALL USI_GET0C( 'DEV', DEV, STATUS )
          CALL GDV_OPEN( DEV, 1, 1, STATUS )
        END IF

      END IF

*  Create structure for holding NDFs
      CALL GMI_CREMULT( OFID, NNDF, STATUS )

*  Connect to local graphics control
      CALL GCB_LCONNECT( STATUS )
      IF ( STATUS .NE. SAI__OK ) GOTO 9000

*  Finally do plotting

*  model only plot
      IF ( MPLOT ) THEN

        CALL SPLOT_MPLOT_SETUP( NCHAN, NTERM, MODSPEC, COMPSPEC, 
     :                          STATUS )
        CALL SPLOT_MPLOT_COPY( OFID, NCHAN, NTERM, COMPSPEC, SAVE, 
     :                         STATUS )

      ELSE

*    Loop through datasets
  	DO N = 1, NDS

*      Current graph number
	  IG = 1 + (N-1)*NGZ

*      Current plot number
          IF ( OVERLAY ) THEN
            IP = 1
          ELSE
            IP = 1+(N-1)*NPZ
          END IF

*      Current X and Y position in plot zones
          IF ( OVERLAY ) THEN
            IUX = 1
            IUY = 1
          ELSE
            IUX = 1 + MOD(N-1,NZX)
	    IUY = 1 + INT((N-1)/NZX)
          END IF

*      Window for current plot zone (in Normalised Device Coords)
	  XMIN = REAL(IUX-1)/NZX
	  XMAX = REAL(IUX)/NZX
	  YMIN = REAL(IUY-1)/NZY
	  YMAX = REAL(IUY)/NZY

*      Number of values in model space, and address of model space data
          NFIT = PREDDAT(N).NMDAT
          IFPTR = PREDDAT(N).DPTR

*      Number of values in channel space, and address of channel space data
          DSID = OBDAT(N).D_ID
          NVAL = OBDAT(N).NDAT
          IDPTR = OBDAT(N).DPTR

*      Number of spectral sets in data
          NSET = OBDAT(N).SETINDEX

*      Quality and variance present in fit data?
          QOK = ((OBDAT(N).QPTR).NE.0)
          VOK = ((OBDAT(N).VPTR).NE.0)

*      Spectral set?
          IF ( NSET .GT. 0 ) THEN
            LDIM(1)=1
            LDIM(2)=NSET
            UDIM(1)=NVAL
            UDIM(2)=NSET
            NEL = NSET * NVAL
          ELSE				! single dataset
            LDIM(1)=1
            UDIM(1)=NVAL
            NEL = NVAL
          END IF

*      Make copy of data and model
          CALL ARR_COP1R( NVAL, %VAL(IDPTR), %VAL(DDPTR), STATUS )
          CALL ARR_COP1R( NVAL, %VAL(IFPTR), %VAL(DFDPTR), STATUS )

*      Copy data variance if present
          IF ( VOK ) THEN
            IVPTR = OBDAT(N).VPTR
            CALL ARR_COP1R( NVAL, %VAL(IVPTR), %VAL(DVPTR), STATUS ) 

*      If not present, use input data assuming Poisson statistics
          ELSE
            CALL DYN_MAPR( 1, NEL, DVPTR, STATUS )
            CALL VEC_ABSR( .FALSE., NEL, %VAL(IDPTR), %VAL(DVPTR),
     :                     IERR, NERR, STATUS )

          END IF

*      Copy data quality if present
          IF ( QOK ) THEN
            CALL BDI_MAPUB( DSID, 'Quality', 'READ', QPTR, STATUS )
            CALL DYN_MAPB( 1, NEL, DQPTR, STATUS )
            CALL ARR_SLCOPB( OBDAT(N).NDIM, OBDAT(N).IDIM, %VAL(QPTR),
     :                       LDIM, UDIM, %VAL(DQPTR), STATUS )
            CALL BDI_GET0UB( DSID, 'QualityMask', MASK, STATUS )
          ELSE
            DQPTR = 0
          END IF

*      Access data channel axis values
          CALL BDI_AXMAPR( DSID, 1, 'Data', 'READ', DXPTR, STATUS )
          CALL BDI_AXMAPR( DSID, 1, 'Width', 'READ', DWPTR, STATUS )

*      Set up data for plots
          CALL SPLOT_GEN_SETUP( INSTR(N), PREDDAT(N), Z, STATUS )

*      Construct plot title
          CALL SPLOT_TITLE( OBDAT(N).DATNAME, MODSPEC, TITLE )

*      Progress report...
          IF ( SAVE ) THEN
            CALL MSG_SETI( 'DS', N )
            CALL MSG_PRNT( 'Dataset ^DS' )
          END IF

*      Data space plot
   	  IF ( DPLOT ) THEN

            CALL SPLOT_DPLOT_SETUP( N, NPZ, XMIN, XMAX, YMIN, YMAX,
     :                              TITLE, STATUS )
            CALL SPLOT_DPLOT_COPY( OFID, IP, IG, N, SAVE, STATUS )

*        Update plot and graph nos.
	    IP = IP + 1
	    IG = IG + 2

          END IF

*      Data space residuals
          IF ( DRPLOT ) THEN

            CALL SPLOT_DRPLOT_SETUP( N, NPZ, XMIN, XMAX, YMIN, YMAX,
     :                                                      STATUS )
            CALL SPLOT_DRPLOT_COPY( OFID, IP, IG, N, SAVE, STATUS )

*        Update plot and graph nos.
            IP = IP + 1 
            IG = IG + 1

          END IF

*      Photon space plot
          IF ( PPLOT ) THEN

            CALL SPLOT_PPLOT_SETUP( N, NPZ, XMIN, XMAX, YMIN, YMAX,
     :                                              TITLE, STATUS )
            CALL SPLOT_PPLOT_COPY( OFID, IP, IG, N, SAVE, STATUS )

*        Update plot and graph nos.
	    IP = IP + 1
	    IG = IG + 2

          END IF

*      Photon space residuals
	  IF ( PRPLOT ) THEN

            CALL SPLOT_PRPLOT_SETUP( N, NPZ, XMIN, XMAX, YMIN, YMAX,
     :                               STATUS )
            CALL SPLOT_PRPLOT_COPY( OFID, IP, IG, N, SAVE, STATUS )

*        Update plot and graph nos.
            IP = IP + 1
            IG = IG + 1

	  END IF

*    End of dataset loop
        END DO

*    Free workspace
        CALL SPLOT_RELEASE_DYN( STATUS )

      END IF

*  Release model stack
      CALL DYN_UNMAP( MODEL.STACKPTR, STATUS )

*  Release output
      IF ( SAVE ) THEN
        CALL USI_ANNUL( 'OUT', STATUS )

*  If in interactive mode - plot
      ELSE
        CALL GDRAW_SUB( OFID, STATUS )

      END IF

*  Exit
 9000 IF ( .NOT. ACTIVE ) THEN
        CALL GDV_CLOSE( STATUS )
      END IF

      CALL GCB_DETACH( STATUS )
      CALL AST_CLOSE()

      END


*+
      SUBROUTINE SPLOT_GET_DYN(ND,NF,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Import :
      INTEGER ND,NF
*    Import-Export :
*    Export :
*    Status :
        INTEGER STATUS
*    Global constants :
        INCLUDE 'SAE_PAR'
        INCLUDE 'FIT_PAR'
*    Global variables :
        INCLUDE 'SPLOT_CMN'
*    Local variables :
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

      CALL DYN_MAPR(1,ND,DDPTR,STATUS)
      CALL DYN_MAPR(1,ND,DVPTR,STATUS)
      CALL DYN_MAPR(1,ND,DRDPTR,STATUS)
      CALL DYN_MAPR(1,ND,DFDPTR,STATUS)
      CALL DYN_MAPR(1,ND,PDPTR,STATUS)
      CALL DYN_MAPR(1,ND,PVPTR,STATUS)
      CALL DYN_MAPR(1,ND,PXPTR,STATUS)
      CALL DYN_MAPR(1,ND,PWPTR,STATUS)
      CALL DYN_MAPR(1,NF,PFDPTR,STATUS)
      CALL DYN_MAPR(1,NF,PFXPTR,STATUS)
      CALL DYN_MAPR(1,ND,PRDPTR,STATUS)
      CALL DYN_MAPR(1,ND,PRVPTR,STATUS)
      CALL DYN_MAPB(1,ND,PRQPTR,STATUS)
      CALL DYN_MAPR(1,ND,PIDPTR,STATUS)

      IF (STATUS.NE.SAI__OK) THEN
        CALL AST_REXIT('SPLOT_GET_DYN',STATUS)
      END IF

      END


*+
      SUBROUTINE SPLOT_RELEASE_DYN(STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Import :
*    Import-Export :
*    Export :
*    Status :
        INTEGER STATUS
*    Global constants :
        INCLUDE 'SAE_PAR'
        INCLUDE 'FIT_PAR'
*    Global variables :
        INCLUDE 'SPLOT_CMN'
*    Local variables :
*-

        CALL DYN_UNMAP(DDPTR,STATUS)
        IF ( .NOT. VOK ) THEN
          CALL DYN_UNMAP(DVPTR,STATUS)
        END IF
        CALL DYN_UNMAP(DRDPTR,STATUS)
        CALL DYN_UNMAP(DFDPTR,STATUS)
        CALL DYN_UNMAP(PDPTR,STATUS)
        CALL DYN_UNMAP(PVPTR,STATUS)
        CALL DYN_UNMAP(PXPTR,STATUS)
        CALL DYN_UNMAP(PWPTR,STATUS)
        CALL DYN_UNMAP(PFDPTR,STATUS)
        CALL DYN_UNMAP(PFXPTR,STATUS)
        CALL DYN_UNMAP(PRDPTR,STATUS)
        CALL DYN_UNMAP(PRVPTR,STATUS)
        CALL DYN_UNMAP(PRQPTR,STATUS)
        CALL DYN_UNMAP(PIDPTR,STATUS)

	END


*+
      SUBROUTINE SPLOT_MPLOT_GET_DYN(NCHAN,NTERM,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Import :
      INTEGER NCHAN,NTERM
*    Import-Export :
*    Export :
*    Status :
        INTEGER STATUS
*    Global constants :
        INCLUDE 'SAE_PAR'
        INCLUDE 'FIT_PAR'
*    Global variables :
        INCLUDE 'SPLOT_CMN'
*    Local variables :
        INTEGER I
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

      CALL DYN_MAPR(1,NCHAN+1,ELPTR,STATUS)
      CALL DYN_MAPR(1,NCHAN+1,EUPTR,STATUS)
      CALL DYN_MAPR(1,NCHAN,MCXPTR,STATUS)
      DO I = 1, NTERM
        CALL DYN_MAPR(1,NCHAN,MCDPTR(I),STATUS)
      END DO
      CALL DYN_MAPR(1,NCHAN,MTDPTR,STATUS)

      IF ( STATUS .NE. SAI__OK ) THEN
        CALL AST_REXIT('SPLOT_MPLOT_GET_DYN',STATUS)
      END IF

      END


*+
      SUBROUTINE SPLOT_MPLOT_RELEASE_DYN(NTERM,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Import :
      INTEGER NTERM
*    Import-Export :
*    Export :
*    Status :
        INTEGER STATUS
*    Global constants :
        INCLUDE 'SAE_PAR'
        INCLUDE 'FIT_PAR'
*    Global variables :
        INCLUDE 'SPLOT_CMN'
*    Local variables :
        INTEGER I
*-

        CALL DYN_UNMAP(ELPTR,STATUS)
        CALL DYN_UNMAP(EUPTR,STATUS)
        CALL DYN_UNMAP(MCXPTR,STATUS)
        DO I=1,NTERM
          CALL DYN_UNMAP(MCDPTR(I),STATUS)
        END DO
        CALL DYN_UNMAP(MTDPTR,STATUS)

	END



*+  SPLOT_MODRES - calc. model space residuals
      SUBROUTINE SPLOT_MODRES(N,D,FIT,V,DR,VR,QR,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Import :
	INTEGER N			! No of data values
	REAL D(*)			! Data array
        REAL FIT(*)
        REAL V(*)
*    Import-Export :
*    Export :
        REAL DR(*)
        REAL VR(*)
        BYTE QR(*)
*    Status :
        INTEGER STATUS
*    Functions :
        BYTE BIT_ORUB
*    Local constants :
	INCLUDE 'QUAL_PAR'
        INCLUDE 'SAE_PAR'
*    Local variables :
	INTEGER I
        LOGICAL WARN
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

      WARN=.FALSE.
      DO I=1,N

        IF (V(I).GT.0.0) THEN
          DR(I)=(D(I)-FIT(I))/SQRT(V(I))
        ELSE
          DR(I) = 0.0
          QR(I) = BIT_ORUB(QR(I),QUAL__ARITH)
          WARN=.TRUE.
        END IF
        VR(I)=1.0

      END DO

      IF ( WARN ) THEN
        CALL MSG_PRNT(' ')
	CALL MSG_PRNT('Warning - photon space model is zero for '//
     :          'some channel energies')
        CALL MSG_PRNT(' ')
      END IF

      END

*+  SPLOT_RESID - calc. data space residuals
      SUBROUTINE SPLOT_RESID(N,D,FIT,DR,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Import :
	INTEGER N			! No of data values
	REAL D(*)			! Data array
        REAL FIT(*)
*    Import-Export :
*    Export :
        REAL DR(*)
*    Status :
        INTEGER STATUS
*    Local constants :
        INCLUDE 'SAE_PAR'
*    Local variables :
	INTEGER I
*-
        IF (STATUS.EQ.SAI__OK) THEN

          DO I=1,N
            DR(I)=D(I) - FIT(I)
          END DO

        END IF

	END


*+  SPLOT_CHEN - Derives channel centres & widths from bounds
      SUBROUTINE SPLOT_CHEN(NDAT,CBOUND,CHEN,CHWID,STATUS)
*    Description :
*    History :
*     24 Aug 88: Original (TJP)
*     21 Jun 89: ASTERIX88; half-widths -> widths (RJV)
*    Type definitions :
      IMPLICIT NONE
*    Import :
	INTEGER NDAT			! No of energy space channels
	REAL CBOUND(0:NDAT)		! Channel bound energies
*    Import-Export :
*    Export :
	REAL CHEN(NDAT)			! Channel centre energies
	REAL CHWID(NDAT)		! Channel widths
*    Status :
       INTEGER STATUS
*    Global constants :
      INCLUDE 'SAE_PAR'
*    Local variables :
	INTEGER I
*-
      IF (STATUS.EQ.SAI__OK) THEN
	DO I=1,NDAT
	  CHEN(I)=(CBOUND(I-1)+CBOUND(I))/2
	  CHWID(I)=CBOUND(I)-CBOUND(I-1)
	END DO
      END IF
      END

*+  SPLOT_NORM - Normalises flux array w.r.t. energy
      SUBROUTINE SPLOT_NORM(NDAT,FLUX,LB,UB,Z,SPECFLUX,STATUS)
*    Description :
*     Normalises flux to spectral flux observed at earth. Since the
*     energy bin bounds are those applying at the source the interval
*     between them is decreased by a factor 1/(1+z) at earth, and the
*     spectral flux (photon/(cm**2*s*keV)) consequently increases by a
*     factor 1+z.
*    History :
*     18 Aug 88: Original (TJP)
*     21 Jun 89: Redshifting added (TJP)
*    Type definitions :
      IMPLICIT NONE
*    Import :
	INTEGER NDAT			! No of energy space channels
	REAL FLUX(NDAT)			! Flux in each channel
	REAL LB(NDAT)			! Lower channel bounds
	REAL UB(NDAT)			! Upper channel bounds
	REAL Z				! Redshift [ Eobs/Esource=1/(1+z) ]
*    Import-Export :
*    Export :
	REAL SPECFLUX(NDAT)		! Flux per unit energy in each channel
*    Status :
      INTEGER STATUS
*    Global constants :
      INCLUDE 'SAE_PAR'
*    Local variables :
	INTEGER I
*-

      IF (STATUS.EQ.SAI__OK) THEN
	DO I=1,NDAT
	  SPECFLUX(I)=(1+Z)*FLUX(I)/(UB(I)-LB(I))
	END DO
      END IF
      END

*+  SPLOT_TRANSFM - Transforms observed data into approx model space values
	SUBROUTINE SPLOT_TRANSFM(NDAT,OBDAT,PREDDAT,ERR,OBVAR,
     :  PREDMOD,TRANDAT,TRANVAR,STATUS)
*    Description :
*     The observed data values OBDAT are transformed approximately back into
*     the model space (e.g. channel spectrum transformed to photon spectrum)
*     using the prescription:
*                TRANDAT = OBDAT*PREDMOD/PREDDAT
*     i.e. the returned values are the model space values from the FIT model
*     (interpolated to give values at the data channel energies) scaled by
*     the ratio of the observed to predicted intensities in each data channel.
*     The PREDMOD values should already be normalised to unit model bin width.
*     This results, in the spectral case, in output values in
*     photon/(cm**2*sec*keV), rather than  photon/(cm**2*sec).
*     Where errors are present they are scaled similarly, so that
*               TRANVAR=OBVAR*(TRANDAT/OBDAT)**2
*     (Note that errors are represented as variances in ASTERIX88)
*     It is assumed that predicted data values will be positive, and to
*     avoid floating zero divides, all are set to be >=PREDLIM.
*    History :
*     25 Jun 87: Original (TJP)
*     25 Nov 88: Proofed against PREDDAT=0 (TJP)
*     21 Jun 89: ASTERIX88 version, errors->variances
*    Type definitions :
      IMPLICIT NONE
*    Import :
	INTEGER NDAT		! No of spectral channels
	REAL OBDAT(*)		! Observed spectrum
	REAL PREDDAT(*)		! Predicted spectrum
	LOGICAL ERR		! Errors available?
	REAL OBVAR(*)		! Data variances
	REAL PREDMOD(*)		! Model space prediction
*    Import-Export :
*    Export :
	REAL TRANDAT(*)		! Transformed data values (i.e. in model space)
	REAL TRANVAR(*)		! Transformed variances
*    Status :
        INTEGER STATUS
*    Global Constants :
        INCLUDE 'SAE_PAR'
*    Local Constants :
	REAL PREDLIM		! Minimum value allowed for predicted data
	PARAMETER (PREDLIM=1.0E-10)
*    Local variables :
	INTEGER I
	REAL PDAT		! PREDDAT value limited to be >=PREDLIM
*-

      IF (STATUS.EQ.SAI__OK) THEN
	DO I=1,NDAT
	  IF(PREDDAT(I).GE.PREDLIM)THEN
	    PDAT=PREDDAT(I)
	  ELSE
	    PDAT=PREDLIM
	  END IF
	  TRANDAT(I)=OBDAT(I)*PREDMOD(I)/PDAT
	  IF(ERR)THEN
	    TRANVAR(I)=OBVAR(I)*(PREDMOD(I)/PDAT)**2
	  END IF
	END DO

      END IF
      END



*+  SPLOT_ZERO - Zeroes any undefined values in model space array
      SUBROUTINE SPLOT_ZERO(N,ARRAY,STATUS)
*    Description :
*     MATH_LINTERP returns values VAL__BADR if asked for a value outside
*     its interpolation range. This can occur if some channel energies lie
*     outside the energy range in the response matrix (which they shouldn't
*     really...). This routine simply zeroes these on the basis that they
*     ought not to contribute to the source counts. This will result in
*     the corresponding transformed data and errors being zeroed too.
*    History :
*     17 May 89: Original (TJP)
*    Type definitions :
      IMPLICIT NONE
*    Import :
	INTEGER N			! No of array elements
*    Import-Export :
	REAL ARRAY(N)			! Array
*    Export :
*    Status :
      INTEGER STATUS
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'PRM_PAR'
*    Local variables :
	INTEGER I
*-

      IF (STATUS.EQ.SAI__OK) THEN
	DO I=1,N
	  IF(ARRAY(I).LE.VAL__BADR)THEN
	    ARRAY(I)=0.0
	  END IF
	END DO
      END IF
      END


      SUBROUTINE SPLOT_DIVWID(N,W,D,STATUS)

      IMPLICIT NONE

      INCLUDE 'SAE_PAR'

      INTEGER STATUS

      INTEGER N
      REAL W(*)
      REAL D(*)

      INTEGER I

      IF (STATUS.EQ.SAI__OK) THEN
        DO I=1,N
          IF (W(I).GT.0.0) THEN
            D(I)=D(I)/W(I)
          END IF
        END DO
      END IF

      END


      SUBROUTINE SPLOT_DIVWID2(N,W,D,STATUS)

      IMPLICIT NONE

      INCLUDE 'SAE_PAR'

      INTEGER STATUS

      INTEGER N
      REAL W
      REAL D(*)

      INTEGER I

      IF (STATUS.EQ.SAI__OK.AND.W.GT.0.0) THEN
        DO I=1,N
          D(I)=D(I)/W
        END DO
      END IF

      END


*+
      SUBROUTINE SPLOT_PLOTMODE(PAR,CHANGE,COMPLEX,STATUS)
*    Description :
*        D = plot observed data (ie counts)
*        C = same as D
*        P = plot photons (ie convolved data - if convolution available)
*        R = plot residuals
*        E = all x-axes to be energy (ie not channel number)
*        L = all axes log scale - by default photon plot axes are log
*        M = plot model by itself, showing each component
*        O = overlay multiple datasets, instead of separate plots
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'FIT_PAR'
*    Global variables :
      INCLUDE 'SPLOT_CMN'
*    Structure definitions :
*    Import :
      CHARACTER*(*) PAR
*    Import-Export :
*    Export :
      LOGICAL CHANGE
      LOGICAL COMPLEX
*    Status :
      INTEGER STATUS
*    Function declarations :
*    Local constants :
*    Local variables :
      CHARACTER*10 MODE,LAST
      SAVE LAST
      INTEGER NP
      LOGICAL D,P,R,E,M,L,O
*-

      IF (STATUS.EQ.SAI__OK) THEN

*  get plotting mode
        MODE=' '
        DO WHILE (MODE.EQ.' '.AND.STATUS.EQ.SAI__OK)
          CALL USI_DEF0C(PAR,LAST,STATUS)
          CALL USI_GET0C(PAR,MODE,STATUS)
          CALL CHR_UCASE(MODE)
          IF (MODE(:1).EQ.'H'.OR.MODE.EQ.' '.AND.
     :                           STATUS.EQ.SAI__OK) THEN
            CALL SPLOT_PLOTMODE_HELP()
            MODE=' '
            CALL USI_CANCL(PAR,STATUS)
          END IF
        END DO

        IF (STATUS.EQ.SAI__OK) THEN

*  see if mode has changed
          IF (MODE.NE.LAST) THEN
            CHANGE=.TRUE.
            LAST=MODE
          END IF

	  DPLOT=.FALSE.
          PPLOT=.FALSE.
          DRPLOT=.FALSE.
          PRPLOT=.FALSE.
          MPLOT=.FALSE.
          EAXIS=.FALSE.
          LOGAX=.FALSE.
          OVERLAY=.FALSE.

          E=(INDEX(MODE,'E').NE.0)
          R=(INDEX(MODE,'R').NE.0)
          M=(INDEX(MODE,'M').NE.0)
          D=(INDEX(MODE,'D').NE.0.OR.INDEX(MODE,'C').NE.0)
          P=(INDEX(MODE,'P').NE.0)
          O=(INDEX(MODE,'O').NE.0)
          L=(INDEX(MODE,'L').NE.0)

          EAXIS=E

          NP=0

          IF (MODE.EQ.' ') THEN
            CALL MSG_PRNT('No plot mode specified - '//
     :                       'defaulting to data plot')
            DPLOT=.TRUE.
            NP=NP+1

          ELSEIF (M) THEN

            MPLOT=.TRUE.
            IF (D.OR.P.OR.R) THEN
              CALL MSG_PRNT('Cannot mix model plot with others')
              CALL MSG_PRNT('    - other modes will be ignored')
            END IF
            NP=NP+1

          ELSE

            IF (R) THEN
              IF (D) THEN
                DRPLOT=.TRUE.
                NP=NP+1
              END IF
              IF (P) THEN
                PRPLOT=.TRUE.
                NP=NP+1
              END IF
              IF (.NOT.(D.OR.P)) THEN
                DRPLOT=.TRUE.
                NP=NP+1
              END IF
            END IF

            IF (D) THEN
              DPLOT=.TRUE.
              NP=NP+1
            END IF

            IF (P) THEN
              PPLOT=.TRUE.
              NP=NP+1
            END IF

            IF (O) THEN
              OVERLAY=.TRUE.
              EAXIS=.TRUE.
            END IF


          END IF

          IF (L) THEN
            LOGAX=.TRUE.
          END IF

          COMPLEX=(NP.NE.1.AND..NOT.OVERLAY)

        END IF

      END IF

      END

*+
      SUBROUTINE SPLOT_PLOTMODE_HELP()

      INTEGER NLINE
      PARAMETER (NLINE=7)

      INTEGER I
      CHARACTER*79 TEXT(NLINE)
      DATA TEXT/
     :  '   D (or C) - plot observed data (counts)',
     :  '   P        - plot convolved data (photons)',
     :  '   R        - plot residuals',
     :  '   E        - all x-axes plotted as energy',
     :  '   L        - all axes plotted with log scale',
     :  '   O        - (multiple data overlayed on same axes)-soon',
     :  '   M        - plot model only, showing components'/
*-
      CALL MSG_BLNK()
      DO I=1,NLINE
        CALL MSG_PRNT(TEXT(I))
      END DO
      CALL MSG_BLNK()

      END


*+
      SUBROUTINE SPLOT_TITLE(DATNAME,MODSPEC,TITLE)

*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
*    Global variables :
*    Structure definitions :
*    Import :
      CHARACTER*(*) DATNAME,MODSPEC
*    Import-Export :
*    Export :
      CHARACTER*(*) TITLE(2)
*    Status :
*    Function declarations :
      INTEGER CHR_LEN
*    Local constants :
*    Local variables :
      INTEGER I,L
*-
      L=CHR_LEN(DATNAME)

      I=L
*  strip off directory spec.
      DO WHILE (.NOT.(DATNAME(I:I).EQ.']'.OR.DATNAME(I:I).EQ.'/')
     :                                               .AND.I.GT.1)
        I=I-1
      END DO
      IF (I.GT.1) THEN
        I=I+1
      END IF

      TITLE(1)='Dataset: '//DATNAME(I:)
      TITLE(2)='Model: '//MODSPEC


      END

*+
      SUBROUTINE SPLOT_LAYOUT(NPZ,NGZ,NZX,NZY,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'FIT_PAR'
*    Global variables :
      INCLUDE 'SPLOT_CMN'
*    Structure definitions :
*    Import :
*    Import-Export :
*    Export :
      INTEGER NPZ,NGZ,NZX,NZY
*    Status :
      INTEGER STATUS
*    Function declarations :
*    Local constants :
*    Local variables :
      INTEGER NXZ,NYZ
*-

      IF (STATUS.EQ.SAI__OK) THEN

*  just plotting model
        IF (MPLOT) THEN
          NPZ=1
          NGZ=1
          NXZ=1
          NYZ=1
          NZX=1
          NZY=1

        ELSE

*    Number of plots per plot zone
          NPZ=0
          NGZ=0
	  IF (DPLOT) THEN
            NPZ=NPZ+1			! one plot
            NGZ=NGZ+2			! two curves
          END IF
	  IF (PPLOT) THEN
            NPZ=NPZ+1			! same as DPLOT
            NGZ=NGZ+2
          END IF
	  IF (DRPLOT) THEN
            NPZ=NPZ+1			! one curve per plot
            NGZ=NGZ+1
          END IF
	  IF (PRPLOT) THEN
            NPZ=NPZ+1
            NGZ=NGZ+1
          END IF

*    Layout within each plot zone (dependent on plot mode)
          IF(NPZ.EQ.1)THEN
	    NXZ=1
	    NYZ=1
	  ELSEIF(NPZ.EQ.2)THEN
	    NXZ=1
	    NYZ=2
	  ELSEIF(NPZ.EQ.4)THEN
	    NXZ=2
	    NYZ=2
	  END IF


*  Layout of plot zones  - one per dataset unless overlayed
	  NZX=1
	  NZY=1
          IF (.NOT.OVERLAY) THEN
            DO WHILE(NZX*NZY.LT.NDS)
*  nx no more than ny+2
	      IF(NZX.GE.NZY+2)THEN
	        NZY=NZY+1
	      ELSE
	        NZX=NZX+1
	      END IF
	    END DO
          END IF

        END IF


      END IF

      END


*+
      SUBROUTINE SPLOT_GEN_SETUP(INSTR,PREDDAT,Z,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'FIT_PAR'
*    Global variables :
      INCLUDE 'SPLOT_CMN'
*    Structure definitions :
       INCLUDE 'FIT_STRUC'
*    Import :
      RECORD /INSTR_RESP/ INSTR
      RECORD /PREDICTION/ PREDDAT
      REAL Z
*    Import-Export :
*    Export :
*    Status :
      INTEGER STATUS
*    Function declarations :
*    Local constants :
      REAL YDEC				! No of decades allowed in range of
      PARAMETER (YDEC=3.1)		! data
*    Local variables :
      INTEGER CBPTR,CIPTR,EIPTR,RPTR
      INTEGER NACT,NRESP
      LOGICAL CBOUNDS
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

*  Divide data and fit by bin width to normalise
      CALL SPLOT_DIVWID(NVAL,%val(DWPTR),%val(DDPTR),STATUS)
      CALL SPLOT_DIVWID(NVAL,%val(DWPTR),%val(DVPTR),STATUS)
      CALL SPLOT_DIVWID(NVAL,%val(DWPTR),%val(DVPTR),STATUS)
      CALL SPLOT_DIVWID(NVAL,%val(DWPTR),%val(DFDPTR),STATUS)

*  Get fit data
      CALL ADI_CGET1R( INSTR.R_ID, 'Energy', NFIT, %val(PFXPTR), 
     :                 NACT, STATUS )
      CALL SPLOT_NORM( NFIT, %val(PREDDAT.MPTR),
     :      %val(PREDDAT.MLBNDPTR),%val(PREDDAT.MUBNDPTR),Z,
     :                                     %val(PFDPTR),STATUS)

*     determine channel energies & widths


*     look for channel bound information
      CALL ADI_CSIZE( INSTR.R_ID, 'Channels', NACT, STATUS )
      CALL ADI_CMAPR( INSTR.R_ID, 'Channels', 'READ', CBPTR, STATUS )

      IF(STATUS.NE.SAI__OK)THEN
        CALL ERR_ANNUL(STATUS)
        CBOUNDS=.FALSE.
      ELSE IF(NACT.NE.NVAL+1)THEN
        CALL MSG_PRNT('Channel bounds array is incorrect length'
     :        //' and will be ignored')
        CBOUNDS=.FALSE.
      ELSE
        CBOUNDS=.TRUE.

*     derive centres and widths from bounds
        CALL SPLOT_CHEN(NVAL,%val(CBPTR),%val(PXPTR),
     :                                     %val(PWPTR),STATUS)
        CALL ADI_CUNMAP( INSTR.R_ID, 'Channels', CBPTR, STATUS )
      
      END IF

*  No bounds available, so derive them by interpoln from response matrix.
*  Can only do this for ASTERIX style responses - not likely to be a
*  problem for non-ASTERIX responses anyhow.
      IF ( .NOT. CBOUNDS ) THEN

        CALL ADI_CSIZE( INSTR.R_ID, 'RMF', NRESP, STATUS )
        CALL ADI_CMAPI( INSTR.R_ID, 'ChannelIndices', 'READ', CIPTR,
     :                  STATUS )
        CALL ADI_CMAPI( INSTR.R_ID, 'EnergyIndices', 'READ', EIPTR,
     :                  STATUS )
        CALL ADI_CMAPR( INSTR.R_ID, 'RMF', 'READ', RPTR, STATUS )
        CALL MSG_PRNT('Deriving channel energies & widths '
     :        //'from response matrix')
        CALL SPEC_CHEN( NVAL, NRESP, %VAL(CIPTR), %VAL(EIPTR),
     :                  %VAL(RPTR), %val(PFXPTR), %val(PXPTR),
     :                                   %val(PWPTR), STATUS )

        CALL ADI_CUNMAP( INSTR.R_ID, 'ChannelIndices', CIPTR, STATUS )
        CALL ADI_CUNMAP( INSTR.R_ID, 'EnergyIndices', EIPTR, STATUS )
        CALL ADI_CUNMAP( INSTR.R_ID, 'RMF', RPTR, STATUS )

      END IF

*  Interpolate to give predicted model space fluxes at channel energies
      CALL MATH_LINTERP(NFIT,%val(PFXPTR),%val(PFDPTR),
     :                NVAL,%val(PXPTR),%val(PIDPTR),STATUS)

*  Safeguard against bad (undefined) model space values (from MATH_LINTERP)
      CALL SPLOT_ZERO(NVAL,%val(PIDPTR),STATUS)

*  Model space data (i.e. transformed back using fitted model)
      CALL SPLOT_TRANSFM(NVAL,%val(IDPTR),%val(IFPTR),
     :                          .TRUE.,%val(IVPTR),%val(PIDPTR),
     :                            %val(PDPTR),%val(PVPTR),STATUS)

      END




*+
      SUBROUTINE SPLOT_DPLOT_SETUP(IDS,NPZ,XMIN,XMAX,YMIN,YMAX,TITLE,
     :                                                        STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'FIT_PAR'
*    Global variables :
*    Structure definitions :
*    Import :
      INTEGER IDS,NPZ
      REAL XMIN,XMAX,YMIN,YMAX
      CHARACTER*(*) TITLE(*)
*    Import-Export :
*    Export :
*    Status :
      INTEGER STATUS
*    Function declarations :
*    Global variables :
        INCLUDE 'SPLOT_CMN'
*    Local constants :
      INTEGER SYMBOL(8)/17,13,16,18,4,7,6,12/
*    Local variables :
      CHARACTER*40 LABEL
      REAL TXTSCALE
      REAL X1,X2,Y1,Y2
      REAL XW1,XW2,YW1,YW2
      REAL BXW1,BXW2,BYW1,BYW2
      SAVE BXW1,BXW2,BYW1,BYW2
      INTEGER ISYM
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

*  Set plot position and text size
      X1=XMIN
      X2=XMAX
      Y1=YMIN
      Y2=YMAX
      IF(NPZ.EQ.2)THEN
        IF(PPLOT)THEN			! Mode DM
          Y2=0.5*(YMIN+YMAX)
        ELSE				! Mode DR
          Y1=YMIN+0.33*(YMAX-YMIN)
        END IF
      ELSEIF (NPZ.GT.2) THEN		! Mode DMR
        X2=0.5*(XMIN+XMAX)
        Y1=YMIN+0.33*(YMAX-YMIN)
      END IF
      TXTSCALE=MIN(0.8,2*(X2-X1))

*  Now allow margin for labels & title
      X1=X1+3.0*TXTSCALE*0.025		! 3.0 char. heights
      Y1=Y1+3.0*TXTSCALE*0.025		! 3.0 char. heights
      Y2=Y2-2.5*TXTSCALE*0.025		! 2.5 char. heights

*  Viewport position
      CALL GCB_SETR('POS_X1',X1,STATUS)
      CALL GCB_SETR('POS_X2',X2,STATUS)
      CALL GCB_SETR('POS_Y1',Y1,STATUS)
      CALL GCB_SETR('POS_Y2',Y2,STATUS)

*  numeric label character size
      CALL GCB_SETR('AXES_SIZE',TXTSCALE,STATUS)

*  axis labels
      CALL GCB_SETR('XLABEL_SIZE',TXTSCALE,STATUS)
      IF (EAXIS) THEN
        LABEL='Energy (keV)'
      ELSE
        LABEL='Channel no.'
      END IF
      CALL GCB_SETC('XLABEL_TEXT',LABEL,STATUS)

      CALL GCB_SETR('YLABEL_SIZE',TXTSCALE,STATUS)
      CALL GCB_SETC('YLABEL_TEXT','count s\u-1\d channel\u-1\d',
     :                                                  STATUS)

      IF (LOGAX) THEN
        CALL GCB_SETL('XAXIS_LOG',.TRUE.,STATUS)
        CALL GCB_SETL('YAXIS_LOG',.TRUE.,STATUS)
      END IF

*  Title lines
      CALL GCB_SETI('TITLE_N',2,STATUS)
      CALL GCB_SET1C('TITLE_TEXT',1,2,TITLE,STATUS)
      CALL GCB_SET1R('TITLE_SIZE',1,1,TXTSCALE,STATUS)
      CALL GCB_SET1R('TITLE_SIZE',2,1,TXTSCALE,STATUS)
      CALL GCB_SET1C('TITLE_JUST',1,1,'L',STATUS)
      CALL GCB_SET1C('TITLE_JUST',2,1,'L',STATUS)

*  if several datasets to be overlayed on same axes need overall max/min
      IF (OVERLAY) THEN
        CALL GFX_DEF1DWNDV(NVAL,%val(PXPTR),%val(DDPTR),%val(DVPTR),
     :                                         XW1,XW2,YW1,YW2,STATUS)
        IF (IDS.EQ.1) THEN
          BXW1=XW1
          BXW2=XW2
          BYW1=YW1
          BYW2=YW2
        ELSE
          BXW1=MIN(XW1,BXW1)
          BXW2=MAX(XW2,BXW2)
          BYW1=MIN(YW1,BYW1)
          BYW2=MAX(YW2,BYW2)
        END IF
        IF (IDS.EQ.NDS) THEN
          CALL GCB_SETR('XAXIS_LO',BXW1,STATUS)
          CALL GCB_SETR('XAXIS_HI',BXW2,STATUS)
          CALL GCB_SETR('YAXIS_LO',BYW1,STATUS)
          CALL GCB_SETR('YAXIS_HI',BYW2,STATUS)
        END IF

*  set plotting symbol for each dataset
        ISYM=MOD(IDS,8)
        IF (ISYM.EQ.0) THEN
          ISYM=8
        END IF
        CALL GCB_SETL('POINT_FLAG',.TRUE.,STATUS)
        CALL GCB_SETI('POINT_SYMBOL',SYMBOL(ISYM),STATUS)
        CALL GCB_SETL('ERR_FLAG',.TRUE.,STATUS)

      END IF

      END


*+
      SUBROUTINE SPLOT_DPLOT_COPY(OFID,IP,IG,IDS,SAVE,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'FIT_PAR'
*    Global variables :
        INCLUDE 'SPLOT_CMN'
*    Structure definitions :
*    Import :
      INTEGER OFID
      INTEGER IP,IG,IDS
      LOGICAL SAVE
*    Import-Export :
*    Export :
*    Status :
      INTEGER STATUS
*    Function declarations :
      INTEGER CHR_LEN
*    Local constants :
*    Local variables :
      CHARACTER*80 OVLY
      CHARACTER*80 UNITS
      INTEGER NDFS(NDSMAX)
      INTEGER NDFID,XPTR,WPTR
      INTEGER I,L
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

*  Axis in channels or energy
      IF ( EAXIS ) THEN
        XPTR = PXPTR
        WPTR = PWPTR
      ELSE
        XPTR = DXPTR
        WPTR = DWPTR
      END IF

*  Create the data graph
      CALL SPLOT_CRENDF( SAVE, 'channel space data',
     :                   OFID, IG, NVAL, DDPTR, DVPTR, DQPTR,
     :                   XPTR, WPTR,
     :                   'Channel/Data space - data',
     :                   NDFID, STATUS )

*  Copy labels
      CALL BDI_COPY( DSID, 'Label,Units,Title', NDFID, ' ', STATUS )

*  Modify units to take account of normalisation
      CALL BDI_GET0C( DSID, 'Units', UNITS, STATUS )
      L = CHR_LEN(UNITS) + 1
      UNITS(L:) = '/channel'
      CALL BDI_PUT0C( NDFID, 'Units', UNITS, STATUS )

*  Ancillary info
      IF ( SAVE ) THEN
        CALL UDI_COPANC( DSID, 'grf', NDFID, STATUS )
      END IF

*  Release graph
      CALL SPLOT_RELNDF( NDFID, STATUS )

*  Cancel attributes that not relevant to other data
      CALL GCB_CAN( 'TITLE_N,YLABEL_TEXT', STATUS )
      CALL GCB_CAN1( 'TITLE_SIZE,TITLE_TEXT,TITLE_JUST', 1, 2, STATUS )

      IF ( OVERLAY ) THEN
        CALL GCB_CAN( 'POINT_FLAG,POINT_SYMBOL', STATUS )
        CALL GCB_CAN( 'ERR_FLAG', STATUS )
        CALL GCB_CAN( 'XAXIS_LO,XAXIS_HI,YAXIS_LO,YAXIS_HI', STATUS )
      END IF

*  Create the fit graph
      CALL SPLOT_CRENDF( SAVE, 'channel space fit',
     :                   OFID, IG+1, NVAL, DFDPTR, 0, 0,
     :                   XPTR, WPTR,
     :                   'Channel/Data space - fit',
     :                   NDFID, STATUS )

*   If single point then set marker to '*' for model point
      IF ( NVAL .EQ. 1 ) THEN
        CALL GCB_SETL('POINT_FLAG',.TRUE.,STATUS)
        CALL GCB_SETI('POINT_SYMBOL',3,STATUS)
      END IF

*  Datasets overlayed - record NDF number
      IF (OVERLAY) THEN
        NDFS(IDS)=IG
*  last dataset - construct overlays
        IF (IDS.EQ.NDS) THEN
          OVLY=' '
          L=0
          DO I=1,NDS-1
            L=L+6
            WRITE(OVLY(L-5:L),'(2(I2,A1))') NDFS(I),',',NDFS(I)+1,','
          END DO
          L=L+1
          WRITE(OVLY(L:L+1),'(I2)') IG+1
          CALL GMI_SETPLOT( OFID, IP, IG, OVLY, STATUS )

        END IF
      ELSE
*  set overlay
        WRITE(OVLY,'(I2)') IG+1
        CALL GMI_SETPLOT( OFID, IP, IG, OVLY, STATUS )

      END IF

*  Release graph
      CALL SPLOT_RELNDF( NDFID, STATUS )

      CALL GCB_CAN( 'POINT_FLAG,POINT_SYMBOL', STATUS )
      CALL GCB_CAN( 'XAXIS_LOG,YAXIS_LOG,YAXIS_LO,YAXIS_HI', STATUS )

      END


*+
      SUBROUTINE SPLOT_DRPLOT_SETUP(IDS,NPZ,XMIN,XMAX,YMIN,YMAX,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'FIT_PAR'
*    Global variables :
        INCLUDE 'SPLOT_CMN'
*    Structure definitions :
*    Import :
      INTEGER IDS,NPZ
      REAL XMIN,XMAX,YMIN,YMAX
*    Import-Export :
*    Export :
*    Status :
      INTEGER STATUS
*    Function declarations :
*    Local constants :
      INTEGER SYMBOL(8)/17,13,16,18,4,7,6,12/
*    Local variables :
      CHARACTER*20 LABEL
      REAL X1,X2,Y1,Y2
      REAL TXTSCALE
      REAL XW1,XW2,YW1,YW2
      REAL BXW1,BXW2,BYW1,BYW2
      SAVE BXW1,BXW2,BYW1,BYW2
      INTEGER ISYM
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

*  Calculate residuals
      CALL SPLOT_RESID(NVAL,%val(DDPTR),%val(DFDPTR),%val(DRDPTR),
     :                                                     STATUS)

*  Set plot position
      X1=XMIN
      X2=XMAX
      Y1=YMIN
      Y2=YMAX
      IF(NPZ.EQ.2)THEN     		! Mode DR
        Y2=YMIN+0.33*(YMAX-YMIN)
      ELSEIF (NPZ.GT.2) THEN		! Mode DMR
        X2=0.5*(XMIN+XMAX)
        Y2=YMIN+0.33*(YMAX-YMIN)
      END IF
      TXTSCALE=MIN(0.8,2*(X2-X1))

*     now allow margin for labels & title
      X1=X1+3.0*TXTSCALE*0.025		! 3.0 char. heights
      Y1=Y1+3.0*TXTSCALE*0.025		! 3.0 char. heights
      Y2=Y2-2.5*TXTSCALE*0.025		! 2.5 char. heights

      CALL GCB_SETR('POS_X1',X1,STATUS)
      CALL GCB_SETR('POS_X2',X2,STATUS)
      CALL GCB_SETR('POS_Y1',Y1,STATUS)
      CALL GCB_SETR('POS_Y2',Y2,STATUS)

      CALL GCB_SETR('AXES_SIZE',TXTSCALE,STATUS)
*  axis labels
      CALL GCB_SETR('XLABEL_SIZE',TXTSCALE,STATUS)
      IF (EAXIS) THEN
        LABEL='Energy (keV)'
      ELSE
        LABEL='Channel no.'
      END IF
      CALL GCB_SETC('XLABEL_TEXT',LABEL,STATUS)
      CALL GCB_SETR('YLABEL_SIZE',TXTSCALE,STATUS)

      IF (LOGAX) THEN
        CALL GCB_SETL('XAXIS_LOG',.TRUE.,STATUS)
      END IF

      CALL GCB_SETI('TITLE_N',1,STATUS)
      CALL GCB_SET1C('TITLE_TEXT',1,1,'Residuals (data-model)',STATUS)
      CALL GCB_SET1R('TITLE_SIZE',1,1,TXTSCALE,STATUS)


*  if several datasets to be overlayed on same axes need overall max/min
      IF (OVERLAY) THEN
        CALL GFX_DEF1DWNDV(NVAL,%val(PXPTR),%val(DRDPTR),%val(DVPTR),
     :                                         XW1,XW2,YW1,YW2,STATUS)
        IF (IDS.EQ.1) THEN
          BXW1=XW1
          BXW2=XW2
          BYW1=YW1
          BYW2=YW2
        ELSE
          BXW1=MIN(XW1,BXW1)
          BXW2=MAX(XW2,BXW2)
          BYW1=MIN(YW1,BYW1)
          BYW2=MAX(YW2,BYW2)
        END IF
        IF (IDS.EQ.NDS) THEN
          CALL GCB_SETR('XAXIS_LO',BXW1,STATUS)
          CALL GCB_SETR('XAXIS_HI',BXW2,STATUS)
          CALL GCB_SETR('YAXIS_LO',BYW1,STATUS)
          CALL GCB_SETR('YAXIS_HI',BYW2,STATUS)
        END IF

*  set plotting symbol for each dataset
        ISYM=MOD(IDS,8)
        IF (ISYM.EQ.0) THEN
          ISYM=8
        END IF
        CALL GCB_SETL('POINT_FLAG',.TRUE.,STATUS)
        CALL GCB_SETI('POINT_SYMBOL',SYMBOL(ISYM),STATUS)
        CALL GCB_SETL('ERR_FLAG',.TRUE.,STATUS)

      END IF

      END





*+
      SUBROUTINE SPLOT_DRPLOT_COPY(OFID,IP,IG,IDS,SAVE,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'FIT_PAR'
*    Global variables :
        INCLUDE 'SPLOT_CMN'
*    Structure definitions :
*    Import :
      INTEGER OFID,IP,IG,IDS
      LOGICAL SAVE
*    Import-Export :
*    Export :
*    Status :
      INTEGER STATUS
*    Function declarations :
*    Local constants :
*    Local variables :
      CHARACTER*80 OVLY
      INTEGER NDFS(NDSMAX)
      INTEGER NDFID,XPTR,WPTR
      INTEGER I,L
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

*  Axis in channels or energy
      IF (EAXIS) THEN
        XPTR=PXPTR
        WPTR=PWPTR
      ELSE
        XPTR=DXPTR
        WPTR=DWPTR
      END IF

*  Create the residuals graph
      CALL SPLOT_CRENDF( SAVE, 'channel space residuals',
     :                   OFID, IG, NVAL, DRDPTR, DVPTR, DQPTR,
     :                   XPTR, WPTR,
     :                   'Channel/Data space - residuals',
     :                   NDFID, STATUS )

*  Add title
      CALL BDI_PUT0C( NDFID, 'Title', 'Residuals (data-model)', STATUS )

*  datasets overlayed - record NDF number
      IF (OVERLAY) THEN
        NDFS(IDS)=IG
*  last dataset - construct overlays
        IF (IDS.EQ.NDS) THEN
          OVLY=' '
          L=0
          DO I=1,NDS-1
            L=L+3
            WRITE(OVLY(L-2:L),'(I2,A1)') NDFS(I),','
          END DO
          OVLY(L:L)=' '
          CALL GMI_SETPLOT( OFID, IP, IG, OVLY, STATUS )
        END IF
      ELSE
        CALL GMI_SETPLOT( OFID, IP, IG, ' ', STATUS )
      END IF

*  Release graph
      CALL SPLOT_RELNDF( NDFID, STATUS )

      CALL GCB_CAN( 'XAXIS_LOG,YAXIS_LOG', STATUS )
      IF ( OVERLAY ) THEN
        CALL GCB_CAN( 'POINT_FLAG,POINT_SYMBOL', STATUS )
        CALL GCB_CAN( 'ERR_FLAG', STATUS )
        CALL GCB_CAN( 'XAXIS_LO,XAXIS_HI,YAXIS_LO,YAXIS_HI', STATUS )
      END IF

      END


*+
      SUBROUTINE SPLOT_PPLOT_SETUP(IDS,NPZ,XMIN,XMAX,YMIN,YMAX,
     :                                            TITLE,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'FIT_PAR'
*    Global variables :
      INCLUDE 'SPLOT_CMN'
*    Structure definitions :
*    Import :
      INTEGER IDS,NPZ
      REAL XMIN,XMAX,YMIN,YMAX
      CHARACTER*(*) TITLE(*)
*    Import-Export :
*    Export :
*    Status :
      INTEGER STATUS
*    Function declarations :
*    Local constants :
      INTEGER SYMBOL(8)/17,13,16,18,4,7,6,12/
*    Local variables :
      REAL X1,X2,Y1,Y2
      REAL TXTSCALE
      REAL XW1,XW2,YW1,YW2
      REAL BXW1,BXW2,BYW1,BYW2
      SAVE BXW1,BXW2,BYW1,BYW2
      INTEGER ISYM
      LOGICAL ERR
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

      ERR = .TRUE.

*  Set up log:log flag
      CALL GCB_SETL('XAXIS_LOG',.TRUE.,STATUS)
      CALL GCB_SETL('YAXIS_LOG',.TRUE.,STATUS)

*  Set plot position
      X1=XMIN				! Mode P
      X2=XMAX
      Y1=YMIN
      Y2=YMAX
      IF(NPZ.EQ.2)THEN
        IF(DPLOT)THEN			! Mode CP
          Y1=0.5*(YMIN+YMAX)
        ELSE				! Mode PR
          Y1=YMIN+0.33*(YMAX-YMIN)
        END IF
      ELSEIF (NPZ.GT.2) THEN		! Mode CPR
        X1=0.5*(XMIN+XMAX)
        Y1=YMIN+0.33*(YMAX-YMIN)
      END IF
      TXTSCALE=MIN(0.8,2*(X2-X1))

*     now allow margin for labels & title
      X1=X1+3.0*TXTSCALE*0.025		! 3.0 char. heights
      Y1=Y1+3.0*TXTSCALE*0.025		! 3.0 char. heights
      Y2=Y2-2.5*TXTSCALE*0.025		! 2.5 char. heights

      CALL GCB_SETR('POS_X1',X1,STATUS)
      CALL GCB_SETR('POS_X2',X2,STATUS)
      CALL GCB_SETR('POS_Y1',Y1,STATUS)
      CALL GCB_SETR('POS_Y2',Y2,STATUS)
      CALL GCB_SETR('AXES_SIZE',TXTSCALE,STATUS)


      CALL GCB_SETC('XLABEL_TEXT','Energy (keV)',STATUS)
      CALL GCB_SETR('XLABEL_SIZE',TXTSCALE,STATUS)
      CALL GCB_SETC('YLABEL_TEXT',
     :            'photon cm\u-2\d s\u-1\d keV\u-1\d',STATUS)
      CALL GCB_SETR('YLABEL_SIZE',TXTSCALE,STATUS)

      CALL GCB_SET1C('TITLE_TEXT',1,2,TITLE,STATUS)
      CALL GCB_SETI('TITLE_N',2,STATUS)
      CALL GCB_SET1R('TITLE_SIZE',1,1,TXTSCALE,STATUS)
      CALL GCB_SET1R('TITLE_SIZE',2,1,TXTSCALE,STATUS)
      CALL GCB_SET1C('TITLE_JUST',1,1,'L',STATUS)
      CALL GCB_SET1C('TITLE_JUST',2,1,'L',STATUS)

*  if several datasets to be overlayed on same axes need overall max/min
      IF (OVERLAY) THEN
        CALL GFX_DEF1DWNDV(NVAL,%val(PXPTR),%val(PDPTR),%val(PVPTR),
     :                                         XW1,XW2,YW1,YW2,STATUS)
        IF (IDS.EQ.1) THEN
          BXW1=XW1
          BXW2=XW2
          BYW1=YW1
          BYW2=YW2
        ELSE
          BXW1=MIN(XW1,BXW1)
          BXW2=MAX(XW2,BXW2)
          BYW1=MIN(YW1,BYW1)
          BYW2=MAX(YW2,BYW2)
        END IF
        IF (IDS.EQ.NDS) THEN
          CALL GCB_SETR('XAXIS_LO',BXW1,STATUS)
          CALL GCB_SETR('XAXIS_HI',BXW2,STATUS)
          CALL GCB_SETR('YAXIS_LO',BYW1,STATUS)
          CALL GCB_SETR('YAXIS_HI',BYW2,STATUS)
        END IF

*  set plotting symbol for each dataset
        ISYM=MOD(IDS,8)
        IF (ISYM.EQ.0) THEN
          ISYM=8
        END IF
        CALL GCB_SETL('POINT_FLAG',.TRUE.,STATUS)
        CALL GCB_SETI('POINT_SYMBOL',SYMBOL(ISYM),STATUS)
        CALL GCB_SETL('ERR_FLAG',.TRUE.,STATUS)

      END IF


      END




*+
      SUBROUTINE SPLOT_PPLOT_COPY(OFID,IP,IG,IDS,SAVE,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'FIT_PAR'
*    Global variables :
        INCLUDE 'SPLOT_CMN'
*    Structure definitions :
*    Import :
      INTEGER OFID,IP,IG,IDS
      LOGICAL SAVE
*    Import-Export :
*    Export :
*    Status :
      INTEGER STATUS
*    Function declarations :
*    Local constants :
*    Local variables :
      CHARACTER*80 OVLY
      INTEGER NDFS(NDSMAX)
      INTEGER NDFID
      INTEGER I,L
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

*  Model space data (i.e. transformed back using fitted model)
      CALL SPLOT_CRENDF( SAVE, 'photon space data',
     :                   OFID, IG, NVAL, PDPTR, PVPTR, DQPTR,
     :                   PXPTR, PWPTR,
     :                   'Photon space - data',
     :                   NDFID, STATUS )

*  Copy data label and create new units
      CALL BDI_COPY( DSID, 'Label', NDFID, ' ', STATUS )
      CALL BDI_PUT0C( NDFID, 'Units', 'photon/(cm**2*sec*keV)', STATUS )

*  Create axis label and units
      CALL BDI_AXPUT0C( NDFID, 1, 'Label', 'Energy', STATUS )
      CALL BDI_AXPUT0C( NDFID, 1, 'Units', 'keV', STATUS )

*  Release graph
      CALL SPLOT_RELNDF( NDFID, STATUS )

      CALL GCB_CAN( 'TITLE_N', STATUS )
      CALL GCB_CAN1( 'TITLE_SIZE,TITLE_TEXT,TITLE_JUST', 1, 2, STATUS )
      CALL GCB_CAN( 'YLABEL_TEXT', STATUS )
      CALL GCB_CAN( 'YAXIS_LO,YAXIS_HI', STATUS )
      IF ( OVERLAY ) THEN
        CALL GCB_CAN( 'POINT_FLAG,POINT_SYMBOL', STATUS )
        CALL GCB_CAN( 'ERR_FLAG', STATUS )
        CALL GCB_CAN( 'XAXIS_LO,XAXIS_HI', STATUS )
      END IF

*   Model space fit (for overlay)
      CALL SPLOT_CRENDF( SAVE, 'photon space fit',
     :                   OFID, IG+1, NFIT, PFDPTR, 0, 0,
     :                   PFXPTR, 0,
     :                   'Photon space - fit',
     :                   NDFID, STATUS )

*  Energy axis
      CALL BDI_AXPUT0C( NDFID, 1, 'Label', 'Energy', STATUS )
      CALL BDI_AXPUT0C( NDFID, 1, 'Units', 'keV', STATUS )

*  Release graph
      CALL SPLOT_RELNDF( NDFID, STATUS )

*  Datasets overlaid - record NDF number
      IF ( OVERLAY ) THEN
        NDFS(IDS)=IG
*  last dataset - construct overlays
        IF (IDS.EQ.NDS) THEN
          OVLY=' '
          L=0
          DO I=1,NDS-1
            L=L+6
            WRITE(OVLY(L-5:L),'(2(I2,A1))') NDFS(I),',',NDFS(I)+1,','
          END DO
          L=L+1
          WRITE(OVLY(L:L+1),'(I2)') IG+1
          CALL GMI_SETPLOT( OFID, IP, IG, OVLY, STATUS )
        END IF
      ELSE
*     set overlay
        WRITE(OVLY,'(I2)') IG+1
        CALL GMI_SETPLOT( OFID, IP, IG, OVLY, STATUS )
      END IF

      CALL GCB_CAN( 'XAXIS_LOG,YAXIS_LOG', STATUS )

      END


*+
      SUBROUTINE SPLOT_PRPLOT_SETUP(IDS,NPZ,XMIN,XMAX,YMIN,YMAX,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'QUAL_PAR'
      INCLUDE 'FIT_PAR'
*    Global variables :
        INCLUDE 'SPLOT_CMN'
*    Structure definitions :
*    Import :
      INTEGER IDS,NPZ
      REAL XMIN,XMAX,YMIN,YMAX
*    Import-Export :
*    Export :
*    Status :
      INTEGER STATUS
*    Function declarations :
*    Local constants :
      INTEGER SYMBOL(8)/17,13,16,18,4,7,6,12/
*    Local variables :
      REAL X1,X2,Y1,Y2
      REAL TXTSCALE
      REAL XW1,XW2,YW1,YW2
      REAL BXW1,BXW2,BYW1,BYW2
      SAVE BXW1,BXW2,BYW1,BYW2
      INTEGER ISYM
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

      IF ( QOK ) THEN
        CALL ARR_COP1B( NVAL, %VAL(DQPTR), %VAL(PRQPTR), STATUS )
      ELSE
        CALL ARR_INIT1B( QUAL__GOOD, NVAL, %VAL(PRQPTR), STATUS )
      END IF

*  Subtract fit from data values & divide by sqrt(variance)
      CALL SPLOT_MODRES( NVAL, %VAL(PDPTR), %VAL(PIDPTR),
     :                   %VAL(PVPTR), %VAL(PRDPTR), %VAL(PRVPTR),
     :                   %VAL(PRQPTR), STATUS )

*  Set plot position
      IF ( NPZ .EQ. 2 ) THEN			! Mode MR
        X1 = XMIN
        X2 = XMAX
        Y1 = YMIN
        Y2 = YMIN+0.33*(YMAX-YMIN)
      ELSE				! Mode DMR
        X1 = 0.5*(XMIN+XMAX)
        X2 = XMAX
        Y1 = YMIN
        Y2 = YMIN+0.33*(YMAX-YMIN)
      END IF
      TXTSCALE = MIN(0.8,2*(X2-X1))

*  Now allow margin for labels & title
      X1=X1+3.0*TXTSCALE*0.025		! 3.0 char. heights
      Y1=Y1+3.0*TXTSCALE*0.025		! 3.0 char. heights
      Y2=Y2-2.5*TXTSCALE*0.025		! 2.5 char. heights

      CALL GCB_SETR('POS_X1',X1,STATUS)
      CALL GCB_SETR('POS_X2',X2,STATUS)
      CALL GCB_SETR('POS_Y1',Y1,STATUS)
      CALL GCB_SETR('POS_Y2',Y2,STATUS)
      CALL GCB_SETR('AXES_SIZE',TXTSCALE,STATUS)
      CALL GCB_SETR('XLABEL_SIZE',TXTSCALE,STATUS)
      CALL GCB_SETC('XLABEL_TEXT','Energy (keV)',STATUS)
      CALL GCB_SETR('YLABEL_SIZE',TXTSCALE,STATUS)
      CALL GCB_SETC('YLABEL_TEXT','Significance',STATUS)
      CALL GCB_SET1C('TITLE_TEXT',1,1,
     :           'Normalised residuals (data-model)/sigma',STATUS)
      CALL GCB_SET1R('TITLE_SIZE',1,1,TXTSCALE,STATUS)
      CALL GCB_SETI('TITLE_N',1,STATUS)

      CALL GCB_SETL('XAXIS_LOG',.TRUE.,STATUS)
      CALL GCB_SETL('YAXIS_LOG',.FALSE.,STATUS)

*  if several datasets to be overlayed on same axes need overall max/min
      IF (OVERLAY) THEN
        CALL GFX_DEF1DWNDV(NVAL,%val(PXPTR),%val(PRDPTR),%val(PRVPTR),
     :                                         XW1,XW2,YW1,YW2,STATUS)
        IF (IDS.EQ.1) THEN
          BXW1=XW1
          BXW2=XW2
          BYW1=YW1
          BYW2=YW2
        ELSE
          BXW1=MIN(XW1,BXW1)
          BXW2=MAX(XW2,BXW2)
          BYW1=MIN(YW1,BYW1)
          BYW2=MAX(YW2,BYW2)
        END IF
        IF (IDS.EQ.NDS) THEN
          CALL GCB_SETR('XAXIS_LO',BXW1,STATUS)
          CALL GCB_SETR('XAXIS_HI',BXW2,STATUS)
          CALL GCB_SETR('YAXIS_LO',BYW1,STATUS)
          CALL GCB_SETR('YAXIS_HI',BYW2,STATUS)
        END IF

*    Set plotting symbol for each dataset
        ISYM=MOD(IDS,8)
        IF (ISYM.EQ.0) THEN
          ISYM=8
        END IF
        CALL GCB_SETL('POINT_FLAG',.TRUE.,STATUS)
        CALL GCB_SETI('POINT_SYMBOL',SYMBOL(ISYM),STATUS)
        CALL GCB_SETL('ERR_FLAG',.TRUE.,STATUS)

      END IF

      END


*+
      SUBROUTINE SPLOT_PRPLOT_COPY(OFID,IP,IG,IDS,SAVE,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'FIT_PAR'
*    Global variables :
      INCLUDE 'SPLOT_CMN'
*    Structure definitions :
*    Import :
      INTEGER OFID,IP,IG,IDS
      LOGICAL SAVE
*    Import-Export :
*    Export :
*    Status :
      INTEGER STATUS
*    Function declarations :
*    Local constants :
*    Local variables :
      CHARACTER*80 OVLY
      INTEGER NDFS(NDSMAX)
      INTEGER NDFID
      INTEGER I,L
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

*  Create residuals graph
      CALL SPLOT_CRENDF( SAVE, 'photon space residuals',
     :                   OFID, IG, NVAL, PRDPTR, PRVPTR, PRQPTR,
     :                   PXPTR, PWPTR,
     :                   'Photon space - residuals',
     :                   NDFID, STATUS )

      CALL BDI_PUT0C( NDFID, 'Title',
     :        'Normalised residuals (data-model)/sigma', STATUS )
      CALL BDI_PUT0C( NDFID, 'Label', 'Significance', STATUS )

      CALL BDI_AXPUT0C( NDFID, 1, 'Label', 'Energy', STATUS )
      CALL BDI_AXPUT0C( NDFID, 1, 'Units', 'keV', STATUS )

*  datasets overlayed - record NDF number
      IF (OVERLAY) THEN
        NDFS(IDS)=IG
*  last dataset - construct overlays
        IF (IDS.EQ.NDS) THEN
          OVLY=' '
          L=0
          DO I=1,NDS-1
            L=L+3
            WRITE(OVLY(L-2:L),'(I2,A1)') NDFS(I),','
          END DO
          OVLY(L:L)=' '
          CALL GMI_SETPLOT( OFID, IP, IG, OVLY, STATUS )
        END IF
      ELSE
        CALL GMI_SETPLOT( OFID, IP, IG, ' ', STATUS )
      END IF

*  Release graph
      CALL SPLOT_RELNDF( NDFID, STATUS )

      CALL GCB_CAN( 'TITLE_N', STATUS )
      CALL GCB_CAN1( 'TITLE_SIZE,TITLE_TEXT', 1, 2, STATUS )
      CALL GCB_CAN( 'XAXIS_LOG,YAXIS_LOG', STATUS )
      IF ( OVERLAY ) THEN
        CALL GCB_CAN( 'POINT_FLAG,POINT_SYMBOL', STATUS )
        CALL GCB_CAN( 'ERR_FLAG', STATUS )
        CALL GCB_CAN( 'XAXIS_LO,XAXIS_HI,YAXIS_LO,YAXIS_HI', STATUS )
      END IF

      END



*+
      SUBROUTINE SPLOT_MPLOT_SETUP(NCHAN,NTERM,MODSPEC,COMPSPEC,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'FIT_PAR'
*    Global variables :
*    Structure definitions :
*    Import :
      INTEGER NCHAN,NTERM
      CHARACTER*(*) MODSPEC,COMPSPEC(*)
*    Import-Export :
*    Export :
*    Status :
      INTEGER STATUS
*    Function declarations :
*    Global variables :
      INCLUDE 'SPLOT_CMN'
*    Local constants :
*    Local variables :
      CHARACTER*80 TEXT
      REAL TXTSCALE
      REAL X1,X2,Y1,Y2
      REAL XW1,XW2,YW1,YW2
      REAL XRAN,YRAN
      REAL XL,YL,XT,YT,XTL,YTL
      REAL XDISP,YSTEP
      INTEGER I
      INTEGER STYLE
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

*  Set plot position and text size
      X1 = 0.0
      X2 = 0.99
      Y1 = 0.0
      Y2 = 0.99

      TXTSCALE=MIN(0.8,2*(X2-X1))

*  Now allow margin for labels & title
      X1=X1+3.0*TXTSCALE*0.025		! 3.0 char. heights
      Y1=Y1+3.0*TXTSCALE*0.025		! 3.0 char. heights
      Y2=Y2-2.5*TXTSCALE*0.025		! 2.5 char. heights

*  Viewport position
      CALL GCB_SETR( 'POS_X1', X1, STATUS )
      CALL GCB_SETR( 'POS_X2', X2, STATUS )
      CALL GCB_SETR( 'POS_Y1', Y1, STATUS )
      CALL GCB_SETR( 'POS_Y2', Y2, STATUS )

      IF ( LOGAX ) THEN
        CALL GCB_SETL('XAXIS_LOG',.TRUE.,STATUS)
        CALL GCB_SETL('YAXIS_LOG',.TRUE.,STATUS)
      END IF

*  Get axis limits for key
      CALL GFX_DEF1DWND(NCHAN,%val(MCXPTR),%val(MTDPTR),
     :                             XW1,XW2,YW1,YW2,STATUS)

*  Get positions for key
      XRAN=XW2-XW1
      YRAN=YW2-YW1
      XDISP=0.1*XRAN
      XL=XW1+0.8*XRAN
      YL=YW1+0.9*YRAN
      XT=XW1+0.91*XRAN
      YT=YL-0.5*TXTSCALE*0.025*YRAN
      YSTEP=0.05*YRAN

c      CALL GCB_SETI('SHAPE_N',NTERM+1,STATUS)
c      CALL GCB_SET1C('SHAPE_TYPE',1,1,'VECTOR',STATUS)
c      CALL GCB_SET1R('SHAPE_DATA1',1,1,XDISP,STATUS)
c      CALL GCB_SET1R('SHAPE_DATA2',1,1,0.0,STATUS)
c      CALL GCB_SET1R('SHAPE_X',1,1,XL,STATUS)
c      CALL GCB_SET1R('SHAPE_Y',1,1,YL,STATUS)
c      CALL GCB_SETI('NOTE_N',NTERM+1,STATUS)
      IF (LOGAX) THEN
        XTL=10.0**XT
        YTL=10.0**YT
c        CALL GCB_SET1R('NOTE_X',1,1,XTL,STATUS)
c        CALL GCB_SET1R('NOTE_Y',1,1,YTL,STATUS)
      ELSE
c        CALL GCB_SET1R('NOTE_X',1,1,XT,STATUS)
c        CALL GCB_SET1R('NOTE_Y',1,1,YT,STATUS)
      END IF
c      CALL GCB_SET1C('NOTE_TEXT',1,1,'Total',STATUS)
c      CALL GCB_SET1R('NOTE_SIZE',1,1,TXTSCALE,STATUS)
      STYLE=0
      DO I=1,NTERM
        STYLE=STYLE+1
        STYLE=STYLE/5 + MOD(STYLE,5) + 1
c        CALL GCB_SET1C('SHAPE_TYPE',I+1,1,'VECTOR',STATUS)
c        CALL GCB_SET1R('SHAPE_DATA1',I+1,1,XDISP,STATUS)
c        CALL GCB_SET1R('SHAPE_DATA2',I+1,1,0.0,STATUS)
c        CALL GCB_SET1I('SHAPE_STYLE',I+1,1,STYLE,STATUS)
c        CALL GCB_SET1R('SHAPE_X',I+1,1,XL,STATUS)
        YL=YL-YSTEP
c        CALL GCB_SET1R('SHAPE_Y',I+1,1,YL,STATUS)
c        CALL GCB_SET1C('NOTE_TEXT',I+1,1,COMPSPEC(I),STATUS)
c        CALL GCB_SET1R('NOTE_SIZE',I+1,1,TXTSCALE,STATUS)
        YT=YT-YSTEP
        IF (LOGAX) THEN
          YTL=10.0**YT
c          CALL GCB_SET1R('NOTE_X',I+1,1,XTL,STATUS)
c          CALL GCB_SET1R('NOTE_Y',I+1,1,YTL,STATUS)
        ELSE
c          CALL GCB_SET1R('NOTE_X',I+1,1,XT,STATUS)
c          CALL GCB_SET1R('NOTE_Y',I+1,1,YT,STATUS)
        END IF
      END DO


*  Numeric label character size
      CALL GCB_SETR('AXES_SIZE',TXTSCALE,STATUS)

*  Axis labels
      CALL GCB_SETR('XLABEL_SIZE',TXTSCALE,STATUS)
      TEXT='Energy (keV)'
      CALL GCB_SETC('XLABEL_TEXT',TEXT,STATUS)

      CALL GCB_SETR('YLABEL_SIZE',TXTSCALE,STATUS)
      TEXT='photon s\u-1\d cm\u-2\d keV\u-1\d'
      CALL GCB_SETC('YLABEL_TEXT',TEXT,STATUS)

*  Title lines
      CALL GCB_SETI('TITLE_N',1,STATUS)
      TEXT = 'Additive components for model: '//MODSPEC
      CALL GCB_SET1C('TITLE_TEXT',1,1,TEXT,STATUS)
      CALL GCB_SET1R('TITLE_SIZE',1,1,TXTSCALE,STATUS)
      CALL GCB_SET1C('TITLE_JUST',1,1,'L',STATUS)

      END



*+
      SUBROUTINE SPLOT_MPLOT_COPY(OFID,NCHAN,NTERM,COMPSPEC,SAVE,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'FIT_PAR'
*    Global variables :
        INCLUDE 'SPLOT_CMN'
*    Structure definitions :
*    Import :
      INTEGER OFID,NCHAN,NTERM
      CHARACTER*(*) COMPSPEC(*)
      LOGICAL SAVE
*    Import-Export :
*    Export :
*    Status :
      INTEGER STATUS
*    Function declarations :
*    Local constants :
*    Local variables :
      CHARACTER*80 OVLY
      INTEGER NDFID
      INTEGER IG
      INTEGER I
      INTEGER STYLE
      INTEGER L
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

*  locate correct NDF and write index entry
      IG = 1
      CALL SPLOT_CRENDF( SAVE, 'total model',
     :                   OFID, IG, NCHAN, MTDPTR, 0, 0,
     :                   MCXPTR, 0, 'Total model',
     :                   NDFID, STATUS )

*  Release graph
      CALL SPLOT_RELNDF( NDFID, STATUS )

*  Now each component model
      L=1
      DO I=1,NTERM
        IG=IG+1
        CALL SPLOT_CRENDF( SAVE, 'component '//COMPSPEC(I), 
     :                     OFID, IG, NCHAN, MCDPTR(I), 0, 0,
     :                     MCXPTR, 0,
     :                     COMPSPEC(I), NDFID, STATUS )

        STYLE = STYLE+1
        STYLE = STYLE/5 + MOD(STYLE,5) + 1
        CALL GCB_SETI('POLY_STYLE',STYLE,STATUS)

*    Release graph
        CALL SPLOT_RELNDF( NDFID, STATUS )

        WRITE(OVLY(L:),'(I2)') IG
        IF (I.LT.NTERM) THEN
          L=L+2
          OVLY(L:L)=','
          L=L+1
        END IF

      END DO

*  Cancel attributes that not relevant to other data
      CALL GCB_CAN( 'SHAPE_N,NOTE_N', STATUS )
      CALL GCB_CAN1( 'SHAPE_TYPE,SHAPE_X,SHAPE_Y,'/
     :        /'SHAPE_DATA1,SHAPE_DATA2,SHAPE_STYLE',1,NTERM+1,STATUS)
      CALL GCB_CAN1( 'NOTE_TEXT,NOTE_X,NOTE_Y', 1, NTERM+1, STATUS )
      CALL GCB_CAN( 'POLY_STYLE', STATUS )
      CALL GCB_CAN( 'TITLE_N', STATUS )
      CALL GCB_CAN1( 'TITLE_SIZE,TITLE_TEXT,TITLE_JUST', 1, 1, STATUS )
      CALL GCB_CAN( 'YLABEL_TEXT', STATUS )
      CALL GCB_CAN( 'XAXIS_LOG,YAXIS_LOG',STATUS)
      CALL GCB_CAN( 'YAXIS_LO,YAXIS_HI', STATUS )

*  Set overlay
      CALL GMI_SETPLOT( OFID, 1, 1, OVLY, STATUS )

      END



*+
      SUBROUTINE SPLOT_MPLOT_ADDCOMP(NCHAN,COMP,TOT,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
*    Global variables :
*    Structure definitions :
*    Import :
      INTEGER NCHAN
      REAL COMP(*)
*    Import-Export :
*    Export :
      REAL TOT(*)
*    Status :
      INTEGER STATUS
*    Function declarations :
*    Local constants :
*    Local variables :
      INTEGER I
*-

      IF (STATUS.EQ.SAI__OK) THEN

        DO I=1,NCHAN
          TOT(I)=TOT(I)+COMP(I)
        END DO

      END IF

      END



*+
      SUBROUTINE SPLOT_MPLOT_EAXIS(NCHAN,EL,EU,ELB,EUB,X,STATUS)
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
*    Import :
      INTEGER NCHAN
      REAL EL,EU
*    Import-Export :
*    Export :
      REAL ELB(*),EUB(*)
      REAL X(*)
*    Status :
      INTEGER STATUS
*    Function declarations :
*    Local constants :
*    Local variables :
      REAL WID,HWID
      INTEGER ICHAN
*-

      IF (STATUS.EQ.SAI__OK) THEN

        WID=(EU-EL)/REAL(NCHAN)
        HWID=WID/2.0

        ELB(1)=EL
        EUB(1)=EL+WID
        X(1)=EL+HWID
        DO ICHAN=2,NCHAN
          ELB(ICHAN)=ELB(ICHAN-1)+WID
          EUB(ICHAN)=ELB(ICHAN)+WID
          X(ICHAN)=ELB(ICHAN)+HWID
        END DO

      END IF

      END




*+
      SUBROUTINE SPLOT_CRENDF( SAVE, ANCE, 
     :      MGID, N, NDAT, DPTR, VPTR, QPTR, XPTR,
     :                         WPTR, NAME, GFID, STATUS )
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
      INCLUDE 'FIT_PAR'
*    Import :
      LOGICAL	SAVE
      INTEGER   MGID, N, NDAT, DPTR, VPTR, QPTR, XPTR, WPTR
      CHARACTER*(*) ANCE,NAME
*    Export:
      INTEGER GFID
*  Global Variables:
      INCLUDE 'SPLOT_CMN'
*    Status :
      INTEGER STATUS
*    Local variables :
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

*  Annouce this graph
      IF ( SAVE ) THEN
        CALL MSG_SETI( 'NDF', N )
        CALL MSG_PRNT('  Writing '//ANCE//' to NDF ^NDF ...')
      END IF

*  Locate the graph file object
      CALL GMI_LOCNDF( MGID, N, '*', GFID, STATUS )

*  Create binned data object and link it to the graph
      CALL BDI_LINK( 'Spectrum', 1, NDAT, 'REAL', GFID, STATUS )

*  Write the index entry
      CALL GMI_PUTINDEX( MGID, N, NAME, STATUS )

*  Graph data
      CALL BDI_PUT1R( GFID, 'Data', NDAT, %VAL(DPTR), STATUS )

*  Graph variance
      IF ( VPTR .NE. 0 ) THEN
        CALL BDI_PUT1R( GFID, 'Variance', NDAT, %VAL(VPTR), STATUS )
      END IF

*  Graph quality
      IF ( QPTR .NE. 0 ) THEN
        CALL BDI_PUT1UB( GFID, 'Quality', NDAT, %VAL(QPTR), STATUS )
        CALL BDI_PUT0UB( GFID, 'QualityMask', MASK, STATUS )
      END IF

*  Axis info
      CALL BDI_AXPUT1R( GFID, 1, 'Data', NDAT, %VAL(XPTR), STATUS )
      IF ( WPTR .NE. 0 ) THEN
        CALL BDI_AXPUT1R( GFID, 1, 'Width', NDAT, %VAL(WPTR), STATUS )
      END IF

      END



*+
      SUBROUTINE SPLOT_RELNDF( NDFID, STATUS )
*    Description :
*    Type definitions :
      IMPLICIT NONE
*    Global constants :
      INCLUDE 'SAE_PAR'
*    Import :
      INTEGER NDFID
*    Status :
      INTEGER STATUS
*    Local variables :
*-

*  Check inherited global status.
      IF ( STATUS .NE. SAI__OK ) RETURN

*  Store graphics control
      CALL GCB_FSAVE( NDFID, STATUS )

*  Release the graph
      CALL ADI_ERASE( NDFID, STATUS )

      END