;+
; NAME:
;     DLASCAN
; PURPOSE:
;     Analyze DELAY SCAN data.  Responds to SCANCODE 1 (TEST DATA) or
;     SCANCODE 9 (DLASCAN DATA).
; CATEGORY:
;     OVRO APC CALIBRATION
; CALLING SEQUENCE:
;     dlascan[,filename][,hrec | ,after=after][,erec][,debug][,/cmdfile]
; INPUTS:
;     filename   the name of the file containing the data.  If
;                  omitted, the file DAILY.ARC in directory
;                  !DEFAULTS.WORKDIR is assumed.
;     hrec       the record number of the scan header.  Data
;                  will be processed up to the next EOS segment.
;                  If this argument is given, the AFTER keyword
;                  is ignored.
;     erec       the record number of the last record in the scan.
;                  If omitted, the file will be read until the EOF
;                  or a new header is reached.
; OPTIONAL (KEYWORD) INPUT PARAMETERS:
;     after      an optional time string of the standard form
;                  [yyyy.ddd ]hh:mm[:ss] after which to start
;                  looking for a valid scan.
;     cmdfile    a switch that indicates that the routine was called
;                  from a command file, so issue no modal messages, and
;                  print any error messages to <WORKDIR>\DLASCAN.MSG.
;     debug      a switch that activates some debugging statements
;                  for getting an indication of intermediate steps.
;                  This switch is not compatible with /CMDFILE switch.
; ROUTINES CALLED:
;     openarc, getdata, lasthrec, tl_decode, decode, get_cycle, congrid, dlafit, dlasolve,
;     dlapred
; OUTPUTS:
; COMMENTS:
;     This routine is fairly general as regards number of antennas, but
;     currently the MUX sequence is not recorded in the data, so one
;     must enter the assignments of AB, BC, and CA channels by hand for
;     each MUX sequence to be used.  Currently two MUX sequences are
;     defined, one for 5-element and one for 6-element.  The channel
;     assignments are:
;
;     5-element MUX sequence, 124, 125, 126, 456 yields:
;      abchan = [ 5,19]             ; Baselines 12 and 45
;      bcchan = [13,15,17,23]       ; Baselines 24, 25, 26, 56
;      cachan = [ 7, 9,11,21]       ; Baselines 14, 15, 16, 46
;
;     6-element MUX sequence, 457, 456, 124, 125, 167, 267 yields:
;      abchan = [ 6,12,20,24]       ; Baselines 12, 16, 26, 45
;      bcchan = [16,18,30,32,34]    ; Baselines 24, 25, 56, 57, 67
;      cachan = [ 8,10,14,22,26,28] ; Baselines 14, 15, 17, 27, 46, 47
;
; SIDE EFFECTS:
; RESTRICTIONS:
; MODIFICATION HISTORY:
;     Written 07-Mar-1999 by Dale Gary
;     15-Mar-1999  DG
;       Major changes to make it work better, add annotation and printing,
;       refine results by setting range to +/- 30 for non-AB baselines,
;       and average points for non-AB baselines.
;     14-May-1999  DG
;       Slight change to reflect change to GET_CYCLE(), which now returns
;       the segment code of the last read record if it is not a data record.
;     05-Feb-2000  DG
;       Removed now unnecessary sin and cos lookup tables in GAINCOR call.
;     14-Mar-2000  DG
;       Significant changes to allow routine to work with either 5 or 6
;       antennas.  Found and fixed additional error in setting the number
;       of cycles to average--now just read it from the cfg segment.
;     22-May-2000  DG
;       Added FIT and SOLVE buttons, and fully implemented the fitting and
;       solution procedures with new or updated versions of DLAFIT and DLASOLVE.
;     10-Jan-2001  DG
;       Fixed problem where program would crash if first few points were NaN.
;     29-Jun-2002  DG
;       Fixed slight problem with FIT button not coming on at end of short scan.
;     07-Oct-2002  DG
;       The new MUX sequences needed for 7-element operation required that I
;       change the assignment of which are AB, BC, and CA baselines.  This
;       should be obtained from *CFG.PMUXSEQ, but for now it is hardwired.
;     23-Jul-2003  DG
;       Changed GET_COLOR to OVSA_GET_COLOR to avoid conflict
;       with routine of the same name in SMM tree.
;     10-Jul-2004  DG
;       Fixed a bug in the assignment of channel type.  Also updated routine
;       to work with 7 elements.
;     16-Jan-2004  DG
;       Try to fix crash that occurred when data were entirely missing for a
;       baseline, when trying to plot that baseline.
;     14-Mar-2005  DG
;       Changed handling of polarization to reflect changes to polarization
;       hardware.
;-
PRO Select_data,state,ax,amp,pha

   j = state.j
   abchan = state.abchan
   bcchan = state.bcchan
   nant = state.header.nant
   ; List of channels, e.g. 5,7,9,11,... for 5-element, or 6,8,10,... for 6-element
   Chanlist = indgen(nant*(nant-1)/2)*2+nant
   range = state.range
   c1 = state.chan
   x = reform(state.avg[c1,0:j])
   y = reform(state.avg[c1+1,0:j])
   ax = indgen(4*range+1)-2*range
   ; Check to see if this is an AB baseline
   junk = where(abchan eq c1,isab)
   ; Check to see if this is a BC baseline, in which case we reverse
   ; sense of x-axis
   junk = where(bcchan eq c1,isbc)
   if (not isab) then begin
      ; This is not an AB baseline, so average adjacent points
      if ((j mod 2) eq 0) then begin
         ; J is even, so length of arrays is odd--drop last and avg
         x = congrid(x(0:j-1),j/2)
         y = congrid(y(0:j-1),j/2)
      endif else begin
         ; J is odd, so length of arrays is even--avg directly
         x = congrid(x,(j+1)/2)
         y = congrid(y,(j+1)/2)
      endelse
      ax = indgen(2*range)-range
   endif
   if (isbc) then ax = -ax
   amp = sqrt(x^2+y^2)
   pha = (atan(x,y)/!dtor+720.) mod 360.

return
end

PRO DLASCAN_Event, Event

  base = Event.handler
  stash = WIDGET_INFO(base, /CHILD)
  WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY

  IF (Event.Id EQ state.SelID) THEN $
       Ev=Event.Value ELSE WIDGET_CONTROL,Event.Id,GET_UVALUE=Ev

  nant = state.header.nant

  ; If the event is the drop-list widget,
  ; set the corresponding state.chan to the channel corresponding
  ; to the index of the selection and update the plot.
  FOR i = 0, 2 DO BEGIN
     IF (Event.Id EQ state.DSrcList) THEN BEGIN

        jndx = Event.Index

        Chanlist = indgen(nant*(nant-1)/2)*2+nant
        ; Droplist widgets return their index in the Event.Index
        ; field of the Event structure
        state.chan = Chanlist(jndx)

        select_data,state,ax,amp,pha
        wset,state.wid(0)

        good = where(finite(amp),ngood)
        if (ngood ge 2) then begin
           plot,ax,amp,psym=1,background=255,color=0,xsty=1,ytitle='Amplitude',$
                xtitle='Delay [nsec] relative to delay center'

        if (state.peak_loc[jndx] ne 0) then begin
           oplot,state.xfit[jndx,*],state.yfit[jndx,*],color=0,thick=1
           plots,state.peak_loc[jndx]*[1,1],[min(!y.crange),max(!y.crange)],/data,color=0
           xyouts,0.8,0.75,/norm,'Delay Center = '+string(state.peak_loc[jndx],$
              format='(F6.2)')+' nsec',align=0.5,charthick=1,charsize=1,color=0
        endif
        if (state.soldif[jndx] ne 0) then begin
           xyouts,0.8,0.7,/norm,'Corrected = '+string(state.soldif[jndx],$
              format='(F6.2)')+' nsec',align=0.5,charthick=1,charsize=1,color=0
        endif

        ichan = (state.chan-nant)/2
        xyouts,0.8,0.8,/norm,state.srclist(ichan),align=0.5,charthick=1,charsize=1,color=0

        wset,state.wid(1)
        plot,ax,pha,psym=6,symsize=0.5,background=255,color=0,xsty=1,ytitle='Phase',$
                xtitle='Delay [nsec] relative to delay center'

        endif else begin
           plot,[-30,30],[0,1],/nodata
           xyouts,0,0.5,"No data (yet)"
        endelse

        goto, WRITE_STATE
     ENDIF
  ENDFOR


  IF (TAG_NAMES(Event, /STRUCTURE_NAME) EQ $
                            'WIDGET_KILL_REQUEST') THEN BEGIN
     IF (state.lun ne 0) THEN free_lun,state.lun
     WIDGET_CONTROL, Event.top, /DESTROY
     RETURN
  ENDIF

  CASE Ev OF
  'This page': state.printall = 0
  'All pages': state.printall = 1
  'PRINT': BEGIN

        old_dev = !d.name
;        abchan = state.abchan
;        bcchan = state.bcchan
;        nant = state.header.nant
        ; List of channels, e.g. 5,7,9,11,... for 5-element, or 6,8,10,... for 6-element
        Chanlist = indgen(nant*(nant-1)/2)*2+nant
        nchan = n_elements(Chanlist)
;        set_plot,'ps'

        set_plot,'printer'
        device,/portrait
        range = state.range
        if (state.printall eq 1) then begin
           c1 = Chanlist[0]
           c2 = Chanlist[nchan-1]
        endif else begin
           c1 = state.chan
           c2 = c1
        endelse
        !p.multi=[0,1,2,0,0]
;        k = -1
        for i = c1, c2, 2 do begin
           state.chan = i
           select_data,state,ax,amp,pha
           title = state.title
           jndx = where(Chanlist eq i)
           plot,ax,amp,psym=1,xsty=1,thick=3,charthick=3,xthick=3,ythick=3,ymar=[-1.8,4],$
              ytitle='Amplitude',title=title,xtickname=replicate(' ',7)
           if (state.peak_loc[jndx] ne 0) then begin
              oplot,state.xfit[jndx,*],state.yfit[jndx,*],color=0,thick=3
              plots,state.peak_loc[jndx]*[1,1],[min(!y.crange),max(!y.crange)],/data,color=0
              xyouts,0.8,0.75,/norm,'Delay Center = '+string(state.peak_loc[jndx],$
                 format='(F6.2)')+' nsec',align=0.5,charthick=3,charsize=1.5,color=0
           endif
           if (state.soldif[jndx] ne 0) then begin
              xyouts,0.8,0.7,/norm,'Corrected = '+string(state.soldif[jndx],$
                 format='(F6.2)')+' nsec',align=0.5,charthick=3,charsize=1.5,color=0
           endif
           ichan = (i-nant)/2
           xyouts,0.8,0.8,/norm,state.srclist(ichan),align=0.5,charthick=3,charsize=1.5,color=0

           plot,ax,pha,psym=6,symsize=0.5,background=255,color=0,xsty=1,thick=3,$
              charthick=3,xthick=3,ythick=3,xtitle='Delay [nsec] relative to delay center',$
              ytitle='Phase',yran=[0,360],ysty=1,yticks=4
        endfor

        !p.multi=0
        device,/close
        set_plot,old_dev
        goto, WRITE_STATE
      END
  'TIMER': BEGIN
      ; Make print button insensitive until we get back into wait mode
      WIDGET_CONTROL,state.prtID,SENSITIVE=0

      ; Restore variable state from STATE structure
      if (not state.first_call) then data = *state.pdata
      state.first_call = 0
      rec = state.rec
      header = state.header
      nndw = 1 + header.ndbw + header.nfgw
      obseq = state.obseq
      cfg = state.cfg
      gparm = state.gparm
      geometry = state.geometry
      tcycle = state.tcycle
      range = state.range
      bigdata = state.bigdata
      pol = state.pol
      ncyc2avg = state.ncyc2avg
      rpol = where(*obseq.ppol eq 0,nrpol)
      lpol = where(*obseq.ppol eq 15,nlpol)
      if (nrpol ne 0) then polinx = 0
      if (nlpol ne 0) then polinx = 1
      navg = state.navg
      nchan = state.nchan
      nant = header.nant
      abchan = state.abchan
      bcchan = state.bcchan
      cachan = state.cachan
      i = state.i
      j = state.j
      a = *state.filptr

      ; Get next (or first) cycle of data
      cycle = get_cycle(a,data,rec,header,obseq,cfg,tcycle)

      n = n_elements(cycle)
      if (n eq 1) then begin
;         print,rec,' No new cycle yet'
         goto,restor  ; No new cycle available yet
      endif else i = i + 1

      while(n_elements(cycle) eq n) do begin

         bigdata(0) = cycle       ; Convert CYCLE to channelized floating array
         flagool,bigdata,header,obseq,/notrack      ; Apply flags for notrack, OOL
         ; Correct for complex gain and attenuation
         smldata = gaincor(bigdata,pol,header,cfg,obseq,tcycle,gparm,geometry)

         ; Save the channels for all frequencies, for L poln only
         ; state.out(*,i) = reform(smldata(*,*,2))
		 if (header.tls.yrday le 2004.300) then begin
            ldat = reform(smldata(*,*,0))
            idat = reform(smldata(*,*,2))
            lgood = where(finite(ldat),nlgood)
            igood = where(finite(idat),nigood)
            if (nigood gt 0) then ldat[igood] = idat[igood]
            if (nlgood gt 0) then idat[lgood] = ldat[lgood]
            state.out(*,i) = idat + ldat
         endif else begin
            state.out[*,i] = reform(smldata[*,*,polinx])
		 endelse
         if (state.ncyc2avg eq 1) then begin
            j = j + 1
            state.avg[*,j] = state.out
            state.sigma[*,j] = !values.f_nan
         endif else begin
            if (i eq (ncyc2avg-1)) then begin
               ; We have read NCYC2AVG cycles, so time to average the data
               j = j + 1
               for k1 = 0, nchan-1 do begin
                  ; Average the NCYC2AVG points for this channel

                  ; Note that the MOMENT() function is screwed up--doesn't work
                  ; when there is only one value, but works for none or any number
                  ; other than 1.  We have to write extra code to handle the
                  ; one-value case
                  good = where(finite(state.out(k1,*)),nfinite)
                  if (nfinite eq 1) then begin
                     state.avg[k1,j] = state.out[k1,good[0]]
                     state.sigma(k1,j) = !values.f_nan
                  endif else begin
                     mom = moment(reform(state.out(k1,*)),/nan)
                     state.avg[k1,j] = mom(0)
                     state.sigma(k1,j) = mom(1)
                  endelse
               endfor
            endif
         endelse

         if (i eq (ncyc2avg-1)) then begin
            i = -1
            if (j gt 0) then begin
               state.j = j
               select_data,state,ax,amp,pha
               wset,state.wid(0)
               good = where(finite(amp),ngood)
               if (ngood ge 2) then plot,ax,amp,psym=1,background=255,color=0,xsty=1,ytitle='Amplitude',$
                 xtitle='Delay [nsec] relative to delay center'
               ichan = (state.chan-nant)/2
               xyouts,0.8,0.8,/norm,state.srclist(ichan),align=0.5,charthick=2,charsize=1.5,color=0
               wset,state.wid(1)
               good = where(finite(pha),ngood)
               if (ngood ge 2) then plot,ax,pha,psym=6,symsize=0.5,background=255,color=0,xsty=1,ytitle='Phase',$
                 xtitle='Delay [nsec] relative to delay center'
               state.ampmax[state.chan] = max(amp)
            endif
         endif

         if (j eq navg-1) then begin
            cycle = 0
         endif else begin
            if (j ge range*4) then goto,restor
            cycle = get_cycle(a,data,rec,header,obseq,cfg,tcycle)
            if (n_elements(cycle) eq 1) then goto,restor
            i = i + 1
         endelse
      endwhile
restor: BEGIN
         ptr_free,state.pdata
         state.pdata = ptr_new(data)
         state.rec = rec
         state.tcycle = tcycle
         state.i = i
         state.j = j
         ; Make print button sensitive if we are in wait mode
         WIDGET_CONTROL,state.prtid,SENSITIVE=1
         ; The convoluted code below is due to the fact that get_cycle returns the
         ; segment code of the last record read (e.g. !SEGM.EOS for an EOS),
         ; in which case we do not want to set the timer again.  However, we cannot
         ; check if cycle = !SEGM.EOS until we ensure that cycle is not an array, hence the
         ; need to check n_elements(cycle)
         if (j lt range*4) then begin
            if (n_elements(cycle) ne 1) then begin
               WIDGET_CONTROL, state.TimerID, TIMER=1
            endif else begin
               if (cycle eq !SEGM.EOS or cycle eq !SEGM.HEADER) then begin
                  ; All done with this scan, so do not set the timer, and activate the FIT button
                  WIDGET_CONTROL,state.fitID,SENSITIVE=1
               endif else begin
                  ; Still working on this scan, so set the timer
                  WIDGET_CONTROL, state.TimerID, TIMER=1
               endelse
            endelse
         endif else begin
            WIDGET_CONTROL,state.fitID,SENSITIVE=1
         endelse
        END
     END
  'FIT': BEGIN
        ; Save a copy of the state variable to !defaults.workdir+'state.sav'
        save,file=!defaults.workdir+'state.sav',state
        ; List of channels, e.g. 5,7,9,11,... for 5-element, or 6,8,10,... for 6-element
        Chanlist = indgen(nant*(nant-1)/2)*2+nant
        nchan = n_elements(Chanlist)
        savchan = state.chan
        j = -1

        ; Loop over baselines, calling DLAFIT to fit the peaks of each delay pattern in turn
        for i = Chanlist[0],Chanlist[nchan-1],2 do begin
           state.chan = i
           j = j + 1
           select_data,state,ax,amp,pha

           dlafit, ax, amp, peak_loc, sigma, xfit, yfit
           print,peak_loc,sigma

           ; Save the results of the fit in the state structure
           state.peak_loc[j] = peak_loc
           state.sig_loc[j] = sigma
           state.xfit[j,*] = xfit
           state.yfit[j,*] = yfit
        endfor
        state.chan = savchan
        ; Turn off sensitivity of FIT button, and turn on SOLVE button
        WIDGET_CONTROL,state.fitID,SENSITIVE=0
        WIDGET_CONTROL,state.SolveID,SENSITIVE=1
     END
  'SOLVE': BEGIN
        ; Get the current delay center values from the CONFIG segment
        d = [state.cfg.dlacent[0:nant-1],state.cfg.bedlaoff]

        ; Get the fitted delay center shifts
        offset = state.peak_loc

        ; Allow the user to make adjustments in the solution if there are some
        ; bogus values
        wdla_adj,offset,out,group=base
        offset = *out

        ; Find the best solution to the delay centers that result in the smallest
        ; possible shifts in the delay patterns
        dlasolve,d,offset,t,new=state.new

        ; Convert the shifts to integer values (nsec) since they cannot be adjusted
        ; to smaller than that.
        t = nint(t)

        ; Print the solution
        print,'     Ant   Input  Output'
        case nant of
         5: begin
             ant = ['1','2','4','5','6']
             for i = 0, nant-1 do print,ant[i],d[i],t[i],format='(A8,2I8)'
             soln = dlapred(d,t)
            end
         6: begin
             ant = ['1','2','4','5','6','7','A','B']
             for i = 0, nant+1 do print,ant[i],d[i],t[i],format='(A8,2I8)'
             soln = dlapred6(d,t,new=state.new)
            end
         7: begin
             ant = ['1','2','4','5','6','7','8','A','B']
             for i = 0, nant+1 do print,ant[i],d[i],t[i],format='(A8,2I8)'
             soln = dlapred7(d,t)
            end
         else:
        endcase

        print,'   Orig Offset  Soln      Difference'
        for p = 0, nant*(nant-1)/2 - 1 do print, offset(p),soln(p),offset(p) - soln(p),format='(3f10.1)'

        state.soldif = offset - soln
     END
     ELSE:
  ENDCASE

WRITE_STATE:


  WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY

END


pro dlascan,filename,hrec,after=after, group=group

   ; If no filename, assume standard DAILY.ARC file
   IF (n_elements(filename) EQ 0) THEN $
                  filename=!defaults.workdir+'DAILY.ARC'

   ; Open the file
   lun = openarc(filename,a,nrec)

   IF (n_elements(hrec) EQ 0) THEN BEGIN
      IF (keyword_set(after)) THEN hrec = lasthrec(a,nrec,tstr=after) $
                              ELSE hrec = lasthrec(a,nrec)
   ENDIF

   ; Read header info, etc.  REC ends up pointing to the record *before* the
   ; start of data
   rec = newscan(a,nrec,hrec,header,obseq,cfg,traj,refcal,gparm,geometry,pRecent,pOld,cyc_str) - 1

   ; Check that this is DLASCAN data
   if (cfg.dlamode ne 2) then begin
      ans = dialog_message('DLASCAN: Delay mode not consistent with DLASCAN data.',/info)
      free_lun,lun
      return
   endif
   range = cfg.dlastep
   ncyc2avg = cfg.ndlacyc

   ; Set up title for plot, giving source name and date
   title = 'Delay Scan for '+strtrim(traj.srcname)+' on '+header.tls.date+' at '+header.tls.timstr

   ; Transfer needed part of cyc_str structure to more convenient variable
   ; names, then free the memory associated with those parts of cyc_str.
   bigdata = temporary(*cyc_str.pbigdata)
   pol = temporary(*cyc_str.ppol)

   if (n_elements(group) eq 0) then group=0

   ; Create widgets
   wbase = widget_base(group_leader=group, column=1, map=1, $
      /tlb_kill_request_events,title='DLASCAN',uvalue='mainbase')

   ExtraBase = WIDGET_BASE(wBase, $
      ROW=1, $
      MAP=1, $
      TITLE='ExtraBase', $
      UVALUE='ExtraBase')

   Label = WIDGET_LABEL(wBase,VALUE=title,FONT='Arial*Bold*20',/ALIGN_CENTER)
; Sizes for plot draw widgets
   xsiz = 600
   ysiz = 200
;   ysiz = 150
   wDraw = intarr(2)
   wid = intarr(2)
   wDraw[0] = WIDGET_DRAW(wBase, $
      XSIZE=xsiz, YSIZE=ysiz,FRAME=1,$
      UVALUE='Draw0',BUTTON_EVENTS=1)
   wDraw[1] = WIDGET_DRAW(wBase, $
      XSIZE=xsiz, YSIZE=ysiz,FRAME=1,$
      UVALUE='Draw1',BUTTON_EVENTS=1)

   TimerID = WIDGET_BASE(wBase, $
      ROW=1, MAP=1, $
      TITLE='ButtonBase', UVALUE='TIMER')

   nant = header.nant
   aatab = header.aatab
   maxant = 8
   droplstr = strarr(nant*(nant-1)/2)
   k = 0
   for i = 0, maxant-1 do begin
      for j = i+1, maxant-1 do begin
         if (aatab[i] ne 255 and aatab[j] ne 255) then begin
            droplstr[k] = string(aatab[i],aatab[j],format='(I1,I1," Baseline")')
            k = k + 1
         endif
      endfor
   endfor

;   droplstr = ['12 Baseline','14 Baseline','15 Baseline','16 Baseline',$
;                             '24 Baseline','25 Baseline','26 Baseline',$
;                             '45 Baseline','46 Baseline','56 Baseline']

   DSrcList = WIDGET_DROPLIST(TimerID,VALUE=droplstr, /DYNAMIC_RESIZE,UVALUE='Data Source')
   PrtID = WIDGET_BUTTON(TimerID,VALUE='PRINT',SENSITIVE=0,UVALUE='PRINT')
   SelID = CW_BGROUP(TimerID,/EXCLUSIVE,['This page','All pages'],$
      SET_VALUE=0, /COLUMN, /RETURN_NAME)
   FitID = WIDGET_BUTTON(TimerID,VALUE='FIT',SENSITIVE=0,UVALUE='FIT')
   SolveID = WIDGET_BUTTON(TimerID,VALUE='SOLVE',SENSITIVE=0,UVALUE='SOLVE')

   WIDGET_CONTROL, wBase, /REALIZE


   ; Use 256-color Pseudo-color
   device,decomposed=0

   ; Fix color table as RAINBOW, but with white as color 0 and black as color 255
   loadct,13
   tvlct,r,g,b,/get
   r(0)   = (g(0)   = (b(0)   =   0))
   r(255) = (g(255) = (b(255) = 255))
   tvlct,r,g,b
   !p.background=ovsa_get_color(255)

   ; Clear all of the windows to white
   for i = 0, 1 do begin
      WIDGET_CONTROL, wDraw[i], GET_VALUE=winid
      wid(i) = winid
      wset,wid(i)
      !p.background=ovsa_get_color(255)
      erase
   endfor

;   !p.background=0

   wset,wid(0)
   plot,indgen(4*range+1)-2*range,indgen(4*range+1),/nodata,yran=[0,4]
   wset,wid(1)
   plot,indgen(4*range+1)-2*range,indgen(4*range+1),/nodata,yran=[0,4]
;   ; Nominal time average is 10 s
;   timavg = 10.
;   ; Want to average over TIMAVG seconds so determine number of cycles
;   ; in TIMAVG s.  If cycle time is not comensurate with TIMAVG s then
;   ; averaging time can be slightly less, so that an integer number
;   ; of cycles is averaged.
;   cycletime = (obseq.nx*cfg.sampintms)  ; Duration of cycle, in msec
;   ; Check that timavg is defined sensibly, or set to 240. if not.
;   if (n_elements(timavg) eq 0) then timavg = 240. $
;            else if (timavg lt cycletime/1000L) then timavg = cycletime/1000L
;   ncyc2avg = fix(timavg*1000L/cycletime)              ; Number of cycles to average

   ; Determine the number of good frequencies in the cycle.  Should be only
   ; 1 frequency for DLASCAN data.
   nf = n_elements(*obseq.phord)
   if (nf ne 1) then begin
      ans = dialog_message(['DLASCAN: Observing sequence contains more than',$
      ' one frequency. Not a valid DLASCAN observing sequence'],/info)
      free_lun,lun
      return
   endif

   offidx = where(*obseq.pnd eq 2)  ; Indexes of obseq where noise diode is off

   ; LEN is the number of cycles in the file
   len = (range*4+1)*ncyc2avg
   navg = len/ncyc2avg
   nant = header.nant
   nchan = nant^2
   nndw = header.ndbw + header.nfgw + 1
   out = fltarr(nchan,ncyc2avg)

   ; AB channels are handled differently from other channels, due to the
   ; way that the delays are scanned.  Channel assignment information
   ; requires knowledge of the MUX sequence.
   abchan = header.lchoff[where(cfg.muxarr eq  0 and header.lchoff ne 255)]
   absrt = abchan(sort(abchan))
   abchan = absrt(uniq(absrt))-nndw
   bcchan = header.lchoff[where(cfg.muxarr eq -1 and header.lchoff ne 255)]
   bcsrt = bcchan(sort(bcchan))
   bcchan = bcsrt(uniq(bcsrt))-nndw
   cachan = header.lchoff[where(cfg.muxarr eq  1 and header.lchoff ne 255)]
   casrt = cachan(sort(cachan))
   cachan = casrt(uniq(casrt))-nndw
   new  = 0  ; This is a switch to handle two MUX sequences used in 6-element DLASCANs
   if (nant eq 6 and header.tls.yrday gt 2002.278) then new = 1

   avg = (sigma = fltarr(nchan,navg))

   state = { $ ; Widget IDs
             wDraw:    wDraw, $ ; Array of 2 draw widgets
          DSrcList:  DSrcList, $ ; Data source droplist ID
               wid:      wid, $ ; Array of window IDs
           TimerID:  TimerID, $ ; The ID of the widget being used for the timer
             PrtID:    PrtID, $ ; The ID of the print button
             FitID:    FitID, $ ; The ID of the FIT button
             SolveID:  SolveID, $ ; The ID of the SOLVE button
            header: header, cfg:cfg, obseq:obseq, $
             title: title, srclist:droplstr, $
             SelID: SelID, printall:0, $
          Geometry: Geometry, GParm:GParm, $
           bigdata: bigdata, pol: pol, pdata: ptr_new(0), $
            filptr: ptr_new(a), ampmax: fltarr(nchan), $
               rec: rec, tcycle:0L,$
              navg: navg, ncyc2avg:ncyc2avg, nchan:nchan, range: range, i:-1, j:-1, $
               out: out, avg: avg, sigma: sigma, chan:nant, $
               peak_loc: fltarr(nant*(nant-1)/2), $
               sig_loc:  fltarr(nant*(nant-1)/2), $
               xfit: fltarr(nant*(nant-1)/2,90), $
               yfit: fltarr(nant*(nant-1)/2,90), $
               soldif: fltarr(nant*(nant-1)/2), $
               new:new, $
        first_call: 1, lun: lun, abchan:abchan, bcchan:bcchan, cachan:cachan $
     }


   WIDGET_CONTROL, ExtraBase, SET_UVALUE=state, /NO_COPY

   ; Set a 1 s timer to get things rolling
   WIDGET_CONTROL, TimerID, TIMER=1

   XMANAGER,CATCH=0

   XMANAGER, 'DLASCAN', wBase

return
end