      SUBROUTINE ADDPEAK( LASTISCN, ISCN, PEAKOPT, IADJUST )
Cf2py intent(in) LASTISCN, ISCN
Cf2py intent(in, out) PEAKOPT, IADJUST
C
C     Routine for SCHED, called by SCHOPT, that inserts reference
C     pointing scans.
C
C     The routine is set up to handle multiple groups of
C     antennas to be processed together.
C
C     It is assumed that the final scan time for the main observing
C     scan has been set.  This routine will establish the final
C     times for the pointing scans.
C
C     PEAKOPT is an instruction generated here (only can be set to
C     zero when SCHOPT is initialized) and used as a flag to indicate
C     what to do on the next call.  It gives the number of peaking
C     scans left to process after this pass through the schopt scan
C     loop is done.
C
      INCLUDE     'sched.inc'
      INCLUDE     'schset.inc'
      INCLUDE     'schpeak.inc'
C
      INTEGER           ISCN, LASTISCN(*), PEAKOPT
      INTEGER           NADDED, NGOOD
C
      INTEGER           IS, ISTA, KSTA, USEPSRC
      INTEGER           LASTKSCN(MAXSTA), LASTJSCN(MAXSTA)
      INTEGER           KSCN, MSCN, KSRC, PSRC, IGRP, JSCN, KEEPORIG
      INTEGER           NTRY, I, YEAR, DAY1, OKSC, NUP(MPKGRP)
      LOGICAL           SROK(MPKSRC), SROK2(MPKSRC), IADJUST
      LOGICAL           TRYGRP(MPKGRP), TRYGRP2(MPKGRP), ADD2
      LOGICAL           WATCHIT, LASTPTG, GOTST, TABHEAD
      REAL              MINEL, MAXEL
      DOUBLE PRECISION  MINSLEW, MAXSLEW, MINTOT
      DOUBLE PRECISION  TGAP(MAXSTA), TOTTIME, TOTTIME2
      DOUBLE PRECISION  STARTK, STOPK, START2, STOP2
      DOUBLE PRECISION  SLEWMIN, SLEWMAX(MPKSRC), START, FREQTEST
      DOUBLE PRECISION  MSETTLE(MPKGRP)
      CHARACTER         TFORM*8, STIME*8
C
      SAVE              NADDED
C ----------------------------------------------------------------------
      IF( DEBUG ) CALL WLOG( 0, 'ADDPEAK starting' )
C
C     Just return if autopointing was not requested or pointing was
C     requested with POINT on a scan not generated by this routine.
C     Recall POINT=-1 is a way for the user to say don't point here
C     when AUTOPEAK is on.
C
      IF( .NOT. AUTOPEAK .OR.
     1    ( POINT(ISCN) .GE. -1 .AND. PEAKOPT .EQ. 0 ) ) GO TO 999
C
C     Peaking requested.  Be sure that a pointing file was
C     provided.
C
      IF( NPKGRP .LE. 0 ) THEN
         CALL WLOG( 1,
     1     'ADDPEAK: Want automatic pointing, but there are no groups' )
         CALL WLOG( 1, '     This should not happen. ' )
         CALL ERRLOG ( 'ADDPEAK: Programming error' )
      END IF
C
C     Deal with a new observing scan.
C
      IF( PEAKOPT .EQ. 0 ) THEN
C
C        Allow the user to watch the decision process.
C
         IF( PKWATCH ) THEN
            CALL WLOG( 0, ' ' )
            CALL TIMEJ( STARTJ(ISCN), YEAR, DAY1, START )
            STIME = TFORM( START, 'T', 0, 2, 2, '::@' )
            WRITE( MSGTXT, '( A, I5, 1X, A, 1X, A )' )
     1         'ADDPEAK: Trying to add pointing scan for target scan ',
     2         ISCN, SCNSRC(ISCN), STIME
            CALL WLOG( 0, MSGTXT )
            MSGTXT = ' '
         END IF
C
C        Some initializations.
C
         DO IGRP = 1, NPKGRP
            TRYGRP(IGRP) = .FALSE.
            TRYGRP2(IGRP) = .FALSE.
            NUP(IGRP) = 0
            MSETTLE(IGRP) = 0.D0
         END DO
C
C        Don't try if there were no antennas up for this scan.
C        OPTTIM in SCHOPT got the scan geometry for the main scan.
C
         NGOOD = 0
         DO ISTA = 1, NSTA
            IGRP = PKGROUP(ISTA)
            IF( STASCN(ISCN,ISTA) .AND. IGRP .NE. 0 ) THEN
               IF( UP1(ISCN,ISTA) .EQ. ' ' .OR.
     1             UP2(ISCN,ISTA) .EQ. ' ' ) THEN
                  NGOOD = NGOOD + 1
                  NUP(IGRP) = NUP(IGRP) + 1
               END IF
            END IF
         END DO
         IF( NGOOD .LE. 0 ) THEN
            IF( PKWATCH ) THEN
               CALL WLOG( 0, 'ADDPEAK:  Source down or below OPMINEL '//
     1          'at all stations.' )
            END IF
            GO TO 999
         END IF
C
C        First save some work when there is clearly not enough time
C        or the frequency is wrong.
C        While at it, flag groups that might be useful.
C        Note TRYGRP2 indicates it is worth trying at add a second
C        peaking scan.
C
C        Don't do pointing if the last scan was recent and
C        was pointing.
C
         DO ISTA = 1, NSTA
            IF( STASCN(ISCN,ISTA) .AND.
     1          PKGROUP(ISTA) .GT. 0 ) THEN
               IS = NSETUP( ISCN, ISTA )
               IGRP = PKGROUP(ISTA)
C
C              Test that the frequency is high enough.
C
               FREQTEST = FREQREF(1,IS)
               IF( PKMINFQ(IGRP) .LT. FREQTEST ) THEN
C
                  IF( LASTISCN(ISTA) .NE. 0 ) THEN
                     TGAP(ISTA) = STARTJ(ISCN) - STOPJ(LASTISCN(ISTA))
                     LASTPTG = ( POINT(LASTISCN(ISTA)) .EQ. 0 .OR.
     1                   POINT(LASTISCN(ISTA)) .EQ. IGRP ) .AND.
     2                   TGAP(ISTA) .LT. 600.D0 / 86400.D0
                     IF( TGAP(ISTA) .GT. PKDWELL(IGRP) .AND.
     1                   .NOT. LASTPTG .AND. NUP(IGRP) .GT. 0 ) THEN
                        TRYGRP(IGRP) = .TRUE.
                     END IF
                     IF( TGAP(ISTA) .GT. 2.D0 * PKDWELL(IGRP) .AND.
     1                   .NOT. LASTPTG .AND. NUP(IGRP) .GT. 0 ) THEN
                        TRYGRP2(IGRP) = .TRUE.
                     END IF
                  ELSE
                     TGAP(ISTA) = 10000.D0
                     TRYGRP(IGRP) = NUP(IGRP) .GT. 0
                     TRYGRP2(IGRP) = NUP(IGRP) .GT. 0
                  END IF
C
               END IF
            END IF
C
C           While in the station loop, set the default for LASTKSCN
C           and LASTJSCN to be LASTISCN.  LASTKSCN is for the target
C           source scan.  LASTJSCN is for a possible second pointing
C           scan.  LASTISCN does not change for the first pointing
C           scan.
C
            LASTKSCN(ISTA) = LASTISCN(ISTA)
            LASTJSCN(ISTA) = LASTISCN(ISTA)
C
         END DO
C
C        Get the maximum number of scans that could be inserted if
C        all groups are used for the number of scans determined to
C        be possible above for the group.
C
         NTRY = 0
         DO IGRP = 1, NPKGRP
            IF( TRYGRP(IGRP) ) NTRY = NTRY + 1
            IF( TRYGRP2(IGRP) ) NTRY = NTRY + 1
         END DO
C
C        Write some output if the user is trying to monitor the
C        process.
C
         IF( PKWATCH ) THEN
            IF( NTRY .GE. 1 ) THEN
               DO IGRP = 1, NPKGRP
                  IF( TRYGRP2(IGRP) ) THEN
                     WRITE( MSGTXT, '( A, I2, A )' )
     1                  'ADDPEAK: Pointing group ', IGRP,
     2                  ':  Will try to add double pointing scans.'
                  ELSE IF( TRYGRP(IGRP) ) THEN
                     WRITE( MSGTXT, '( A, I2, A )' )
     1                  'ADDPEAK: Pointing group ', IGRP,
     2                  ':  Will try to add one pointing scan.'
                  ELSE
                     IF( NUP(IGRP) .EQ. 0 ) THEN
                        WRITE( MSGTXT, '( A, I2, A, A )' )
     1                  'ADDPEAK: Pointing group ', IGRP,
     2                  ':  No stations up in scan.'
                     ELSE
                        WRITE( MSGTXT, '( A, I2, A, A )' )
     1                  'ADDPEAK: Pointing group ', IGRP,
     2                  ':  Gap too short to add pointing scans.'
                     END IF
                  END IF
                  CALL WLOG( 0, MSGTXT )
                  MSGTXT = ' '
               END DO
            ELSE
               CALL WLOG( 0, 'ADDPEAK: Insufficient time to add '//
     1            'pointing or last scan was pointing.' )
            END IF
         END IF
C
C        Return if there were no possible places to add scans.
C
         IF( NTRY .EQ. 0 ) GO TO 999
C
C        Ok, there is a chance that something will fit and this is
C        a frequency at which we should be thinking about doing
C        something, at least for some station.
C
C        Now make NTRY new scans to be the templates.  The calculated
C        parameters will be copied.  Note that with the third argument
C        (COPYALL) true, the start, stop, duronly and annot will also
C        be copied so this preserves scan times as desired for moving
C        as opposed to duplicating a scan (we're mainly worried about
C        the last copy - the one that will become the main observing
C        scan (scan MSCN below).  Also note that there end up being 
C        NTRY+1 versions of this scan of which at most NTRY will become 
C        pointing scans.  Set ORIGEN to 4 to indicate these are added
C        scans.  Later we will set the original scan back to its
C        input value.
C
         KEEPORIG = ORIGEN(ISCN)
         ORIGEN(ISCN) = 4
         DO I = 1, NTRY
            KSCN = ISCN + I
            CALL SCNDUP( KSCN, ISCN, .TRUE., 'ADDPEAK' )
            ORIGEN(KSCN) = 4
         END DO
C
C        Loop through the groups.  MSCN is the one that will stay the
C        original for sure so it can be used for slew calculations etc.
C        KSCN is the one we are trying to insert.  NADDED is the number
C        already added.
C
         NADDED = 0
         MSCN = ISCN + NTRY
         DO IGRP = 1, NPKGRP
            IF( TRYGRP(IGRP) ) THEN
               IF( PKWATCH ) THEN
                  WRITE( MSGTXT, '( A, I2 )' )
     1               'ADDPEAK:  Working on pointing group ', IGRP
                  CALL WLOG( 0, MSGTXT )
                  MSGTXT = ' '
                  TABHEAD = .TRUE.
               END IF
C
               KSCN = ISCN + NADDED
C
C              Get the stations that will be in the inserted scan.
C              GOTST indicates that we got at least one for this group.
C
               GOTST = .FALSE.
               DO ISTA = 1, NSTA
                  STASCN(KSCN,ISTA) = STASCN(MSCN,ISTA) .AND.
     1                PKGROUP(ISTA) .EQ. IGRP .AND.
     2                ( UP1(MSCN,ISTA) .EQ. ' ' .OR.
     3                UP2(MSCN,ISTA) .EQ. ' ' )
                  IF( STASCN(KSCN,ISTA) ) GOTST = .TRUE.
               END DO
C
C              Loop through the possible pointing sources, looking
C              for the one closest to the target source that is
C              up at all stations for which the target is up
C              (the latter is guaranteed by the above setting of
C              STASCN).
C
               IF( GOTST ) THEN
                  DO PSRC = 1, NPKSRC(IGRP)
C
C                    Insert the source into the current scan with
C                    some guesses for the times.  SRINSERT will do
C                    the geometry calculations for both this scan
C                    and MSCN, to get slew times.
C
                     STOPK = STARTJ(MSCN) - 20.0 * ONESEC
                     STARTK = STOPK - PKDWELL(IGRP)
                     KSRC = PKSRNUM(PSRC,IGRP)
                     CALL SRINSERT( KSCN, KSRC, PKSRC(PSRC,IGRP),
     1                              STARTK, STOPK, LASTISCN, MSCN )
C
C                    Look for the one closest to the target that is
C                    up at all required stations.  First check that
C                    the source is above the minimum elevation at all 
C                    stations that need it.  Recall STASCN retains 
C                    the information about whether the target source 
C                    is up at the station.
C
                     SROK(PSRC) = .TRUE.
                     SROK2(PSRC) = .TRUE.
                     WATCHIT = .FALSE.
                     MINEL = 100.0
                     MAXEL = 0.0
                     MINSLEW = 1000.0D0
                     MAXSLEW = 0.0D0
                     MINTOT = 10000.0D0
                     DO ISTA = 1, NSTA
                        IF( STASCN(KSCN,ISTA) .AND.
     1                      EL1(KSCN,ISTA) .LT. PKMINEL(IGRP) ) THEN
                           SROK(PSRC) = .FALSE.
                           SROK2(PSRC) = .FALSE.
                        END IF
C
C                       Determine whether to print anything about this
C                       source if PKWATCH is set.
C
                        IF( PKWATCH ) THEN
                           IF( STASCN(KSCN,ISTA) .AND.
     1                         UP1(KSCN,ISTA) .EQ. ' ' .AND.
     2                         UP2(KSCN,ISTA) .EQ. ' ' ) THEN
                              WATCHIT = .TRUE.
                           END IF
C
C                          Collect extrema.
C
                           IF( STASCN(KSCN,ISTA) ) THEN
                              MINEL = MIN( MINEL, EL1(KSCN,ISTA) )
                              MAXEL = MAX( MAXEL, EL1(KSCN,ISTA) )
                              MINSLEW = MIN( MINSLEW, 
     1                             TSLEW(MSCN,ISTA) * 86400.D0 )
                              MAXSLEW = MAX( MAXSLEW, 
     1                             TSLEW(MSCN,ISTA) * 86400.D0 )
                           END IF
                        END IF
                     END DO
C
C                    Now test that the pointing scans have any chance of
C                    fitting in the slot at all stations in the group.
C
                     IF( SROK(PSRC) ) THEN
                        DO ISTA = 1, NSTA
                           IF( STASCN(KSCN,ISTA) ) THEN
C
C                             Check time for one scan.
C
                              TOTTIME = PKDWELL(IGRP) +
     1                            TSLEW(KSCN,ISTA) + TSLEW(MSCN,ISTA)
                              IF( TGAP(ISTA) .LT. TOTTIME ) THEN
                                 SROK(PSRC) = .FALSE.
                              END IF
                              MINTOT = MIN( MINTOT, TOTTIME * 86400.D0 )
C
C                             Check time for 2 scans.  Add a "slew" 
C                             time for the second pointing set.  Use
C                             the TSETTLE (sec) time.
C
                              KSTA = STANUM(ISTA)
                              TOTTIME2 = 2.D0 * PKDWELL(IGRP) +
     1                           TSLEW(KSCN,ISTA) + TSLEW(MSCN,ISTA) +
     2                           TSETTLE(KSTA) / 86400.D0
                              IF( TGAP(ISTA) .LT. TOTTIME2 ) THEN
                                 SROK2(PSRC) = .FALSE.
                              END IF
C
C                             Collect the largest TSETTLE into MSETTLE
C                             It doesn't matter too much where this is
C                             done since these are fixed values per 
C                             station.  This is a place where we are
C                             only looking at the stations in the group
C                             which is what we want.
C
                              MSETTLE(IGRP) = 
     1                            MAX( MSETTLE(IGRP), TSETTLE(KSTA) )
                           END IF
                        END DO
                     END IF
C
C                    Now find the maximum slew time between the
C                    reference and target for this source.
C
                     SLEWMAX(PSRC) = 0.D0
                     IF( SROK(PSRC) ) THEN
                        DO ISTA = 1, NSTA
                           IF( STASCN(KSCN,ISTA) ) THEN
                              SLEWMAX(PSRC) = MAX( SLEWMAX(PSRC),
     1                               TSLEW(MSCN,ISTA) )
                           END IF
                        END DO
                     END IF
C
C                    Watch line.
C
                     IF( PKWATCH .AND. WATCHIT ) THEN
                        IF( TABHEAD ) THEN
                           CALL WLOG( 0, ' Num   Source      '//
     1                             'Slew times (sec) '//
     2                             '  Elevations (deg)  Scans OK'//
     3                             '  Min T' )
                           TABHEAD = .FALSE.
                        END IF
                        WRITE( MSGTXT, '(I5, 2X, A, F7.0, A, F5.0,'//
     1                     ' 6X, F4.0, A, F4.0, L6, L3, F9.0 )' )
     2                     PSRC, PKSRC(PSRC,IGRP),
     3                     MINSLEW, ' to ', MAXSLEW,
     4                     MINEL, ' to ', MAXEL,
     5                     SROK(PSRC), SROK2(PSRC),
     6                     MINTOT
                        CALL WLOG( 0, MSGTXT )
                        MSGTXT = ' '
                     END IF
                  END DO
C
C                 Get the source with the smallest maximum slew time.
C
                  USEPSRC = 0
                  SLEWMIN = 1.D0
                  DO PSRC = 1, NPKSRC(IGRP)
                     IF( SROK(PSRC) ) THEN
                        IF( SLEWMAX(PSRC) .GT. 0.D0 .AND.
     1                      SLEWMAX(PSRC) .LT. SLEWMIN ) THEN
                           SLEWMIN = SLEWMAX(PSRC)
                           USEPSRC = PSRC
                        END IF
                     END IF
                  END DO
C
C                 Ok, now have the source to use, or know there
C                 isn't one.
C
                  IF( USEPSRC .NE. 0 ) THEN
                     PSRC = USEPSRC
                     KSRC = PKSRNUM(PSRC,IGRP)
C
C                    Determine if we add one or two scans.  Only add two
C                    if TRYGRP2 was true, or there might not be enough
C                    dummy scans.
C
                     ADD2 = TRYGRP2(IGRP) .AND. SROK2(PSRC)
C
C                    Insert the actual scan(s) that we are going to use.
C                    JSCN is the one just before the target, and
C                    possibly the only one.  The 2 scan (START2 etc)
C                    is the first one of two, if there are two.
C
                     JSCN = KSCN
                     OKSC = 0
                     STOPK = STARTJ(MSCN) - SLEWMIN
                     STARTK = STOPK - PKDWELL(IGRP)
C
C                    Deal with the second scan, if one is to be added.
C                    This will actually be the first in the time
C                    sequence.
C
                     IF( ADD2 ) THEN
                        NADDED = NADDED + 2
                        OKSC = 2
C
C                       Insert the first scan of the two.  Note that
C                       SRINSERT runs SCNGEO for both the new scan
C                       and MSCN.  For the new scan, this should be
C                       all that is needed.  For MSCN, LASTISCN may
C                       change so it should be run again later.  It
C                       is in SRINSERT for the use above where slews
C                       were needed.
C                       Place a gap of TSETTLE between the pointing 
C                       scans.
C
                        STOP2 = STARTK - MSETTLE(IGRP) / 86400.D0
                        START2 = STOP2 - PKDWELL(IGRP)
                        CALL SRINSERT( KSCN, KSRC, PKSRC(PSRC,IGRP),
     1                                 START2, STOP2, LASTISCN, MSCN )
                        POINT(KSCN) = IGRP
C
C                       Set up for the second scan.  Recall LASTJSCN
C                       is set to LASTISCN much earlier.
C
                        JSCN = KSCN + 1
                        DO ISTA = 1, NSTA
                           IF( STASCN(KSCN,ISTA) ) THEN
                              LASTJSCN(ISTA) = KSCN
                           END IF
                        END DO
                     ELSE
                        JSCN = KSCN
                        NADDED = NADDED + 1
                        OKSC = 1
                     END IF
C
C                    Add the scan closest in time to the target source.
C
                     CALL SRINSERT( JSCN, KSRC, PKSRC(PSRC,IGRP),
     1                              STARTK, STOPK, LASTJSCN, MSCN )
                     POINT(JSCN) = IGRP
C
C                    Watch print.
C
                     IF( PKWATCH ) THEN
                        WRITE( MSGTXT, '( A, I2, A, A, A, I2 )' )
     1                     'ADDPEAK: Adding ', OKSC, ' scan(s) on ',
     2                     PKSRC(PSRC,IGRP), ' for pointing group ',
     3                     IGRP
                        CALL WLOG( 0, MSGTXT )
                        MSGTXT = ' '
                     END IF
C
C                    Record this scan as the last before the target for
C                    the participating stations.  This will only be used
C                    for the geometry calculations for the output target
C                    scan.
C
                     DO ISTA = 1, NSTA
                        IF( STASCN(JSCN,ISTA) ) THEN
                           LASTKSCN(ISTA) = JSCN
                        END IF
                     END DO
C
                  ELSE
C
C                    Deal with no source available.
C                    Nothing to do, I think
C
                     IF( PKWATCH ) THEN
                        WRITE( MSGTXT, '( A, A, I2 )' )
     1                     'ADDPEAK: No pointing sources available ',
     2                     'for pointing group ', IGRP
                        CALL WLOG( 0, MSGTXT )
                        MSGTXT = ' '
                     END IF
                  END IF
               ELSE
C
C                 Let user know there were no stations in this
C                 group/scan.
C
                  IF( PKWATCH ) THEN
                     WRITE( MSGTXT, '( A, I2, A )' )
     1                   'ADDPEAK:  No stations for group ', IGRP,
     2                   ' in this scan. '
                     CALL WLOG( 0, MSGTXT )
                     MSGTXT = ' '
                  END IF
               END IF
C
C
            END IF
         END DO
C
C        Now cover ourselves in case we didn't add a scan after
C        having inserted hypothetical ones.  Copy MSCN to the
C        scan after the last of the inserts. Then update the
C        slew times etc.  Keep the original scan's ORIGEN.
C
         KSCN = ISCN + NADDED
         IF( KSCN .NE. MSCN) THEN
            CALL SCNDUP( KSCN, MSCN, .TRUE., 'ADDPEAK2' )
         END IF
         ORIGEN(KSCN) = KEEPORIG
C
C        Set some scan variables to more reasonable values if
C        scans were inserted.
C
C        SCHED used to set gap to zero here, but that created problems
C        with DURATION/GAP schedules that had some DWELL scans.  Such
C        schedules want fixed intervals between the DUR/GAP scans but
C        the whole timing needs to be able to slide because of the
C        DWELL scans.  This was all found while dealing with Krichbaum's
C        GMVA schedule in Feb. 2014.
C
C        Instead now use ORIGEN and LASTSSCN to keep track of the 
C        last non-inserted scan.  In OPTTIM, respect GAP for original
C        scans but not inserted ones.
C
C         IF( NADDED .NE. 0 ) THEN
C            GAP(KSCN) = 0.D0
C         END IF
C
C        Update the scan slew times, geometry etc.  SRINSERT may
C        have taken care of this, as may SCHOPT later, but just to 
C        be sure it is all done right and for the right "last scans",
C        do it here.
C
         CALL SCNGEO( LASTKSCN, NGOOD, KSCN )
         POINT(KSCN) = -999
C
C        Set the counter for adding the scans.
C
         IF( NADDED .GT. 0 ) THEN
            PEAKOPT = NADDED
         ELSE
            PEAKOPT = 0
         END IF
C
      ELSE
C
C        Grind through any scans set up by the processing of the
C        last target scan.  There really isn't much to do as we
C        set everything up before.  We just need to decrement
C        PEAKOPT.
C
C        Note that PEAKOPT will not hit zero until the NADDED new
C        scans, and the original observing scan, have been flushed
C        through.  So it is zero when the original scan is sent.
C
         IF( PEAKOPT .GT. 0 ) PEAKOPT = PEAKOPT - 1
C
C        Note that LASTISCN will still be correct for the first pointing
C        scan and the normal mechanism for updating LASTISCN will work
C        ok for all other scans.
C
      END IF
C
C     For IADJUST, we want to set it false for any added pointing
C     scans.  One could debate whether to override the original ADJUST
C     for the last scan, but I think it is ok to keep the original.
C     That is easier because PEAKOPT will be zero for it, or for any 
C     scans we are not touching, so we can simply test on PEAKOPT.
C
      IF( PEAKOPT .GE. 1 ) IADJUST = .FALSE.
C
  999 CONTINUE
      RETURN
      END
