
;+
; NAME:
;     EIS_FIND_FILE
;
; PURPOSE:
;     For the specified input day and time, this routine searches for
;     the EIS level-0 file nearest in time. Options exist to search
;     for level-1 and quicklook files, too.
;
;     Please see EIS Software Note 18 for information on how to
;     organize EIS data on your computer.
;
; CATEGORY:
;     Hinode/EIS; file-handling
;
; CALLING SEQUENCE:
;     Result = EIS_FIND_FILE(Time)
;
; INPUTS:
;     Time:  This can be in any format accepted by the ANYTIM suite of
;            routines. For example, '1-jan-2010', '2010-01-01 05:00'.
;
; OPTIONAL INPUTS:
;     Twindow:  By default the routine finds the nearest file to the
;               input time. This keyword will match a file, if the
;               start time of the file lies in the interval
;               TIME+/-TWINDOW, where TWINDOW is specified in
;               seconds. 
;
; KEYWORD PARAMETERS:
;     QUICKLOOK:Search the EIS quicklook directories.
;
;     LEVEL1:   Look for level-1 files.
;
;     ERROR:    Look for level-1 error files.
;
;     ALL:      If set, then all filenames for the specified day will
;               be returned.
;
;     QUIET:    If set, then no information messages are printed.
;
;     BACKWARDS: If set, then the search for the nearest file goes
;                backward in time from TIME. 
;
;     SEQUENCE: If set, then the routine searches for the file closest
;               to the input time and, if found, it then searches for
;               all files that belong to the same raster sequence as
;               the found file. The complete list of files is then
;               returned.
;
; OUTPUTS:
;     A string containing the full path to an EIS file. If the keyword
;     /ALL was given, then a string array containing all matching EIS
;     files will be returned.
;
;     If the keyword /SEQUENCE is given, then the names of all files
;     that belong to the same raster sequence as the found file will
;     be returned.
;
;     If there are no matches, then an empty string is returned.
;
; OPTIONAL OUTPUTS:
;
;     Count: An integer containing the number of matching files.
;
; EXAMPLES:
;
;     IDL> file=eis_find_file('1-jan-2010 05:00')
;
;     IDL> files=eis_find_file('1-jan-2010')
;
;     If a raster is repeated at 10min intervals (11:00, 11:10, 11:20,
;     ...), and you know that an event occurs at 11:19, then it will
;     be captured by the raster beginning at 11:10, not the one at
;     11:20. In this case, use the /backwards keyword:
;
;     IDL> file=eis_find_file('1-jan-2010 11:09',/backwards)
;
;     On 29-Mar-2014 14:05 a raster was repeated 104 times, finishing
;     at 17:57. The complete set of raster files can be found by
;     doing:
;
;     IDL> files=eis_find_file('29-mar-2014 16:00',/sequence)
;
; CALLS:
;     ANYTIM2DIR, ANYTIM2UTC, HMS2SEC, EIS_OBS_STRUCTURE
;
; MODIFICATION HISTORY:
;     Ver.1, 8-Aug-2012, Peter Young
;        renamed from eis_day_files.pro.
;     Ver.2, 15-Aug-2012, Peter Young
;        corrected bug when /all and /quiet were set - not all of the
;        files were being returned.
;     Ver.3, 27-Aug-2012, Peter Young
;        I've added compatibility with $EIS_FITS_DATA since some
;        users may use this. However, $HINODE_DATA takes precedence. 
;     Ver.4, 28-Aug-2012, Peter Young
;        Updated header. No change to code.
;     Ver.5, 7-Jan-2012, Peter Young
;        Added TWINDOW= keyword; now prints message giving time
;        difference between found time and requested time.
;     Ver.6, 18-Oct-2013, Peter Young
;        Added /backwards keyword.
;     Ver.7, 4-Aug-2014, Peter Young
;        Added /sequence keyword.
;     Ver.8, 6-Aug-2014, Peter Young
;        Fixed problem if local files don't exist for
;        /sequence; correctly implemented /quiet.
;     Ver.9, 22-Oct-2014, Peter Young
;        Corrected bug when no files are found and /quiet set.
;     Ver.10, 14-Jan-2015, Peter Young
;        Added warning in case where /quicklook and /sequence keywords
;        are used together.
;     Ver.11, 15-Jan-2015, Peter Young
;        For very new level-0 files, the user may not have an
;        up-to-date as-run database so I check for this now. 
;     Ver.12, 5-Mar-2015, Peter Young
;        Fixed minor bug.
;     Ver.13, 20-Oct-2015, Peter Young
;        Fixed a problem when using /SEQUENCE for response
;        studies. The routine now correctly picks up the right
;        sequence.
;     Ver.14, 15-Dec-2023, Peter Young
;        Added /quick keyword in call to eis_obs_structure.
;     Ver.15, 13-Mar-2026, Peter Young
;        If $HINODE_DATA or $EIS_FITS_DATA contain multiple paths,
;        then eis_find_file will look for files along both paths.
;-


FUNCTION eff_sequence, filename, quicklook=quicklook, level1=level1, count=count, quiet=quiet
;
; In order to find the list of files in the raster sequence, the key
; thing is the timeline ID (tl_id). I read the fits file to extract
; tl_id, then use eis_obs_structure to retrieve a list of all the
; files in the sequence.
;
;  Filename:  Name of an EIS file.
;  Quicklook: Search for quicklook files.
;  Level1:    Search for level-1 files.
;  Count:     The number of files that have been found.
;

;
; Response studies (those with tl_id=1 to 4) cause a problem for
; eff_sequence, but I get around this by extracting some information
; for the "found" file below. In particular tseq0_tai and tseq1_tai
; give a time bound for when the response study group should occur. I
; then filter on this later in the code.
;
; Note that I tested this using data from 7-Jun-2013 when the flare
; trigger went off at 22:37 and then again at 23:56. My routine is
; able to differentiate between these two groups.
;
d=obj_new('eis_data',filename)
tl_id=d->getinfo('TL_ID')
t0_tai=anytim2tai(d->getinfo('DATE_OBS'))
t1_tai=anytim2tai(d->getinfo('DATE_END'))
dt=t1_tai-t0_tai
rrep_req=d->getinfo('RREP_REQ')
rrep_pfd=d->getinfo('RREP_PFD')
tseq0_tai=t0_tai-(rrep_pfd-1)*dt -dt   ; dt is subtracted for margin
tseq1_tai=t0_tai+(rrep_req-rrep_pfd)*dt +dt  ; dt is added for margin
obj_destroy,d

str=eis_obs_structure(tl_id=tl_id,count=n,/quick)
IF n EQ 1 AND str[0].tl_id EQ 0 THEN BEGIN
  print,'% EFF_SEQUENCE: no entries found in the as-run database. Try updating your Solarsoft.'
  list=''
ENDIF ELSE BEGIN
 ;
 ; I have to do some filtering for response study rasters (tl_id
 ; between 1 and 4).
 ;
  IF tl_id GE 1 AND tl_id LE 4 THEN BEGIN
    t_tai=anytim2tai(str.date_obs)
    k=where(t_tai GE tseq0_tai AND t_tai LE tseq1_tai,nk)
    str=str[k]
    n=n_elements(str)
  ENDIF
  
  list=''
  FOR i=0,n-1 DO BEGIN
    file=eis_find_file(str[i].date_obs,level1=level1,quicklook=quicklook,count=nn, $
                       /quiet,twindow=5)
    IF nn NE 0 THEN BEGIN
      list=[list,file]
    ENDIF ELSE BEGIN
      tt=anytim2utc(/ccsds,str[i].date_obs,/time,/trunc)
      IF NOT keyword_set(quiet) THEN print,'% EIS_FIND_FILE: sequence file not available on local disk ('+tt+')'
    ENDELSE 
  ENDFOR 
  list=list[1:*]
  
  count=n_elements(list)

  IF count NE n THEN BEGIN
    IF NOT keyword_set(quiet) THEN print,'% EIS_FIND_FILE: only '+trim(count)+' of '+trim(n)+' files available locally.'
  ENDIF 
ENDELSE 

return,list

END


FUNCTION eis_find_file, ttime, quicklook=quicklook, $
                        level1=level1, error=error, count=count, quiet=quiet, $
                        all=all, twindow=twindow, backwards=backwards, $
                        sequence=sequence


IF n_params() LT 1 THEN BEGIN
  print,'Use:  IDL> file=eis_find_file(time [, /all, /level1, /quicklook, /quiet, count=, twindow=])'
  print,''
  print," Example time formats:  '1-jan-2010 05:00', '2010-01-01 05:00'"
  return,''
ENDIF 

IF keyword_set(quicklook) AND keyword_set(sequence) THEN BEGIN
  print,'% EIS_FIND_FILE:  Sorry, the /quicklook and /sequence keywords are incompatible with each other. '
  print,'                  (The /sequence keyword accesses the as-run database, and quicklook files are '
  print,'                  not in the as-run database.)'
  return,''
ENDIF 

eisdata=getenv('EIS_FITS_DATA')
hindata=getenv('HINODE_DATA')

IF eisdata EQ '' AND hindata EQ '' THEN BEGIN
  print,'% EIS_FIND_FILE: please define the environment variable $HINODE_DATA to point to the location'
  print,'                 of your Hinode data'
  return,''
ENDIF

IF hindata NE '' THEN BEGIN
  hinode_paths=BREAK_path(hindata,/nocurrent)
  eisdata=concat_dir(hinode_paths,'eis')
ENDIF ELSE BEGIN
  eisdata=BREAK_path(eisdata,/nocurrent)
ENDELSE 

;
; The default quicklook data location is set to be the same as that
; used at ISAS.
;
qdir=getenv('EIS_QL_DATA')
IF qdir EQ '' THEN BEGIN
  qdir=concat_dir(eisdata,'quicklook')
  qdir=concat_dir(qdir,'mission')
ENDIF 

l0dir=getenv('EIS_L0_DATA')
IF l0dir EQ '' THEN l0dir=concat_dir(eisdata,'level0')

l1dir=getenv('EIS_L1_DATA')
IF l1dir EQ '' THEN l1dir=concat_dir(eisdata,'level1')


CASE 1 OF
  keyword_set(quicklook): BEGIN
    dir=qdir
    ttstr='_l0_'
  END 
  keyword_set(level1): BEGIN
    dir=l1dir
    ttstr='_l1_'
  END 
  keyword_set(error): BEGIN
    dir=l1dir
    ttstr='_er_'
  END 
  ELSE: BEGIN
    dir=l0dir
    ttstr='_l0_'
  END
ENDCASE 

datedir=anytim2dir(ttime)

;
; Note that file_search accepts an array of search directories.
;
searchdir=concat_dir(dir,datedir)
list=file_search(searchdir,'*'+ttstr+'*.fits*',count=count)
print,searchdir

IF count EQ 0 THEN BEGIN
  IF NOT keyword_set(quiet) THEN message,/info,/cont,'There are no files for this day. Returning...'
  return,''
ENDIF 

;
; This returns all files for the specified data.
;
IF keyword_set(all) THEN BEGIN
  IF count GT 0 THEN BEGIN
    IF NOT keyword_set(quiet) THEN BEGIN
      print,trim(count)+' files found: '
      FOR i=0,count-1 DO BEGIN
        print,format='(i3,2x,a30)',i,file_basename(list[i])
      ENDFOR 
    ENDIF 
    return,list
  ENDIF
ENDIF 

hhmmss=anytim2utc(ttime,/trunc,/time,/ccsds)
hhmmss=str_replace(hhmmss,':','')

sec_ref=hms2sec(hhmmss)

;
; The following extracts the file start time from the filename.
;
list_times=strmid(file_basename(list),16,6)

sec_all=hms2sec(list_times)

;
; Now find closest file to input time.
; 
IF keyword_set(backwards) THEN BEGIN
  k=where(sec_ref GE sec_all,nk)
  IF nk GT 0 THEN BEGIN
    getmin=min(sec_ref-sec_all[k],imin)
  ENDIF ELSE BEGIN
    print,'% EIS_FIND_FILE:  no file was found.'
    return,''
  ENDELSE 
ENDIF ELSE BEGIN 
  getmin=min(abs(sec_ref-sec_all),imin)
ENDELSE 

IF NOT keyword_set(quiet) THEN BEGIN
  IF getmin GE 120 THEN BEGIN
    tstr=trim(string(format='(f12.1)',getmin/60.))+' mins'
  ENDIF ELSE BEGIN
    tstr=trim(string(format='(f12.1)',getmin))+' secs'
  ENDELSE 
  print,'% EIS_FIND_FILE:  nearest file is '+tstr+' from requested time.'
ENDIF 

IF n_elements(twindow) NE 0 THEN BEGIN
  IF getmin GT twindow THEN BEGIN
    count=0
    IF NOT keyword_set(quiet) THEN print,'% EIS_FIND_FILE:  no filename returned.'
    return,''
  ENDIF 
ENDIF 

count=1

outfile=list[imin]

;
; Retrieve the list of files belonging to the same raster sequence as outfile.
;  (eff_sequence is an internal routine).
;
IF keyword_set(sequence) THEN BEGIN
  outfile=eff_sequence(outfile,quicklook=quicklook,level1=level1,count=count)
ENDIF 

return,outfile

END

