
C LAST UPDATE: 
C+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
C
C**************************
C**   LFN_AUTO_SOFT      **
C**************************
C
C
CD-Routine: Automatic Soft Limit Determination - LFN_AUTO_SOFT
C This is a high level routine used to carry out an automatic procedure
C for determining improved soft limits (dmin and lambda-min) for pack
C or set of packs. It enables control of non-default parameters via
C a user defined options string. The routine make use of the LFN_SOFT
C routine in the actual determination of the soft limit. A number of
C routines are passed to the LFN_AUTO_SOFT routine and these may be
C tailored to meet any particular requirements of the calling program.
C Possible routines for some of those functions are supplied.
CD-end
CD-Fortran:
      SUBROUTINE LFN_AUTO_SOFT (IPACK, IPLATE, IOPT, OPTSTR,
     +                          IPKALL_DF, NPROF_DF, PROF_ROT_DF,
     +                          PROMIN_DF, 
     +                          FRAC_DF, SIGTEST_DF, FRTEST_DF,
     +                          NBINS_DF, BINW_DF,
     +                          IMG_PK, IMG_PL, RD_IMG, 
     +                          IMG, MAXIMG, ITYPE, NF_OFF,
     +                          IUN_LOG, MONITOR, PROGRESS,
     +                          LOG_RESULTS, LOG_ERR, CANCEL,
     +                          MAXBINS, NMEAS, NGTSIG, RBIN,
     +                          IUPD, IERR, ERRSTR, ERRSTR2)
CD-end
      INCLUDE 'implicit_none.finc'
C
C Purpose: Automatic soft limit determination
C
C Author:  John W. Campbell, November 1994
C
C Arguments:
C
      INTEGER IPACK
      INTEGER IPLATE
      INTEGER IOPT
      CHARACTER*(*) OPTSTR
      INTEGER IPKALL_DF
      INTEGER NPROF_DF
      LOGICAL PROF_ROT_DF
      REAL PROMIN_DF
      REAL FRAC_DF
      REAL SIGTEST_DF
      REAL FRTEST_DF
      INTEGER NBINS_DF
      REAL BINW_DF
      INTEGER IMG_PK
      INTEGER IMG_PL
      EXTERNAL RD_IMG
      INTEGER IMG(*)
      INTEGER MAXIMG
      INTEGER ITYPE
      INTEGER NF_OFF
      INTEGER IUN_LOG
      EXTERNAL MONITOR
      EXTERNAL PROGRESS
      EXTERNAL LOG_RESULTS
      EXTERNAL LOG_ERR
      LOGICAL CANCEL
      EXTERNAL CANCEL
      INTEGER MAXBINS
      INTEGER NMEAS(*)
      INTEGER NGTSIG(*)
      REAL RBIN(*)
      INTEGER IUPD
      INTEGER IERR
      CHARACTER*(*) ERRSTR
      CHARACTER*(*) ERRSTR2
C
CD-Parameters:
C IPACK       i  (M)  Current pack number (On o/p last pack accessed)
C IPLATE      i  (M)  Current plate number (On o/p last pack accessed)
C IOPT        i  (R)  Option =1 dmin determination, 
C                            =2 lambda-min determination
C OPTSTR      c  (R)  Options string (max. 80 characters long)
C                     All keywords may be upper or lower case.
C                     'PACK' or 'ALL' (default=pack) may be specified.
C                     Any combination of the following keyword/value
C                     pairs may be given .
C                     NPROF nprof     No. of bins for determining intensity 
C                                     profiles
C                     PROMIN promin   Minimum intensity of spot for 
C                                     inclusion in profiles
C                     NBINS nbins     Number of bins to use in analysis
C                     BINW binw       Bin width to use
C                     FRAC frac       Fraction of current dmin or 
C                                     lambda-min defining low end of range 
C                                     for the analysis
C                     SIGTEST sigtest No. of sigmas used to define
C                                     significant intensity
C                     FRTEST frtest   Significant/measured ratio test for 
C                                     soft limit
C                     Defaults are passed as parameters (see below) - note
C                     some values may be dependent on current LDM parameter
C                     values
C IPKALL_DF   i  (R)  Default flag for pack or all packs (1 or 2)
C NPROF_DFi   i  (R)  Default no. of bins for determining intensity profiles 
C                     e.g. 8
C PROF_ROT_DF l  (R)  Default value for rotate profiles when integrating
C                     elliptical spots flag.
C PROMIN_DF   r  (R)  Default minimum intensity of spot for inclusion in 
C                     profiles e.g. 100.0 for film, otherwise 600.0 
C FRAC_DF     r  (R)  Default fraction of current dmin or lambda-min defining 
C                     low end of range for the analysis e.g. .8
C SIGTEST_DF  r  (R)  Default no. of sigmas used to define significant 
C                     intensity e.g. 5.0
C FRTEST_DF   r  (R)  Default significant/measured ratio test for soft limit
C                     e.g. 0.15
C NBINS_DF    i  (R)  Default number of bins to use 
C                     e.g. for DMIN = 5*((NINT (DMIN/BINW)+4)/5) 
C                     e.g. for LMIN = 50
C BINW_DF     r  (R)  Default bin width to use 
C                     e.g for DMIN 0.02 if dmin <=1.0
C                                  0.05 if dmin >1.0 & <=3.0
C                                  otherwise 0.1
C                     e.g. for LMIN 0.02
C IMG_PK      i  (M)  Pack number for current image in IMG; 0 if none.
C                     On output will be for the last image read or 0 if 
C                     there was an error reading the image.
C IMG_PL      i  (M)  Plate number for current image in IMG; 0 if none.
C                     On output will be for the last image read or 0 if 
C                     there was an error reading the image.
C RD_IMG      s  (R)  Subroutine to open the image file and read an image. 
C                     The call is as follows:
C  
C                         CALL RD_IMG (IPK, IPL, ITYPE, NF_OFF, IMG, 
C                        +             MAXIMG, KERR, KERRSTR)
C
C                        where
C
C                         IPK     i  (R)  Pack number
C                         IPL     i  (R)  Plate number
C                         ITYPE   i  (M)  See below 
C                         NF_OFF  i  (M)  See below
C                         IMG(*)  i  (W)  See below
C                         MAXIMG  i  (R)  See below
C                         KERR    i  (W)  Error return flag: Routine must
C                                         set this to 0 if image read was
C                                         successful or to a non-zero
C                                         value if there was an error.
C                         KERRSTR c  (W)  Error message string set by the
C                                         routine if an error was
C                                         encountered when reading the
C                                         image.
C
C                     Note: In some instances it may be appropriate
C                     for the routine to set x_cen_f, y_cen_f values e.g 
C                     derived from fiducial positions if it finds that
C                     these parameters have not already been set as
C                     the refinement procedure needs these in order to
C                     continue
C IMG(*)      i  (R)  Array containing the (possibly packed) image data
C                     for the current plate.
C MAXIMG      i  (R)  Maximum no. of words in IMG array
C ITYPE       i  (M)  Image data type in IMG =1 unsigned byte
C                                            =2 unsigned two byte
C                                            =3 signed (full) integer
C                                            =4 squashed i2 data
C                     Note: May be reset by RD_IMG subroutine but must
C                     be given an input value if a previously read  image 
C                     is passed to the routine.
C NF_OFF      i  (M)  Fast offset between (slow) rasters of image (e.g. 
C                     1'st dimension of the the image data if the data
C                     are held in a two dimensional array). This value is
C                     the number of elements for the image data type
C                     as indicated by ITYPE.
C                     Note: May be reset by RD_IMG subroutine but must be
C                     given an input value if a previously read  image
C                     is passed to the routine.
C IUN_LOG     i  (R)  Unit number for output passed to LOG_RESULTS and
C                     LOG_ERR routines as one of their parameters when 
C                     called.
C MONITOR     s  (R)  Subroutine called at various stages of the procedure
C                     to enable the progress to be monitored. If desired
C                     the routine LFN_SOFT_MON may be passed. Note that the
C                     routine must be declared as EXTERNAL in the calling
C                     program. The call for the MONITOR routine is as
C                     follows:
C
C                          CALL MONITOR (IUN_LOG, IOPT, ISTAGE, 
C                         +              IPACK, IPLATE)
C
C                          IUN_LOG  i (R)  Log file unit number as 
C                                          passed to LFN_AUTO_SOFT
C                          IOPT     i (R)  1=dmin, 2-lambda-min
C                                          determination
C                          ISTAGE   i (R)  Stage reached flag
C                                          = 0  Start of new pack
C                                          = 1  Starting to read image
C                                          = 2  Finished image reading
C                                          = 3  Starting actual soft limit 
C                                               determination for the pack
C                                          = 4  Finished soft limit 
C                                               determination for the pack
C                          IPACK    i (R)  Pack number
C                          IPLATE   i (R)  Plate number
C
C PROGRESS    s  (R)  Subroutine which will be called at intervals during
C                     the integration which may be used to display its
C                     progress if required. It is passed as a parameter
C                     to the LFN_SAINT routine  (see LFN_SAINT routine 
C                     documentation for details of its arguments). If
C                     progess display is not required, the dummy routine
C                     LFN_SOFT_PROG may be passed. Note that the routine
C                     must be declared as EXTERNAL in the calling program.
C LOG_RESULTS s  (R)  User defined subroutine to output results of the
C                     refinement. For output to a log file only, this
C                     may be the routine LFN_SOFT_LIST. Note that the
C                     routine must be declared as EXTERNAL in the calling
C                     program. The call is as documented for the
C                     LFN_SOFT_LIST subroutine.
C LOG_ERR     s  (R)  User defined subroutine called when an error
C                     condition is encountered. For certain conditions
C                     the routine may allow the refinement to continue
C                     for the next plate etc. For output only the
C                     subroutine LFN_SOFT_ERR may be used. This
C                     outputs the error message to IUN_LOG and terminates
C                     the refinement after any error is found. Note that
C                     the routine must be declared as EXTERNAL in the
C                     calling program. The call is as follows:
C    
C                         CALL LOG_ERR (IUN_LOG, ICONT, ERRSTR,
C                        +              ERRSTR2, NEXT)
C   
C                        where
C
C                        IUN_LOG     i  (R)  Unit number for log file
C                                            as passed to LFN_AUTO_SOFT 
C                        ICONT       i  (R)  = 0 terminate refinement
C                                            = 1 may continue with next
C                                                pack if desired.
C                                            =-1 Interrupted
C                        ERRSTR      c  (R)  Error string (max 80 chars)
C                        ERRSTR2     c  (R)  Subsidiary error string -
C                                            may be blank (max 80 chars)
C                        NEXT        l  (W)  Set by the routine. If
C                                            .true. then refinement will
C                                            be continued with next pack
C                                            or plate. If .false. then
C                                            refinement will be 
C                                            terminated. Note: the routine
C                                            must set it to .false. if
C                                            ICONT is 0 or -1.
C CANCEL      f  (R)  Logical function used to interrupt procedure
C                     It has one dummy argument and must return a
C                     logical value of .TRUE. to cancel the procedure
C                     or .FALSE. to let it proceed.
C                     The actual function passed must be declared as
C                     both LOGICAL and EXTERNAL in the calling program.
C                     (The dummy function LFN_DUMMY_CNCL may be used)
C MAXBINS     i  (R)  Maximum no. of 'd' or lambda bins which may be used 
C                     for soft limit determination.
C NMEAS(*)    i  (*)  Work array to hold no. of spots measured in each bin
C                     (dimensioned to at least MAXBINS)
C NGTSIG(*)   i  (*)  Work aray to hold no. of significant spots in each
C                     bin. (dimensioned to at least MAXBINS)
C RBIN(*)     r  (*)  Work array for significant/measured ratios in each
C                     bin. (dimensioned to at least MAXBINS)
C IUPD        r  (R)  Update LDM with determined soft limits flag
C                            = 1 Update provided no error in determination
C                            = 2 Update provided no error in determination
C                                unless IWARN = 1, or IWARN = 3 from
C                                the LFN_SOFT call.
C                            = 0 Do not update. In this case the updating
C                                should be done in a user supplied version
C                                of the LOG_RESULTS or MONITOR subroutines.
C                                This may, if required, give the user an
C                                opportunity of deciding whether or not
C                                to accept the new limit(s).
C IERR        i  (W)  Error flag for last error found
C                                =  0 OK (no errors)
C                                = -1 Invalid current pack number.
C                                = -2 Invalid current plate number.
C                                = -3 Invalid soft-limit type
C                                = -4 Invalid/ambiguous option requested 
C                                     options string
C                                =  1 Key plate not yet refined
C                                =  2 Error reading image
C                                =  3 Error from LFN_SOFT soft limit
C                                     determining routine
C                                =100 Procedure interrupted
C ERRSTR      c  (W)  Error message string (max 80 chars) if IERR is
C                     non-zero
C ERRSTR2     c  (W)  Additional error information (max 80 chars) if
C                     IERR is non-zero (blank for some error conditions)
CD-end
C
C====== Parameter statements
C 

C
C====== GLOBALS:
C

C
C====== FUNCTION TYPES:
C
      INTEGER LENSTR
      INTEGER NXTTOK
      INTEGER LDM_INTFP
C
C====== LOCALS:
C
      LOGICAL NEXT
      LOGICAL PROF_ROT
      INTEGER I
      INTEGER II
      INTEGER IL
      INTEGER M1
      INTEGER M2
      INTEGER NKEYS
      INTEGER IKEY
      INTEGER NPROF
      INTEGER NBINS
      INTEGER IPK_MIN
      INTEGER IPK_MAX
      INTEGER IPK
      INTEGER NPACKS
      INTEGER NPLATES
      INTEGER IPKALL
      INTEGER INP(10)
      INTEGER KPACK
      INTEGER KPLATE
      INTEGER KEYPLATE
      INTEGER IRFL
      INTEGER KERR
      INTEGER IWARN
      INTEGER IFLAG
      INTEGER ND
      INTEGER NTOT_MEAS
      INTEGER NTOT_GTSIG
      INTEGER IBIN_SEL
      INTEGER NXRAST
      INTEGER NYRAST
      INTEGER IORDER
      INTEGER ISWAP
      INTEGER IV
      INTEGER ICONT
      REAL FP
      REAL PROMIN
      REAL FRAC
      REAL SIGTEST
      REAL FRTEST
      REAL BINW
      REAL SOFT_MIN
      REAL SOFT_MAX
      REAL SOFT_SEL
      CHARACTER*80 KERRSTR
      CHARACTER*80 WARNSTR
      CHARACTER*25 NAME
      CHARACTER*2 VALSTR
      CHARACTER*4 SEP
      CHARACTER*12 KEYS(10)
      CHARACTER*20 STR

C     LOGICAL NEXT               !Continue with next pack flag
C     LOGICAL PROF_ROT           !Rotate profiles flag
C     INTEGER I                  !Temp/loop variable
C     INTEGER II                 !LDM_INTFP function return value
C     INTEGER IL                 !Index to last character processed in string
C     INTEGER M1                 !Index to first character in token
C     INTEGER M2                 !Index to final character in token
C     INTEGER NKEYS              !No. of option keys
C     INTEGER IKEY               !Option key number
C     INTEGER NPROF              !No. bins for determining profiles
C     INTEGER NBINS              !No. bins for soft limit determination
C     INTEGER IPK_MIN            !Minimum pack number for processing
C     INTEGER IPK_MAX            !Maximum pack number for processing
C     INTEGER IPK                !No. of pack being processed
C     INTEGER NPACKS             !No. of packs
C     INTEGER NPLATES            !No. of plates
C     INTEGER IPKALL             !Process all/pack flag
C     INTEGER INP(10)            !Flags for option key already input
C     INTEGER KPACK              !Pack number, 0 = all packs
C     INTEGER KPLATE             !Plate number, 0 = all plates
C     INTEGER KEYPLATE           !Key plate
C     INTEGER IRFL               !Plate refined flag 1=yes, 0=no
C     INTEGER KERR               !Error flag
C     INTEGER IWARN              !Warning flag
C     INTEGER IFLAG              !Parameter status flag
C     INTEGER ND                 !No. of decimal places flag
C     INTEGER NTOT_MEAS          !Total no. of measured spots
C     INTEGER NTOT_GTSIG         !Total no. of significant spots
C     INTEGER IBIN_SEL           !Selected bin number
C     INTEGER NXRAST             !No. of x-rasters
C     INTEGER NYRAST             !No. of y-rasters
C     INTEGER IORDER             !Image data order
C     INTEGER ISWAP              !Swap bytes flag
C     INTEGER IV                 !Integer value
C     INTEGER ICONT              !Continue with next pack flag =1 allowable, 
C                                 =0 not allowable/possible
C     REAL FP                    !Real value
C     REAL PROMIN                !Minimum intensity for inclusion in profiles
C     REAL FRAC                  !Start fraction for soft limit determination
C     REAL SIGTEST               !Significant spots sigma test value
C     REAL FRTEST                !Fraction for soft limit  test
C     REAL BINW                  !Bin width
C     REAL SOFT_MIN              !Minimum of range for soft_limit
C     REAL SOFT_MAX              !Maximum of range for soft_limit
C     REAL SOFT_SEL              !Determined soft limit value
C     CHARACTER*80 KERRSTR       !Error string
C     CHARACTER*80 WARNSTR       !Warning string
C     CHARACTER*25 NAME          !Option key name
C     CHARACTER*2 VALSTR         !Value string (dummy)
C     CHARACTER*4 SEP            !Token separator characters
C     CHARACTER*12 KEYS(10)      !Option keys
C     CHARACTER*20 STR           !Temp string

      DATA SEP /'  ,='/
      DATA KEYS /'PACK',
     +           'ALL',
     +           'NPROF',
     +           'PROF_ROTATE',
     +           'PROMIN',
     +           'NBINS',
     +           'BINW',
     +           'FRAC',
     +           'SIGTEST',
     +           'FRTEST'/
C
C-------------------------------------------------------------------------------
C
C====== Initialise and interpret options string
C
      IERR = 0
      ERRSTR = ' '
      ERRSTR2 = ' '

      IF (IOPT.NE.1.AND.IOPT.NE.2) THEN
         ERRSTR = 'Invalid soft-limit type requested'
         CALL LOG_ERR (IUN_LOG, 0, ERRSTR, ERRSTR2, NEXT)
         IERR = -3
         RETURN
      END IF

      CALL LDM_GET_NUMP (NPACKS, IFLAG)
      CALL LDM_GET_NPLAT (NPLATES, IFLAG)
      IF (IPACK.LT.1.OR.IPACK.GT.NPACKS) THEN
         IERR = -1
         ERRSTR = 'Current pack number is invalid'
         ERRSTR2 = 'Pack ='
         CALL STR_ADDI (ERRSTR2, IPACK, 1)
         CALL STR_ADDS (ERRSTR2, ', plate =', 0)
         CALL STR_ADDI (ERRSTR2, IPLATE, 1)
         CALL LOG_ERR (IUN_LOG, 0, ERRSTR, ERRSTR2, NEXT)
         RETURN
      END IF
      IF (IPLATE.LT.1.OR.IPLATE.GT.NPLATES) THEN
         IERR = -2
         ERRSTR = 'Current plate number is invalid'
         ERRSTR2 = 'Pack ='
         CALL STR_ADDI (ERRSTR2, IPACK, 1)
         CALL STR_ADDS (ERRSTR2, ', plate =', 0)
         CALL STR_ADDI (ERRSTR2, IPLATE, 1)
         CALL LOG_ERR (IUN_LOG, 0, ERRSTR, ERRSTR2, NEXT)
         RETURN
      END IF

      NPROF = NPROF_DF
      PROF_ROT = PROF_ROT_DF
      PROMIN = PROMIN_DF
      FRAC = FRAC_DF
      SIGTEST = SIGTEST_DF
      FRTEST = FRTEST_DF
      NBINS = NBINS_DF
      BINW = BINW_DF

      DO 10 I = 1, 10
         INP(I) = 0
 10   CONTINUE
      IPKALL = 0
C
C===== Interpret command line
C
      NKEYS = 10
      SEP(2:2) = CHAR(9)
      IL = 0
100   I = NXTTOK (OPTSTR, SEP, IL, M1, M2)
      IF (I.EQ.-1) GO TO 200
      IF (I.EQ.0) GO TO 100
      NAME = OPTSTR(M1:M2)
      CALL CCPUPC (NAME)
      CALL GETOPT (KEYS, NKEYS, NAME, IKEY, KERR)
      IF (KERR.NE.0) THEN
         IF (KERR.EQ.1)  ERRSTR = 'Ambiguous option'
         IF (KERR.EQ.2)  ERRSTR = 'Invalid option'
         ERRSTR2 = 'Option string:'
         CALL STR_ADDS (ERRSTR2, NAME, 1) 
         CALL LOG_ERR (IUN_LOG, 0, ERRSTR, ERRSTR2, NEXT) 
         IERR = -4
         RETURN
      END IF
      IF (INP(IKEY).EQ.1) THEN
         ERRSTR = 'Duplicate option'
         ERRSTR2 = 'Option string:'
         CALL STR_ADDS (ERRSTR2, NAME, 1)  
         CALL LOG_ERR (IUN_LOG, 0, ERRSTR, ERRSTR2, NEXT) 
         IERR = -4
         RETURN
      END IF
      IF (IKEY.LE.2) THEN
         IF (IPKALL.NE.0) THEN
            ERRSTR = 'Inconsistent option'
            ERRSTR2 = 'Option string:'
            CALL STR_ADDS (ERRSTR2, NAME, 1)  
            CALL LOG_ERR (IUN_LOG, 0, ERRSTR, ERRSTR2, NEXT) 
            IERR = -4
            RETURN
         ELSE
            INP(IKEY) = 1
            IPKALL = IKEY
         END IF
      ELSE
         INP(IKEY) = 1
         I = NXTTOK (OPTSTR, SEP, IL, M1, M2)
         IF (I.LE.0) THEN
            ERRSTR =  'Option'
            CALL STR_ADDS (ERRSTR, NAME, 1)
            CALL STR_ADDS (ERRSTR, 'not followed by a value', 1)
            CALL LOG_ERR (IUN_LOG, 0, ERRSTR, ERRSTR2, NEXT) 
            IERR = -4
            RETURN
         END IF
         II = LDM_INTFP (OPTSTR(M1:M2), FP, IV, ND)
         IF (II.LE.0) THEN 
            ERRSTR =  'Option'
            CALL STR_ADDS (ERRSTR, NAME, 1)
            CALL STR_ADDS (ERRSTR, 'not followed by a valid value', 1)
            CALL LOG_ERR (IUN_LOG, 0, ERRSTR, ERRSTR2, NEXT) 
            IERR = -4
            RETURN
         END IF
         IF (IKEY.EQ.3) THEN
            IF (II.NE.1.OR.IV.LT.1.OR.IV.GT.17) GO TO 150
            NPROF = IV
         ELSE IF (IKEY.EQ.4) THEN
            STR = OPTSTR(M1:M2)
            CALL CCPUPC(STR)
            IF (STR.NE.'YES'.AND.STR.NE.'NO') GO TO 150
            IF (STR.EQ.'YES') PROF_ROT = .TRUE.
            IF (STR.EQ.'NO') PROF_ROT = .FALSE.
         ELSE IF (IKEY.EQ.5) THEN
            IF (FP.LE.0.0) GO TO 150
            PROMIN = FP
         ELSE IF (IKEY.EQ.6) THEN
            IF (II.NE.1.OR.IV.LT.2.OR.IV.GT.MAXBINS) GO TO 150
            NBINS = IV
         ELSE IF (IKEY.EQ.7) THEN
            IF (FP.LE.0.0) GO TO 150
            BINW = FP
         ELSE IF (IKEY.EQ.8) THEN
            IF (FP.LE.0.0.OR.FP.GT.1.0) GO TO 150
            FRAC = FP
         ELSE IF (IKEY.EQ.9) THEN
            IF (FP.LE.0.0) GO TO 150
            SIGTEST = FP
         ELSE IF (IKEY.EQ.10) THEN
            IF (FP.LE.0.0.OR.FP.GT.1.0) GO TO 150
            FRTEST = FP
         END IF
      END IF
      GO TO 100
C
C====== Invalid value
C
 150  ERRSTR = OPTSTR(M1:M2)
      CALL STR_ADDS (ERRSTR, 'is not a valid value for option', 1)
      CALL STR_ADDS (ERRSTR, NAME, 1)
      CALL LOG_ERR (IUN_LOG, 0, ERRSTR, ERRSTR2, NEXT) 
      IERR = -4
      RETURN
C
C====== Set pack  range 
C
 200  IF (IPKALL.EQ.0) THEN
         IPKALL = IPKALL_DF
         IF (IPKALL.LT.1.OR.IPKALL.GT.2) IPKALL = 1
      END IF
      IF (IPKALL.EQ.1) THEN
         IPK_MIN = IPACK
         IPK_MAX = IPACK
      ELSE
         IPK_MIN = 1
         CALL LDM_GET_NUMP (IPK_MAX, IFLAG)
         IF (IPK_MAX.LT.1) IPK_MAX = 1
      END IF
      IF (CANCEL(0)) GO TO 900
             
C
C====== Loop through required packs
C====== ===========================
C
      DO 2000 IPK = IPK_MIN, IPK_MAX
         ICONT = 1
         IF (IPK.EQ.IPK_MAX) ICONT = 0
         CALL LDM_GET_KEYP (IPK, KEYPLATE, IFLAG, KERR, ERRSTR)
         IPACK = IPK
         IPLATE = KEYPLATE
C
C====== Update parameter tables
C
         CALL MONITOR (IUN_LOG, IOPT, 0, IPACK, IPLATE)  
C
C====== Check that plate has been refined
C
         CALL LDM_GET_RFL(IPACK, IPLATE, IRFL, IFLAG, KERR, KERRSTR)
         IF (IRFL.EQ.0) THEN
            ERRSTR = 'Key plate not refined for this pack'
            CALL LOG_ERR (IUN_LOG, ICONT, ERRSTR, ERRSTR2, NEXT)
            IERR = 1
            IF (.NOT.NEXT) RETURN
            GO TO 2000
         END IF
C
C====== Read image if not already read
C
         IF (IPACK.NE.IMG_PK.OR.IPLATE.NE.IMG_PL) THEN
            CALL MONITOR (IUN_LOG, IOPT, 1, IPACK, IPLATE)
            CALL RD_IMG (IPACK, IPLATE, ITYPE, NF_OFF, IMG, MAXIMG,
     +                   KERR, KERRSTR)
            CALL MONITOR (IUN_LOG, IOPT, 2, IPACK, IPLATE)
            IF (KERR.NE.0) THEN
               IERR = 2
               ERRSTR = 'Error reading image for pack'
               CALL STR_ADDI (ERRSTR, IPACK, 1)
               CALL STR_ADDS (ERRSTR, ', plate', 0)
               CALL STR_ADDI (ERRSTR, IPLATE, 1)
               ERRSTR2 = KERRSTR
               ICONT = 1
               IF (IPACK.EQ.IPK_MAX) ICONT = 0
               IMG_PK = 0
               IMG_PL = 0
               CALL LOG_ERR (IUN_LOG, ICONT, ERRSTR, ERRSTR2, NEXT)
               IF (.NOT.NEXT) RETURN
               GO TO 2000
            END IF
            IMG_PK = IPACK
            IMG_PL = IPLATE
         END IF
         IF (CANCEL(0)) GO TO 900
C
C====== Get some image related details
C
         CALL LDM_GET_NXRAS (NXRAST, IFLAG)
         CALL LDM_GET_NYRAS (NYRAST, IFLAG)
         CALL LDM_GET_AXORD (VALSTR, IORDER, ISWAP, IFLAG)
C
C====== Calculate the soft limit
C
         CALL MONITOR (IUN_LOG, IOPT, 3, IPACK, IPLATE)
         CALL LFN_SOFT (IPACK, IPLATE, IOPT, IMG, ITYPE, IORDER,
     +                  NF_OFF, NXRAST, NYRAST, PROMIN, NPROF, 
     +                  PROF_ROT, 
     +                  PROGRESS, CANCEL, FRAC, SIGTEST, FRTEST, 
     +                  NBINS, BINW,
     +                  NTOT_MEAS, NTOT_GTSIG, NMEAS, NGTSIG, RBIN,
     +                  SOFT_MIN, SOFT_MAX, SOFT_SEL, IBIN_SEL,
     +                  KERR, ERRSTR, IWARN, WARNSTR)
         IF (KERR.NE.0) THEN
            IF (KERR.EQ.100) GO TO 900
            CALL LOG_ERR (IUN_LOG, 0, ERRSTR, ERRSTR2, NEXT)
            IERR = 3
            RETURN
         END IF

         CALL MONITOR (IUN_LOG, IOPT, 4, IPACK, IPLATE)

         CALL LOG_RESULTS (IUN_LOG, 0, IPACK, IPLATE, 
     +                     IOPT, PROMIN, NPROF, PROF_ROT, SIGTEST, 
     +                     FRTEST, NBINS, BINW,
     +                     NMEAS, NGTSIG, RBIN, SOFT_MIN, SOFT_MAX, 
     +                     SOFT_SEL, IBIN_SEL, IWARN, WARNSTR)

         IF (IUPD.EQ.1.OR.(IUPD.EQ.2.AND.IWARN.NE.1.AND.IWARN.NE.3)) 
     +      THEN
            IF (IOPT.EQ.1) THEN
               CALL LDM_SET_DMIN (IPACK, SOFT_SEL, KERR, KERRSTR)
            ELSE IF (IOPT.EQ.2) THEN
               CALL LDM_SET_LMIN (IPACK, SOFT_SEL, KERR, KERRSTR)
            END IF
         END IF

         IF (CANCEL(0)) GO TO 900

 2000 CONTINUE
      RETURN
C
C====== Cancel requested
C
 900  CALL LOG_ERR (IUN_LOG, -1, 
     + '==Soft limit determination interrupted==', ' ', NEXT)
      IERR = 100
      RETURN
      END
