SUBROUTINE SERROR( STATUS ) *+ * Name: * SERROR * Purpose: * Spectral error program * Language: * Starlink Fortran * Type of Module: * ASTERIX task * Invocation: * CALL SERROR( STATUS ) * Arguments: * STATUS = INTEGER (Given and Returned) * The global status. * Description: * Evaluates confidence interval corresponding to specified * chi-squared increase, along each (non-frozen) parameter dimension in * the fit space. For likelihood fitting, the Cash statistic is used, since * this is still chi-squared distributed about its minimum. * Usage: * serror {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 * MODEL = CHAR (read) * Data object containing model specification * DS = REAL (read) * Increase in chi-squared which defines confidence region * MAX = INTEGER (read) * Max number of iterations to be performed * PARS = CHAR (read) * List of parameters to have error evaluated * MIN = REAL (read) * Minimum reduced chi-squared slope forcing continued iteration * OP = LOGICAL (read) * Spool (or send to file) summary of fit results? * FITOUT = CHAR (read) * Name of fit text output * APPEND = LOGICAL (read) * Append output to existing file? * Examples: * {routine_example_text} * {routine_example_description} * Pitfalls: * {pitfall_description}... * Notes: * {routine_notes}... * Prior Requirements: * {routine_prior_requirements}... * Side Effects: * {routine_side_effects}... * Algorithm: * The confidence regions are evaluated by FIT_PARCON. * Each parameter in turn is adjusted (using initial guesses LE,UE which * are either picked up from the model file or generated from the parameter * range) and frozen. FIT_MIN is then called to evaluate the optimum fit * obtainable by allowing the other parameters to vary. From the actual * fitstat values attained, the parameter offset giving the specified * chi-sq. increase (SOFF) is estimated on the assumption * that the minimum fitstat surface is a parabolic function of the * parameter whose error is being evaluated. The parabola may have a * different shape on each side of the minimum, the curve on each side * being defined by the assumption of zero slope at the minimum, and the * requirement that it should pass through the single offset point * evaluated. e.g. * * . ! * * ! . * . ! * .<----------------------->!<--------->. - * . ! * ^ * . ! . SOFF * . ! . ^ * M ^ * * where * are the evaluated points, and the resulting confidence limits * are shown by <---->. * * From Lampton, Margon & Bowyer (Ap.J. 208, p177, 1976) a value SOFF=1 * gives a 1 sigma (i.e. 68% confidence) interval and SOFF=2.71 a 90% * confidence interval for the case where the model is linear (i.e. the * predicted values are linear functions of the parameters). Where this * is not the case (i.e. always!) the results may still be approximately * right (see LMB and also Avni Ap.J. 210, p642, 1976). For likelihood * fitting the Cash statistic C=-2*log(P/P_min) is chi-squared distributed * about its minimum (see Cash, Ap.J. 228, 939 (1979)). * A safe limit in all cases is obtained by projecting the full * NPAR-dimensional confidence interval onto the subspace desired (a single * parameter axis in this case). This corresponds to taking * SOFF = chi-squared with NPAR d.o.f.( n% conf) * for a safe upper bound on the n% confidence limit. For large NPAR this * will be way above the linear approximation result. * * If the number of free parameters (apart from that whose interval is * being evaluated) is reduced as a result of parameter bounds being * encountered, then a warning is issued. The confidence region for an * affected parameter must be treated with caution. Pegging of a parameter * is likely to truncate the confidence limit (since an extra impediment * to fstat minimisation is introduced). Where the limit encountered * is real (i.e. the user KNOWS it cannot be crossed) the derived confidence * limit stands. If the bound is arbitrary then it should be removed and the * confidence region reevaluated. * * Note that the assumption that the chi-squared surface is parabolic * about the best fit may NOT be a good one if the minimum is up * against a bound (the minimum of the parabola may then be BEYOND * this bound). In this case the initial estimate produced by SERROR * can be quite poor, but should converge to the correct value on * further invocations. * 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: * serror, usage:public * Copyright: * Copyright (C) University of Birmingham, 1995 * Authors: * TJP: Trevor Ponman (University of Birmingham) * DJA: David J. Allan (Jet-X, University of Birmingham) * {enter_new_authors_here} * History: * 22 Jun 1988 V0.6-1 (TJP): * Original version. * 1 Jul 1988 V0.6-2 (TJP): * APPEND option * 11 Aug 1988 V0.6-3 (TJP): * New (more efficient) SPEC_BH and FIT_FOLD * 26 Oct 1988 V0.6-4 (TJP): * Model file listed in printout * 19 Jun 1989 V1.0-1 (TJP): * First ASTERIX88 version * 7 Dec 1990 V1.4-1 (TJP): * Bug with multiple spectra and model compts fixed * 5 Aug 1991 V1.5-1 (TJP): * INIT flag added * 29 Aug 1991 V1.5-2 (TJP): * Confidence region zeroed for FROZEN parameters * 1 Apr 1992 V1.5-3 (RJV): * FIT_ERRORS merged into top level * 24 Jun 1992 V1.6-1 (TJP): * Supports likelihood fitting * 23 Sep 1992 V1.6-2 (DJA): * Statistic in D.P. * 24 Nov 1992 V1.6-3 (TJP): * Write (non-zero) redshift to output listing * 4 Dec 1992 V1.7-0 (DJA): * Fit error report and red-shift in subroutines * 8 Dec 1992 V1.7-1 (DJA): * Direct terminal i/o replaced by MSG_ * 11 Jan 1993 V1.7-2 (DJA): * Output open/close moved to subroutines * 13 Jan 1993 V1.7-3 (DJA): * User can select parameters for error analysis (DJA) * 8 Sep 1993 V1.7-4 (DJA): * Added SPEC_INIT call and removed reference to SPEC_CMN_RZ * 21 Jul 1994 V1.7-5 (DJA): * Updated output file handling * 25 Jul 1994 V1.7-6 (DJA): * Use AIO for all text output * 24 Nov 1994 V1.8-0 (DJA): * Now use USI for user interface * 21 Apr 1995 V1.8-1 (DJA): * Removed explicit use of HDS * 1 Dec 1995 V2.0-0 (DJA): * ADI port * 17 Apr 1996 V2.0-1 (DJA): * 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 'USER_ERR' INCLUDE 'ADI_PAR' INCLUDE 'FIT_PAR' * Structure Definitions: INCLUDE 'FIT_STRUC' * Status: INTEGER STATUS ! Global status * External References: EXTERNAL FIT_PREDDAT * Local Constants: INTEGER OPCHAN ! Output channel for diagnostic ! messages ( <1 for no messages) PARAMETER ( OPCHAN = 6 ) REAL OFFRAC ! Fraction of parameter range used PARAMETER ( OFFRAC = 0.01 ) ! for offset if no estimates available CHARACTER*30 VERSION PARAMETER ( VERSION = 'SERROR Version V2.0-1' ) * Local Variables: RECORD /DATASET/ OBDAT(NDSMAX) ! Observed datasets RECORD /INSTR_RESP/ INSTR(NDSMAX) ! Instrument responses RECORD /PREDICTION/ PREDDAT(NDSMAX) ! Data predicted by model RECORD /MODEL_SPEC/ MODEL ! Model specification DOUBLE PRECISION STAT ! Fit statistic REAL DPAR(NPAMAX) ! Differential parameter increments REAL LB(NPAMAX) ! Parameter lower bounds REAL LE(NPAMAX) ! Lower error estimate REAL PARAM(NPAMAX) ! Model parameters REAL SOFF ! Chi-squared increase for conf.region REAL UB(NPAMAX) ! Parameter upper bounds REAL UE(NPAMAX) ! Upper error estimate REAL Z ! Redshift [ Eobs/Esource=1/(1+z) ] INTEGER FSTAT ! Fit statistic flag (1=chisq, 2=l'hood) INTEGER IFID ! Input dataset id INTEGER MFID ! Model spec id INTEGER NDS ! No of datasets INTEGER NGOOD ! # good data elements INTEGER NDOF ! Degrees of freedom INTEGER NEPAR ! # pars for error analysis INTEGER SSCALE ! Factor for scaling fitstat INTEGER NPAR ! No of parameters INTEGER FITERR ! Fitting error encountered INTEGER J ! Parameter index INTEGER MCTRL ! Minimisation control INTEGER OCI ! Logical unit number for o/p file INTEGER PARS(NPAMAX) ! Parameters to have errors evaluated INTEGER PEGC(NPAMAX) ! Pegging code (flags pegging changes) LOGICAL FINISHED ! Iterations finished LOGICAL FROZEN(NPAMAX) ! Frozen parameter flag LOGICAL LIKSTAT ! Fitstat is Cash likelihood statistic? LOGICAL OP ! Printout required? LOGICAL PEGGED(NPAMAX) ! Parameter pegged on bound LOGICAL WORKSPACE ! Set up workspace for fstat 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 statistic? CALL USI_GET0L('LIK',LIKSTAT,STATUS) 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, : (.NOT. LIKSTAT), 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 ( .NOT. LIKSTAT ) THEN * Derive from model spec and frozen array CALL FIT1_NDOF( NGOOD, MODEL, FROZEN, NDOF, STATUS ) * NDOF to be used for scaling chisq statistic SSCALE = NDOF END IF * Chi-squared offset CALL USI_GET0R( 'DS', SOFF, STATUS ) IF ( SOFF .LE. 0.0 ) THEN STATUS=SAI__ERROR CALL ERR_REP( ' ', 'Non-positive confidence interval', STATUS ) GOTO 99 END IF * Get minimisation control CALL FCI_GETMC( MCTRL, STATUS ) * Parameters to have errors evaluated CALL PRS_GETLIST( 'PARS', NPAR, PARS, NEPAR, STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 DO J = 1, NEPAR IF ( (PARS(J).LE.0) .OR. (PARS(J).GT.NPAR) ) THEN CALL MSG_SETI( 'NP', PARS(J) ) STATUS = SAI__ERROR CALL ERR_REP( ' ', 'Invalid parameter number ^NP', STATUS ) GOTO 99 END IF END DO * Set up workspace for model stack CALL SFIT_MAPMODSTK( NDS, PREDDAT, MODEL.STACKPTR, STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 * Set up offsets for parameters DO J = 1, NPAR * Don't do errors for frozen parameters IF ( .NOT. FROZEN(J) ) THEN * Upper offset IF ( UE(J) .LE. 0.0 ) THEN IF(LE(J).GT.0.0)THEN * Use parabolically scaled upper error UE(J)=LE(J)*SQRT(SOFF) ELSE * No existing error estimates available, use OFFRAC*param range UE(J)=OFFRAC*(UB(J)-LB(J)) END IF ELSE * Scale the 1 sigma error (parabolically) to confidence SOFF UE(J)=UE(J)*SQRT(SOFF) END IF * Repeat for lower error IF(LE(J).LE.0.0)THEN IF(UE(J).GT.0.0)THEN LE(J)=UE(J) ! UE is already scaled ELSE * No existing error estimates available, use OFFRAC*param range LE(J)=OFFRAC*(UB(J)-LB(J)) ENDIF ELSE * Scale the 1 sigma error (parabolically) to confidence SOFF LE(J)=LE(J)*SQRT(SOFF) ENDIF * Zero error array values for FROZEN parameters ELSE LE(J) = 0.0 UE(J) = 0.0 END IF * Next parameter END DO * Check that starting point is a minimum FINISHED = .FALSE. CALL MSG_PRNT( '* Checking initial minimum' ) CALL FIT_MIN( NDS, OBDAT, INSTR, MODEL, MCTRL, OPCHAN, .FALSE., : NPAR, LB, UB, FROZEN, SSCALE, FSTAT, : FIT_PREDDAT, PREDDAT, PARAM, DPAR, PEGGED, STAT, : FINISHED, FITERR, STATUS ) IF ( STATUS .NE. SAI__OK ) GOTO 99 * Fitting error? IF ( FITERR .NE. 0 ) THEN CALL FIT_REPFERR( FITERR, STATUS ) GOTO 99 END IF * Warning if minimum not found IF ( .NOT. FINISHED ) THEN CALL MSG_PRNT( '!! Warning - minimum not achieved !!' ) END IF * Update parameters if necessary CALL FIT_MODUP( MFID, MODEL.NCOMP, NPAR, PARAM, LE, UE, 0.0, : STATUS ) ! * Repeat until successful error run FINISHED = .FALSE. CALL MSG_PRNT( '* Calculating confidence limits' ) DO WHILE ( .NOT. FINISHED ) * Calculate parameter confidence limits CALL FIT_PARCON( NDS, OBDAT, INSTR, MODEL, MCTRL, SOFF, : OPCHAN, NEPAR, PARS, NPAR, LB, UB, FROZEN, : SSCALE, DPAR, FSTAT, FIT_PREDDAT, PREDDAT, : STAT, PARAM, PEGGED, LE, UE, PEGC, STATUS ) * Point lower than "minimum" encountered, try again IF ( STATUS .EQ. USER__001 ) THEN CALL ERR_ANNUL( STATUS ) CALL MSG_PRNT('Point below "minimum" found -'// : ' trying again with updated minimum') CALL FIT_MODUP(MFID,MODEL.NCOMP,NPAR,PARAM,LE,UE, : 0.0,STATUS ) ELSE IF(STATUS.NE.SAI__OK)THEN GOTO 99 ELSE FINISHED = .TRUE. END IF END DO * Update fit_model object CALL FIT_MODUP( MFID, MODEL.NCOMP, NPAR, PARAM, LE, UE, : SOFF, STATUS ) CALL MSG_PRNT( '* Model spec updated' ) * Display results to terminal CALL SFIT_OPETABLE( NPAR, PARAM, NEPAR, PARS, LE, UE, FROZEN, : PEGC, MODEL, 0, STATUS ) * Fit statistic at minimum CALL SFIT_OPSTAT( FSTAT, STAT, NDOF, NGOOD, 0, STATUS ) IF ( Z .NE. 0.0 ) THEN CALL MSG_FMTR( 'Z', 'F7.5', Z ) CALL MSG_PRNT( '--- Redshift = ^Z' ) CALL MSG_BLNK() END IF * Printed summary of fit results? CALL SFIT_OPOPEN( OP, OCI, STATUS ) * Output? IF ( OP ) THEN * Write header CALL AIO_TITLE( OCI, VERSION, STATUS ) * Write file list CALL SFIT_OPFILES( FSTAT, NDS, OBDAT, MODEL, OCI, STATUS ) * Red-shift IF ( Z .NE. 0.0 ) THEN CALL MSG_FMTR( 'Z', 'F7.5', Z ) CALL AIO_WRITE( OCI, '--- Redshifted to z = ^Z', STATUS ) CALL AIO_BLNK( OCI, STATUS ) END IF * Report confidence interval CALL MSG_FMTR( 'SOFF', '1PG11.4', SOFF ) CALL AIO_WRITE( OCI, 'Confidence region corresponds to '/ : /'chi-squared increase of ^SOFF', STATUS ) CALL AIO_BLNK( OCI, STATUS ) * Parameter error table CALL SFIT_OPETABLE( NPAR, PARAM, NEPAR, PARS, LE, UE, FROZEN, : PEGC, MODEL, OCI, STATUS ) * Statistic at minimum CALL SFIT_OPSTAT( FSTAT, STAT, NDOF, NGOOD, OCI, STATUS ) * Close file CALL SFIT_OPCLOSE( OCI, STATUS ) END IF * Tidy up & exit 99 CALL USI_ANNUL( 'MODEL', STATUS ) CALL USI_ANNUL( 'INP', STATUS ) CALL AST_CLOSE() CALL AST_ERR( STATUS ) END