SUBROUTINE SGRID( STATUS ) *+ * Name: * SGRID * Purpose: * Spectral gridding program * Language: * Starlink Fortran * Type of Module: * ASTERIX task * Invocation: * CALL SGRID( STATUS ) * Arguments: * STATUS = INTEGER (Given and Returned) * The global status. * Description: * Select one or more parameters in a multicomponent model over which * grid or grid(s) of fit statistic/reoptimised parameters will be * constructed. * * Those parameters chosen as the grid axes are automatically unfrozen. * * Adjusts parameters in a to achieve minimum * chi-squared or maximum likelihood fit to one or more datasets. * Only a single input dataset can be entered - if multiple datasets are * to be fitted a file containing references to them must be first set up * using SDATA. * Usage: * sgrid {parameter_usage} * Environment Parameters: * LIK = LOGICAL (read) * Likelihood fit (else chi-squared) * INP = CHAR (read) * Input data (either a single dataset or a file of references). * Z = REAL (read) * Redshift of spectrum * FIT_MOD = CHAR (read) * Data object containing model specification * MAX = INTEGER (read) * Max number of iterations to be performed * MINS = REAL (read) * Minimum `reduced statistic' slope forcing continued iteration * PARS = INTEGER (read) * List of parameters for grid axes * OPT = LOGICAL (read) * Mode for specifying grid spacing * ERR = LOGICAL (read) * Take AXISn defaults from parameter errors? * AXIS1..7 = CHAR (read) * Parameter range to grid * LOG1..7 = LOGICAL (read) * Log spacing for this axis * GPARS = INTEGER (read) * Values to be gridded * SUBSTAT = LOGICAL (read) * Subtract minimum value of statistic from grid * UP = LOGICAL (read) * Update model with best fit in the grid? * OUTROOT = CHAR (read) * Root of output filenames in AUTO mode * OUT = CHAR (read) * Name of output file in non-AUTO mode, where NGRID=1 * OUT2..5 = CHAR (read) * Output file names for extra grids * 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 Status: * {routine_implementation_status} * External Routines Used: * {name_of_facility_or_package}: * {routine_used}... * Implementation Deficiencies: * {routine_deficiencies}... * References: * {task_references}... * Keywords: * sgrid, usage:public * Copyright: * Copyright (C) University of Birmingham, 1995 * Authors: * DJA: David J. Allan (Jet-X, University of Birmingham) * {enter_new_authors_here} * History: * 9 Nov 1992 V1.7-0 (DJA): * Original, derived from SFIT * 3 Dec 1992 V1.7-1 (DJA): * Corrected calculation of SSCALE in chi-squared fitting * 4 Jan 1993 V1.7-2 (DJA): * Updated quality handling * 1 Apr 1993 V1.7-3 (DJA): * Add minimum statistic to history * 7 Apr 1993 V1.7-4 (DJA): * Removed limits on size of axes * 8 Sep 1993 V1.7-5 (DJA): * Change in behaviour in AUTO mode to handle parameter * system funnies. Added SPEC_INIT call * 28 Feb 1994 V1.7-6 (DJA): * Use BIT_ routines to do bit manipulations * 7 Sep 1994 V1.8-0 (DJA): * Added fit probability option * 24 Nov 1994 V1.8-1 (DJA): * Now use USI for user interface * 1 Dec 1995 V2.0-0 (DJA): * ADI port * 17 Apr 1996 V2.0-1 (DJA): * Use new minimisation control * {enter_changes_here} * Bugs: * {note_any_bugs_here} *- * Type Definitions: IMPLICIT NONE ! No implicit typing * Global Constants: INCLUDE 'SAE_PAR' ! Standard SAE constants INCLUDE 'ADI_PAR' INCLUDE 'FIT_PAR' * Structure Definitions: INCLUDE 'FIT_STRUC' * Status: INTEGER STATUS ! Global status * External References: EXTERNAL CHR_LEN INTEGER CHR_LEN EXTERNAL FIT_PREDDAT * Local Constants: INTEGER MXGRID ! Max # grids PARAMETER ( MXGRID = 5 ) INTEGER OPCHAN ! Output channel for FIT_GRID PARAMETER ( OPCHAN = 6 ) INTEGER PROB_REPLY PARAMETER ( PROB_REPLY = 99 ) CHARACTER*30 VERSION PARAMETER ( VERSION = 'SGRID Version V2.0-1' ) * Local Variables: RECORD /GRID_AXIS/ GAX(ADI__MXDIM) ! Grid axes RECORD /INSTR_RESP/ INSTR(NDSMAX) ! Instrument responses RECORD /MODEL_SPEC/ MODEL ! Model specification RECORD /DATASET/ OBDAT(NDSMAX) ! Observed datasets RECORD /PREDICTION/ PREDDAT(NDSMAX) ! Data predicted by model CHARACTER*132 HBUF(7) ! History buffer CHARACTER*40 LABEL ! Grid label CHARACTER*1 PC ! Parameter code CHARACTER*80 ROOT, OUTFN ! Output grid file names CHARACTER*80 TEXT ! Various o/p text DOUBLE PRECISION STATMIN ! Fit statistic REAL BASE, SCALE ! Grid axis values REAL LB(NPAMAX) ! Parameter lower bounds REAL LE(NPAMAX) ! Parameter lower errors REAL ALO, AHI ! Grid axis bounds REAL PARAM(NPAMAX) ! Model parameters REAL RANGE(2) ! User supplied axis range REAL UB(NPAMAX) ! Parameter upper bounds REAL UE(NPAMAX) ! Parameter upper errors REAL Z ! Redshift [ Eobs/Esource=1/(1+z) ] INTEGER BDID ! New BinDS object INTEGER FSTAT ! Fit statistic flag (1=chisq, 2=l'hood) INTEGER GDPTR(MXGRID) ! Grid data pointer INTEGER GDIMS(ADI__MXDIM) ! Grid dimensions INTEGER GFID(MXGRID) ! Fit grid datasets INTEGER GNELM ! # grid elements INTEGER GPARS(MXGRID) ! Things to be gridded INTEGER GPS(ADI__MXDIM) ! Grid parameters INTEGER GQPTR ! Grid quality pointer INTEGER I, J ! Loop variables INTEGER IFID ! Input dataset id INTEGER MCTRL ! Minimisation control INTEGER MFID ! Model spec dataset id INTEGER NDOF ! d.o.f. - no of data values ! - no of unfrozen params INTEGER NDS ! No of datasets INTEGER NGOOD ! # good data elements INTEGER NGRIDAX ! # grid axes INTEGER NGRID ! # grids INTEGER NHBUF ! # lines used in HBUF INTEGER NRANGE ! # range values entered INTEGER NPAR ! No of parameters INTEGER PCOMP(NPAMAX) ! Model par nos. INTEGER PPAR(NPAMAX) ! Model comp nos. INTEGER OPTION ! Grid definition options INTEGER SSCALE ! Factor for scaling fitstat INTEGER TLEN ! Used length of TEXT BYTE GQMASK ! Grid quality mask LOGICAL ANYBAD ! Any bad grid points? LOGICAL ANYBADISH ! Any bad(ish) grid points? LOGICAL AUTO ! Automatic o/p file naming? LOGICAL CHISTAT ! Fitstat is chi-squared? LOGICAL ERR ! Take AXISn defaults from ! parameter errors? LOGICAL FROZEN(NPAMAX) ! Frozen parameter flag LOGICAL LIKSTAT ! Fitstat is Cash likelihood statistic? LOGICAL LOGARITHMIC ! Logarithmic grid axis? LOGICAL OPTIMISING ! Using FIT_MIN in FIT_GRID? LOGICAL PFLAG(NPAMAX) ! Parameter in use flags LOGICAL SUBSTAT ! Subtract minimum statistic? LOGICAL UP ! Update model after grid LOGICAL WORKSPACE ! Set up workspace for STAT gradients? *. * Check inherited global status. IF ( STATUS .NE. SAI__OK ) RETURN * Version id CALL MSG_PRNT( VERSION ) * Set up genus in MODEL structure MODEL.GENUS = 'SPEC' * Initialise ASTERIX CALL AST_INIT() CALL SPEC_INIT( STATUS ) * Chi-squared or likelihood fitting? CALL USI_GET0L( 'LIK', LIKSTAT, STATUS ) CHISTAT=.NOT.LIKSTAT IF ( LIKSTAT ) THEN FSTAT = FIT__LOGL ELSE FSTAT = FIT__CHISQ END IF * Get observed data (setting up data weights) and response CALL USI_ASSOC( 'INP', 'FileSet|BinDS', 'READ', IFID, STATUS ) WORKSPACE = .TRUE. CALL FIT_GETDAT( ADI__NULLID, IFID, 'SPEC', FSTAT, WORKSPACE, : CHISTAT, NDS, : OBDAT, NGOOD, SSCALE, PREDDAT, INSTR, STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 * Look for redshift CALL SFIT_GETZ( Z, STATUS ) * Apply red-shift and check data structures CALL SFIT_PRECHK( NDS, Z, PREDDAT, STATUS ) * Get model specification CALL USI_ASSOC( 'MODEL', '*', 'UPDATE', MFID, STATUS ) CALL FIT_MODGET( MFID, MODEL, NPAR, PARAM, LB, UB, LE, UE, : FROZEN, STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 * Number of degrees of freedom for chi-squared IF ( CHISTAT ) THEN CALL FIT1_NDOF( NGOOD, MODEL, FROZEN, NDOF, STATUS ) SSCALE = NDOF END IF * Allocate space for model stack CALL SFIT_MAPMODSTK( NDS, PREDDAT, MODEL.STACKPTR, STATUS ) * List parameters CALL SEDIT_LISTPAR( MFID, NPAR, PCOMP, PPAR, 6, STATUS ) * Select parameters for grid axes CALL PRS_GETLIST( 'PARS', ADI__MXDIM, GPS, NGRIDAX, STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 * Check free parameters IF ( (NDOF+NGRIDAX) .LT. 0 ) THEN STATUS = SAI__ERROR CALL ERR_REP( ' ','More free parameters than data values!', : STATUS ) GOTO 99 END IF * Get AXISn defaults from errors CALL USI_GET0L( 'ERR', ERR, STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 * Option for choosing binning characteristics CALL USI_GET0I( 'OPT', OPTION, STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 IF ( (OPTION .LT. 1) .OR. (OPTION.GT.3) ) THEN STATUS = SAI__ERROR CALL ERR_REP( ' ', 'OPT must lie between 1 and 3', STATUS ) ELSE IF ( OPTION .EQ. 1 ) THEN CALL MSG_PRNT( 'All axes will be linearly spaced' ) ELSE IF ( OPTION .EQ. 2 ) THEN CALL MSG_PRNT( 'All axes will be spaced linearly in '/ : /'log(parameter) value' ) END IF * Check each grid axis DO I = 1, NGRIDAX * Construct parameter code WRITE( PC, '(I1.1)' ) I * Is this a valid fit parameter number IF ( (GPS(I).LT.1) .OR. (GPS(I).GT.NPAR) ) THEN STATUS = SAI__ERROR CALL MSG_SETI( 'P', GPS(I) ) CALL ERR_REP( ' ', 'Invalid parameter number /^P/', STATUS ) GOTO 99 END IF * Already selected as a grid axis? DO J = 1, I-1 IF ( GAX(J).PAR .EQ. GPS(I) ) THEN CALL MSG_SETI( 'AX', J ) CALL MSG_PRNT( '! WARNING : Already using this '/ : /'parameter in grid axis ^AX' ) END IF END DO * Define default for parameter range IF ( ERR ) THEN CALL MSG_SETR( 'LO', PARAM(GPS(I))-LE(GPS(I)) ) CALL MSG_SETR( 'HI', PARAM(GPS(I))+UE(GPS(I)) ) ELSE CALL MSG_SETR( 'LO', LB(GPS(I)) ) CALL MSG_SETR( 'HI', UB(GPS(I)) ) END IF CALL MSG_MAKE( '^LO:^HI', TEXT, TLEN ) CALL USI_DEF0C( 'AXIS'//PC, TEXT(:TLEN), STATUS ) * Remind user of units IF ( MODEL.UNITS(GPS(I)) .GT. ' ' ) THEN CALL MSG_SETC( 'PAR', MODEL.PARNAME(GPS(I)) ) CALL MSG_SETC( 'UNIT', MODEL.UNITS(GPS(I)) ) CALL MSG_PRNT( 'Enter ^PAR values in units of ^UNIT' ) END IF * Get parameter range CALL PRS_GETRANGES( 'AXIS'//PC, 2, 1, LB(GPS(I)), UB(GPS(I)), : RANGE, NRANGE, STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 * Get # grid values CALL USI_GET0I( 'NBIN'//PC, GDIMS(I), STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 IF ( GDIMS(I) .LT. 1 ) THEN STATUS = SAI__ERROR CALL ERR_REP( ' ', 'Number of bins must be 1 or greater', : STATUS ) GOTO 99 END IF * Regular or logarithmic IF ( OPTION .EQ. 1 ) THEN LOGARITHMIC = .FALSE. ELSE IF ( OPTION .EQ. 2 ) THEN LOGARITHMIC = .TRUE. ELSE CALL USI_GET0L( 'LOG'//PC, LOGARITHMIC, STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 END IF * Extract extrema of range supplied ALO = RANGE(1) AHI = RANGE(2) * Check within bounds IF ( ALO .LT. LB(GPS(I)) ) THEN ALO = LB(GPS(I)) CALL MSG_PRNT( 'Lower limit adjusted to parameter'/ : /' lower bound' ) END IF IF ( AHI .GT. UB(GPS(I)) ) THEN AHI = UB(GPS(I)) CALL MSG_PRNT( 'Upper limit adjusted to parameter'/ : /' upper bound' ) END IF * Check log axis is sensible IF ( LOGARITHMIC ) THEN IF ( (ALO.LE.0.0) .OR. (AHI.LE.0.0) ) THEN CALL MSG_PRNT( 'Cannot have logarithmic axis containing '/ : /'zero or negative values' ) END IF END IF * Calculate base and scale IF ( LOGARITHMIC ) THEN SCALE = (LOG10(AHI)-LOG10(ALO))/GDIMS(I) BASE = LOG10(ALO)+SCALE/2.0 ELSE SCALE = (AHI-ALO)/GDIMS(I) BASE = ALO + SCALE/2.0 END IF * Define the grid axis CALL FIT_DEFREGRID( GPS(I), GDIMS(I), LOGARITHMIC, BASE, : SCALE, GAX(I), STATUS ) * Adjust SSCALE IF ( CHISTAT ) SSCALE = SSCALE + 1 END DO IF ( STATUS .NE. SAI__OK ) GOTO 99 * Total number of grid elements CALL ARR_SUMDIM( NGRIDAX, GDIMS, GNELM ) * Are any parameters left to be optimised? DO I = 1, NPAR PFLAG(I) = (.NOT.FROZEN(I)) END DO DO I = 1, NGRIDAX PFLAG(GAX(I).PAR) = .FALSE. END DO OPTIMISING = .FALSE. DO I = 1, NPAR OPTIMISING = (OPTIMISING.OR.PFLAG(I)) END DO * Get things to be gridded CALL USI_GET1I( 'GPARS', MXGRID, GPARS, NGRID, STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 * Check valid IF ( NGRID .GT. 0 ) THEN DO I = 1, NGRID IF ( ((GPARS(I) .LT. 0) .OR. (GPARS(I).GT.NPAR)) .AND. : (GPARS(I).NE.PROB_REPLY) ) THEN STATUS = SAI__ERROR CALL MSG_SETI( 'ITEM', GPARS(I) ) CALL ERR_REP( ' ', 'Invalid grid item, ^ITEM', STATUS ) GOTO 99 END IF END DO ELSE STATUS = SAI__ERROR CALL ERR_REP( ' ', 'Must grid at least one value', STATUS ) END IF * Automatic naming or ask for each one? IF ( NGRID .GT. 1 ) THEN CALL USI_GET0L( 'AUTO', AUTO, STATUS ) IF ( AUTO ) THEN CALL USI_GET0C( 'OUTROOT', ROOT, STATUS ) END IF END IF IF ( STATUS .NE. SAI__OK ) GOTO 99 * Open grid data files DO I = 1, NGRID * Create interface object CALL BDI_NEW( 'BinDS', NGRIDAX, GDIMS, 'REAL', BDID, STATUS ) * First input in automatic mode, or sole output in non-automatic * Automatic file naming? IF ( AUTO ) THEN * Create file name WRITE( OUTFN, '(2A,I2.2)' ) ROOT(:CHR_LEN(ROOT)),'_g', : GPARS(I) * Open the file CALL ADI_FCREAT( OUTFN, BDID, GFID(I), STATUS ) * Manual file naming ELSE IF ( I .EQ. 1 ) THEN IF ( NGRID .GT. 1 ) THEN CALL USI_PROMT( 'OUT', 'Output filename for 1st grid', : STATUS ) END IF CALL USI_CREAT( 'OUT', BDID, GFID(I), STATUS ) * Prompt for o/p filename ELSE WRITE( PC, '(I1.1)' ) I CALL USI_CREAT( 'OUT'//PC, BDID, GFID(I), STATUS ) END IF END IF IF ( STATUS .NE. SAI__OK ) GOTO 99 * Create grid axes CALL FIT_CREGRIDAX( GFID(I), NGRIDAX, GAX, STATUS ) * Write axis labels and units DO J = 1, NGRIDAX CALL BDI_AXPUT0C( GFID(I), J, 'Label', : MODEL.PARNAME(GAX(J).PAR), STATUS ) CALL BDI_AXPUT0C( GFID(I), J, 'Units', : MODEL.UNITS(GAX(J).PAR), STATUS ) END DO * Title and units for this grid IF ( GPARS(I) .EQ. 0 ) THEN IF ( CHISTAT ) THEN LABEL = 'Chi-squared' ELSE LABEL = 'Cash statistic' END IF ELSE IF ( GPARS(I) .EQ. PROB_REPLY ) THEN LABEL = 'Fit probability' ELSE LABEL = MODEL.PARNAME(GPARS(I)) END IF * Write as axis label for 1-d, otherwise title IF ( NGRIDAX .EQ. 1 ) THEN CALL BDI_PUT0C( GFID(I), 'Label', LABEL, STATUS ) ELSE CALL BDI_PUT0C( GFID(I), 'Title', LABEL, STATUS ) END IF * Grid units IF ( (GPARS(I) .NE. 0) .AND. (GPARS(I).NE.PROB_REPLY) ) THEN IF ( MODEL.UNITS(GPARS(I)) .GT. ' ' ) THEN IF ( NGRIDAX .GT. 1 ) THEN CALL BDI_PUT0C( GFID(I), 'Title', LABEL(:CHR_LEN(LABEL))// : ' ('//MODEL.UNITS(GPARS(I))(: : CHR_LEN(MODEL.UNITS(GPARS(I))))//')', STATUS ) ELSE CALL BDI_PUT0C( GFID(I), 'Units', MODEL.UNITS(GPARS(I)), : STATUS ) END IF END IF END IF * Write some history - copy first bit from first grid IF ( I .EQ. 1 ) THEN * Version id CALL HSI_ADD( GFID(I), VERSION, STATUS ) * Input file(s) and model HBUF(1) = 'Data {INP}' HBUF(2) = 'Model {MODEL}' NHBUF = 6 CALL USI_TEXT( 2, HBUF, NHBUF, STATUS ) CALL HSI_PTXT( GFID(1), NHBUF, HBUF, STATUS ) * Grid parameters TEXT = 'Gridded parameters (' TLEN = CHR_LEN(TEXT) DO J = 1, NGRIDAX CALL MSG_SETI( 'P', GPS(J) ) CALL MSG_MAKE( TEXT(:TLEN)//' ^P', TEXT, TLEN ) END DO CALL HSI_PTXT( GFID(1), 1, TEXT(:TLEN)//' )', STATUS ) ELSE CALL HSI_COPY( GFID(1), GFID(I), STATUS ) END IF * The item being gridded IF ( GPARS(I) .EQ. 0 ) THEN CALL FIT_STATTOK( FSTAT, 'STAT', STATUS ) CALL MSG_MAKE( 'Gridded values are ^STAT', TEXT, TLEN ) ELSE IF ( GPARS(I) .EQ. PROB_REPLY ) THEN CALL MSG_MAKE( 'Gridded values are fit probability', : TEXT, TLEN ) ELSE CALL MSG_SETI( 'P', GPARS(I) ) CALL MSG_SETC( 'TAG', MODEL.PARNAME(GPARS(I)) ) CALL MSG_MAKE( 'Gridded values are parameter ^P, ^TAG', : TEXT, TLEN ) END IF CALL HSI_PTXT( GFID(I), 1, TEXT(:TLEN), STATUS ) * Create and map data array CALL BDI_MAPR( GFID(I), 'Data', 'WRITE', GDPTR(I), STATUS ) END DO * Map grid quality array CALL DYN_MAPB( NGRIDAX, GDIMS, GQPTR, STATUS ) * Set iteration limits IF ( OPTIMISING ) THEN CALL FCI_GETMC( MCTRL, STATUS ) CALL MSG_PRNT( 'There are free non-grid parameters - '/ : /' optimising at each grid point.' ) ELSE CALL MSG_PRNT( 'No free non-grid parameters - simple model'/ : /' evaluation at each point.' ) END IF IF ( STATUS .NE. SAI__OK ) GOTO 99 * Evaluate grid CALL FIT_GRID( NDS, OBDAT, INSTR, MODEL, MCTRL, OPCHAN, NGRIDAX, : GAX, NGRID, GPARS, NPAR, LB, UB, FROZEN, SSCALE, : FSTAT, FIT_PREDDAT, PREDDAT, PARAM, : STATMIN, GDPTR, %VAL(GQPTR), GQMASK, STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 * Report minimum & write to history CALL FIT_STATTOK( FSTAT, 'STAT', STATUS ) CALL MSG_SETR( 'VAL', REAL(STATMIN) ) CALL MSG_MAKE( 'The minimum value of ^STAT in the grid'/ : /' is ^VAL.', TEXT, TLEN ) CALL MSG_PRNT( TEXT(:TLEN) ) DO I = 1, NGRID CALL HSI_PTXT( GFID(I), 1, TEXT(:TLEN), STATUS ) END DO * Update the model? CALL USI_GET0L( 'UP', UP, STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 IF ( UP ) THEN CALL MSG_PRNT( '** Updating model spec - do not exit'/ : /' until completed **' ) CALL FIT_MODUP( MFID, MODEL.NCOMP, NPAR, PARAM, LE, UE, : -99.0, STATUS ) CALL MSG_PRNT( '** Model dataset updated **' ) END IF * Did user grid the statistic ? DO I = 1, NGRID IF ( GPARS(I) .EQ. 0 ) THEN * Subtract minimum from statistic grid? CALL USI_GET0L( 'SUBSTAT', SUBSTAT, STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 * Do subtraction IF ( SUBSTAT ) THEN CALL SGRID_SUBSTAT( GNELM, %VAL(GDPTR(I)), %VAL(GQPTR), : GQMASK, REAL(STATMIN), STATUS ) END IF END IF END DO * Any bad points in quality array? CALL SGRID_ANYBAD( GNELM, %VAL(GQPTR), ANYBAD, ANYBADISH, : STATUS ) IF ( ANYBADISH ) THEN CALL MSG_PRNT( '! WARNING : There are points on the grid'/ : /' where a minimum was not achieved' ) CALL MSG_PRNT( ' due to insufficient iterations' ) END IF * If bad quality points, write a copy of quality to each output file IF ( ANYBAD .OR. ANYBADISH ) THEN * Write quality to each grid DO I = 1, NGRID CALL BDI_PUTUB( GFID(I), 'Quality', NGRIDAX, GDIMS, : %VAL(GQPTR), STATUS ) CALL BDI_PUT0UB( GFID(I), 'QualityMask', GQMASK, STATUS ) END DO END IF * Close o/p grid files DO I = 1, NGRID IF ( AUTO ) THEN CALL ADI_FCLOSE( GFID(I), STATUS ) ELSE IF ( I .EQ. 1 ) THEN CALL USI_ANNUL( 'OUT', STATUS ) ELSE WRITE( PC, '(I1.1)' ) I CALL USI_ANNUL( 'OUT'//PC, STATUS ) END IF END DO * Tidy up & exit 99 CALL USI_ANNUL( 'MODEL', STATUS ) CALL USI_ANNUL( 'INP', STATUS ) CALL AST_CLOSE() CALL AST_ERR( STATUS ) END *+ SGRID_ANYBAD - Any bad values in quality array, regardless of mask? SUBROUTINE SGRID_ANYBAD( N, QUAL, ANYBAD, ANYBADISH, STATUS ) * * Description : * * * Method : * Deficiencies : * Bugs : * Authors : * * David J. Allan (BHVAD::DJA) * * History : * * 9 Nov 92 : Original (DJA) * * Type definitions : * IMPLICIT NONE * * Global constants : * INCLUDE 'SAE_PAR' INCLUDE 'QUAL_PAR' * * Status : * INTEGER STATUS * * Import : * INTEGER N ! # quality values BYTE QUAL(N) ! Quality values * * Export : * LOGICAL ANYBAD ! Any MISSING quality values LOGICAL ANYBADISH ! Any IGNORE quality values * * Local variables : * INTEGER I ! Loop over quality values *- * Check status IF ( STATUS .NE. SAI__OK ) RETURN * Initialise ANYBAD = .FALSE. ANYBADISH = .FALSE. * Try to find first non-good value DO I = 1, N IF ( QUAL(I) .EQ. QUAL__MISSING ) THEN ANYBAD = .TRUE. GOTO 89 END IF END DO 89 DO I = 1, N IF ( QUAL(I) .EQ. QUAL__IGNORE ) THEN ANYBADISH = .TRUE. GOTO 99 END IF END DO 99 CONTINUE END *+ SGRID_SUBSTAT - Subtract minimum value of statistic from grid SUBROUTINE SGRID_SUBSTAT( N, STAT, QUAL, MASK, SMIN, STATUS ) * * Description : * * * Method : * Deficiencies : * Bugs : * Authors : * * David J. Allan (BHVAD::DJA) * * History : * * 9 Nov 92 : Original (DJA) * * Type definitions : * IMPLICIT NONE * * Global constants : * INCLUDE 'SAE_PAR' INCLUDE 'QUAL_PAR' * * Status : * INTEGER STATUS * * Import : * INTEGER N ! # quality values BYTE QUAL(N) ! Quality values BYTE MASK ! Quality mask value REAL SMIN ! Minimum value of statistic * * Import / export : * REAL STAT(N) ! Quality values * * Functions : * BYTE BIT_ANDUB * * Local variables : * INTEGER I ! Loop over quality values *- * Check status IF ( STATUS .NE. SAI__OK ) RETURN * Try to find first non-good value DO I = 1, N IF ( BIT_ANDUB(QUAL(I),MASK) .EQ. QUAL__GOOD ) : STAT(I) = STAT(I) - SMIN END DO END