Viewing contents of file '../idllib/contrib/groupk/findsrc.pro'
;+
; NAME:
;        FINDSRC
;
; PURPOSE:
;        Interactively finds all x-ray sources around a primary source
;        within the field of view of a HEAO A-1 scan. Uses the XXX database.
;
; CATEGORY:
;        Database.
;
; CALLING SEQUENCE:
;
;        Result = FINDSRC( Module, Cts, Src, Sat )
;
; INPUTS:
;        Module:   Collimator module number.
;
;        Cts:      Counts of the scan, fltarr(nbin).
;
;        Src:      Structure containing information about the primary source.
;                  Its must have the following tags defined:
;
;                  RA:  The RA of the primary source in DEGREES.
;                  DEC: The DEC of the primary source in DEGREES.
;                  trn: The collimator transmissions of the primary source
;                       across the scan, fltarr(nbin).
;
;        Sat:      Structure containing information about the satellite's
;                  position. It must have the following tags defined:
;
;                  RAY,DEY:  The RA,DEC of the Y-axis of the satellite
;                            in RADIANS at either the beginning of each
;                            major frame, fltarr( nmjfs ) or at each
;                            bin, fltarr( nbin ).
;                  RAZ,DEZ:  The RA,DEC of the Z-axis of the satellite
;                            in RADIANS at either the beginning of each
;                            major frame, fltarr( nmjfs ) or at each
;                            bin, fltarr( nbin ).
;
; OPTIONAL INPUT KEYWORD PARAMETERS:
;
;        DEGREES:  Set this keyword to interactively input the RA and
;                  DEC of any additional USER-defined sources not
;                  found in the database in DEGREES. ((hh mm ss) and
;                  (dd mm ss)] = Default).
;
;        FLUX_CUTOFF:   Minimum flux requirement in MICROJY for any
;                  source found in the database, (i.e. you want to find
;                  all sources with its max. flux > FLUX_CUTOFF). (0=Default)
;
;        MJFS:     List of major frame numbers for this scan, lonarr( nmjf ).
;
;        USERSRC:  ARRAY of structures holding information about each
;                  USER-defined source to be plotted and returned
;                  in addition to those found by the database. It must
;                  have the following tags defined for each structure.
;
;                  Name:     The name of the source, string.
;                  RA:       The RA of the source in DEGREES.
;                  DEC:      The DEC of the source in DEGREES.
;
;                  (See example below for implementation).
;
; OUTPUTS:
;        This function first finds all the sources around a primary source
;        and within the field of view of a scan by searching a database.
;        Only those sources the USER interactively specifies will be
;        returned in an ARRAY of structures with tags defined as:
;
;        Name:     The name of the source, string.
;        RA:       The RA of the source in DEGREES.
;        DEC:      The DEC of the source in DEGREES.
;
;        If no sources are accepted by the USER then -1 is returned.
;
; RESTRICTIONS:
;        There are TWO PRECONDITIONS that must be satisfied before calling
;        this routine, 1) That the XXX database is currently opened using
;        the Astronomy Library routine DBOPEN; and 2) The light curve
;        color table has already been loaded by calling the LCLOADCT routine.
;        (See example below).
;
; PROCEDURE:
;        When you call this routine, a database is first searched for all
;        sources within a cone about the primary source, defined by the
;        Src structure. The (1/2) separation or polar angle defining this
;        cone is the larger of the two angles between the source position
;        on the scan and the bin edges of the scan added in quadrature with
;        8 degrees to account for the collimator's acceptance.
;
;        For each source found, its corresponding transmissions are
;        calculated across the scan. The transmissions for this source
;        as well as for the primary source are then plotted over the
;        light curve for this scan.  The USER is then prompted about
;        whether to add this source to the list that will eventually be
;        returned.
;
; EXAMPLE:
;        Let's say we want to find all the sources around 1H1741-32
;        that will actually show up in the scan because they're within
;        the acceptance of the collimator module.
;
;        name = '1H1741-32'
;        src  = { RA:265.4, DEC:-32.2, Trn:trn }
;        sat  = { RAY:RAY, DEY:DEY, RAZ:RAZ, DEZ:DEZ }
;
;        Let's additionally say we already know two sources, 1H1715-321
;        and 1H1728-334.A that will show up; so we want them plotted
;        immediately:
;
;        othersrc = { name:'', RA:0.0, DEC:0.0 }
;        othersrc = REPLICATE( othersrc, 2)
;        othersrc( 0).name =
;        othersrc( 0).RA   =  258.885
;        othersrc( 0).DEC  =  -32.1261
;        othersrc( 1).name = '
;        othersrc( 1).RA   =  262.165
;        othersrc( 1).DEC  =  -33.7969
;
;        We must first open the XXX database, and load the light curve
;        color table:
;
;        DBOPEN,'xxx'
;        LCLOADCT
;
;        Now, we can go ahead and interactively get the list:
;
;        list = FINDSRC( Module, Cts, Src, Sat, USERSRC=othersrc )
;
;        You will find, in addition to those you accept:
;
;        list(0).name   = 1H1715-321
;        list(1).name   = 1H1728-334.A
;
;        ..etc
;
; MODIFICATION HISTORY:
;        Written by:    Han Wen, November, 1994.
;        30-DEC-1994    Widgetized this routine FINDSRC->FINDSRC.
;        10-JAN-1995    Fixed small typo bug.
;        22-JAN-1995    Moved FINDSRC -> OBSOLETE directory. Renamed
;                       XFINDSRC->FINDSRC
;-
function FINDSRC, Module, Cts, Src, Sat, DEGREES=Degrees, $
                  FLUX_CUTOFF=Flux_cutoff, USERSRC=USERsrc, MJFS=Mjfs


         common lc_colors, ncolors, linecolors, black, cyan, white

         Msg_ID=0

         WIDGET_CONTROL,/HOURGLASS

         lcloadct

         title=''
         if keyword_set(MJFS) then title = 'MJF:'+arr2str(mjfs)
         xfmsg     = 'Findsrc Message'
         xfw       = 'Findsrc WARNING'

;   Define XQUERY buttons

         buttons = [ $
                   '?', $
                   'Add current source to list',$
                   'Redo source selection for this scan',$
                   'Quit source hunting for this scan' $
                   ]
         values  = [ 'N', 'A', 'R', 'Q' ]


;   Unpack data from Src and Sat structures

         trn_src   = Src.trn
         srcRA     = Src.RA
         srcDEC    = Src.DEC

         RAY       = Sat.RAY
         DEY       = Sat.DEY
         RAZ       = Sat.RAZ
         DEZ       = Sat.DEZ

;   Extract number of elements info

         nbin      = N_ELEMENTS( Cts )
         nasp      = N_ELEMENTS( RAY )

         nsrcmax   = 200
         asrc      = { findsrc, name: '',  RA: 0.0, DEC: 0.0 }
         othersrc  = REPLICATE( asrc, nsrcmax )
         othertrns = fltarr( nbin, nsrcmax )
         srccolor  = intarr( nsrcmax )
         nother    = 0

;   Scale transmissions to the middle 1/2 of the screen

         ct_min    = MIN( cts, MAX=ct_max )
         ct_rng    = ct_max - ct_min
         avg_bkd   = 0.25 * ct_rng + ct_min
         Iavg      = 0.50 * ct_rng

;   Find existing sources in the XXX database

         trnmax    = MAX( trn_src, binmax )
         sang      = abs( nbin-1 - binmax ) > binmax
         sang      = 0.05 * sang             ;degrees, 38.4 min spin period
         sang      = sqrt( sang^2. + 8.^2. ) ;collimator 1x4 window
         cone= ['Considering a cone of polar angle:',$
                 strtrim(sang,2)+' [deg]']
         xmsg, cone, TITLE=xfmsg, /LEFT, /TOP, /NOBUTTON, MSG_ID=cone_id

         if n_elements( FLUX_CUTOFF ) eq 0 then Flux_cutoff = 0.0

         list      = dbcircle( srcRA/15., srcDEC, 60.*sang, dist )
         if list(0) ne -1 then begin
              dbext,list,'name,ra_deg,dec,flux_min,flux_max',$
                        fovName,fovRA,fovDEC,fluxmin,fluxmax

              here_avg  = where( fluxmax eq 0, nmin ) ;Average flux sources
              here_rng  = where( fluxmax gt 0, nmax ) ;Range of fluxes sources

;   If there are average flux sources see if any of them are
;   greater than the cutoff flux

              if nmin gt 0 then begin
                   hhere_min =  $
                        where( fluxmin( here_avg ) gt Flux_cutoff, nmin )
              endif

;   If there are range of fluxes sources see if any of them have their
;   maximum flux greater than the cutoff flux

              if nmax gt 0 then begin
                   hhere_max =  $
                        where( fluxmax( here_rng ) gt Flux_cutoff, nmax )
              endif

              nfov      = nmin + nmax
              CASE nfov OF
                      0 :    here = -1
                   nmin :    here =  here_avg( hhere_min )
                   nmax :    here =  here_rng( hhere_max )
                   else :    here = [here_avg( hhere_min ), $
                                     here_rng( hhere_max )]
              ENDCASE

              if nfov gt 0 then begin
                   list      = list( here )
                   dist      = dist( here )
                   fovName   = fovName( here )
                   fovRA     = fovRA( here )
                   fovDEC    = fovDEC( here )
                   fluxmin   = fluxmin( here )
                   fluxmax   = fluxmax( here )
                   xmsg, [strtrim(nfov,2)+' sources found within '+$
                          'Field of View of scan ',$
                          'with Flux >'+strtrim(Flux_cutoff,2)], $
                          TITLE=xfmsg
                   newline
                   dbprint,list
              endif else $
                   xmsg,'No sources within Field of View',TITLE=xfmsg
         endif else nfov = 0

         WIDGET_CONTROL, cone_id, /DESTROY

;   Start adding new sources in

         landscape,title='Source Hunting...'
REDO:    isrc      = 0
         name      = ''
         eol       = 0
         j         = 0
         DEG_SET   = keyword_set( DEGREES )
         if Msg_ID ne 0 then begin
              WIDGET_CONTROL, Msg_ID, /DESTROY
              Msg_ID=0
         endif
         if keyword_set( USERSRC ) then begin
              nuser     = N_ELEMENTS( USERSRC )
              nother    = nuser
              srccolor(0:nuser-1)     = linecolors( 1+indgen( nuser ) )
              othersrc(0:nuser-1).name= USERsrc.name
              othersrc(0:nuser-1).RA  = USERsrc.RA
              othersrc(0:nuser-1).DEC = USERsrc.DEC

              RAs       = [ USERsrc.RA ]*!dtor
              DECs      = [ USERsrc.DEC]*!dtor

              for i=0,nuser-1 do begin
                   if nasp eq nbin then $

                        trns = COLLF( module, RAs(i), DECs(i), $
                                      RAY, DEY, RAZ, DEZ ) $

                   else begin

                        if nasp gt 1 then begin
                             trns = GET_TRNS( module, nbin, RAs(i), $
                                              DECs(i), RAY, DEY, RAZ, DEZ )
                        endif else begin
                             xmsg,['WARNING: Only ONE MJF in this scan',$
                                   '-> Cannot determine transmissions', $
                                   'for extra sources.'], TITLE=xfw

                             trns = REPLICATE(0.,nbin)
                        endelse
                   endelse
                   othertrns(*,i)      = trns
              endfor

         endif else begin
              nuser     = 0
              nother    = 0
              srccolor(*)       = 0
              othersrc(*).name  = ''
              othersrc(*).RA    = 0.0
              othersrc(*).DEC   = 0.0
              othertrns         = fltarr(nbin,nsrcmax)
         endelse


NEWSRC:  if j lt nfov then begin
              Action    = 'Display next source'
              name      = fovName(j)
              RA        = fovRA(j)
              DEC       = fovDEC(j)
              flux      = [fluxmin(j),fluxmax(j)]
              srcsep    = dist(j)/60.
              j         = j+1
         endif else begin
           if (j eq nfov) and (eol eq 0) then begin
                Action  = 'Add USER-defined source'
                endlist   = ['Reached end of list',$
                        'of sources in FOV.']
                xmsg, endlist, TITLE=xfmsg
                eol  = 1
                goto, QUERY
           endif else begin
                 Action  = 'Add USER-defined source'
                 udsrc= 'USER-defined source'
                 name = XQUERY( 'Name of source: ', TITLE=udsrc )
                 name = name(0)

                 flux = [0.,0.]
                 if DEG_SET then begin
                      qs   = ['RA  [Degrees]: ','DEC [Degrees]: ']
                      dirs = XQUERY( qs, TITLE=udsrc )
                      RA   = float( qs(0) )
                      DEC  = float( qs(1) )
                 endif else begin
                      qs   = ['RA    [hours]: ', $
                              'RA  [minutes]: ', $
                              'RA  [seconds]: ', $
                              'DEC [degrees]: ', $
                              'DEC [minutes]: ', $
                              'DEC [seconds]: '  ]
                      dirs = XQUERY( qs, TITLE=udsrc )
                      RAhr = float( dirs(0) )
                      RAmin= float( dirs(1) )
                      RAsec= float( dirs(2) )
                      DEChr= float( dirs(3) )
                      DECmin=float( dirs(4) )
                      DECsec=float( dirs(5) )

                      signRA    = sign( RAhr )
                      signDEC   = sign( DEChr )
                      RA   = signRA  * 15.*(abs(RAhr) + RAmin/60. + RAsec/3600.)
                      DEC  = signDEC * (abs(DEChr) + DECmin/60. + DECsec/3600.)
                      xmsg, [ 'RA  [Degrees]:'+strtrim(RA,2), $
                              'DEC [Degrees]:'+strtrim(DEC,2) ], TITLE=udsrc
                 endelse
                 srcRA_rad = srcRA*!dtor
                 srcDEC_rad= srcDEC*!dtor
                 RA_rad    = RA*!dtor
                 DEC_rad   = DEC*!dtor
                 srcsep    = SEPANGLE( srcRA_rad, srcDEC_rad, RA_rad, DEC_rad )
                 srcsep    = srcsep * !radeg
           endelse
         endelse


;   See if next source is the primary

         if srcsep lt 0.001 then begin
              print,'Source ',name,' is the Primary source.'
              if j ne nfov then goto, NEWSRC
         endif

;   Determine the transmissions for the next source on the list

         RAs  = RA*!dtor
         DECs = DEC*!dtor

         if nasp eq nbin then $

              trns = COLLF( module, RAs, DECs, $
                            RAY, DEY, RAZ, DEZ ) $

         else begin

              if nasp gt 1 then begin
                   trns = GET_TRNS( module, nbin, RAs, $
                                    DECs, RAY, DEY, RAZ, DEZ )
              endif else begin
                   xmsg,['WARNING: Only ONE MJF in this scan',$
                         '-> Cannot determine transmissions', $
                         'for extra sources.'], TITLE=xfw

                   trns = REPLICATE(0.,nbin)
              endelse
         endelse

         trnsum    = total( trns )
         if trnsum eq 0 then begin
              print,'Source ',name,' outside scan field of view.'
              if j ne nfov then goto, NEWSRC
         endif

;   First plot the data with the primary source transmission

         plot,cts,psym=10,/xstyle, color=white, $     ;data
              xtitle='Bin',$
              ytitle='Counts/mode', $
              title =title, $
              subtitle='Source:'+name
         src  = avg_bkd + Iavg * trn_src
         oplot,src,color=linecolors(0)                ;primary source

;   Then plot any additional sources added to our list

         for i=0,nother-1 do begin
              src  = avg_bkd + Iavg * othertrns(*,i)
              oplot,src,color=srccolor(i)
         endfor

;   And overplot the next source transmissions

;   Check to see if it has already been added to the list

         here = where( name eq othersrc.name, nfind )
         if name eq '' then nfind = 0
         if nfind eq 0 then begin

              src       = avg_bkd + Iavg * trns
              icolor    = (isrc + 1) MOD ncolors
              oplot,src,color=linecolors(icolor)
              legendstr = LCLEGEND( name, max(flux) )
              legend, legendstr, /right, colors=linecolors(icolor), $
                      textcolors=[white,white], psym=8, /fill
              if !D.NAME eq 'WIN' then wshow

              isrc = isrc + 1

         endif else begin
              print,'Plotting existing sources.'
              goto, NEWSRC
         endelse

         udtxt = [ 'Name of additional source:'+name, $
                   'Distance to primary source [deg]:'+$
                    arr2str(srcsep,3),$
                   'Flux min:'+arr2str(flux(0),4)+' [microJy]',$
                   'Flux max:'+arr2str(flux(1),5)+' [microJy]' ]
         xmsg, udtxt, TITLE=xfmsg, /ALIGN, /LEFT, /BOTTOM, /NOBUTTON, $
               MSG_ID=Msg_ID


;   Query USER whether or not to add this next source to our list

QUERY:   buttons(0) = Action
         rp = XBUTTON( buttons, values, /COLUMN, TITLE='Source Hunting Menu' )
         if Msg_ID ne 0 then begin
              WIDGET_CONTROL, Msg_ID, /DESTROY
              Msg_ID=0
         endif
         case rp of
              'N'  : goto, NEWSRC
              'A'  : begin
                        ; Check to see if it has already been added
                        here = where( name eq othersrc.name, nfind )
                        if nfind ge 1 then $
                             xmsg,'Source already added to list.',TITLE=xfmsg $
                        else begin
                             srccolor(nother)       = linecolors(icolor)
                             othersrc(nother).name  = name
                             othersrc(nother).RA    = RA
                             othersrc(nother).DEC   = DEC
                             othertrns(*,nother)    = trns
                             nother  = nother + 1
                             xmsg,'Added source to list.',TITLE=xfmsg,$
                                  /NOBUTTON, MSG_ID=Msg_ID
                        endelse
                        goto, QUERY
                     end
              'Q'  : begin
                        data = -1
                        if nother gt 0 then data = othersrc(0:nother-1)
                        return, data
                     end
              'R'  : begin
                        xmsg,'Redoing source selection for this scan.',$
                             TITLE=xfmsg, /NOBUTTON, MSG_ID=Msg_ID
                        goto, REDO
                     end
         endcase
end