; $Id: fdave_read3colascii.pro,v 1.6 2005/02/09 13:38:36 dimeo Exp $
;###############################################################################
;
; NAME:
;  FDAVE_READ3COLASCII
;
; PURPOSE:
;  Reads in a 3 column ascii file into the DAVE data structure.
;
; CATEGORY:
;  DAVE, ASCII data reader.
;
; AUTHOR:
;   Robert M. Dimeo, Ph.D.
;   NIST Center for Neutron Research
;   100 Bureau Drive
;   Gaithersburg, MD 20899
;   Phone: (301) 975-8135
;   E-mail: robert.dimeo@nist.gov
;   http://www.ncnr.nist.gov/staff/dimeo
;
; 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.
;
;###############################################################################
; fdave_read3ColAscii.pro
;
; This routine reads in three-column ascii data into the
; standard DAVE data structure.
;
; Written by R.M.Dimeo (11/13/01)
;
; Modification history:
; ----------------------
; 11/14/01-RMD:	allow printing to a postscript file.
;
;
;;;;;;;;;;;;
pro fdaveRTCSaveWorkspace,event
widget_control,event.top,get_uvalue = pState
cd,(*!dave_defaults).workdir
filename = DIALOG_PICKFILE(dialog_parent = event.top,$
                                              title = 'Enter filename',$
                                              /write,filter = '*.dave')
if filename eq '' then return
filename = filename+'.dave'
davePtr = (*pState).davePtr
save, davePtr, FILENAME = filename
end
;;;;;;;;;;;;
pro fdaveRTCCleanup,tlb
widget_control,tlb,get_uvalue = pState

s = size((*pState).notifyIDs)
if s[0] eq 1 then count = 0 else count = s[2]-1
for j = 0,count do begin
  fdaveRTCInfo = {FDAVERTCEVENT,$
                            ID:(*pState).notifyIDs[0,j],$
                            Top:(*pState).notifyIDs[1,j],$
                            Handler:0l}
  if widget_info((*pState).notifyIDs[0,j],/valid_id) then begin $
    widget_control,(*pState).notifyIDs[0,j],send_event = fdaveRTCInfo
  endif
endfor

wdelete,(*pState).winPix
ptr_free,(*pState).xPtr
ptr_free,(*pState).yPtr
ptr_free,(*pState).yerrPtr
ptr_free,(*pState).dataoPtr
ptr_free,(*pState).erroroPtr
ptr_free,(*pState).xoPtr
ptr_free,pState
help,/heap,/brief
end
;;;;;;;;;;;;
pro fdaveRTCDismiss,event
widget_control,event.top,get_uvalue = pState
if n_elements(*(*(*(*pState).davePtr).dataStrPtr).specificPtr) ne 0 then begin
  text = 'Do you want to save your workspace?'
  response = dialog_message(dialog_parent = event.top,text,/question)
  if strupcase(response) eq 'YES' then begin
    fdaveRTCSaveWorkSpace,event
  endif
endif
s = size((*pState).notifyIDs)
if s[0] eq 1 then count = 0 else count = s[2]-1
for j = 0,count do begin
  fdaveRTCInfo = {FDAVERTCEVENT,$
                            ID:(*pState).notifyIDs[0,j],$
                            Top:(*pState).notifyIDs[1,j],$
                            Handler:0l}
  if widget_info((*pState).notifyIDs[0,j],/valid_id) then begin $
    widget_control,(*pState).notifyIDs[0,j],send_event = fdaveRTCInfo
  endif
endfor
widget_control,event.top,/destroy
return
end
;;;;;;;;;;;;
pro fdaveRTCPlot,event
widget_control,event.top,get_uvalue = pState
if n_elements(*(*pState).xPtr) eq 0 then return

x = *(*pState).xPtr
y = *(*pState).yPtr
yerr = *(*pState).yerrPtr

if (*pState).autoscale eq 1 then begin
  (*pState).xviewrange = [min(x),max(x)]
  dy = max(y)-min(y)
  (*pState).yviewrange = [min(y)-0.1*dy,max(y)+0.1*dy]
endif
xlabel = (*(*(*pState).davePtr).dataStrPtr).commonStr.xlabel
ylabel = (*(*(*pState).davePtr).dataStrPtr).commonStr.histlabel
plot,x,y,psym = 8,xrange = (*pState).xviewrange,$
      yrange = (*pState).yviewrange,xstyle = 1,ystyle = 1,$
      xtitle = xlabel,ytitle = ylabel
errplot,x,y-yerr,y+yerr,width = 0.0
end
;;;;;;;;;;;;
pro fdaveRTCPrint,event
widget_control,event.top,get_uvalue = pState
if n_elements(*(*pState).xPtr) eq 0 then begin
  void = dialog_message(dialog_parent = event.top,'Nothing loaded yet')
  return
endif

  printPath = (*!dave_defaults).workDir
  cd,printPath
  thisDevice = !d.name
  ; use one of Fanning's routines, PS_FORM.PRO, to allow
  ; user to interactively configure
  ; the postscript output
  deviceKeywords = ps_form(Cancel = canceled,parent = event.top)
  if canceled ne 1 then begin
    SET_PLOT, 'PS'
    DEVICE, _EXTRA = deviceKeywords
    fdaveRTCPlot,event
    DEVICE, /CLOSE_FILE
    set_plot,thisDevice
  endif
end
;;;;;;;;;;;;
pro fdaveRTCRebin,event
widget_control,event.top,get_uvalue = pState
if n_elements(*(*pState).xPtr) eq 0 then return
xsort = sort(*(*pState).xPtr)
x = (*(*pState).xPtr)[xsort]

if n_elements((*(*(*(*pState).davePtr).dataStrPtr).commonStr.histPtr)) eq 0 $
	then return
y = (*(*(*(*pState).davePtr).dataStrPtr).commonStr.histPtr).y
x =  (*(*(*(*pState).davePtr).dataStrPtr).commonStr.histPtr).x
dat =  (*(*(*(*pState).davePtr).dataStrPtr).commonStr.histPtr).qty
daterr =  (*(*(*(*pState).davePtr).dataStrPtr).commonStr.histPtr).err

nx = n_elements(x)
result = opan_rebin_widget(x,group_leader = event.top)
if result.cancel then return
if result.nbins gt nx then begin
  strout = 'Number of desired bins cannot exceed the number of input bins'
  void = dialog_message(dialog_parent = event.top,strout)
  return
endif
; Ok, we've done the error checking...now do the rebinning
xlo = result.xlo & xhi = result.xhi
nbins = result.nbins
dx = (xhi-xlo)/(nbins-1.0)
x_out = xlo+dx*dindgen(nbins)

x_in = x
z_in = dat
dz_in = daterr
drebin,x_in,z_in,dz_in,x_out,z_out,dz_out,$
			/points,/to_points,err=err,emsg=emsg

newState = {qty:z_out,err:dz_out,x:x_out,y:0.0}
*(*(*(*pState).davePtr).dataStrPtr).commonStr.histPtr = newState

*(*pState).xPtr = x_out
*(*pState).yPtr = z_out
*(*pState).yerrPtr = dz_out







;;;;;;;;;;;;;;;;;;;;;;;;;;
;npts = n_elements(x)
;xlo = min(x)
;xhi = max(x)
;oldbinsize = max(deriv(x))
;rebVals = hfbs_RebWidget(xlo = xlo,xhi = xhi,$
;               binsize = oldbinsize,$
;               group_leader = event.top)
;xlo = rebVals[0] & xhi = rebVals[1] & binsize = rebVals[2]
;nbins = 1+fix((xhi-xlo)/binsize)
;
;nchan = nbins
;data = fltarr(nchan)
;error = fltarr(nchan)
;xbin = hfbs_makepoints(xlo = xlo,xhi = xhi,npts = nbins)
;
;chanw = round(binsize/oldbinsize)
;if chanw le 1 then begin
;  strout = 'Bin size is too small'
;  void = dialog_message(/error,strout,dialog_parent = event.top)
;  widget_control,event.top,set_uvalue = pState,/no_copy
;  return
;endif
;yint = fltarr(nbins)
;errint = fltarr(nbins)
;
;  y =  (*(*(*(*pState).davePtr).dataStrPtr).commonStr.histPtr).qty
;  yerr = (*(*(*(*pState).davePtr).dataStrPtr).commonStr.histPtr).err
;  ysmooth = smooth(y,chanw,/edge_truncate)
;  yerr = yerr/sqrt(chanw)
;  yint = interpol(ysmooth,x,xbin)
;  errint = interpol(yerr,x,xbin)
;  data[0:nchan-1] = yint[0:nchan-1]
;  error[0:nchan-1] = errint[0:nchan-1]
;
;*(*pState).xPtr = xbin
;*(*pState).yPtr = data
;*(*pState).yerrPtr = error
;
;newState = {qty:data,err:error,x:xbin,y:0.0}
;*(*(*(*pState).davePtr).dataStrPtr).commonStr.histPtr = newState
wset,(*pState).winPix
fdaveRTCplot,event
wset,(*pState).winVis
device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
text = 'Rebinned into equal channel widths'
oldText = *(*(*(*pState).davePtr).dataStrPtr).commonStr.treatmentPtr
text = [oldText,text]
*(*(*(*pState).davePtr).dataStrPtr).commonStr.treatmentPtr = text

end
;;;;;;;;;;;;
pro fdaveRTCOldBinning,event
widget_control,event.top,get_uvalue = pState
if n_elements(*(*pState).xPtr) eq 0 then return
qty = *(*pState).dataoPtr
err = *(*pState).erroroPtr
y = 0.0
x = *(*pState).xoPtr
newState = {qty:qty,err:err,y:y,x:x}
*(*(*(*pState).davePtr).dataStrPtr).commonStr.histPtr = newState
wset,(*pState).winPix
fdaveRTCplot,event
wset,(*pState).winVis
device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]

text = 'Revert to original binning'
oldText = *(*(*(*pState).davePtr).dataStrPtr).commonStr.treatmentPtr
text = [oldText,text]
*(*(*(*pState).davePtr).dataStrPtr).commonStr.treatmentPtr = text
end
;;;;;;;;;;;;
pro fdaveRTCLoad,event
widget_control,event.top,get_uvalue = pState
cd,(*!dave_defaults).datDir
filename = dialog_pickfile(dialog_parent = event.top,$
                title = 'Select ASCII file',$
                filter = '*.txt')
if filename eq '' then begin
  strout = 'No file selected'
  void = dialog_message(dialog_parent = event.top,strout,/error)
  return
endif
widget_control,hourglass = 1
; set up error catching
catch,anError
if anError ne 0 then begin
  catch,/cancel
  print,'Unknown problem here...returning.'
  widget_control,hourglass = 0
  return
endif

 openr, lun, filename, /get_lun
 nbig  = 50000L
 x     = dblarr(nbig)
 y     = dblarr(nbig)
 yerr  = dblarr(nbig)
 x1    = 0.0
 y1    = 0.0
 y1err = 0.0
 count = 0
 ;;;;
 dummy = ''

 while (not eof(lun)) do begin
	readf,lun,dummy
	reads,dummy,x1,y1,y1err
 ;   readf, lun, x1,y1,y1err
    x[count] = x1
    y[count] = y1
    yerr[count] = y1err
    count = count + 1L
 endwhile
 free_lun, lun
x = x[0:count-1]
y = y[0:count-1]
yerr = yerr[0:count-1]
xsort = sort(x)
x = x[xsort] & y = y[xsort] & yerr = yerr[xsort]
*(*pState).xPtr = x
*(*pState).yPtr = y
*(*pState).yerrPtr = yerr
(*pState).xviewrange = [min(x),max(x)]
dy = max(y)-min(y)
(*pState).yviewrange = [min(y)-0.1*dy,max(y)+0.1*dy]

  *(*(*(*pState).davePtr).dataStrPtr).commonStr.histPtr = {qty:y,$
                                                err:yerr,$
                                                x:x,$
                                                y:0.0}
  *(*pState).dataoPtr = y
  *(*pState).erroroPtr = yerr
  *(*pState).xoPtr = x

(*(*(*pState).davePtr).dataStrPtr).commonStr.instrument = 'unknown'
(*(*(*pState).davePtr).dataStrPtr).commonStr.xlabel = 'x'
(*(*(*pState).davePtr).dataStrPtr).commonStr.ylabel = 'No label'
(*(*(*pState).davePtr).dataStrPtr).commonStr.xunits = 'x units'
(*(*(*pState).davePtr).dataStrPtr).commonStr.yunits = 'No units'
(*(*(*pState).davePtr).dataStrPtr).commonStr.histunits = 'arbitrary units'
(*(*(*pState).davePtr).dataStrPtr).commonStr.histlabel = 'Intensity (arbitrary units)'
treatment = ['converted from ASCII to DAVE']
*(*(*(*pState).davePtr).dataStrPtr).commonStr.treatmentPtr = treatment
(*(*(*pState).davePtr).dataStrPtr).commonStr.xtype = 'POINTS'
(*(*(*pState).davePtr).dataStrPtr).commonStr.ytype = ''
comments = ''
specific = {filename:filename,$
                comments:comments}
*(*(*(*pState).davePtr).dataStrPtr).specificPtr = specific
widget_control,hourglass = 0
catch,/cancel
wset,(*pState).winPix
fdaveRTCplot,event
wset,(*pState).winVis
device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
end
;;;;;;;;;;;;
pro fdaveRTCDraw,event
widget_control,event.top,get_uvalue = pState
if not ptr_valid((*pState).xPtr) then return

case event.type of
0: begin	; button press
      (*pState).mouse = event.press
      if (*pState).mouse eq 4 then begin
        (*pState).autoscale = 1
        wset,(*pState).winPix
        fdaveRTCplot,event
        wset,(*pState).winVis
        device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
      endif
      if (*pState).mouse eq 1 then begin
        widget_control,(*pState).plotWin,draw_motion_events = 1
        (*pState).autoscale = 0
        (*pState).xbox[0] = event.x
        (*pState).ybox[0] = event.y
        wset,(*pState).winVis
        device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
      endif
    end
1:  begin
      if (*pState).mouse eq 4 then begin
        (*pState).mouse = 0B
      endif
      if (*pState).mouse eq 1 then begin
        xll = (*pState).xbox[0] < (*pState).xbox[1]
        yll = (*pState).ybox[0] < (*pState).ybox[1]
        w = abs((*pState).xbox[1]-(*pState).xbox[0])
        h = abs((*pState).ybox[1]-(*pState).ybox[0])
        xur = xll + w
        yur = yll + h
        ll = convert_coord(xll,yll,/device,/to_data)
        ur = convert_coord(xur,yur,/device,/to_data)
        (*pState).xviewrange = [ll[0],ur[0]]
        (*pState).yviewrange = [ll[1],ur[1]]
		wset,(*pState).winPix
		fdaveRTCplot,event
		wset,(*pState).winVis
		device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
        widget_control,(*pState).plotWin,draw_motion_events = 0
        (*pState).mouse = 0B
      endif
    end
2:  begin
       if (*pState).mouse eq 1 then begin
         (*pState).xbox[1] = event.x
         (*pState).ybox[1] = event.y
         xc = [(*pState).xbox[0],event.x,event.x,(*pState).xbox[0],(*pState).xbox[0]]
         yc = [(*pState).ybox[0],(*pState).ybox[0],event.y,event.y,(*pState).ybox[0]]
         wset,(*pState).winVis
         device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
         plots,xc,yc,/device
         empty
       endif
     end
else:
endcase

end
;;;;;;;;;;;;
pro fdaveRTFileEntry,event
widget_control,event.top,get_uvalue = pState
y = fdave_enterinfo((*pState).davePtr,group_leader = event.top)
wset,(*pState).winPix
fdaveRTCplot,event
wset,(*pState).winVis
device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
end
;;;;;;;;;;;;
pro fdave_read3ColAscii,notifyIDs,group_leader = group_leader
; widget definition module
widget_control,group_leader,get_uvalue = state_ptr
davePtr = (*state_ptr).davePtr

loadct,0,/silent
butsize = 250
; create the filled circle symbols for use in plotting the data
th = hfbs_makepoints(xlo = 0.0,xhi = 2.0*!pi,npts = 30)
xsym = cos(th) & ysym = sin(th)
usersym,xsym,ysym

tlb = widget_base(/row,title = 'ASCII Data Conversion Utility',group_leader = group_leader,$
                  tlb_frame_attr = 1,mbar = bar)

base = widget_base(tlb,/col)
filemenu = widget_button(bar,value = 'File',/menu)
treatmenu = widget_button(bar,value = 'Treatment',/menu)
printmenu = widget_button(bar,value = 'Print',/menu)
void = widget_button(printmenu,value = 'Print screen to PS file',event_pro = 'fdaveRTCPrint')
void = widget_button(treatmenu,value = 'Rebin data',event_pro = 'fdaveRTCRebin')
void = widget_button(treatmenu,value = 'Original binning',event_pro = 'fdaveRTCOldBinning')
void = widget_button(treatmenu,value = 'Enter file information',event_pro = 'fdaveRTFileEntry')
void = widget_button(filemenu,value = 'Load ascii file',$
         event_pro = 'fdaveRTCLoad')
void = widget_button(filemenu,value = 'Save workspace',$
         event_pro = 'fdaveRTCSaveWorkspace')

void = widget_button(filemenu,value = 'Dismiss',$
         event_pro = 'fdaveRTCDismiss')

winxsize = 400 & winysize = 350
plotWin = widget_draw(tlb,xsize = winxsize,ysize = winysize,$
               /button_events,event_pro = 'fdaveRTCDraw')

centertlb,tlb
widget_control,tlb,/realize
widget_control,plotWin,get_value = winVis
window,/free,/pixmap,xsize = winxsize,ysize = winysize
winPix = !d.window

state = {	davePtr:davePtr,$
            notifyIDs:notifyIDs,$
            plotWin:plotWin,$
            winVis:winVis,$
            winPix:winPix,$
            mouse:0B,$,
            autoscale:1,$
            xviewrange:[0.0,1.0],$
            yviewrange:[0.0,1.0],$
            xbox:[0.0,1.0],$
            ybox:[0.0,1.0],$
            xPtr:ptr_new(/allocate_heap),$
            yPtr:ptr_new(/allocate_heap),$
            yerrPtr:ptr_new(/allocate_heap),$
            dataoPtr:ptr_new(/allocate_heap),$
            erroroPtr:ptr_new(/allocate_heap),$
            xoPtr:ptr_new(/allocate_heap)}

pState = ptr_new(state)

widget_control,tlb,set_uvalue = pState
xmanager,'fdave_read3ColAscii',tlb,cleanup = 'fDaveRTCCleanup'
end