; Copyright (c) 1998-2016 A.P. Hitchcock, B. Watts  All rights reserved
;+
;NAME:
; READ_NXS
;
;LAST CHANGED: ----------------------------------- 17-May-16 (aph)
;
;PURPOSE:
; This function reads in Soleil PEEM files in *.nxs (hdf5 NeXus) format
;
; CATEGORY:
; Input / output utilty; stand alone or from ax_nxs / axis2000
;
; CALLING SEQUENCE:
; Result = READ_NXS(file, HEADER_ONLY=HEADER_ONLY)
;
; INPUTS: FILE   filename (if not provided, will ask)
;
; KEYWORDS:
; HEADER_ONLY extract and return header contents only
; VERBOSE  - print all
; SILENT   - print none
;
; OUTPUTS:
; stack, even for 'single images' which are taken as a series (time stack)
; returns average image of the stack
;
; COMMON BLOCKS:
; STACK_PROCESS_COM common for stack_process
; AXIS_COM  standard set of common blocks
; BSIF_COM  stack common
; VOLUME_DATA stack data set
; NEXUS_COM   common for NeXus read in
;
;MODIFICATION HISTORY:
; (11-May-16 aph) first written
; (12-May-16 aph) add return of 2D image (avg); despike; check for data_02
; (17-May-16 aph) by pass despike (not yet working)
;-

FUNCTION read_nxs, file, verbose=verbose, silent=silent, HEADER_ONLY=HEADER_ONLY
  @axis_com
  @bsif_com
  @stack_process_com
  @nexus_com
  COMMON volume_data, image_stack

  on_error,2

; ------ check if the version of IDL will have the necessary hdf5 commands
	if float(!version.release) LT 7.0 then begin
		axis_log, 'only versions of IDL above 7.0 can read Soleil NeXus (*.nxs) files'
		return, 0
	endif

  ; ------ get filename

  if NOT keyword_set(group) then group = 0 else begin
    if n_elements(axis_ID) EQ 1 then group = axis_ID
  endelse
  if keyword_set(verbose) then print, 'group, axis_ID', group, axis_ID
  ; the preceding is a kluge !!
  ; want to make the group be flexible - if just called from ax_sdf widget, group is sdf_ID, otherwise
  ; should be axis_ID.

  if n_elements(file) eq 0 then begin  ;popup file dialog box
    if not keyword_set(filter) then fltr='*.nxs' else fltr = filter
    file=PICKFILE2(/Read, FILTER=fltr, /LPATH, DEFPATH=defpath)
  endif
  s = ''
  if strlen(file) LE 0 THEN return, s  ; bail-out if no filename
  ; ------- Open the file and read the structure -------
  ; first force to be a header
  t = findfile(file)
  IF strlen(t(0)) EQ 0 then begin
    axis_log, 'read_nxs: File not found'
    return, s
  ENDIF else begin
    nxs_structure=h5_parse(file)
    if keyword_Set(HEADER_ONLY) then return, nxs_structure
  endelse

  ; ---- OK, now read for real
  ax_wait
  nxs_structure=h5_parse(file, /read_data)

  ; ----- if there is an actuator, read it and identify file as an energy stack
  actuated = 0
  r=tag_names(nxs_structure.(6).scan_data)

  for i = 0, n_elements(r)-1 do begin
    if r(i) EQ 'ACTUATOR_1_1' then actuated = 1
  endfor
  if actuated EQ 1 then begin
;      if nxs_structure.(6).scan_data.alias._data EQ 'nrj' then
    nxs_energy = nxs_structure.(6).scan_data.actuator_1_1._data
  endif
  ; TO WRITE

 ; loc_id= h5f_open(file)
 ; data_name = h5g_get_member_name(loc_id, '.',0)
; ---- can also get data_name from nxs_structure._name which is
; the string '/Users/aph/data/XRM/Soleil-PEEM/scan_xpeem0120.nxs'
; but my problem is to construct a string referencing this

 ; ----- read in the stack  assuming the actual data will be the 7th entry
 ;  this avoids having to know how to generate a variable name from strings

 image_stack = nxs_structure.(6).scan_data.data_03._data
  t = size(image_stack)
  if t(0) LT 3 then image_stack = nxs_structure.(6).scan_data.data_02._data
  t = size(image_stack)
  if t(0) LT 3 then begin
    axis_log, 'This NeXus file has the stack of images stored in an area other than data_03 (May16) or data_02 (fall 2015)'
    return, 0
  endif
; if keyword_Set(HEADER_ONLY) then return, image_stack

 count_time = 1000*nxs_structure.(6).scan_data.integration_times._data
 filename = pickfile2(filter='*.ncb', title='binary stack file ', WRITE=write)
 IF strlen(filename) GT 0 THEN BEGIN
     t = ax_name(filename)
     filename = t(0) + t(1) +'.ncb'
     shortname = t(1)
     t=size(image_Stack)
; ------- set up meaningful co-ordinates
     px_size = nxs_structure.(6).sample_xpeem.rz._data(0)   ; in nm
     t = size(image_stack)
     nx = t(1)   &  ny = t(2)
     n_e = t(3)
     x_center =  nxs_structure.(6).sample_xpeem.tx._data(0)
     x_start = x_center - nx*px_size/2.
     x_stop = x_center + nx*px_size/2.
     y_center =  nxs_structure.(6).sample_xpeem.ty._data(0)
     y_start = y_center - ny*px_size/2.
     y_stop = y_center + ny*px_size/2.
     ev=findgen(n_e)
     if actuated EQ 1 then ev = nxs_energy

;     goto, continue           ;  for now, skip until get despike to work
     ; ----- remove hot and cold spots
     t = size(image_Stack)
     t_img=fltarr(t(1), t(2))
     nspot_hot = 0
     nspot_cold = 0
     for i = 0, n_e-1 do begin
       t_img = remove_zeros(image_stack(*,*,i),/silent, remove_hot=rh, remove_cold = rc)
       test = t_img - image_stack(*,*,i)
       image_stack(*,*,i) = t_img
       tp = where(test GT 0, count)
       if count GT 0 then nspot_cold = nspot_cold + count
       tp = where(test LT 0, count)
       if count GT 0 then nspot_hot = nspot_hot + count
     endfor
     ; check if any changes - if so flag
     text = 'Image processed to remove ' + string(nspot_hot) + ' hot spots' + $
       string(nspot_cold) + ' cold spots'
       axis_log, text

;     continue:

     filename_ev_msec_list = strarr(n_elements(ev))
     FOR i = 0, n_elements(ev)-1 DO BEGIN
       filename_ev_msec_list(i) = shortname + string(i) + ' ' + string(ev(i), format = '(F10.2)') + $
         ' eV ' +  string(count_time(i), format='(F7.2)') + ' msec'
     ENDFOR

   stack_wb, filename

   ; ----- create average image and return as an aXis2000 *.axb file

   log_text = string(format='(" (",i4," x ",i4," ) read from ",A,". Dwell =",f6.2," ms.")', ny, nx, shortname, count_time[0])
   IF NOT keyword_set(silent) THEN axis_log, log_text

   x =  x_start + findgen(nx)*px_size
   y =  y_start + findgen(ny)*px_size
   e = median(ev)
   d = total(image_stack, 3, /double)
   d = float(d)/float(n_e)

   IF actuated NE 1 THEN BEGIN ; if set of images without an actuator
     E_string = string(FORMAT='("Energy (eV)    Dwell = ",f7.2," ms")', e, count_time[0])
     y_string = 'y (um) average of ' +  string(n_e) + ' PEEM images'
     tmp = {t:'2d', x: x, y:y, d:d, e:e, xl:E_string, yl:y_string, dl:shortname}
   ENDIF ELSE BEGIN ; if energy stack (or other actuation)
     X_string = string(FORMAT='(" x (um)   E = ",f8.3," to ",f8.3,"  eV     dwell = ",f6.2," ms")', $
               ev(0), ev(n_elements(ev)-1), count_time[0])
     Y_string = 'y (um) average of ' +  string(n_e) + ' images fo a PEEM stack'
     tmp =  {t:'2d', x:x, y:y, d:d, e:e, xl:X_string, yl:Y_string, dl:shortname}
   ENDELSE
   return, tmp
 ENDIF ELSE return, 0
  end
