function ssw_extra2struct,_extra=_extra

return,_extra
end

pro sotsp_l2struct2data, l2struct, index, data, $
   add_losmag=add_losmag, scale=scale, autoscale=autoscale, debug=debug, $
   xycoord=xycoord, scan_info=scan_info, silent=silent

;+
;   Name: sotsp_l2struct2data
;
;   Purpose: SOT-SP Level2 struct ( from save or binext FITS) -> "index,data"
;
;   Input Parameters:
;      l2struct - structure, from Level2 save or BinExt FITS (via merlin)
;
;   Output:
;      returns index,data  
;
;   Suggeseted Calling Sequence (this routine is transparent intermediary..)
;   IDL> read_sotsp,<splevel2file>, index, data [,/add_losmag] ,[,/silent]
;
;   Keyword Parameters:
;     scale (switch) - if set, apply PI teams suggested scale (def=floating)
;     add_losmag (switch) - if set, include LoS Magnetogram in 'index,data'
;     xycoord (switch) - if set, include X & Y coordinate arrays
;     scan_info (output) ; structure with 1D tags TIMES, SLITPOS, SCATTPRO
;          (scan time, slitpos, scattered light profile)
;
;   History:
;     1-May-2008 - S.L.Freeland, using PI Team code for guidence
;    27-may-2008 - S.L.Freeeland - got back to this & "completed" it
;     2-jun-2008 - S.L.Freeland - add /XYCOORD switch
;                  add 1D (Obstime, slitpos, stray light vectors to index
;     9-jan-2009 - S.L.Freeland - include crota1/crota2 in output index
;    13-apr-2020 - P.G.Shirts - changed array indexing from () to [] to
;                  for image[ssinf] to avoid namespace collision w/new
;                  IDL function 'image()'.
;    14-jul-2020 - M.DeRosa - added silent keyword
;    14-jul-2020 - M.DeRosa - CUNITi keywords are now correct, and added BUNIT
;                  keyword to better conform to FITS standard
;     8-Jul-2021 - M.DeRosa - fixed bug in that was preventing the last FITS
;                  extension from populating the data array
;    23-Dec-2021 - M.DeRosa - (version 1.1) fixed two issues when /scale
;                  switch is set: (1) routine now removes non-finite values
;                  (Inf or NaN) before performing the scaling, and (2) routine
;                  now ensures positive values when doing log scaling for
;                  cases where the minimum image value is 0
;
;   Restrictions:
;      Not for casual users; 'read_sotsp.pro' is recommended for them
;      Currently includes All data extensions in "data" - plan for user
;      defined subset which is easy but not done as of now 
;
;-
version=1.1

if not required_tags(l2struct,'header,data_labels') then begin 
  box_message,'Expect SOT-SP Level 2 FITS structure'
  return
endif
if ~tag_exist(l2struct,'times')  then begin
  box_message, 'Missing TIMES tag in l2struct.  Returning.'
  return
endif else time_window,l2struct.times,date_obs,date_end
if date_obs eq date_end then begin ; HAO Level2 Format Change... 22-jan-2010 
  ntimes=gt_tagval(l2struct.header,/naxis1)
  tgrid=timegrid(gt_tagval(l2struct.header,/tstart), gt_tagval(l2struct.header,/tend),nsamp=ntimes,out='ecs')
  l2struct=rep_tag_value(l2struct,tgrid,'times')
  date_obs=anytim(tgrid(0),/ccsds)
  date_end=anytim(last_nelem(tgrid),/ccsds)
endif

add_losmag=keyword_set(add_losmag)
xycoord=keyword_set(xycoord)
autoscale=keyword_set(autoscale)
scale=keyword_set(scale) or autoscale

fitstags=merlin_taginfo(/fits, xycoord=xycoord)
fieldlabs=merlin_taginfo(/data,/maps_only, xycoord=xycoord)
ranges=merlin_taginfo(/range,xycoord=xycoord)
logs=merlin_taginfo(/log,xycoord=xycoord)
units=merlin_taginfo(/unit,xycoord=xycoord)

nout=n_elements(fitstags) + add_losmag 

index=replicate(fitshead2struct(l2struct.header),nout)
mag=gt_tagval(l2struct,/sfld)
misstemp=make_array(size=size(mag))-1 ; missing 
data=make_array(data_chk(mag,/nx),data_chk(mag,/ny), nout, /float)

for i=0,n_elements(fitstags)-1 do begin ; LOS Mag is derived after loop
  tind=tag_index(l2struct,fitstags(i))
  if tind gt 0 then data(0,0,i)=l2struct.(tind) else begin 
    if ~keyword_set(silent) then box_message,'No Tag>> ' + fitstags(i) + ' ..trying backup'
    if fitstags(i) eq 'ICONT' then data(0,0,i)= $
      gt_tagval(l2struct,/scct,missing=mistemp) 
   endelse
endfor
if add_losmag then begin 
  data(0,0,i)=sotsp_l2struct2losmag(l2struct)
  ranges=[[[ranges],[-2000.,2000.]]]
  logs=[logs,0] 
  units=[units,'']
  fitstags=[fitstags,'LOSMAG']
  fieldlabs=[fieldlabs,'LOSMAG']
endif

;  loop through the various output quantities and scale
if keyword_set(scale) then begin
  sdata=make_array(data_chk(data,/nx),data_chk(data,/ny),nout,/byte) 
  low=reform(ranges(0,*))
  high=reform(ranges(1,*))
  for i=0,nout-1 do begin  ; optional scaling loop

    image=data(*,*,i)

    ;  remove bad scaling values
    ssinf=where(1-finite(image),icnt)
    if icnt gt 0 then begin 
      if ~keyword_set(silent) then box_message,'Inf fixup.'
      image[ssinf]=0
    endif

    ;  re-scale, if desired/needed
    if (low(i) eq high(i)) or autoscale then begin 
      top=fix(get_logenv('sotsp_l2top'))
      hstats=ssw_image_stats(index(i),image,percent=[3,top],status=status) ; 
      if not status then begin 
        if ~keyword_set(silent) then box_message,'Problem with Hist, reducing percentile..'
        hstats=ssw_image_stats(index(i), image,percent=[3,top-6], status=status)
      endif
      if not status then hstats={low:min(image),high:max(image)}
      low(i)=hstats.(0)
      high(i)=hstats.(1)
    endif

    ;  scale the image
    if logs(i) then begin
      if low(i) eq 0 then low(i)=min(image+(image eq 0)*high(i))
      sdata(0,0,i) = bytscl(alog10(image>low(i)), $
                            min=alog10(low(i)),max=alog10(high(i)))
    endif else sdata(0,0,i)=bytscl(image,min=low(i),max=high(i))
  endfor
  delvarx,data & data=temporary(sdata)
endif

info={FITSTAGS:'',CUNIT1:'',CUNIT2:'',FTYPE:'',INSTRUME:'',TELESCOP:'', $
      cdelt1:0.0, cdelt2:0.0, crota1:0, crota2:0, date_obs:'', date_end:'', $
      BUNIT:''}
info=replicate(info,nout)
info.fitstags=fitstags
info.cunit1='arcsec'
info.cunit2='arcsec'
info.ftype=fieldlabs
info.telescop='HINODE'
info.INSTRUME='SOT/SP ' + fieldlabs
info.date_obs=date_obs
info.date_end=date_end
info.cdelt1=gt_tagval(l2struct.header,/xscale,missing=.29)
info.cdelt2=gt_tagval(l2struct.header,/yscale,missing=.32)
info.bunit=units
index=join_struct(temporary(index),info)

scan_info=str_subset(l2struct,'times,slitpos,scattpro')

update_history,index,version=version,/caller

return
end
