;$Id: cropxdata.pro,v 1.5 2008/02/13 20:48:19 kneller Exp $
;###############################################################################
;
; NAME:
;   cropXData
;
; PURPOSE:
;   Lets user specify x limits or domain of resolution
;   function. Displays the limits as vertical lines overplotted on a
;   display of the resolution data. Extends basic functionality
;   provided by getResLimit
;
; CATEGORY:
;   Data Analysis (PAN)
;
; AUTHOR:
;   Richard Tumanjong Azuah
;   NIST Center for Neutron Research
;   100 Bureau Drive, Gaithersburg, MD 20899
;   United States
;   azuah@nist.gov; (301) 9755604
;   July, 2006
;
; 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.
;
;###############################################################################
pro cropXData_Display, sPtr

    dSize = size((*sPtr).data)
    nd = (dSize[0] eq 2) ? dSize[2] : 1
    
    if (nd gt 1) then begin
        widget_control, (*sPtr).wSlider, get_value=grpnos
        data = reform((*sPtr).data[*,grpnos-1])
        mask = reform((*sPtr).mask[*,grpnos-1])
    endif else begin
        data = reform((*sPtr).data)
        mask = reform((*sPtr).mask)
    endelse

    whnotmasked = where(mask ne 0, nmcount)
    whmasked = where(mask eq 0, mcount)

    if mcount ne 0 then begin
        ;SOMETHING MASKED
        if nmcount gt 0 then begin
          xplot = ((*sPtr).xres)[whnotmasked]
  ;        ;yplot = ((*sPtr).data)[whnotmasked]
          yplot = data[whnotmasked]
        endif else begin
          ;CREATE A DUMMY POINT FOR GROUPS WITH NO RESOLUTION DATA
          xplot = [0]
          yplot = [0]
        endelse
;        xplot = ((*sPtr).xres)[whmasked]
;        yplot = data[whmasked]
    endif else begin
        ;NOTHING MASKED
        xplot = (*sPtr).xres
        yplot = data;(*sPtr).data
    endelse

    if ((*sPtr).zoom eq 1) then begin
        xr = (*sPtr).xr
        yr = (*sPtr).yr
    endif else begin
        ;xmin = min((*sPtr).xres,max=xmax)
        xmin = min(xplot,max=xmax)

        xlo = (*sPtr).limits[0]
        xhi = (*sPtr).limits[1]
        ;dx = 5*((*sPtr).xres[1] - (*sPtr).xres[0])

        dx = 0.05*(xmax-xmin)
        xr = [xlo-dx,xhi+dx]


        ;ylo = min(data,max=yhi)
        ylo = min(yplot,max=yhi)


        ;dy = 5*(data[1] - data[0])
        dy = 0.05*(yhi-ylo)


        yr = [ylo-dy,yhi+dy]
    endelse

    wset, (*sPtr).winPix
    device,decomposed = 1, get_decomposed=old_dc
    red = fsc_color('red')
    green = fsc_color('green')
    black = fsc_color('black')
    white = fsc_color('white')

    ;plot,(*sPtr).xres,data,xrange=xr,yrange=yr,linestyle = 0 $ ;
    ;     ,color=black,background=white,/xsty,psym=4 ;/ysty
    
    
    if nmcount gt 0 then begin
      plot,xplot,yplot,xrange=xr,yrange=yr,linestyle = 0 $ ;
          ,color=black,background=white,/xsty,psym=4 ;/ysty
    endif else begin
      ;IF THERE IS NO RES DATA, THEN SHOW NO DATA IN THE PLOT TO AVOID CONFUSION.
      plot,xplot,yplot,xrange=xr,yrange=yr,linestyle = 0 $ ;
          ,color=black,background=white,/xsty,psym=4,/nodata
    endelse

    plots,[(*sPtr).limits[0],(*sPtr).limits[0]],!y.crange,linestyle = 2,color=red,thick=3
    plots,[(*sPtr).limits[1],(*sPtr).limits[1]],!y.crange,linestyle = 2,color=green,thick=3
    device, decomposed=old_dc

    wset, (*sPtr).winVis            ; set winVis as destination window
    device, copy=[0,0,(*sPtr).xs,(*sPtr).ys,0,0,(*sPtr).winPix] ; copy contents of winPix to winVis

end;cropXData_Display

;###############################################################################
pro cropXData_Event, event

widget_control, event.top, get_uvalue=sPtr

wLO = widget_info(event.top, find_by_uname='LOLIM')
wHI = widget_info(event.top, find_by_uname='UPLIM')
widget_control, wLO, get_value=lo
widget_control, wHI, get_value=hi
(*sPtr).limits = [lo,hi]

uname = widget_info(event.id,/uname)
case uname of
   'GRPNOS': begin
      cropXData_Display, sPtr
   end

   'OK': begin
      (*sPtr).cancel = 0
      widget_control, event.top, /destroy
   end

   'CANCEL': begin
      (*sPtr).cancel = 1
      widget_control, event.top, /destroy
   end

   'GRLDRAW' : begin
      case event.type of
         0: begin               ; button press
            (*sPtr).mouseType = event.press
            if ((*sPtr).mouseType eq 4) then begin ; right-hand mb so reset plot to full range
               (*sPtr).zoom = 0
               cropXData_Display, sPtr
               (*sPtr).mouseType = 0 ; set mouse type to undefined value
               return
            endif
            if ((*sPtr).mouseType eq 1) then begin ; left-hand mb so record mouse location
               (*sPtr).zp1 = [event.x,event.y]
            endif
         end
         1: begin               ; button release
            if ((*sPtr).mouseType eq 1) then begin ; mouse press was a left-hand mb
               zp1 = (*sPtr).zp1
               zp2 = (*sPtr).zp2
               x = min([zp1[0], zp2[0]])
               y = min([zp1[1], zp2[1]])
               w = abs(zp1[0] - zp2[0])
               h = abs(zp1[1] - zp2[1])
               x2 = x+w
               y2 = y+h
               lc = convert_coord(x, y, /device, /to_data)
               uc = convert_coord(x2, y2, /device, /to_data)
               (*sPtr).xr = [lc[0],uc[0]]
               (*sPtr).yr = [lc[1],uc[1]]
               (*sPtr).zoom = 1
               cropXData_Display, sPtr
               (*sPtr).zp2 = [0.0,0.0] ; reset to zero
            endif
            (*sPtr).mouseType = 0
         end
         2: begin               ; mouse motion
            if ((*sPtr).mouseType eq 1) then begin ; mouse press was a left-hand mb
               (*sPtr).zp2 = [event.x, event.y]
               zp1 = (*sPtr).zp1
               zp2 = (*sPtr).zp2
               xc = [zp1[0], event.x, event.x, zp1[0], zp1[0]]
               yc = [zp1[1], zp1[1], event.y, event.y, zp1[1]]
               device, copy=[0,0,(*sPtr).xs,(*sPtr).ys,0,0,(*sPtr).winPix] ; copy contents of winPix to winVis
               plots, xc, yc, color=fsc_color('blue'), /device
            endif
         end
         else:
      endcase
   end

   else: begin
      cropXData_Display, sPtr
   end
endcase

end;cropXData_Event


;###############################################################################
function cropXData, xres, data, inLimits, group_leader=group_leader, title=title,mask=mask

    if n_elements(mask) ne n_elements(data) then mask = byte(0*data +1)

    if (n_params() lt 2) then return, {cancel:0}

    if (n_elements(title) eq 0) then title=''
    if (n_elements(group_leader) ne 0) then begin
       modal = 1
       wTLB = widget_base(group_leader=group_leader,/tlb_frame_attr, /col,/modal,/base_align_center,title=title)
    endif else begin
       modal = 0
       wTLB = widget_base(/tlb_frame_attr, /col,/base_align_center,title=title)
    endelse

    prec = 3

    ;dx = 0.05*abs(max(xres))
    if (n_elements(inLimits) eq 0) then inLimits =  [min(xres),max(xres)]
    inLimits = float(inLimits)
    fsize=12

    msg1 = 'Enter new values in fields and press carriage return to update display'
    msg2 = 'Vertical lines show lower (red), upper (green) limits of desired range'
    msg3 = "When satisfied, press 'DISMISS' button to accept changes and exit"
    void = widget_label(wTLB,value=msg1)
    void = widget_label(wTLB,value=msg2)
    wCB0 = widget_base(wTLB,/row)

;HERE THE DATA ARE MESSED UP BY THE PRECISION CALL FOR NSE X VALUES (i.e. ns)
    void = fsc_field(wCB0,title = 'Lower Limit',decimal=prec,value=inLimits[0],/highlight $
                     ,uname='LOLIM',/cr_only,xsize=fsize,event_pro='cropxdata_event')
    void = fsc_field(wCB0,title = 'Upper Limit',decimal=prec,value=inLimits[1],/highlight $
                     ,uname='UPLIM',/cr_only,xsize=fsize,event_pro='cropxdata_event')

    dSize = size(data)
    nd = (dSize[0] eq 2)? dSize[2] : 1
    wSlider = 0L
    if (nd gt 1) then begin
       geom = widget_info(wTLB,/geometry)
       wSlider = widget_slider(wTLB,title='Select Group',minimum=1,maximum=nd,uname='GRPNOS',xsize=0.9*geom.xsize)
    endif

    wCB1 = widget_base(wTLB,/col)
    xs = 450
    ys = 350
    wDraw = widget_draw(wCB1,xsize = xs,ysize = ys, uname='GRLDRAW',/button_events,/motion_events)
    void = widget_label(wTLB,value=msg3)

    window,/free,/pixmap,xsize=xs,ysize=ys
    winPix = !d.window

    wCB2 = widget_base(wTLB,/row)
    tt1 = 'Refresh the display'
    tt2 = 'Accept current values and exit'
    tt3 = 'Exit without performing any cropping'
    void = widget_button(wCB2,value='REFRESH',uname='',tooltip=tt1)
    void = widget_button(wCB2,value='ACCEPT',uname='OK',tooltip=tt2)
    void = widget_button(wCB2,value='CANCEL',uname='CANCEL',tooltip=tt3)

    sPtr = ptr_new({limits:inLimits,$
                    cancel:0,$
                    xres:xres,$
                    data:data,$
                    mask:mask,$
                    wSlider:wSlider, $
                    zp1:[0,0],zp2:[0,0],$
                    mouseType:0, $
                    xr:[0.0,0.0],$
                    yr:[0.0,0.0],$
                    zoom:0,$
                    winVis:winPix,$
                    winPix:winPix,$
                    xs:xs,ys:ys})

    widget_control, wTLB, /realize, set_uvalue=sPtr
    widget_control, wDraw, get_value=winVis
    (*sPtr).winVis = winVis

    event = {id:0L,top:wTLB,handler:0L}
    widget_control, wTLB, send_event=event

    xmanager, 'cropXData', wTLB, no_block=modal

    limits = (*sPtr).limits

    retVal = {limits:(*sPtr).limits,cancel:(*sPtr).cancel}
    wdelete, (*sPtr).winPix
    heap_free, sPtr

    return, retVal
end;cropXData


