; $Id: fans_browser.pro,v 1.9 2005/02/01 13:27:38 azuah Exp $
;###############################################################################
;
; NAME:
;   fans_browser
;
; PURPOSE:
;   Basic data browser which essentially searches a directory and
;   loads all (*.bt4) files found in it. It is then possible to
;   quickly step through all files found using a droplist widget. The
;   integrated counts vs energy transfer is displayed in the plot
;   window for the chosen file.
;
; CATEGORY:
;   FANS Data Reduction
;
; AUTHOR:
;   Richard Tumanjong Azuah
;   NIST Center for Neutron Research
;   100 Bureau Drive, Gaithersburg, MD 20899
;   United States
;   azuah@nist.gov; (301) 9755604
;   May, 2002
;
; LICENSE:
;  The software in this file is written by an employee of 
;  National Institute of Standards and Technology 
;  as part of the DAVE software project.
;
;  The DAVE software package is not subject to copyright protection
;  and is in the public domain. It should be considered as an
;  experimental neutron scattering data reduction, visualization, and
;  analysis system. As such, the authors assume no responsibility
;  whatsoever for its use, and make no guarantees, expressed or
;  implied, about its quality, reliability, or any other
;  characteristic. The use of certain trade names or commercial
;  products does not imply any endorsement of a particular product,
;  nor does it imply that the named product is necessarily the best
;  product for the stated purpose. We would appreciate acknowledgment
;  if the DAVE software is used of if the code in this file is
;  included in another product.
;
;###############################################################################




;===============================================================================
; fans_brGetFiles
;
; PURPOSE:
;   Get all .bt4 in a given directory
;
; PARAMETERS:
;   statePtr [in] - pointer to state structure
;
pro fans_brGetFiles, statePtr

; make sure input parameter is defined
if ( ptr_valid(statePtr) eq 0) then begin
    message = 'Error:: statePtr is undefined'
    if (!debug) then print, message
    return
endif

widget_control, (*statePtr).dirID,get_value=newDir ; Go to new dir and get FANS files
cd, newDir[0], current=oldDir              
fileList=findfile('*.bt4',count=fileCount)
cd, oldDir

if (fileCount le 0) then begin     ; if no files found print a message
    message = ['No FANS (*.bt4) files found in:', $
              newDir,'Please, select another directory!']
    void = dialog_message(dialog_parent=(*statePtr).tlbID,message,/information)
    fileList = 'no files yet'
;    return
endif

; populate the files droplist box with the files found
widget_control, (*statePtr).fileID,set_value=fileList

; store useful info in statePtr
(*(*statePtr).fileListPtr) = fileList
(*statePtr).fileCount = fileCount
(*statePtr).fileName = fileList[0]

end
;-------------------------------------------------------------------------------



;===============================================================================
; fans_brGetData
;
; PURPOSE:
;   Gets the currently selected file from the droplist widget, opens
;   it and reads the title and integrated counts and energy transfer.
;
; PARAMETERS:
;   statePtr [in] - pointer to state structure
;
pro fans_brGetData, statePtr

; parameter must be defined
if ( ptr_valid(statePtr) eq 0) then begin
    message = 'Error:: statePtr is undefined'
     if (!debug) then print, message
    return
endif

; Exit now if no valid files available
if ( (*statePtr).fileCount le 0) then $
  return

; Get the file
widget_control, (*statePtr).dirID, get_value=dir
fileName = (*statePtr).fileName
file = filepath(root_dir=dir[0],fileName)

if (strlen(file) le 0) then begin
    message = ['file: ',fileName,' was not found in: ',dir]
    void = dialog_message(dialog_parent=(*statePtr).tlbID,message)
    return
endif

; open and read data from file
readFansIntCounts,file,title,date,energy,counts

; save data in statePtr
widget_control,(*statePtr).fileTitleID,set_value=title
(*statePtr).energyPtr = ptr_new(energy)
(*statePtr).countsPtr = ptr_new(counts)
(*statePtr).exptDate = date

end
;-------------------------------------------------------------------------------



;===============================================================================
; readFansIntCounts
;
; PURPOSE:
;   Open and read a FANS data file. Only the Title, energy values and
;   total counts and returned from the file
;
; PARAMETERS:
;   file [in] - name of file to be read
;
;   title [out] - experiment title.
;
;   date [out] - date of experiment.
;
;   energy [out] - energy transfer array covered by measurement.
;
;   counts [out] - data
;
pro readFansIntCounts,file,title,date,energy,counts

if (n_params() ne 5) then begin
    message = 'readFansIntCounts requires 4 parameters'
    if (!debug) then print, message
    return
endif

if (n_elements(file) le 0 ) then begin
    message = 'No input file specified'
     if (!debug) then print, message
    return
endif

openr,lun,file,/get_lun

if (n_elements(lun) le 0) then begin
    message = 'File "'+file+'" was not found or could not be opened!'
     if (!debug) then print, message
    return
endif

header = strarr(12)
readf,lun,header             ; read header block

date = strmid(header[0],16,17)
title = header[2]
tflag = strmid(header[11],37,1)

ndets = 128
nspec = 2000
detCounts = intarr(ndets)
energy = fltarr(nspec)
counts = lonarr(nspec)

if (tflag eq 'T') then buffSize = 7 else buffSize = 6
buff = fltarr(buffSize)
    
ispec = 0
while (not eof(lun)) do begin
    readf,lun,buff
    energy[ispec] = buff[3]
    counts[ispec] = buff[buffSize - 1]
    ispec = ispec + 1
    readf,lun,detCounts
endwhile

energy = energy[0:ispec-1]
counts = counts[0:ispec-1]

free_lun, lun

end
;-------------------------------------------------------------------------------



;===============================================================================
; fans_brPlotData
;
; PURPOSE:
;   Plot current data in the plot window
;
; PARAMETERS:
;   statePtr [in] - pointer to state structure
;
pro fans_brPlotData, statePtr

if ( (*statePtr).fileCount le 0) then begin
    message = 'Error: There was no data to be plotted'
     if (!debug) then print,message
    return
endif

energy = *(*statePtr).energyPtr
counts = *(*statePtr).countsPtr

plot,energy,counts, $
     xstyle=1,ystyle=1,xtitle='Energy transfer (meV)',ytitle='Raw counts', $
     title=(*statePtr).exptDate,charsize=1.4

end
;-------------------------------------------------------------------------------



;===============================================================================
; selDir
;
; PURPOSE:
;   Event handler; Choose data directory
;
; PARAMETERS:
;   event [in] - event structure to be handled
;
pro selDir, event

widget_control,event.top,get_uvalue=statePtr

; Save previous directory
dirID = (*statePtr).dirID
widget_control,dirID,get_value=oldDir

newDir = dialog_pickfile(/directory,path=oldDir[0],dialog_parent=event.top) 

if (strlen(newDir) le 0) then newDir = oldDir[0]   ; use oldDir if nothing selected

if (strlen(newDir) le 0) then begin        ; can't have a null directory
    message = ['No directory was selected and none is available.', $
               'This is not a good situation!', $
               'Please select a directory containg FANS data.']
    void = dialog_message(dialog_parent=event.top,message,/information,dialog_parent=event.top)
;    return
endif

widget_control,dirID,set_value=newDir[0]  ; update dirID text field

fans_brGetFiles, statePtr

if ( (*statePtr).fileCount gt 0) then begin
    fans_brGetData, statePtr
    fans_brPlotData, statePtr
endif else begin
    erase
    widget_control,(*statePtr).fileTitleID,set_value=''
endelse

end
;-------------------------------------------------------------------------------



;===============================================================================
; selFile
;
; PURPOSE:
;   Event handler; The current file selection in the droplist widget
;   has changed.
;
; PARAMETERS:
;   event [in] - event structure to be handled
;
pro selFile, event

widget_control, event.top,get_uvalue=statePtr

(*statePtr).fileName = (*(*statePtr).fileListPtr)[event.index]

if ( (*statePtr).fileCount gt 0) then begin
    fans_brGetData, statePtr
    fans_brPlotData, statePtr
endif else begin
    erase
    widget_control,(*statePtr).fileTitleID,set_value=''
endelse

end
;-------------------------------------------------------------------------------



;===============================================================================
; resize
;
; PURPOSE:
;   Event handler; resize event for the top-level-base. Resize the
;   plot window widget.
;
; PARAMETERS:
;   event [in] - event structure to be handled
;
pro resize, event

widget_control, event.top,get_uvalue=statePtr

; get new size of the top widget base
tlbInfo = widget_info(event.top,/geometry)
tlbXsize = event.x  ; new xsize of tlb (xcl any frame provided by the window manager)
tlbYsize = event.y  ; new ysize of tlb (xcl any frame provided by the window manager)


; the following dimensions remain the same
labXsize = (*statePtr).labXsize
butXsize = (*statePtr).butXsize
fileXsize = (*statePtr).fileXsize

; set new X dimension of dir and filetitle text field widgets
dirXsize = tlbXsize - labXsize - butXsize - 10*tlbInfo.xpad
ftXsize = tlbXsize - labXsize - fileXsize - 10*tlbInfo.xpad
widget_control, (*statePtr).dirID,scr_xsize=dirXsize;scr_ysize=dirYsize
widget_control, (*statePtr).fileTitleID,scr_xsize=ftXsize;scr_ysize=ftYsize

; set new dimensions of plot window
cb1Info = widget_info((*statePtr).cb1ID,/geometry)
cb2Info = widget_info((*statePtr).cb2ID,/geometry)
plotXsize = tlbXsize - 2*tlbInfo.xpad
plotYsize = tlbYsize - cb1Info.scr_ysize - cb2Info.scr_ysize - $
  2*tlbInfo.space - 2*tlbInfo.ypad
widget_control, (*statePtr).plotID, xsize=plotXsize, ysize=plotYsize

; renew plot if data exist
if ( (*statePtr).fileCount gt 0) then fans_brPlotData, statePtr


end
;-------------------------------------------------------------------------------



;===============================================================================
; fans_browserCleanup
;
; PURPOSE:
;   Cleanup procedure for tlb widget
;
; PARAMETERS:
;   tlbID [in] - widget id of tlb
;
pro fans_browser_cleanup, tlbID
widget_control, tlbID,get_uvalue=pState

fansInfo = {FANSBROWSEREVENT,$
          id:(*pState).notifyIDs[0],$
          top:(*pState).notifyIDs[1],$
          handler:0L}
if widget_info((*pState).notifyIDs[0],/valid_id) then begin
  widget_control,(*pState).notifyIDs[0],send_event = fansInfo
endif


;print,'Cleaning up ...'
ptr_free, (*pState).fileListPtr
ptr_free, (*pState).energyPtr
ptr_free, (*pState).countsPtr
ptr_free, pState

;print, 'All Done!'

end
;-------------------------------------------------------------------------------



;===============================================================================
; fans_browser
;
; PURPOSE:
;   Main entry point and dialog builder for application.
;
; PARAMETERS:
;
; KEYWORDS:
;   notifyIds [in] - widget id(s) of that are interested in receiving
;                    notification messages from this application.
;
;   group_leader [in] - the ID of the parent widget from which this
;                       dialog was launched.
;
pro fans_browser, notifyIds=notifyIds,group_leader=group_leader

dir = (*!dave_defaults).datDir
;print,dir
; create top-level-base
tlbID = widget_base(group_leader=group_leader,/col,title='FANS DATA BROWSER',/tlb_size_events)

cb1ID = widget_base(tlbID,/row)
cb2ID = widget_base(tlbID,/row)

voID = widget_label(cb1ID,value='Data Directory:',/align_right)
labInfo = widget_info(voID,/geometry)
labXsize = labInfo.scr_xsize + 2*labInfo.margin ; xsize of future labels
startDir = '' 
if (n_elements(dir) gt 0) then startDir = dir
dirXsize = 350
dirID = widget_text(cb1ID,value=startDir,scr_xsize=dirXsize)
selID = widget_button(cb1ID,value='Browse',event_pro='selDir')
butInfo = widget_info(selID,/geometry)
butXsize = butInfo.scr_xsize + 2*butInfo.margin
butYsize = butInfo.scr_ysize + 2*butInfo.margin

fileList = '  no files yet  '
voID = widget_label(cb2ID,value='Data Files:',/align_right,scr_xsize=labXsize)
fileID = widget_droplist(cb2ID,event_pro='selFile',value=fileList)
fileInfo = widget_info(fileID,/geometry)
fileXsize = fileInfo.scr_xsize + 2*fileInfo.margin
fileTitleID = widget_text(cb2ID,value='',scr_xsize=dirXsize+butXsize-fileXsize)

widget_control,tlbID,/realize

plotXsize = labXsize+dirXsize+butXsize
plotYsize = plotXsize*0.75
plotID = widget_draw(tlbID,xsize=plotXsize,ysize=plotYsize)
widget_control, plotID,get_value=plotWinID
wset, plotWinID


state = {fileID:fileID, $
         dirID:dirID, $
         cb1ID:cb1ID, $
         cb2ID:cb2ID, $
         fileTitleID:fileTitleID, $
         plotID:plotID, $
         labXsize:labXsize, $
         butXsize:butXsize, $
         fileXsize:fileXsize, $
         fileListPtr:ptr_new(fileList), $
         fileCount:0, $
         fileName:'', $
         exptDate:'', $
         energyPtr:ptr_new(), $
         countsPtr:ptr_new(), $
         tlbID:tlbID, $
         notifyIds:notifyIds $
        }
statePtr = ptr_new(state)

widget_control,tlbID,set_uvalue=statePtr

; locate and plot any *.bt4 files in startDIR
if ( strlen(startDir) gt 0) then begin
    fans_brGetFiles, statePtr
    fans_brGetData, statePtr
    fans_brPlotData, statePtr
endif


xmanager,'fans_browser',tlbID,event_handler='resize',cleanup='fans_browser_cleanup'

if (!debug) then $
  print,'Gone beyond xmanager...'

end
