SUBROUTINE ERI1_WRITRMF( NARG, ARGS, OARG, STATUS )
*+
*  Name:
*     ERI1_WRITRMF

*  Purpose:
*     Write simple energy response to a HDS file

*  Language:
*     Starlink Fortran

*  Invocation:
*     CALL ERI1_WRITRMF( NARG, ARGS, OARG, STATUS )

*  Description:
*     This method writes simple format energy respones to a HDS file.
*     Such a response is simply a 2D array of values. It writes only 
*     that information which is contained within the RMFID passed as 
*     the second argument. Other data of interest must be written by 
*     surrounding methods which have access to the dataset to which 
*     this response is "attached". 
*
*     The response is written in one of two formats. If the input 
*     compression method is NONE, the the response is written as a simple 
*     2D array in a fixed size BINTABLE extension. If the method is ASTERIX
*     or OGIP_CMP then the response is written to a variable field size 
*     BINTABLE.

*  Arguments:
*     NARG = INTEGER (given)
*        Number of method arguments
*     ARGS(*) = INTEGER (given)
*        ADI identifier of method arguments
*     OARG = INTEGER (returned) 
*        Output data
*     STATUS = INTEGER (given and returned)
*        The global status.

*  Examples:
*     {routine_example_text}
*        {routine_example_description}

*  Pitfalls:
*     {pitfall_description}...

*  Notes:
*     {routine_notes}...

*  Prior Requirements:
*     {routine_prior_requirements}...

*  Side Effects:
*     {routine_side_effects}...

*  Algorithm:
*     {algorithm_description}...

*  Accuracy:
*     {routine_accuracy}

*  Timing:
*     {routine_timing}

*  External Routines Used:
*     ADI:
*        ADI2_POGIPK	- Write OGIP classification keywords

*  Implementation Deficiencies:
*     {routine_deficiencies}...

*  References:
*     ERI Subroutine Guide : http://www.sr.bham.ac.uk/asterix-docs/Programmer/Guides/eri.html

*  Keywords:
*     package:eri, usage:private

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

*  Authors:
*     DJA: David J. Allan (Jet-X, University of Birmingham)
*     {enter_new_authors_here}

*  History:
*     28 Feb 1995 (DJA):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

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

*  Global Constants:
      INCLUDE 'SAE_PAR'          			! SAE constants
      INCLUDE 'ADI_PAR'					! ADI constants

*  Arguments Given:
      INTEGER                   NARG                    ! # arguments
      INTEGER                   ARGS(*)                 ! Method arguments

*  Arguments Returned:
      INTEGER                   OARG                    ! Returned data

*  Status:
      INTEGER                   STATUS                  ! Global status

*  External References:
      EXTERNAL			ADI2_POGIPK

*  Local Variables:
      CHARACTER*5		STR			! NCHAN in characters
      CHARACTER*8		TTYPE(3)		! Column names
      CHARACTER*8		TFORM(3)		! Column types
      CHARACTER*3		TUNIT(3)		! Column units

      INTEGER			EBPTR			! Energy bounds ptr
      INTEGER			FID			! FITSfile object
      INTEGER			FSTAT			! FITSIO status
      INTEGER			IDX			! Response number
      INTEGER			NRESP			! # responses in file
      INTEGER			LUN			! Logical unit
      INTEGER			NCHAN			! # channel bins
      INTEGER			NDIG			! Chars used in STR
      INTEGER			NENER			! # energy bins
      INTEGER			RMFID			! Response object
      INTEGER			RPTR			! Mapped RMF

*  Local data;
      DATA    TUNIT/'keV', 'keV', ' '/
*.

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

*  Extract arguments
      FID = ARGS(1)
      CALL ADI_CGET0I( ARGS(2), IDX, STATUS )
      CALL ADI_CGET0I( ARGS(3), NRESP, STATUS )
      RMFID = ARGS(4)

*  Get size of conceptual RMF
      CALL ADI_CGET0I( RMFID, 'NCHAN', NCHAN, STATUS )
      CALL ADI_CGET0I( RMFID, 'NENERGY', NENER, STATUS )

*  Get file's logical unit
      CALL ADI2_GETLUN( FID, LUN, STATUS )

*  Write keywords rather than fields for the N_GRP, F_CHAN and N_CHAN
*  fields, as their values are constant
      CALL ADI2_PKEY0I( FID, 'MATRIX', 'N_GRP', 1, ' ', STATUS )
      CALL ADI2_PKEY0I( FID, 'MATRIX', 'F_CHAN', 1, ' ', STATUS )
      CALL ADI2_PKEY0I( FID, 'MATRIX', 'N_CHAN', NCHAN, ' ', STATUS )

*  Construct the field descriptions for the BINTABLE
      TTYPE(1) = 'ENERG_LO'
      TFORM(1) = '1E'
      TTYPE(2) = 'ENERG_HI'
      TFORM(2) = '1E'
      TTYPE(3) = 'MATRIX'
      CALL CHR_ITOC( NCHAN, STR, NDIG )
      TFORM(3) = STR(:NDIG)//'E'

*  Define the HDU data area
      CALL ADI2_DEFBTB( FID, 'MATRIX', NENER, 3, TTYPE, TFORM,
     :                  TUNIT, 0, STATUS )

*  Write keywords for response extension
      CALL ADI2_POGIPK( FID, 'MATRIX', 'RESPONSE', '1.0.0', 
     :                  'RSP_MATRIX', '1.1.0', 'REDIST', ' ', STATUS )

*  Write the energy boundaries into the table
      CALL ADI_CMAPR( RMFID, 'Energy', 'READ', EBPTR, STATUS )
      FSTAT = 0
      CALL FTPCLE( LUN, 1, 1, 1, NENER, %VAL(EBPTR), FSTAT )
      CALL FTPCLE( LUN, 2, 1, 1, NENER, %VAL(EBPTR+4), FSTAT )
      CALL ADI_CUNMAP( RMFID, 'Energy', EBPTR, STATUS )

*  Map the matrix data
      CALL ADI_CMAPR( RMFID, 'RMF', 'READ', RPTR, STATUS )
    
*  Simply write the data
      CALL FTPCLE( LUN, 3, 1, 1, NENER*NCHAN, %VAL(RPTR), STATUS )

*  Release the matrix data
      CALL ADI_CUNMAP( RMFID, 'RMF', RPTR, STATUS )

*  Report any errors
      IF ( STATUS .NE. SAI__OK ) THEN
        CALL AST_REXIT( 'ERI1_WRITRMF', STATUS )
      END IF

      END



      SUBROUTINE ERI1_WRITE_OGIP_RMFARF( NARG, ARGS, OARG, STATUS )
*+
*  Name:
*     ERI1_WRITE_OGIP_RMFARF

*  Purpose:
*     Write OGIP format energy response with ancillary response to an HDS file

*  Language:
*     Starlink Fortran

*  Invocation:
*     CALL ERI1_WRITE_OGIP_RMFARF( NARG, ARGS, OARG, STATUS )

*  Description:
*     Writes the RMF component to HDS. Remaps response array and scales
*     each value by the corresponding value in the ancillary response.

*  Arguments:
*     NARG = INTEGER (given)
*        Number of method arguments
*     ARGS(*) = INTEGER (given)
*        ADI identifier of method arguments
*     OARG = INTEGER (returned) 
*        Output data
*     STATUS = INTEGER (given and returned)
*        The global status.

*  Examples:
*     {routine_example_text}
*        {routine_example_description}

*  Pitfalls:
*     {pitfall_description}...

*  Notes:
*     {routine_notes}...

*  Prior Requirements:
*     {routine_prior_requirements}...

*  Side Effects:
*     {routine_side_effects}...

*  Algorithm:
*     {algorithm_description}...

*  Accuracy:
*     {routine_accuracy}

*  Timing:
*     {routine_timing}

*  External Routines Used:
*     ADI:
*        ADI2_POGIPK	- Write OGIP classification keywords

*  Implementation Deficiencies:
*     {routine_deficiencies}...

*  References:
*     ERI Subroutine Guide : http://www.sr.bham.ac.uk/asterix-docs/Programmer/Guides/eri.html

*  Keywords:
*     package:eri, usage:private

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

*  Authors:
*     DJA: David J. Allan (Jet-X, University of Birmingham)
*     {enter_new_authors_here}

*  History:
*     28 Feb 1995 (DJA):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

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

*  Global Constants:
      INCLUDE 'SAE_PAR'          			! SAE constants
      INCLUDE 'DAT_PAR'					! HDS constants
      INCLUDE 'ADI_PAR'					! ADI constants

*  Arguments Given:
      INTEGER                   NARG                    ! # arguments
      INTEGER                   ARGS(*)                 ! Method arguments

*  Arguments Returned:
      INTEGER                   OARG                    ! Returned data

*  Status:
      INTEGER                   STATUS                  ! Global status

*  Local Variables:
      CHARACTER*(DAT__SZLOC)	ELOC			! ENERGY_RESP object
      CHARACTER*(DAT__SZLOC)	ENLOC			! .ENERGY
      CHARACTER*(DAT__SZLOC)	RELOC			! .RESPONSE

      INTEGER			EIPTR			! Energy indices
      INTEGER			NENER			! # energy bins
      INTEGER			NMAP			! # mapped elements
      INTEGER			RPTR			! Mapped RMF
      INTEGER			SCPTR			! Mapped ARF values
*.

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

*  Write the RMF bit by calling the method routine for RMF alone
      CALL ERI1_WRITRMF_OGIP( 4, ARGS, OARG, STATUS )

*  Locate the response
      CALL ERI1_LOCRESP( ARGS, .FALSE., ELOC, STATUS )

*  Now fold in the scale factors contained in the ancillary response. For
*  this we need the response values and their energy indices. 
      CALL DAT_FIND( ELOC, 'ENERGY', ENLOC, STATUS )
      CALL DAT_FIND( ELOC, 'RESPONSE', RELOC, STATUS )
      CALL CMP_MAPV( ENLOC, 'DATA_ARRAY', '_INTEGER', 'READ', EIPTR,
     :               NMAP, STATUS )
      CALL CMP_MAPV( RELOC, 'DATA_ARRAY', '_REAL', 'UPDATE', RPTR,
     :               NMAP, STATUS )

*  Map the scale factors in the ancillary response
      CALL ADI_CGET0I( ARGS(5), 'NENERGY', NENER, STATUS )
      CALL ADI_CMAPR( ARGS(5), 'Response', 'READ', SCPTR, STATUS )

*  Scale the response 
      CALL ERI1_WRITE_OGIP_RMFARF1( NENER, %VAL(SCPTR), NMAP,
     :                      %VAL(EIPTR), %VAL(RPTR), STATUS )

*  Release ADI object
      CALL ADI_CUNMAP( ARGS(5), 'Response', SCPTR, STATUS )
      
*  Free the HDS objects we've mapped and found
      CALL CMP_UNMAP( ENLOC, 'DATA_ARRAY', STATUS )
      CALL CMP_UNMAP( RELOC, 'DATA_ARRAY', STATUS )
      CALL DAT_ANNUL( ENLOC, STATUS )
      CALL DAT_ANNUL( RELOC, STATUS )
      CALL DAT_ANNUL( ELOC, STATUS )

*  Report any errors
      IF ( STATUS .NE. SAI__OK ) THEN
        CALL AST_REXIT( 'ERI1_WRITE_OGIP_RMFARF', STATUS )
      END IF

      END

      SUBROUTINE ERI1_WRITE_OGIP_RMFARF1( NE, SCALE, NRMF, EIND, RSP,
     :               STATUS )
      IMPLICIT NONE
      INTEGER NE,NRMF,EIND(*),STATUS
      REAL	SCALE(NE), RSP(*)
      INTEGER I
      IF ( STATUS .EQ. 0 ) THEN
      DO I = 1, NRMF
         RSP(I) = RSP(I) * SCALE(EIND(I))
      END DO
      END IF

      END



      SUBROUTINE ERI1_WRITRMF_OGIP( NARG, ARGS, OARG, STATUS )
*+
*  Name:
*     ERI1_WRITRMF_OGIP

*  Purpose:
*     Write OGIP format energy response to an HDS file

*  Language:
*     Starlink Fortran

*  Invocation:
*     CALL ERI1_WRITRMF_OGIP( NARG, ARGS, OARG, STATUS )

*  Description:
*     This method provides the low level mechanism of writing a energy
*     response structure to a dataset. It writes only that information
*     which is contained within the RMFID passed as the second argument.
*     Other data of interest must be written by surrounding methods
*     which have access to the dataset to which this response is 
*     "attached". 
*
*     The response is written in one of two formats. If the input 
*     compression method is NONE, the the response is written as a simple 
*     2D array in a fixed size BINTABLE extension. If the method is ASTERIX
*     or OGIP_CMP then the response is written to a variable field size 
*     BINTABLE.

*  Arguments:
*     NARG = INTEGER (given)
*        Number of method arguments
*     ARGS(*) = INTEGER (given)
*        ADI identifier of method arguments
*     OARG = INTEGER (returned) 
*        Output data
*     STATUS = INTEGER (given and returned)
*        The global status.

*  Examples:
*     {routine_example_text}
*        {routine_example_description}

*  Pitfalls:
*     {pitfall_description}...

*  Notes:
*     {routine_notes}...

*  Prior Requirements:
*     {routine_prior_requirements}...

*  Side Effects:
*     {routine_side_effects}...

*  Algorithm:
*     {algorithm_description}...

*  Accuracy:
*     {routine_accuracy}

*  Timing:
*     {routine_timing}

*  External Routines Used:
*     ADI:
*        ADI2_POGIPK	- Write OGIP classification keywords

*  Implementation Deficiencies:
*     {routine_deficiencies}...

*  References:
*     ERI Subroutine Guide : http://www.sr.bham.ac.uk/asterix-docs/Programmer/Guides/eri.html

*  Keywords:
*     package:eri, usage:private

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

*  Authors:
*     DJA: David J. Allan (Jet-X, University of Birmingham)
*     {enter_new_authors_here}

*  History:
*     28 Feb 1995 (DJA):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

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

*  Global Constants:
      INCLUDE 'SAE_PAR'          			! SAE constants
      INCLUDE 'DAT_PAR'					! HDS constants
      INCLUDE 'ADI_PAR'					! ADI constants

*  Arguments Given:
      INTEGER                   NARG                    ! # arguments
      INTEGER                   ARGS(*)                 ! Method arguments

*  Arguments Returned:
      INTEGER                   OARG                    ! Returned data

*  Status:
      INTEGER                   STATUS                  ! Global status

*  External References:
      EXTERNAL			ADI2_POGIPK

*  Local Variables:
      CHARACTER*(DAT__SZLOC)	ELOC			! ENERGY_RESP object
      CHARACTER*(DAT__SZLOC)	CHLOC			! .CHANNEL
      CHARACTER*(DAT__SZLOC)	ENLOC			! .ENERGY
      CHARACTER*(DAT__SZLOC)	RELOC			! .RESPONSE

      INTEGER			CIPTR			! Channel indices
      INTEGER			CSPTR			! Channel spec ptr
      INTEGER			EIPTR			! Energy indices
      INTEGER			FCPTR			! F_chan data
      INTEGER			NCHAN			! # channel bins
      INTEGER			NCPTR			! N_chan data
      INTEGER			NENER			! # energy bins
      INTEGER			NGPTR			! N_grp data
      INTEGER			NMAP			! # mapped elements
      INTEGER			NRMF			! # response elements
      INTEGER			RMFID			! Response object

      LOGICAL			THERE			! Object exists?
*.

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

*  Extract arguments
      RMFID = ARGS(4)

*  Get size of conceptual RMF
      CALL ADI_CGET0I( RMFID, 'NCHAN', NCHAN, STATUS )
      CALL ADI_CGET0I( RMFID, 'NENERGY', NENER, STATUS )

*  Locate the response
      CALL ERI1_LOCRESP( ARGS, .TRUE., ELOC, STATUS )

*  Ensure the three structures are present in ELOC
      CALL DAT_THERE( ELOC, 'ENERGY', THERE, STATUS )
      IF ( .NOT. THERE ) THEN
        CALL DAT_NEW( ELOC, 'ENERGY', 'LIST', 0, 0, STATUS )
      END IF
      CALL DAT_FIND( ELOC, 'ENERGY', ENLOC, STATUS )
      CALL DAT_THERE( ELOC, 'CHANNEL', THERE, STATUS )
      IF ( .NOT. THERE ) THEN
        CALL DAT_NEW( ELOC, 'CHANNEL', 'LIST', 0, 0, STATUS )
      END IF
      CALL DAT_FIND( ELOC, 'CHANNEL', CHLOC, STATUS )
      CALL DAT_THERE( ELOC, 'RESPONSE', THERE, STATUS )
      IF ( .NOT. THERE ) THEN
        CALL DAT_NEW( ELOC, 'RESPONSE', 'LIST', 0, 0, STATUS )
      END IF
      CALL DAT_FIND( ELOC, 'RESPONSE', RELOC, STATUS )

*  Write energy bounds
      CALL ADI1_CCA2HR( RMFID, 'Energy', ENLOC, 'ENERGY_BOUNDS',
     :                  STATUS )

*  Invent the ENERGY_SPEC array by taking the centre values of the bounds
      CALL ERI1_WRITRMF_EB2C( RMFID, NENER, ENLOC, STATUS )
      
*  Write the channel bounds
      CALL ADI1_CCA2HR( RMFID, 'Channels', CHLOC, 'CHANNEL_BOUNDS',
     :                  STATUS )

*  OGIP responses are always 1 channel wide, so create a dummy CHANNEL_SPEC
*  array
      CALL DAT_NEW1R( CHLOC, 'CHANNEL_SPEC', NCHAN, STATUS ) 
      CALL CMP_MAPV( CHLOC, 'CHANNEL_SPEC', '_REAL', 'WRITE', CSPTR, 
     :               NMAP, STATUS )
      CALL ARR_REG1R( 1.0, 1.0, NCHAN, %VAL(CSPTR), STATUS )
      CALL CMP_UNMAP( CHLOC, 'CHANNEL_SPEC', STATUS )

*  Write the response values
      CALL ADI1_CCA2HR( RMFID, 'RMF', RELOC, 'DATA_ARRAY', STATUS )

*  Convert the N_grp, F_chan and N_chan members to energy and channel
*  indices. Create the latter as _WORD arrays, but use integer in code
*  for portability
      CALL ADI_CMAPI( RMFID, 'Ngrp', 'READ', NGPTR, STATUS )
      CALL ADI_CMAPI( RMFID, 'Fchan', 'READ', FCPTR, STATUS )
      CALL ADI_CMAPI( RMFID, 'Nchan', 'READ', NCPTR, STATUS )
      CALL ADI_CSIZE( RMFID, 'RMF', NRMF, STATUS )
      CALL DAT_NEW( ENLOC, 'DATA_ARRAY', '_WORD', 1, NRMF, STATUS )
      CALL CMP_MAPV( ENLOC, 'DATA_ARRAY', '_INTEGER', 'WRITE', 
     :               EIPTR, NMAP, STATUS )
      CALL DAT_NEW( CHLOC, 'DATA_ARRAY', '_WORD', 1, NRMF, STATUS )
      CALL CMP_MAPV( CHLOC, 'DATA_ARRAY', '_INTEGER', 'WRITE', 
     :               CIPTR, NMAP, STATUS )
      CALL ERI1_WRITRMF_OGIP1( NENER, %VAL(NGPTR), %VAL(FCPTR), 
     :                         %VAL(NCPTR), %VAL(EIPTR),
     :                         %VAL(CIPTR), STATUS )
      CALL ADI_CUNMAP( RMFID, 'Nchan', NCPTR, STATUS )
      CALL ADI_CUNMAP( RMFID, 'Fchan', FCPTR, STATUS )
      CALL ADI_CUNMAP( RMFID, 'Ngrp', NGPTR, STATUS )

*  Free the response object
      CALL CMP_UNMAP( ENLOC, 'DATA_ARRAY', STATUS )
      CALL CMP_UNMAP( CHLOC, 'DATA_ARRAY', STATUS )
      CALL DAT_ANNUL( RELOC, STATUS )
      CALL DAT_ANNUL( CHLOC, STATUS )
      CALL DAT_ANNUL( ENLOC, STATUS )
      CALL DAT_ANNUL( ELOC, STATUS )

*  Report any errors
      IF ( STATUS .NE. SAI__OK ) THEN
        CALL AST_REXIT( 'ERI1_WRITRMF_OGIP', STATUS )
      END IF

      END

      SUBROUTINE ERI1_WRITRMF_OGIP1( NE, NGRP, FC, NC,
     :                               EI, CI, STATUS )
      INTEGER NE,NGRP(*),FC(*),NC(*),EI(*),CI(*),STATUS
 	INTEGER I,IG,R
 
      IG = 1
      R =  1
      DO I = 1, NE
        DO J = 1, NGRP(I)
          DO K = 1, NC(IG)
            EI(R) = I
            CI(R) = FC(IG) + K - 1
            R = R + 1
          END DO
          IG = IG + 1
        END DO
      END DO

      END 


      SUBROUTINE ERI1_WRITRMF_AST( NARG, ARGS, OARG, STATUS )
*+
*  Name:
*     ERI1_WRITRMF_AST

*  Purpose:
*     Write ASTERIX type energy response to a HDS file

*  Language:
*     Starlink Fortran

*  Invocation:
*     CALL ERI1_WRITRMF_AST( NARG, ARGS, OARG, STATUS )

*  Description:
*     This method provides the low level mechanism of writing a energy
*     response structure to a dataset. It writes only that information
*     which is contained within the RMFID passed as the second argument.
*     Other data of interest must be written by surrounding methods
*     which have access to the dataset to which this response is 
*     "attached". 

*  Arguments:
*     NARG = INTEGER (given)
*        Number of method arguments
*     ARGS(*) = INTEGER (given)
*        ADI identifier of method arguments
*     OARG = INTEGER (returned) 
*        Output data
*     STATUS = INTEGER (given and returned)
*        The global status.

*  Examples:
*     {routine_example_text}
*        {routine_example_description}

*  Pitfalls:
*     {pitfall_description}...

*  Notes:
*     {routine_notes}...

*  Prior Requirements:
*     {routine_prior_requirements}...

*  Side Effects:
*     {routine_side_effects}...

*  Algorithm:
*     {algorithm_description}...

*  Accuracy:
*     {routine_accuracy}

*  Timing:
*     {routine_timing}

*  External Routines Used:
*     ADI:
*        ADI2_POGIPK	- Write OGIP classification keywords

*  Implementation Deficiencies:
*     {routine_deficiencies}...

*  References:
*     ERI Subroutine Guide : http://www.sr.bham.ac.uk/asterix-docs/Programmer/Guides/eri.html

*  Keywords:
*     package:eri, usage:private

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

*  Authors:
*     DJA: David J. Allan (Jet-X, University of Birmingham)
*     {enter_new_authors_here}

*  History:
*     28 Feb 1995 (DJA):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

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

*  Global Constants:
      INCLUDE 'SAE_PAR'          			! SAE constants
      INCLUDE 'ADI_PAR'					! ADI constants
      INCLUDE 'DAT_PAR'					! HDS constants

*  Arguments Given:
      INTEGER                   NARG                    ! # arguments
      INTEGER                   ARGS(*)                 ! Method arguments

*  Arguments Returned:
      INTEGER                   OARG                    ! Returned data

*  Status:
      INTEGER                   STATUS                  ! Global status

*  Local Variables:
      CHARACTER*(DAT__SZLOC)	ELOC			! ENERGY_RESP object
      CHARACTER*(DAT__SZLOC)	CHLOC			! .CHANNEL
      CHARACTER*(DAT__SZLOC)	ENLOC			! .ENERGY
      CHARACTER*(DAT__SZLOC)	RELOC			! .RESPONSE

      INTEGER			NCHAN			! # channel bins
      INTEGER			NENER			! # energy bins
      INTEGER			RMFID			! Response object

      LOGICAL			THERE			! 
*.

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

*  Extract arguments
      RMFID = ARGS(4)

*  Get size of conceptual RMF
      CALL ADI_CGET0I( RMFID, 'NCHAN', NCHAN, STATUS )
      CALL ADI_CGET0I( RMFID, 'NENERGY', NENER, STATUS )

*  Locate the response
      CALL ERI1_LOCRESP( ARGS, .TRUE., ELOC, STATUS )

*  Ensure the three structures are present in ELOC
      CALL DAT_THERE( ELOC, 'ENERGY', THERE, STATUS )
      IF ( .NOT. THERE ) THEN
        CALL DAT_NEW( ELOC, 'ENERGY', 'LIST', 0, 0, STATUS )
      END IF
      CALL DAT_FIND( ELOC, 'ENERGY', ENLOC, STATUS )
      CALL DAT_THERE( ELOC, 'CHANNEL', THERE, STATUS )
      IF ( .NOT. THERE ) THEN
        CALL DAT_NEW( ELOC, 'CHANNEL', 'LIST', 0, 0, STATUS )
      END IF
      CALL DAT_FIND( ELOC, 'CHANNEL', CHLOC, STATUS )
      CALL DAT_THERE( ELOC, 'RESPONSE', THERE, STATUS )
      IF ( .NOT. THERE ) THEN
        CALL DAT_NEW( ELOC, 'RESPONSE', 'LIST', 0, 0, STATUS )
      END IF
      CALL DAT_FIND( ELOC, 'RESPONSE', RELOC, STATUS )

*  Write the arrays
      CALL ADI1_CCA2HR( RMFID, 'Energy', ENLOC, 'ENERGY_BOUNDS',
     :                  STATUS )
      CALL ADI1_CCA2HI( RMFID, 'EnergyIndices', ENLOC, 'DATA_ARRAY',
     :                  STATUS )
      CALL ADI1_CCA2HR( RMFID, 'Channels', CHLOC, 'CHANNEL_BOUNDS',
     :                  STATUS )
      CALL ADI1_CCA2HI( RMFID, 'ChannelIndices', CHLOC, 'DATA_ARRAY',
     :                  STATUS )
      CALL ADI1_CCA2HR( RMFID, 'ChannelSpec', CHLOC, 'CHANNEL_SPEC',
     :                  STATUS )
      CALL ADI1_CCA2HR( RMFID, 'RMF', RELOC, 'DATA_ARRAY', STATUS )

*  Invent the ENERGY_SPEC array by taking the centre values of the bounds
      CALL ERI1_WRITRMF_EB2C( RMFID, NENER, ENLOC, STATUS )
      
*  Free the response object
      CALL DAT_ANNUL( ENLOC, STATUS )
      CALL DAT_ANNUL( CHLOC, STATUS )
      CALL DAT_ANNUL( RELOC, STATUS )
      CALL DAT_ANNUL( ELOC, STATUS )

*  Report any errors
      IF ( STATUS .NE. SAI__OK ) THEN
        CALL AST_REXIT( 'ERI1_WRITRMF_AST', STATUS )
      END IF

      END



      SUBROUTINE ERI1_WRITRMF_AST1( FID, NE, MAXE, NCH, NRMF, EBND, CI, 
     :                              EI, RSP, WRK1, WRK2, STATUS )
*+
*  Name:
*     ERI1_WRITRMF_AST1

*  Purpose:
*     Write ASTERIX energy response elements to a HDS file

*  Language:
*     Starlink Fortran

*  Invocation:
*     CALL ERI1_WRITRMF_AST1( FID, NE, NCH, NRMF, EBND, CI, EI, 
*                             RSP, WRK1, WRK2, STATUS )

*  Description:
*

*  Arguments:
*     LUN = INTEGER (given)
*        Logical unit for output
*     NE = INTEGER (given)
*        Number of energy bins (ie number of rows in table)
*     NCH = INTEGER (given)
*        Number of channel bins 
*     NRMF = INTEGER (given)
*        Number of specified response elements
*     EBND[] = REAL (given)
*        Energy bounds array
*     CI[] = INTEGER (given)
*        Channel indices of non-zero elements
*     EI[] = INTEGER (given)
*        Energy indices of non-zero elements
*     RSP[] = REAL (given)
*        Response elements
*     WRK1[] = INTEGER (given)
*        Workspace as big as NE
*     WRK2[] = INTEGER (given)
*        Workspace as big as NRMF
*     STATUS = INTEGER (given and returned)
*        The global status.

*  Examples:
*     {routine_example_text}
*        {routine_example_description}

*  Pitfalls:
*     {pitfall_description}...

*  Notes:
*     {routine_notes}...

*  Prior Requirements:
*     {routine_prior_requirements}...

*  Side Effects:
*     {routine_side_effects}...

*  Algorithm:
*     {algorithm_description}...

*  Accuracy:
*     {routine_accuracy}

*  Timing:
*     {routine_timing}

*  Implementation Deficiencies:
*     {routine_deficiencies}...

*  References:
*     ERI Subroutine Guide : http://www.sr.bham.ac.uk/asterix-docs/Programmer/Guides/eri.html

*  Keywords:
*     package:eri, usage:private

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

*  Authors:
*     DJA: David J. Allan (Jet-X, University of Birmingham)
*     {enter_new_authors_here}

*  History:
*     28 Feb 1995 (DJA):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

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

*  Global Constants:
      INCLUDE 'SAE_PAR'          			! SAE constants

*  Arguments Given:
      INTEGER			FID			! See above
      INTEGER			NE, MAXE, NCH, NRMF     !
      REAL			EBND(*)
      INTEGER			CI(*), EI(*)		!
      REAL			RSP(*)			!
      INTEGER			WRK1(NE,2), WRK2(NRMF,2)

*  Status:
      INTEGER                   STATUS                  ! Global status

*  External References:
      EXTERNAL			ADI2_POGIPK

*  Local Variables:
      CHARACTER*10		STR
      CHARACTER*8		TTYPE(6)		! Column names
      CHARACTER*8		TFORM(6)		! Column types
      CHARACTER*3		TUNIT(6)		! Column units

      INTEGER			ACTHEAP			! Actual heap size
      INTEGER			CS
      INTEGER			E			! Loop over energy
      INTEGER			FSTAT			! FITSIO status
      INTEGER			I			! 
      INTEGER			LASTR			! 
      INTEGER			LC			! Last channel bin
      INTEGER			LE			! Last energy bin
      INTEGER			LUN			! Logical unit
      INTEGER			MAX_NGRP		! Max value of N_GRP
      INTEGER			MAX_SMAT		! Max width of matrix
      INTEGER			NDIG			! 
      INTEGER			NFIXED			! 
      INTEGER			NS			! Number of subsets
      INTEGER			R			! Loop over RMF
      INTEGER			SMAT			! Elements != 0 in row

      LOGICAL			FNVAR, MATVAR		! Use variable lengths?

*  Local data;
      DATA    TUNIT/'keV', 'keV', ' ', ' ', ' ', ' '/
*.

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

*  Initialise
      FSTAT = 0
      DO E = 1, NE
        WRK1(E,1) = 0
      END DO

*  Get file's logical unit
      CALL ADI2_GETLUN( FID, LUN, STATUS )

*  Count number of channel subsets
      R = 1
      LE = -1
      LC = -1
      NS = 0
      DO WHILE ( R .LE. NRMF )

*    Same energy as before?
        IF ( EI(R) .EQ. LE ) THEN

*      Channel index has not advanced by one?
          IF ( CI(R) .NE. (LC+1) ) THEN

*        Increment number of subsets in this energy bin
            WRK1(LE,1) = WRK1(LE,1) + 1

*      Mark length of current subset
            IF ( NS .GT. 0 ) WRK2(NS,2) = CI(R-1) - WRK2(NS,1) + 1

*        Start new subset
            NS = NS + 1
            WRK2(NS,1) = CI(R)

          END IF
          
        ELSE

*      Mark length of current subset
          WRK2(NS,2) = CI(R-1) - WRK2(NS,1) + 1

*      Advance to next energy bin, start new subset
          LE = EI(R)

          NS = NS + 1
          WRK1(LE,1) = 1
          WRK1(LE,2) = R
          WRK2(NS,1) = CI(R)

        END IF
        
*    Next element
        LC = CI(R)
        R = R + 1

      END DO
      WRK2(NS,2) = CI(NRMF) - WRK2(NS,1) + 1

*  Find maximum size of N_GRP
      MAX_NGRP = 0
      MAX_SMAT = 0
      DO E = 1, NE
        MAX_NGRP = MAX( MAX_NGRP, WRK1(E,1) )
        IF ( (WRK1(E,1) .EQ. 0) .OR. (E.GT.LE) ) THEN
          SMAT = 0
        ELSE IF ( E .EQ. LE ) THEN
          SMAT = NRMF - WRK1(E,2)
        ELSE
          SMAT = WRK1(E+1,2) - WRK1(E,2)
        END IF
        MAX_SMAT = MAX( MAX_SMAT, SMAT )
      END DO

*  Use a variable length array for the F_CHAN and N_CHAN columns? Six is
*  factor by which a single element of F_CHAN or N_CHAN is smaller than 
*  the descriptor required to store a variable length array element.
      NFIXED = MAX_NGRP * MAXE
      IF ( (MAX_NGRP .GT. 6) .AND. (NS .NE. NFIXED) .AND.
     :                              (NS .LE. 6*NFIXED) ) THEN
        ACTHEAP = 2*2*NS
        FNVAR = .TRUE.
      ELSE
        ACTHEAP = 0
        FNVAR = .FALSE.
      END IF
      
*  Use a variable length array for the matrix column? Three is the
*  factor by which a single element of the response is smaller than 
*  the descriptor required to store a variable length array element.
      NFIXED = MAX_SMAT * MAXE
      IF ( (MAX_SMAT .GT. 3) .AND. (NRMF .NE. NFIXED) .AND.
     :                              (NRMF .le. 3* NFIXED) ) THEN
        ACTHEAP = ACTHEAP + 4*NRMF
        MATVAR = .TRUE.
      ELSE
        MATVAR = .FALSE.
      END IF

*  Construct the field descriptions for the BINTABLE
      TTYPE(1) = 'ENERG_LO'
      TFORM(1) = '1E'
      TTYPE(2) = 'ENERG_HI'
      TFORM(2) = '1E'
      TTYPE(3) = 'N_GRP'
      TFORM(3) = '1I'
      TTYPE(4) = 'F_CHAN'
      TTYPE(5) = 'N_CHAN'
      IF ( FNVAR ) THEN
        TFORM(4) = 'PI'
        TFORM(5) = 'PI'
      ELSE
        CALL CHR_ITOC( MAX_NGRP, STR, NDIG )
        TFORM(4) = STR(:NDIG)//'I'
        TFORM(5) = STR(:NDIG)//'I'
      END IF
      TTYPE(6) = 'MATRIX'
      IF ( MATVAR ) THEN
        TFORM(6) = 'PE'
      ELSE
        CALL CHR_ITOC( MAX_SMAT, STR, NDIG )
        TFORM(6) = STR(:NDIG)//'E'
      END IF

*  Define the HDU data area
      CALL ADI2_DEFBTB( FID, 'MATRIX', MAXE, 6, TTYPE, TFORM,
     :                  TUNIT, ACTHEAP, STATUS )

*  Other mandatory keywords
      CALL ADI2_PKEY0I( FID, 'MATRIX', 'DETCHANS', NCH,
     :       'Total number of raw PHA channels', STATUS )

*  Write keywords for response extension
      CALL ADI2_POGIPK( FID, 'MATRIX', 'RESPONSE', '1.0.0', 
     :                  'RSP_MATRIX', '1.1.0', 'REDIST', ' ', STATUS )

*  Write energy lower and upper bounds
      CALL FTPCLE( LUN, 1, 1, 1, MAXE, EBND(1), FSTAT )
      CALL FTPCLE( LUN, 2, 1, 1, MAXE, EBND(2), FSTAT )

*  The N_GRP field
      CALL FTPCLJ( LUN, 3, 1, 1, MAXE, WRK1(1,1), FSTAT )

*  Write the table data
      R = 1
      CS = 1
      DO E = 1, MAXE

*    Subsets in this energy bin?
        IF ( WRK1(E,1) .GT. 0 ) THEN

*      Write the F_CHAN fields 
          CALL FTPCLJ( LUN, 4, E, 1, WRK1(E,1), WRK2(CS,1), FSTAT )
          IF ( .NOT. FNVAR ) THEN
            DO I = WRK1(E,1) + 1, MAX_NGRP
              CALL FTPCLJ( LUN, 4, E, 1, I, 0, FSTAT )
            END DO
          END IF

*      Write the N_CHAN field
          CALL FTPCLJ( LUN, 5, E, 1, WRK1(E,1), WRK2(CS,2), FSTAT )
          IF ( .NOT. FNVAR ) THEN
            DO I = WRK1(E,1) + 1, MAX_NGRP
              CALL FTPCLJ( LUN, 5, E, 1, I, 0, FSTAT )
            END DO
          END IF

*      Write the channel values
          IF ( E .LE. LE ) THEN
            IF ( E .EQ. LE ) THEN
              LASTR = NRMF
            ELSE
              LASTR = WRK1(E+1,2)
            END IF
            CALL FTPCLE( LUN, 6, E, 1, LASTR - R + 1, RSP(R), FSTAT )
            IF ( .NOT. MATVAR ) THEN
              DO I = (LASTR - R + 1) + 1, MAX_SMAT
                CALL FTPCLE( LUN, 6, E, 1, I, 0.0, FSTAT )
              END DO
            END IF
          ELSE
            IF ( .NOT. MATVAR ) THEN
              DO I = 1, MAX_SMAT
                CALL FTPCLE( LUN, 6, E, 1, I, 0.0, FSTAT )
              END DO
            END IF
          END IF

*      Advance the element counter
          R = LASTR + 1
          CS = CS + WRK1(E,1)

*    Fill in zeroes if not vector columns
        ELSE IF ( .NOT. FNVAR ) THEN

          DO I = 1, MAX_NGRP
            CALL FTPCLJ( LUN, 4, E, 1, I, 0, FSTAT )
            CALL FTPCLJ( LUN, 5, E, 1, I, 0, FSTAT )
          END DO
          IF ( .NOT. MATVAR ) THEN
            DO I = 1, MAX_SMAT
              CALL FTPCLE( LUN, 6, E, 1, I, 0.0, FSTAT )
            END DO
          END IF

        END IF

      END DO

*   Define the length of data area properly
      CALL ADI2_DEFHP( FID, 'MATRIX', ACTHEAP, STATUS )

      END



      SUBROUTINE ERI1_WRITRMF_CEBND( FID, RMFID, STATUS )
*+
*  Name:
*     ERI1_WRITRMF_CEBND

*  Purpose:
*     Write channel energy bounds to EBOUNDS extension

*  Language:
*     Starlink Fortran

*  Invocation:
*     CALL ERI1_WRITRMF_CEBND( FID, RMFID, STATUS )

*  Description:
*

*  Arguments:
*     FID = INTEGER (given)
*        FITSfile object to which bounds will be written
*     RMFID = INTEGER (given)
*        Response containing
*     STATUS = INTEGER (given and returned)
*        The global status.

*  Examples:
*     {routine_example_text}
*        {routine_example_description}

*  Pitfalls:
*     {pitfall_description}...

*  Notes:
*     {routine_notes}...

*  Prior Requirements:
*     {routine_prior_requirements}...

*  Side Effects:
*     {routine_side_effects}...

*  Algorithm:
*     {algorithm_description}...

*  Accuracy:
*     {routine_accuracy}

*  Timing:
*     {routine_timing}

*  Implementation Deficiencies:
*     {routine_deficiencies}...

*  References:
*     ERI Subroutine Guide : http://www.sr.bham.ac.uk/asterix-docs/Programmer/Guides/eri.html

*  Keywords:
*     package:eri, usage:private

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

*  Authors:
*     DJA: David J. Allan (Jet-X, University of Birmingham)
*     {enter_new_authors_here}

*  History:
*     28 Feb 1995 (DJA):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

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

*  Global Constants:
      INCLUDE 'SAE_PAR'          			! SAE constants

*  Arguments Given:
      INTEGER			FID			! See above
      INTEGER			RMFID			!

*  Status:
      INTEGER                   STATUS                  ! Global status

*  Local Variables:
      CHARACTER*8		TTYPE(3)		! Column names
      CHARACTER*8		TFORM(3)		! Column types
      CHARACTER*3		TUNIT(3)		! Column units

      INTEGER			CBPTR			! Channel energies
      INTEGER			FSTAT			! FITSIO status
      INTEGER			I			! 
      INTEGER			LUN			! Logical unit
      INTEGER			NCHAN			! Number of channels
   
      LOGICAL			THERE			! Bounds specified?

*  Local data:
      DATA    			TUNIT/' ', ' ', ' '/
*.

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

*  Get number of channels
      CALL ADI_CGET0I( RMFID, 'NCHAN', NCHAN, STATUS )

*  Does the Channels member exist?
      CALL ADI_THERE( RMFID, 'Channels', THERE, STATUS )
      IF ( THERE ) THEN

*    Other mandatory keywords
        CALL ADI2_PKEY0I( FID, 'EBOUNDS', 'DETCHANS', NCHAN,
     :          'Total number of raw PHA channels', STATUS )

*    Get file's logical unit
        CALL ADI2_GETLUN( FID, LUN, STATUS )

*    Construct the field descriptions for the BINTABLE
        TTYPE(1) = 'CHANNEL'
        TFORM(1) = '1I'
        TTYPE(2) = 'E_MIN'
        TFORM(2) = '1E'
        TTYPE(3) = 'E_MAX'
        TFORM(3) = '1E'

*    Define the HDU data area
        CALL ADI2_DEFBTB( FID, 'EBOUNDS', NCHAN, 3, TTYPE, TFORM,
     :                    TUNIT, 0, STATUS )

*    Other mandatory keywords
        CALL ADI2_PKEY0I( FID, 'EBOUNDS', 'DETCHANS', NCHAN,
     :          'Total number of raw PHA channels', STATUS )

*    Write the channels column
        FSTAT = 0
        DO I = 1, NCHAN
          CALL FTPCLJ( LUN, 1, I, 1, 1, I, FSTAT )
        END DO

*  Map the channel bounds array
        CALL ADI_CMAPR( RMFID, 'Channels', 'READ', CBPTR, STATUS )

*  Write the bounds columns
        CALL FTPCLE( LUN, 2, 1, 1, NCHAN, %VAL(CBPTR), FSTAT )
        CALL FTPCLE( LUN, 3, 1, 1, NCHAN, %VAL(CBPTR+4), FSTAT )

*  End of Channels presence test 
      END IF
 
      END



      SUBROUTINE ERI1_WRITRMF_EB2C( RMFID, NE, ENLOC, STATUS )
      IMPLICIT NONE

*  Global Constants:
      INCLUDE 'SAE_PAR'          			! SAE constants
      INCLUDE 'DAT_PAR'

      INTEGER	RMFID
      CHARACTER*(DAT__SZLOC)	ENLOC
	INTEGER NE, STATUS, NMAP
      INTEGER	EBPTR, ESPTR

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

*  Map the energy bounds
      CALL ADI_CMAPR( RMFID, 'Energy', 'READ', EBPTR, STATUS )

*  Create and map the ENERGY_SPEC array 
      CALL DAT_NEW1R( ENLOC, 'ENERGY_SPEC', NE, STATUS )
      CALL CMP_MAPV( ENLOC, 'ENERGY_SPEC', '_REAL', 'WRITE', ESPTR, 
     :               NMAP, STATUS )

*  Convert bounds to centres
      CALL ERI1_WRITRMF_EB2C_INT( NE, %VAL(EBPTR), %VAL(ESPTR),
     :                            STATUS )

*  Release ADI and HDS objects
      CALL CMP_UNMAP( ENLOC, 'ENERGY_SPEC', STATUS )
      CALL ADI_CUNMAP( RMFID, 'Energy', EBPTR, STATUS )
      
*  Report any errors
      IF ( STATUS .NE. SAI__OK ) THEN
        CALL AST_REXIT( 'ERI1_WRITRMF_EB2C', STATUS )
      END IF

      END


      SUBROUTINE ERI1_WRITRMF_EB2C_INT( NE, BNDS, CEN, STATUS )
      IMPLICIT NONE

*  Global Constants:
      INCLUDE 'SAE_PAR'          			! SAE constants

	INTEGER NE, STATUS,I
      REAL	CEN(*),BNDS(*)

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

      DO I = 1, NE
        CEN(I) = (BNDS(I)+BNDS(I+1))/2.0
      END DO

      END


      SUBROUTINE ERI1_LOCRESP( ARGS, CREATE, ELOC, STATUS )
*+
*  Name:
*     ERI1_LOCRESP

*  Purpose:
*     Locate response structure, creating if specified

*  Language:
*     Starlink Fortran

*  Invocation:
*     CALL ERI1_LOCRESP( ARGS, CREATE, ELOC, STATUS )

*  Description:
*     This method writes simple format energy respones to a HDS file.
*     Such a response is simply a 2D array of values. It writes only 
*     that information which is contained within the RMFID passed as 
*     the second argument. Other data of interest must be written by 
*     surrounding methods which have access to the dataset to which 
*     this response is "attached". 
*
*     The response is written in one of two formats. If the input 
*     compression method is NONE, the the response is written as a simple 
*     2D array in a fixed size BINTABLE extension. If the method is ASTERIX
*     or OGIP_CMP then the response is written to a variable field size 
*     BINTABLE.

*  Arguments:
*     ARGS(*) = INTEGER (given)
*        ADI identifier of method arguments
*     CREATE = LOGICAL (given) 
*        Create response if it doesn't exist
*     ELOC = CHARACTER*(DAT__SZLOC) (returned) 
*        Energy response locator
*     STATUS = INTEGER (given and returned)
*        The global status.

*  Examples:
*     {routine_example_text}
*        {routine_example_description}

*  Pitfalls:
*     {pitfall_description}...

*  Notes:
*     {routine_notes}...

*  Prior Requirements:
*     {routine_prior_requirements}...

*  Side Effects:
*     {routine_side_effects}...

*  Algorithm:
*     {algorithm_description}...

*  Accuracy:
*     {routine_accuracy}

*  Timing:
*     {routine_timing}

*  Implementation Deficiencies:
*     {routine_deficiencies}...

*  References:
*     ERI Subroutine Guide : http://www.sr.bham.ac.uk/asterix-docs/Programmer/Guides/eri.html

*  Keywords:
*     package:eri, usage:private

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

*  Authors:
*     DJA: David J. Allan (Jet-X, University of Birmingham)
*     {enter_new_authors_here}

*  History:
*     28 Feb 1995 (DJA):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

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

*  Global Constants:
      INCLUDE 'SAE_PAR'          			! SAE constants
      INCLUDE 'DAT_PAR'					! ADI constants

*  Arguments Given:
      INTEGER                   ARGS(*)
      LOGICAL			CREATE

*  Arguments Returned:
      CHARACTER*(DAT__SZLOC)	ELOC

*  Status:
      INTEGER                   STATUS                  ! Global status

*  Local Variables:
      CHARACTER*(DAT__SZLOC)	ALOC			! File ASTERIX box
      CHARACTER*(DAT__SZLOC)	ECLOC			! Vector response
      CHARACTER*(DAT__SZLOC)	LOC			! File locator
      CHARACTER*(DAT__SZNAM)	NAME			! File object name

      INTEGER			IDX			! Response number
      INTEGER			NRESP			! # responses in file

      LOGICAL			THERE			! Response exists?
*.

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

*  Get the name of the HDS object. If it is not ENERGY_RESP, then we assume
*  we are in an NDF, so MORE.ASTERIX.ENERGY_RESP must be present
      CALL ADI1_GETLOC( ARGS(1), LOC, STATUS )
      CALL DAT_NAME( LOC, NAME, STATUS )
      IF ( NAME(1:11) .EQ. 'ENERGY_RESP' ) THEN
        CALL DAT_CLONE( LOC, ELOC, STATUS )
      ELSE

*    Locate ASTERIX box, creating if we're allowed to do so
        CALL ADI1_LOCAST( ARGS(1), CREATE, ALOC, STATUS )
        
*    Extract the response number
        CALL ADI_GET0I( ARGS(3), NRESP, STATUS )

*    Does ENERGY_RESP exist?
        CALL DAT_THERE( ALOC, 'ENERGY_RESP', THERE, STATUS )
        IF ( THERE ) THEN
          CALL DAT_FIND( ALOC, 'ENERGY_RESP', ELOC, STATUS )

*    Create if allowed to do so
        ELSE IF ( CREATE ) THEN

*      Create as vector if more than one response in file
          IF ( NRESP .GT. 1 ) THEN
            CALL DAT_NEW( ALOC, 'ENERGY_RESP', 'EXT', 1, NRESP, STATUS )
          ELSE
            CALL DAT_NEW( ALOC, 'ENERGY_RESP', 'EXT', 0, 0, STATUS )
          END IF
          CALL DAT_FIND( ALOC, 'ENERGY_RESP', ELOC, STATUS )

        END IF

*    Create as vector if more than one response in file
        IF ( NRESP .GT. 1 ) THEN

*      Get the number of the response we want
          CALL ADI_GET0I( ARGS(2), IDX, STATUS )
          ECLOC = ELOC
          CALL DAT_CELL( ECLOC, 1, IDX, ELOC, STATUS )
          CALL DAT_ANNUL( ECLOC, STATUS )
        END IF

      END IF

      END