SUBROUTINE ERI2_WRITRMF( NARG, ARGS, OARG, STATUS ) *+ * Name: * ERI2_WRITRMF * Purpose: * Write simple energy response to a FITS file * Language: * Starlink Fortran * Invocation: * CALL ERI2_WRITRMF( NARG, ARGS, OARG, STATUS ) * Description: * This method writes simple format energy respones to a FITS 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 INCLUDE 'PRM_PAR' * 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 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 INTEGER I,CRPTR * Local data; DATA TUNIT/'keV', 'keV', ' '/ *. * Check inherited global status. IF ( STATUS .NE. SAI__OK ) RETURN * Extract arguments FID = ARGS(1) RMFID = ARGS(2) * 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+VAL__NBR), FSTAT ) CALL ADI_CUNMAP( RMFID, 'Energy', EBPTR, STATUS ) * Map the matrix data CALL ADI_CMAPR( RMFID, 'RMF', 'READ', RPTR, STATUS ) * Simply write the data CRPTR = RPTR DO I = 1, NENER CALL FTPCLE( LUN, 3, I, 1, NCHAN, %VAL(CRPTR), STATUS ) CRPTR = CRPTR + NCHAN * VAL__NBR END DO * Release the matrix data CALL ADI_CUNMAP( RMFID, 'RMF', RPTR, STATUS ) * Report any errors IF ( STATUS .NE. SAI__OK ) THEN CALL AST_REXIT( 'ERI2_WRITRMF', STATUS ) END IF END SUBROUTINE ERI2_WRITRMF_OGIP( NARG, ARGS, OARG, STATUS ) *+ * Name: * ERI2_WRITRMF_OGIP * Purpose: * Write OGIP format energy response to a FITS file * Language: * Starlink Fortran * Invocation: * CALL ERI2_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 '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*8 TTYPE(6) ! Column names CHARACTER*8 TFORM(6) ! Column types CHARACTER*3 TUNIT(6) ! Column units INTEGER CPTR ! INTEGER DIMS(2) INTEGER EBPTR ! Energy bounds ptr INTEGER FID ! FITSfile object INTEGER FSTAT ! FITSIO status INTEGER LUN ! Logical unit INTEGER NCHAN ! # channel bins INTEGER NDIM ! Dimensionality 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) RMFID = ARGS(2) * 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 ) * 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' TFORM(4) = 'PI' TTYPE(5) = 'N_CHAN' TFORM(5) = 'PI' TTYPE(6) = 'MATRIX' TFORM(6) = 'PE' * Define the HDU data area CALL ADI2_DEFBTB( FID, 'MATRIX', NENER, 6, 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 and write the N_grp field CALL ADI_CMAPW( RMFID, 'N_grp', 'READ', CPTR, STATUS ) CALL FTPCLI( LUN, 3, 1, 1, NENER, %VAL(CPTR), FSTAT ) CALL ADI_CUNMAP( RMFID, 'N_grp', CPTR, STATUS ) * Map the matrix data CALL ADI_CSHAPE( RMFID, 'RMF', 2, DIMS, NDIM, STATUS ) CALL ADI_CMAPR( RMFID, 'RMF', 'READ', RPTR, STATUS ) CALL ADI_CUNMAP( RMFID, 'RMF', RPTR, STATUS ) * Report any errors IF ( STATUS .NE. SAI__OK ) THEN CALL AST_REXIT( 'ERI2_WRITRMF_OGIP', STATUS ) END IF END SUBROUTINE ERI2_WRITRMF_AST( NARG, ARGS, OARG, STATUS ) *+ * Name: * ERI2_WRITRMF_AST * Purpose: * Write ASTERIX type energy response to a FITS file * Language: * Starlink Fortran * Invocation: * CALL ERI2_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". * * 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. * 14 Aug 1995 (DJA): * Divide ASTERIX response by geometrical area if available. * {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 * Local Variables: REAL AREA ! Geometrical area INTEGER CIPTR ! Channel indices INTEGER EBPTR ! Energy bounds ptr INTEGER EIPTR ! Energy indices INTEGER FID ! FITSfile object INTEGER NCHAN ! # channel bins INTEGER NENER ! # energy bins INTEGER NRMF ! # response elements INTEGER RMFID ! Response object INTEGER RPTR ! Mapped RMF INTEGER WPTR1, WPTR2 ! *. * Check inherited global status. IF ( STATUS .NE. SAI__OK ) RETURN * Extract arguments FID = ARGS(1) RMFID = ARGS(2) * Get size of conceptual RMF CALL ADI_CGET0I( RMFID, 'NCHAN', NCHAN, STATUS ) CALL ADI_CGET0I( RMFID, 'NENERGY', NENER, STATUS ) * Get size of matrix CALL ADI_CSIZE( RMFID, 'RMF', NRMF, STATUS ) * Write the energy boundaries into the table CALL ADI_CMAPR( RMFID, 'Energy', 'READ', EBPTR, STATUS ) * Map the matrix data CALL ADI_CMAPR( RMFID, 'RMF', 'READ', RPTR, STATUS ) * Map the energy and channel index arrays CALL ADI_CMAPI( RMFID, 'ChannelIndices', 'READ', CIPTR, STATUS ) CALL ADI_CMAPI( RMFID, 'EnergyIndices', 'READ', EIPTR, STATUS ) * Map some workspace CALL DYN_MAPI( 1, NENER*2, WPTR1, STATUS ) CALL DYN_MAPI( 1, NRMF*2, WPTR2, STATUS ) * Get geometrical area CALL ADI_CGET0R( RMFID, 'GeometricalArea', AREA, STATUS ) IF ( STATUS .NE. SAI__OK ) THEN CALL ERR_ANNUL( STATUS ) AREA = 1.0 END IF * Write the variable length fields CALL ERI2_WRITRMF_AST1( FID, NENER, NCHAN, NRMF, %VAL(EBPTR), : %VAL(CIPTR), %VAL(EIPTR), %VAL(RPTR), : AREA, %VAL(WPTR1), %VAL(WPTR2), STATUS ) * Release workspace CALL DYN_UNMAP( WPTR1, STATUS ) CALL DYN_UNMAP( WPTR2, STATUS ) * Release index arrays CALL ADI_CUNMAP( RMFID, 'ChannelIndices', CIPTR, STATUS ) CALL ADI_CUNMAP( RMFID, 'EnergyIndices', EIPTR, STATUS ) * Release the matrix data CALL ADI_CUNMAP( RMFID, 'Energy', EBPTR, STATUS ) CALL ADI_CUNMAP( RMFID, 'RMF', RPTR, STATUS ) * Write channel energy bounds extension CALL ERI2_WRITRMF_CEBND( FID, RMFID, STATUS ) * Report any errors IF ( STATUS .NE. SAI__OK ) THEN CALL AST_REXIT( 'ERI2_WRITRMF_AST', STATUS ) END IF END SUBROUTINE ERI2_WRITRMF_AST1( FID, NE, NCH, NRMF, EBND, CI, : EI, RSP, AREA, WRK1, WRK2, STATUS ) *+ * Name: * ERI2_WRITRMF_AST1 * Purpose: * Write ASTERIX energy response elements to a FITS file * Language: * Starlink Fortran * Invocation: * CALL ERI2_WRITRMF_AST1( FID, NE, NCH, NRMF, EBND, CI, EI, * RSP, AREA, 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 * AREA = REAL (given) * Geometrical area in cm**2 * 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, NE, NCH, NRMF, CI(*), EI(*) REAL EBND(*),AREA,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 NRPTR ! Workspace 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 * NE 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 * NE 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 * Workspace for normalised response CALL DYN_MAPR( 1, MAX_SMAT, NRPTR, STATUS ) * Define the HDU data area CALL ADI2_DEFBTB( FID, 'MATRIX', NE, 6, TTYPE, TFORM, : TUNIT, ACTHEAP, STATUS ) * Other mandatory keywords CALL ADI2_PKEY0I( FID, 'MATRIX', 'DETCHANS', NCH, : 'Total number of raw PHA channels', STATUS ) CALL ADI2_PKEY0C( FID, 'MATRIX', 'CHANTYPE', 'PHA', : 'Channels assigned by detector electronics', STATUS ) CALL ADI2_PKEY0C( FID, 'MATRIX', 'RMFVERSN', '1992a', : 'OGIP classification of FITS format style', STATUS ) * Write keywords for response extension CALL ADI2_POGIPK( FID, 'MATRIX', 'RESPONSE', '1.0.0', : 'RSP_MATRIX', '1.1.0', 'FULL', ' ', STATUS ) * Write energy lower and upper bounds CALL FTPCLE( LUN, 1, 1, 1, NE, EBND(1), FSTAT ) CALL FTPCLE( LUN, 2, 1, 1, NE, EBND(2), FSTAT ) * The N_GRP field CALL FTPCLJ( LUN, 3, 1, 1, NE, WRK1(1,1), FSTAT ) * Write the table data R = 1 CS = 1 DO E = 1, NE * 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 ( CS .LE. NS ) THEN IF ( CS .EQ. NS ) THEN LASTR = NRMF ELSE LASTR = WRK1(E+1,2) - 1 END IF * Copy response values and normalise CALL ARR_COP1R( LASTR - R + 1, RSP(R), %VAL(NRPTR), STATUS ) CALL ARR_MULT1R( LASTR - R + 1, %VAL(NRPTR), 1.0/AREA, : %VAL(NRPTR), STATUS ) CALL FTPCLE( LUN, 6, E, 1, LASTR - R + 1, %VAL(NRPTR), : 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 ) * Free workspace CALL DYN_UNMAP( NRPTR, STATUS ) END SUBROUTINE ERI2_WRITRMF_CEBND( FID, RMFID, STATUS ) *+ * Name: * ERI2_WRITRMF_CEBND * Purpose: * Write channel energy bounds to EBOUNDS extension * Language: * Starlink Fortran * Invocation: * CALL ERI2_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 ) CALL ADI2_PKEY0C( FID, 'EBOUNDS', 'RMFVERSN', '1992a', : 'OGIP classification of FITS format style', 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