;+
; Name: grs2fits
; 
; Purpose: Write the SMM / GRS data stored in UNH-provided .USE files into FITS files
; 
; Method: The UNH .USE files are stored on 'ftp://umbra.nascom.nasa.gov/pub/smm/smmgrs/solar_flare/
;  Ran grs2fits through a main program that looked like this:
;    sock_dir,'ftp://umbra.nascom.nasa.gov/pub/smm/smmgrs/solar_flare/', list
;    for i=0,n_elements(list)-1 do begin
;      if file_basename(list[i]) ne 'test.dat' then begin
;        sock_copy, list[i], local_file=usefile
;        grs2fits, usefile
;      endif
;    endfor
;    end
;  Output FITS files are written in /data/smm/grs/yyyy directories and named with the start/end time of the
;  data as well as the original .USE file name.
;
; Calling sequence:  grsdfits, usefile
; 
; Calling arguments:
;   usefile - name of .USE file to use as input
;   
;Written:  Kim Tolbert, 18-Mar-2019
; Modifications: 
;  29-Mar-2019, Kim.  Include full original USE file name in new output file name, and add an extension containing
;    the full structure returned by grs_extract - contains all data from USE file.
;  23-Apr-2019, Kim. Call str_named2anon to convert all_data structure (and nested structures) to anonymous before
;    writing them in last extension. (When named structures, user can't restore the structure without access to the
;    structure defintion files which are in grs_user_str in the smm/grs branch of SSW)
;-

 
pro grs2fits, infile
  data = grs_read_use_file(infile)
  
  if ~is_struct(data) || $
    ~have_tag(data,'edges') || $
    n_elements(data.edges) eq 0 || $
    data[0].ut[0] eq 0 then begin
    message, /cont, 'Error reading file ' + infile
    return
  endif
  
  orig_filename = file_basename(infile, '.USE')
  
  nchan = n_elements(data.edges) / 2.
  ntime = n_elements(data.ut) / 2.

  tr = [data.ut[0,0], data.ut[1,ntime-1]]
  stime = time2file(tr[0], sec=0)
  etime = time2file(tr[1], sec=0)
  
  outdir = '/data/smm/grs/' + strmid(stime,0,4) + '/'
  if ~is_dir(outdir) then file_mkdir, outdir
  outfile = 'smm_grs_' + stime + '_' + strmid(etime,9,4) + '_' + orig_filename + '.fits'
  outfile = outdir + outfile
  
  specnum = indgen(ntime)+1
  channel = rebin(lindgen(nchan), nchan, ntime)
  timedel = get_edges(data.ut, /width)
  timecen = get_edges(data.ut, /mean)
  timezero = anytim(data.ut[0], /MJD )
  mjd = anytim(tr, /mjd)
  timezero = mjd[0]
  timezeri = mjd[0].mjd    ; Integer part of reference time minus mjdref
  tstartf = double(mjd[0].time)/8.64d7   ; fractional part of ref time, msec / total msec in day
  timezerf = 0.0
  ; Final time of data collection, integer and fractional parts.
  tstopi = mjd[1].mjd
  tstopf = double(mjd[1].time) / 8.64d7

  rate_struct = default_rate_header()
  rate_struct.telescope = 'SMM'
  rate_struct.instrument = 'GRS'
  rate_struct.object = 'Sun'
  rate_struct.origin = 'SMM'
  rate_struct.author = 'SPECTRUM2FITS'
  rate_struct.detchans = nchan
  rate_struct.timezero = timezeri - rate_struct.mjdref
  rate_struct.tstarti = timezeri - long(rate_struct.mjdref)
  rate_struct.tstartf = tstartf
  rate_struct.tstopi = tstopi - long(rate_struct.mjdref)
  rate_struct.tstopf = tstopf
  rate_struct.telapse = double(((tstopi-timezeri) + (tstopf-tstartf))*86400.0)

  fxhmake, hdr, 0, /extend, /date
  fxaddpar, hdr, 'DATE_OBS', anytim(tr[0], /ccsds)
  fxaddpar, hdr, 'DATE_END', anytim(tr[1], /ccsds)
  fxaddpar, hdr, 'ENERGY_L', min(data.edges), 'keV'
  fxaddpar, hdr, 'ENERGY_H', max(data.edges), 'keV'
  fxaddpar, hdr, 'TELESCOP', 'SMM'
  fxaddpar, hdr, 'INSTRUME', 'GRS'
  fxaddpar, hdr, 'OBJECT', 'Sun'
  primary_hdr = hdr
  fxaddpar, primary_hdr, 'COMMENT', 'These FITS files are derived from the .USE files at '
  fxaddpar, primary_hdr, 'COMMENT', 'ftp://umbra.nascom.nasa.gov/pub/smm/smmgrs/solar_flare/'
  fxaddpar, primary_hdr, 'COMMENT', 'The files are named smm_grs_yyyymmddd_hhmm_hhmm_FYDOY_xx.fits'
  fxaddpar, primary_hdr, 'COMMENT', ' where yyyymmdd_hhmm is the start time of the data in the file,'
  fxaddpar, primary_hdr, 'COMMENT', ' the second hhmm is the end time, FYdoy_xx is the original name'
  fxaddpar, primary_hdr, 'COMMENT', ' of the .USE file, where Y is the last digit of the year in the'
  fxaddpar, primary_hdr, 'COMMENT', ' 1980s, doy is the day of year, and xx is FD, DB, or DA for'
  fxaddpar, primary_hdr, 'COMMENT', ' Flare Data, Day Before, and Day After (DB and DA are for background).'


  fxbhmake, hdr, ntime, /date
  ext_hdr = hdr
  
  ; write spectra as second extension in FITS file
  spectrum2fits, outfile, RATE_STRUCT=rate_struct, /WRITE_PRIMARY_HEADER, $
    PRIMARY_HEADER=primary_hdr, EXTENSION_HEADER=ext_hdr, $
    DATA=data.rate, ERROR=data.erate, $
    UNITS='counts/sec', SPEC_NUM=specnum, CHANNEL=channel, $
    TIMEDEL=timedel, $
    TIMECEN=timecen, $
    NROWS = N_elements( timecen ), $ ;added 24-sep-2003 to remove ambiguity
    LIVETIME=data.ltime, NUMBAND=nchan, MINCHAN=Lindgen(nchan), $
    MAXCHAN=Lindgen(nchan)+1, $   ; S.Bansal-08/31/04-added 1 to each element
    E_MIN=Reform( data.edges[0,*] ), $
    E_MAX=Reform( data.edges[1,*] ), E_UNIT='keV', $
    ERR_CODE=err_code, _EXTRA=extra_keys, ERR_MSG=err_msg
    
    
  ; Now write structure with all data from the .USE file into a separate extension, so everything is available.
  ; Need to make data.all_data (and its nested structures) an anonymous structure so str_sub2top names are simpler 
  ; (for named structure, they're extra long), and so that user can call st2_top2sub to restore original structure
  ; without needing to have structure definition routines.
  
;  all_str=create_struct(data.all_data[0])
;  nst = n_elements(data.all_data)
;  all_str = replicate(all_str, nst)
;  for i=1,nst-1 do all_str[i] = data.all_data[i]
  all_str = str_named2anon(data.all_data)

  ; Now all_str is same as data.all_data, except named structures are now anonymous.
  ; mwrfits doesn't allow nested structures, so call str_sub2top to make it all a top level structure
  ; To restore original nested structure, user will have to call str_top2sub on the structure after reading.
  
  all_str = str_sub2top(all_str)
  fxaddpar, ext_hdr, 'EXTNAME', 'All GRS Data'
  fxaddpar, ext_hdr, 'COMMENT', 'To recreate the original structure, call str_top2sub on the
  fxaddpar, ext_hdr, 'COMMENT', 'structure returned (nested structures not allowed in FITS binary'
  fxaddpar, ext_hdr, 'COMMENT', 'extensions, so str_sub2top was used to move all substructures to top'
  fxaddpar, ext_hdr, 'COMMENT', 'level before writing file).'
  mwrfits, all_str, outfile, ext_hdr

end