SUBROUTINE ERI0_REBIN_AST( NARG, ARGS, OARG, STATUS ) *+ * Name: * ERI0_REBIN_AST * Purpose: * Rebin an AsterixRMF using channel bounds or grouping * Language: * Starlink Fortran * Invocation: * CALL ERI0_REBIN_AST( NARG, ARGS, OARG, STATUS ) * Description: * {routine_description} * 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: * {name_of_facility_or_package}: * {routine_used}... * 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, rebinning, response * Copyright: * Copyright (C) University of Birmingham, 1995 * Authors: * DJA: David J. Allan (Jet-X, University of Birmingham) * {enter_new_authors_here} * History: * 7 Apr 1995 (DJA): * Original version. * 28 Mar 1996 (DJA): * Added rebinning by bounds * {enter_changes_here} * Bugs: * {note_any_bugs_here} *- * Type Definitions: IMPLICIT NONE ! No implicit typing * Global Constants: INCLUDE 'SAE_PAR' ! Standard SAE constants * Arguments Given: INTEGER NARG, ARGS(*) * Arguments Returned: INTEGER OARG * Status: INTEGER STATUS ! Global status * Local Variables: REAL CBND ! Channel bound value REAL CSPEC ! Channel spec value INTEGER BNDPTR ! Bounds array INTEGER EPTR ! Energy bounds ptr INTEGER I,J ! Loop variables INTEGER ICBPTR ! i/p channel bounds INTEGER ICIPTR ! i/p channel indices INTEGER ICSPTR ! i/p channel specs INTEGER IEIPTR ! i/p energy indices INTEGER IGRP ! Grouping factor INTEGER IRPTR ! i/p response data INTEGER LOCCH, HICCH ! Elements of below INTEGER MINCCH, MAXCCH ! Min/max contrib chans INTEGER NBND ! # channel bounds INTEGER NCHAN ! # i/p channel bins INTEGER NENER ! # energy bins INTEGER NRMF ! # i/p response els INTEGER RMFID ! Input RMF INTEGER OCIPTR ! o/p channel indices INTEGER OCBPTR ! o/p channel bounds INTEGER OCSPTR ! o/p channel specs INTEGER OEIPTR ! o/p energy indices INTEGER ONCHAN ! # o/p channel bins INTEGER ONRMF ! # o/p response els INTEGER ORPTR ! o/p response data LOGICAL GROUP ! Rebin by grouping? *. * Check inherited global status. IF ( STATUS .NE. SAI__OK ) RETURN * Get input args RMFID = ARGS(1) GROUP = (NARG.EQ.2) IF ( GROUP ) THEN CALL ADI_GET0I( ARGS(2), IGRP, STATUS ) ELSE CALL ADI_GET0I( ARGS(2), NBND, STATUS ) CALL ADI_MAPR( ARGS(3), 'READ', BNDPTR, STATUS ) END IF * Create output CALL ADI_NEW0( 'AsterixRMF', OARG, STATUS ) * Copy energy stuff which is unchanged CALL ADI_CGET0I( RMFID, 'NENERGY', NENER, STATUS ) CALL ADI_CPUT0I( OARG, 'NENERGY', NENER, STATUS ) CALL ADI_CMAPR( RMFID, 'Energy', 'READ', EPTR, STATUS ) CALL ADI_CNEWV1R( OARG, 'Energy', NENER+1, %VAL(EPTR), STATUS ) * Get old number of channel bins and calculate new CALL ADI_CGET0I( RMFID, 'NCHAN', NCHAN, STATUS ) IF ( GROUP ) THEN ONCHAN = (NCHAN-1) / IGRP + 1 ELSE ONCHAN = NBND - 1 END IF CALL ADI_CPUT0I( OARG, 'NCHAN', ONCHAN, STATUS ) * Create output channel structures CALL ADI_CNEW1R( OARG, 'Channels', ONCHAN + 1, STATUS ) CALL ADI_CNEW1R( OARG, 'ChannelSpec', ONCHAN, STATUS ) * Map response data CALL ADI_CSIZE( RMFID, 'RMF', NRMF, STATUS ) CALL ADI_CMAPR( RMFID, 'RMF', 'READ', IRPTR, STATUS ) * Map old energy and channel indices, and the channel bounds CALL ADI_CMAPI( RMFID, 'EnergyIndices', 'READ', IEIPTR, STATUS ) CALL ADI_CMAPI( RMFID, 'ChannelIndices', 'READ', ICIPTR, STATUS ) CALL ADI_CMAPR( RMFID, 'ChannelSpec', 'READ', ICSPTR, STATUS ) * Workspace to store min & max contributing input channel numbers CALL DYN_MAPI( 1, NCHAN+1, MINCCH, STATUS ) CALL DYN_MAPI( 1, NCHAN+1, MAXCCH, STATUS ) CALL ARR_INIT1I( NCHAN+1, NCHAN+1, %VAL(MINCCH), STATUS ) CALL ARR_INIT1I( 0, NCHAN+1, %VAL(MAXCCH), STATUS ) * Calculate number of new response elements CALL ERI0_REBIN_AST1( NRMF, %VAL(IEIPTR), %VAL(ICIPTR), : %VAL(ICSPTR), GROUP, IGRP, NBND, : %VAL(BNDPTR), ONRMF, : %VAL(MINCCH), %VAL(MAXCCH), STATUS ) * Define sizes of output arrays, and map them CALL ADI_CNEW1I( OARG, 'ChannelIndices', ONRMF, STATUS ) CALL ADI_CNEW1I( OARG, 'EnergyIndices', ONRMF, STATUS ) CALL ADI_CNEW1R( OARG, 'RMF', ONRMF, STATUS ) CALL ADI_CMAPI( OARG, 'ChannelIndices', 'WRITE', OCIPTR, STATUS ) CALL ADI_CMAPI( OARG, 'EnergyIndices', 'WRITE', OEIPTR, STATUS ) CALL ADI_CMAPR( OARG, 'RMF', 'WRITE', ORPTR, STATUS ) * Find new response values and indices CALL ERI0_REBIN_AST2( NRMF, %VAL(IRPTR), %VAL(IEIPTR), : %VAL(ICIPTR), %VAL(ICSPTR), GROUP, : IGRP, NBND, %VAL(BNDPTR), ONRMF, : %VAL(ORPTR), %VAL(OEIPTR), %VAL(OCIPTR), : STATUS ) * Pick the output channel spec values CALL ADI_CMAPR( RMFID, 'Channels', 'READ', ICBPTR, STATUS ) CALL ADI_CMAPR( OARG, 'Channels', 'WRITE', OCBPTR, STATUS ) CALL ADI_CMAPR( OARG, 'ChannelSpec', 'WRITE', OCSPTR, STATUS ) J = 1 IF ( GROUP ) THEN J = 1 DO I = 1, ONCHAN+1 IF ( I .LE. ONCHAN ) THEN CALL ARR_ELEM1R( ICSPTR, NCHAN+1, J, CSPEC, STATUS ) CALL ARR_SELEM1R( OCSPTR, ONCHAN+1, I, CSPEC, STATUS ) END IF CALL ARR_ELEM1R( ICBPTR, NCHAN+1, J, CBND, STATUS ) CALL ARR_SELEM1R( OCBPTR, ONCHAN+1, I, CBND, STATUS ) J = MIN( NCHAN+1, J + IGRP ) END DO ELSE CALL ERI0_REBIN_B2C( ONCHAN, %VAL(BNDPTR), %VAL(OCSPTR), : STATUS ) CALL ARR_ELEM1I( MINCCH, NCHAN+1, 1, LOCCH, STATUS ) CALL ARR_ELEM1R( ICBPTR, NCHAN+1, LOCCH, CSPEC, STATUS ) CALL ARR_SELEM1R( OCBPTR, ONCHAN+1, 1, CSPEC, STATUS ) DO I = 1, ONCHAN CALL ARR_ELEM1I( MAXCCH, NCHAN+1, I, HICCH, STATUS ) CALL ARR_ELEM1R( ICBPTR, NCHAN+1, HICCH, CSPEC, STATUS ) CALL ARR_SELEM1R( OCBPTR, ONCHAN+1, I+1, CSPEC, STATUS ) END DO END IF CALL ADI_CUNMAP( RMFID, 'ChannelSpec', ICSPTR, STATUS ) CALL ADI_CUNMAP( OARG, 'ChannelSpec', OCSPTR, STATUS ) CALL ADI_CUNMAP( RMFID, 'Channels', ICBPTR, STATUS ) CALL ADI_CUNMAP( OARG, 'Channels', OCBPTR, STATUS ) * Free output response length arrays CALL ADI_CUNMAP( OARG, 'ChannelIndices', OCIPTR, STATUS ) CALL ADI_CUNMAP( OARG, 'EnergyIndices', OEIPTR, STATUS ) CALL ADI_CUNMAP( OARG, 'RMF', ORPTR, STATUS ) * Free input arrays CALL ADI_CUNMAP( RMFID, 'ChannelIndices', ICIPTR, STATUS ) CALL ADI_CUNMAP( RMFID, 'EnergyIndices', IEIPTR, STATUS ) CALL ADI_CUNMAP( RMFID, 'RMF', IRPTR, STATUS ) * Free workspace CALL DYN_UNMAP( MINCCH, STATUS ) CALL DYN_UNMAP( MAXCCH, STATUS ) * Free mapped bounds IF ( .NOT. GROUP ) THEN CALL ADI_UNMAP( ARGS(3), BNDPTR, STATUS ) END IF * Report any errors IF ( STATUS .NE. SAI__OK ) CALL AST_REXIT( 'ERI0_REBIN_AST', : STATUS ) END *+ ERI0_REBIN_AST1 - Finds number of output response elements SUBROUTINE ERI0_REBIN_AST1( N, EI, CI, CSPEC, GROUP, IGRP, NBND, : BNDS, ON, MINCCH, MAXCCH, STATUS ) * Description: * Loop over response elements finding new channel index. Merge * together response elements with identical indices. * IMPLICIT NONE INTEGER N, EI(*), CI(*), ON, STATUS, IGRP, NBND REAL CSPEC(*), BNDS(*) INTEGER MINCCH(*), MAXCCH(*) LOGICAL GROUP INTEGER ERI0_REBIN_NCI INTEGER LAST_E,LAST_NCI,I,NCI IF ( STATUS .EQ. 0 ) THEN * Loop LAST_E = -1 LAST_NCI = -1 ON = 0 DO I = 1, N * Find new channel index NCI = ERI0_REBIN_NCI( GROUP, IGRP, NBND, BNDS, CSPEC, CI(I) ) IF ( NCI .GT. 0 ) THEN IF ( (EI(I) .NE. LAST_E) .OR. (NCI.NE.LAST_NCI) ) THEN ON = ON + 1 END IF LAST_E = EI(I) LAST_NCI = NCI MAXCCH(NCI) = MAX( MAXCCH(NCI), CI(I) ) MINCCH(NCI) = MIN( MINCCH(NCI), CI(I) ) END IF END DO END IF END SUBROUTINE ERI0_REBIN_AST2( IN, IR, IEI, ICI, CSPEC, GROUP, : IGRP, NBND, BNDS, ON, : OR, OEI, OCI, STATUS ) IMPLICIT NONE INTEGER IN, IEI(*), ICI(*), ON, OEI(*), OCI(*), STATUS, igrp INTEGER NBND REAL CSPEC(*), BNDS(*) LOGICAL GROUP REAL IR(*), OR(*) INTEGER ERI0_REBIN_NCI INTEGER LAST_E,LAST_NCI,I,NCI IF ( STATUS .EQ. 0 ) THEN LAST_E = -1 LAST_NCI = -1 ON = 0 DO I = 1, IN * Find new channel index NCI = ERI0_REBIN_NCI( GROUP, IGRP, NBND, BNDS, CSPEC, : ICI(I) ) IF ( NCI .GT. 0 ) THEN IF ( (IEI(I) .NE. LAST_E) .OR. (NCI.NE.LAST_NCI) ) THEN ON = ON + 1 OR(ON) = IR(I) OEI(ON) = IEI(I) OCI(ON) = NCI ELSE OR(ON) = OR(ON) + IR(I) END IF LAST_E = IEI(I) LAST_NCI = NCI END IF END DO END IF END * Find new channel index given old one INTEGERFUNCTION ERI0_REBIN_NCI( GROUP, IGRP, NBND, BNDS, : CSPEC, OLDIND ) IMPLICIT NONE LOGICAL GROUP INTEGER IGRP, NBND, OLDIND REAL BNDS(*), CSPEC(*) INTEGER NCI,IBND REAL CHAN * Find new channel index IF ( GROUP ) THEN NCI = (OLDIND-1)/IGRP + 1 ELSE * Bounds in range? CHAN = CSPEC(OLDIND) NCI = 0 IF ( (CHAN .GE. BNDS(1)) .AND. : (CHAN .LE. BNDS(NBND)) ) THEN IBND = 2 DO WHILE ( (IBND .LE. NBND) .AND. (NCI.EQ.0) ) IF ( CHAN .LE. BNDS(IBND) ) THEN NCI = IBND - 1 ELSE IBND = IBND + 1 END IF END DO END IF END IF ERI0_REBIN_NCI = NCI END SUBROUTINE ERI0_REBIN_B2C( N, BNDS, CEN, STATUS ) INTEGER N,STATUS,I REAL BNDS(*), CEN(*) DO I = 1, N CEN(I) = (BNDS(I+1) + BNDS(I))/2.0 END DO END