; Copyright (c) 1998-2015 A.P. Hitchcock  All rights reserved
;+
;NAME:
;		AX_SELECT
;
;LAST CHANGED: ----------------------------------- 	02-Jan-15
;
; PURPOSE:
;	This set of procedures is a widget which allows user to select
;  a range of the data to make a 0/1 BIT MASK which can be used as
;  a region of interest (ROI) selector in stack_analyze
;
; CATEGORY:
;	aXis2000 capitve. Image manipulation
;
; CALLING SEQUENCE:
;	AX_SELECT
;
; INPUTS: default set of buffers are R=4, G=5, B=6
;
; KEYWORDS:
;	GROUP_LEADER 	calling widget
;	no_axis 		if set, do not execute aXis2000 specific lines (eg display in aXis2000)
;
; OUTPUTS:
; a ROI file suitable to be used in stack_analyze is written
;
; AX_SELECT_EVENT ROUTINES:
;
; NUM_FORMAT			standard number format for limits
; MAKE_Threshold_Image 	generate image with threshold overlay
; SLIDER_R				adjust  min / max value
; TEXT_select_max		adjust max value
; TEXT_select_min		adjust min value
; BUT_select_CANCEL		cancel
; BUT_select_SAVE_MASK  save mask
; BUT_select_SAVE_ROI	save ROI file
;
; COMMON BLOCKS:
;	AXIS_COM	standard set of common blocks
;	AX_SELECT_COM  parameters specifc to ax_select
;
; SIDE EFFECTS:
;	A window is created/destroyed.
;
; RESTRICTIONS:
;	Any known ?
;
; MODIFICATION HISTORY:
; (29-Dec-07 aph) first version adapted from AX_RGB_MAP
; (29-Jan-11 aph) add separate saving of ROI_file and the mask image
;         allow arbitary buffer to store mask images
; (02-Jan-15 aph) allow use of ax_select outside of aXis2000, with no_axis parameter
;-

FUNCTION num_format, value
num_string = strtrim(string(value,format = '(g9.2)'))
return, num_string
END

PRO Make_Threshold_Image
@axis_com
@ax_select_com
on_error,2

;  ************ Generate a composite of image and a semitransparent red overlay *******
; ------- identify pixels within slider range
; NM for external use, the image array is passed as an array in the call and set to pic
if axis_on then begin
	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 THEN RETURN
	IF tmp.t NE '2d' THEN RETURN
	pic = tmp.d
endif

r_image = pic
r_mask=pic
r_mask[*,*] = 1.
lo_index = where(r_image LT r_min, count)
if count GT 0 then r_mask(lo_index)=0.
hi_index = where(r_image GT r_max, count)
if count GT 0 then r_mask(hi_index)=0.
t = size(pic)
img_size=[t(1), t(2)]

image = bytarr(3,img_size(0), img_size(1))
Arslope = 255./(Ar_max-Ar_min)
gs_image = byte(Arslope*(r_image-Ar_min))
image(0,*,*) = gs_image
image(1,*,*) = gs_image
image(2,*,*) = gs_image
mask_index = where(r_mask EQ 1, count)
if count GT 0 then begin
	r_image(mask_index) = Ar_max
	image(0,*,*) = byte(Arslope*(r_image-Ar_min))
endif
wset, Select_display
; ------ set up color scale (use default if it is not already set)
if n_elements(ax_top_color_index) EQ 0 then ax_top_color_index = 256
r = indgen(ax_top_color_index) & g = indgen(ax_top_color_index) & b = indgen(ax_top_color_index) ; make linear color tables for R G B
tvlct, r,g,b
; ------- generate thrershold marked image
main = 360*gr_scale
t_scl = main/max([img_size(0), img_size(1)])
nx = fix(t_scl*img_size(0))
ny = fix(t_scl*img_size(1))
t_image = intarr(3, nx, ny)
for i=0,2 do $
	t_image(i,*,*) = congrid(reform(image(i,*,*)),nx, ny, /interp)
tv, t_image, /true
END

;-----------------------------------------------------------------
PRO Select_histogram_update
@axis_com
@ax_select_com
on_error,2

wset, Select_hist_ID
if n_elements(r_hist) GT 1 then begin
;	if keyword_Set(new) then $
	        plot, r_hist(0,*),r_hist(1,*), xstyle=5, ystyle=5, xmargin=[0,0],ymargin=[0,0]
    y_min = min(r_hist(1,*), max=y_max)
	oplot, [r_min, r_min], [y_min, y_max]
	oplot, [r_max, r_max], [y_min, y_max]
endif else erase
END

;-----------------------------------------------------------------
pro TEXT_select_max, Event
@axis_com
@ax_select_com
on_error,2
id = widget_info(Event.top, FIND_BY_UNAME = 'TEXT_select_max')
WIDGET_CONTROL,id, Get_value = r_max
r_max = float(r_max(0))
WIDGET_CONTROL,id, Set_value = num_format(r_max)
Rvalue=[double(r_min), double(r_max)]
id = widget_info(Event.top, FIND_BY_UNAME = 'SLIDER_R')
CW_RSLIDER_SET_VALUE, id, Rvalue
Select_histogram_update
Make_Threshold_Image
end

;-----------------------------------------------------------------
pro TEXT_select_min, Event
@axis_com
@ax_select_com
on_error,2
id = widget_info(Event.top, FIND_BY_UNAME = 'TEXT_select_min')
WIDGET_CONTROL,id, Get_value = r_min
r_min = float(r_min)
WIDGET_CONTROL,id, Set_value = num_format(r_min)
Rvalue=[double(r_min), double(r_max)]
id = widget_info(Event.top, FIND_BY_UNAME = 'SLIDER_R')
CW_RSLIDER_SET_VALUE, id, Rvalue
Select_histogram_update
Make_Threshold_Image
end

; ***********************SLIDER EVENTS *************
;   -----------------------------------------------
pro SLIDER_Red, Event
@axis_com
@ax_select_com
on_error,2

if n_elements(r_hist) LE 1 then return	; in case user changes slider while there is no image
r_min =  event.values(0)
r_max =  event.values(1)
id = widget_info(Event.top, FIND_BY_UNAME = 'TEXT_select_min')
WIDGET_CONTROL,id, Set_value = num_format(r_min)
id = widget_info(Event.top, FIND_BY_UNAME = 'TEXT_select_max')
WIDGET_CONTROL,id, Set_value = num_format(r_max)
Select_histogram_update
Make_Threshold_Image
end

;-----------------------------------------------------------------
pro BUT_SELECT_SAVE_ROI, Event
@axis_com
@ax_select_com
on_error,2


roi_file = pickfile2(/write, FILTER='*.roi', /LPATH, DEFPATH=defpath)

if roi_file NE '' then begin
	high = where(r_mask EQ 1.0, count)
	print, count, ' points masked'
	t = ax_name(roi_file)
	roi_file = t(0)+t(1) + '.roi'
	openw,lun,roi_file,/xdr, /get_lun
	writeu,lun,n_elements(high),0
	writeu,lun,long(high)
	close,lun & free_lun,lun
  	axis_log,'Wrote ROI file: ' + t(1)
endif
Make_Threshold_Image

end

;-----------------------------------------------------------------
pro BUT_SELECT_SAVE_MASK, Event
@axis_com
@ax_select_com
on_error,2

IF axis_on then begin
	HANDLE_VALUE, Data(CurBuf), tmp
	CurBuf_tmp = CurBuf
	tmp.dl = tmp.dl + ' Mask:' + strcompress(string(r_min,format='(g8.2)')) + '-' $
	                           + strcompress(string(r_max,format='(g8.2)'))
	tmp.d = r_mask
	CurBuf = buffer(group=aXis_ID)
	ax_mask_flag = CurBuf
	Label(CurBuf) = tmp.dl
	HANDLE_VALUE, Data(CurBuf), tmp, /set
	TVLCT, UserR, UserB, UserG	; load current user-defined color table
	ax_color						; set standard axis color scheme
	PlotBuf,CurBuf
	CurBuf = CurBuf_tmp		; return to original data to allow further use of the widget
ENDIF ELSE BEGIN
; --------- generate an axis format image of the mask and save to disk
	mask = float(r_mask)		; if mask UINT the r_mask is not 0 / 1
	r_mask = mask				; use r:mask to trasnfer in ax_display_ptycho
	t = size(mask)
	x = findgen(t(1))
	y = findgen(t(2))
	tmp = {t:'2d', x:x, y:y, xl:'x (um)', yl:'y', d: mask, dl:'bright-field mask'}
	t = AXB_SAVE(tmp, /no_axis)

ENDELSE

end

;-----------------------------------------------------------------
pro  WIDGET_KILL_REQUEST, Event
@axis_com
@ax_select_com
on_error,2
ax_color						; set standard axis color scheme
WIDGET_CONTROL, Event.Top, /DESTROY
end

;-----------------------------------------------------------------
pro BUT_SELECT_CANCEL, Event
@axis_com
@ax_select_com
on_error,2

if axis_on then BEGIN
	if ax_mask_flag GE 0 then begin
		print, 'shift to mask buffer
		CurBuf = ax_mask_flag  ; shift active buffer to the mask
	endif
	HANDLE_VALUE, Data(CurBuf), tmp
	TVLCT, UserR, UserB, UserG	; load current user-defined color table
	ax_color						; set standard axis color scheme
	HANDLE_VALUE, Data(CurBuf), tmp
	PlotBuf,CurBuf
	ax_mask_flag = -1
endif
WIDGET_CONTROL, Event.Top, /DESTROY
end

; **************************************************************************
; ---------------------------------  PROCESS CLICKS etc -------------------
pro AX_SELECT_BASE_event, Event
@axis_com
@ax_select_com
on_error,2

wWidget =  Event.top

  case Event.id of

; --------- kill ax_select widget if use X in upper right corner --------------
    Widget_Info(wWidget, FIND_BY_UNAME='AX_SELECT_BASE'): begin
      if( Tag_Names(Event, /STRUCTURE_NAME) eq 'WIDGET_KILL_REQUEST' )then $
       WIDGET_KILL_REQUEST, Event
    end

; -------------- adjust maxima and minima with compound slider
    Widget_Info(wWidget, FIND_BY_UNAME='SLIDER_R'): SLIDER_Red, Event

; ------ adjust minima & maxima numerically
    Widget_Info(wWidget, FIND_BY_UNAME='TEXT_select_max'): TEXT_select_max, Event
    Widget_Info(wWidget, FIND_BY_UNAME='TEXT_select_min'): TEXT_select_min, Event

    Widget_Info(wWidget, FIND_BY_UNAME='AX_SELECT_cancel'): BUT_SELECT_CANCEL, Event

    Widget_Info(wWidget, FIND_BY_UNAME='AX_SELECT_BUTTON_save_roi'): BUT_SELECT_SAVE_ROI, Event

    Widget_Info(wWidget, FIND_BY_UNAME='AX_SELECT_BUTTON_save_mask'): BUT_SELECT_SAVE_MASK, Event

    else: print, 'Undefined action'
  endcase

end

; --------------------------------------------------------------------------------------
; **************************************************************************************
; --------------------------------------------------------------------------------------


pro ax_select, tiff=tiff, GROUP_LEADER=wGroup, no_axis=no_axis, _EXTRA=_VWBExtra_
@axis_com
@ax_select_com
on_error,2

; default is to operate as pre-Jan2015 assuming called from aXis2000,
; but allow stand-alone for operation from ax_display_ptycho
axis_on = 1
if keyword_set(no_axis) then axis_on = ~ no_axis

; ------------- switch to use a tif image
help, tiff
if keyword_Set(tiff) then select_tiff = 1 else select_tiff = 0

tx = size(wGroup)
IF tx(1) EQ 0 THEN modal_val=0 else modal_val=1

  AX_SELECT_BASE = Widget_Base( GROUP_LEADER=wGroup, UNAME='AX_SELECT_BASE',  $
      modal = modal_val, TITLE='aXis2000 ROI selector', $
     /TLB_KILL_REQUEST_EVENTS, SPACE=3 ,XPAD=3 ,YPAD=3)

; ------------------ GUI parameterization
number_size = 9
hist_offset = 78
hist_Vsize = 100
hist_Hsize = 200
T_size = 78
Tmin_x_offset =  0
Tmax_x_offset =  hist_Hsize  + hist_offset
color_size  = hist_Vsize + 30
R_y_offset = hist_Vsize
main = fix(360*gr_scale)
main_offset = 360

yoffset_red = main + 7
xoffset_lists = main_offset
label_size = 60
Index_size = label_size + 30

ax_mask_flag = -1.

 AX_SELECT_image = Widget_Draw(AX_SELECT_BASE, UNAME='AX_SELECT_image' ,XOFFSET=main_offset  $
      ,SCR_XSIZE=main ,SCR_YSIZE=main)

  TEXT_select_max = Widget_Text(AX_SELECT_BASE, UNAME='TEXT_select_max'  $
      ,XOFFSET=Tmax_x_offset, YOFFSET=R_y_offset ,/EDITABLE, XSIZE=number_size ,YSIZE=1)
  TEXT_select_min = Widget_Text(AX_SELECT_BASE, UNAME='TEXT_select_min'  $
      ,XOFFSET=Tmin_x_offset ,YOFFSET=R_y_offset, /EDITABLE,XSIZE=number_size ,YSIZE=1)

; ------------------------- histogram plot
  Select_histogram = Widget_Draw(AX_SELECT_BASE, UNAME=' Select_Histogram' ,XOFFSET=hist_offset, YOFFSET=0  $
      ,SCR_XSIZE=hist_Hsize ,SCR_YSIZE=hist_Vsize)

 param_offset = 240
  AX_SELECT_BUTTON_cancel = Widget_Button(AX_SELECT_BASE,  $
      UNAME='AX_SELECT_cancel' ,XOFFSET=65 ,YOFFSET= param_offset+60  $
      ,SCR_XSIZE=100 ,SCR_YSIZE=40 ,/ALIGN_CENTER ,VALUE='Dismiss')
  AX_SELECT_BUTTON_save_roi = Widget_Button(AX_SELECT_BASE, UNAME='AX_SELECT_BUTTON_save_roi'  $
      ,XOFFSET=150 ,YOFFSET= param_offset ,SCR_XSIZE=100 ,SCR_YSIZE=40  $
      ,/ALIGN_CENTER ,VALUE='Save ROI')
  AX_SELECT_BUTTON_save_mask = Widget_Button(AX_SELECT_BASE, UNAME='AX_SELECT_BUTTON_save_mask'  $
      ,XOFFSET=15 ,YOFFSET= param_offset ,SCR_XSIZE=100 ,SCR_YSIZE=40  $
      ,/ALIGN_CENTER ,VALUE='Save mask image')

  text = 'Left button - lower limit      Right button - upper limit      Both or middle button = move both'
  tlabel = widget_label(AX_SELECT_BASE, XOFFSET=10,YOFFSET= main+10, value=text)

; populate the Widget parameters


; ------ display image
if axis_on then begin
	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 THEN RETURN
	IF tmp.t NE '2d' THEN RETURN
	pic = tmp.d
endif

if select_tiff EQ 1 then pic = tiff else select_tiff = 0

r_min=min(pic,max=r_max)
Ar_min = r_min & Ar_max = r_max
r_range = r_max - r_min
r_min = max([0.,r_min+0.2*r_range])
hist_bins = 100
r_hist = ax_histogram(pic, n_bins=hist_bins)

; ----- set up slider and initial value with min set to 0 or 10% of value
S_margin = 0.05
widget_control, TEXT_select_min, set_value=num_format(r_min)
widget_control, TEXT_select_max, set_value=num_format(r_max)
RS_min = double(Ar_min - S_margin*(Ar_max-Ar_min))
RS_max = double(Ar_max + S_margin*(Ar_max-Ar_min))
Rvalue = [double(r_min), double(r_max)]
RS_base = WIDGET_BASE(AX_SELECT_BASE, UNAME='WID_BASE_R', TITLE="Red", XPAD = 5, YPAD = 5, $
           XOFFSET=T_size, YOFFSET=hist_Vsize, SCR_YSIZE=70,SCR_XSIZE=200)
sliderR = CW_RSLIDER(RS_BASE, UNAME='SLIDER_R', color=[255,0,0],  $
            XSIZE=196, YSIZE = 20, $
            MINIMUM=RS_min, MAXIMUM=RS_max, VALUE=Rvalue)

; --------- realize and load the widget --------
Widget_Control, /REALIZE, AX_SELECT_BASE
; ---- get index of the draw and histogram windows
WIDGET_CONTROL, AX_SELECT_image, GET_VALUE = Select_display
WIDGET_CONTROL,  Select_histogram, GET_VALUE =  Select_hist_ID

; --------- generate histogram plots
Select_histogram_update

; generate image and overlay of top 10%
Make_Threshold_Image

XManager, 'AX_SELECT_BASE', AX_SELECT_BASE

end

