; Copyright (c) 1998-2015 A.P. Hitchcock  All rights reserved
;+
;NAME:
;	AX_XYCAL
;
;LAST CHANGED: ----------------------------------- 22-Mar-15 (aph)
;
;PURPOSE:
;	This procedure calibrate the XY-values of currently displayed image.

;CATEGORY:
;	AXIS: image analysis
;
;CALLING SEQUENCE:
;	AX_XYCAL, ONE=one
;
;CALLED FROM AXIS:
;	Images->CalibrateXY->{1 point, 2 points}

;INPUTS: none
;
;KEYWORDS:
;	ONE - use only 1-point to calibrate (shift)
; The default is a 2-point calibration (stretch-shift)
;
;OUTPUTS:
;	recalibrated image is placed in buffer 0.
;
;COMMON BLOCKS:
;	@AXIS_COM	standard set of common blocks
;
;MODIFICATION HISTORY:
; ( 4-Jun-98 aph) added 1-point version
; (14-jun-98 aph) axis_com
; (30-Dec-98 aph) format Uprompt
; ( 8-jun-99 aph) add group to get_num call; FIXED major error for 2-point calib !
; (20-oct-99 aph) add meshing and truncating to make same as image alignment procedure
; (01-jan-00 aph) set (xmin, xmax, ymin, ymax to limits); AXIS standard documentation
; (07-nov-00 aph) add tmp.E to preserve Energy of images
; (28-oct-01 aph) add check for tmp.E, set to zero if not found
; (29-Nov-11 aph)  add zoom box for more precise placement
;                 - NOT COMPLETED  - need cursor on zoom & right color
; (22-May-15 aph) use real not integer pixle size (in nm)
;-

PRO AX_XYCal, ONE=one
@axis_com
HANDLE_VALUE, Data(CurBuf), tmp
IF n_tags(tmp) EQ 0 THEN RETURN
 if tmp.t EQ '2d' then begin         ; ONLY for images
 	SetGraf, 'MainImg'
	WIDGET_CONTROL, Uprompt,  Bad_ID=badID, SET_VALUE='Calib XY: select 1st point'
;	ax_zoom_pan,/continuous, /interp, xsize=wsz, ysize=wsz
	cursor, x1, y1, /data, /down
	Xn1 = get_num(prompt='new X1-value',val=xlock(0), group = axis_id)
	Yn1 = get_num(prompt='new Y1-value',val=ylock(0), group = axis_id)
	xlock(0) = Xn1                ; use xlock, ylock COMMON to preserve user def.
    ylock(0) = Yn1
	CurInd = DIndex(x1(0),y1(0),tmp)
	CurX1 = CurInd(0) & CurY1 = CurInd(1)
	Xd1 = tmp.x(curx1) & Yd1 = tmp.y(cury1)
;		print, '1st point: ', x1(0), y1(0), ' in tmp', xd1, yd1
	xslope = 1.0 &  yslope = 1.0
	if NOT keyword_set(one) THEN BEGIN
		WIDGET_CONTROL, Uprompt,  Bad_ID=badID, SET_VALUE='Calib XY: select 2nd point'
		cursor, x2, y2, /data, /down
		CurInd = DIndex(x2(0),y2(0),tmp)
		CurX2 = CurInd(0) & CurY2 = CurInd(1)
		Xd2 = tmp.x(curx2) & Yd2 = tmp.y(cury2)
		Xn2 = get_num(prompt='new X2-value',val=xlock(1), group = axis_id)
		Yn2 = get_num(prompt='new Y2-value',val=ylock(1), group = axis_id)
		xlock(1) = Xn2
    	ylock(1) = Yn2
;			print, '2nd point: ', x2(0), y2(0), ' in tmp', xd2, yd2
		xslope = (Xn1 - Xn2) /(X1 - X2)
		yslope = (Yn1 - Yn2) /(Y1 - Y2)
	endif
	xint = Xn1 - xslope*X1(0)
	yint = Yn1 - yslope*Y1(0)
	pix_siz = 1000.*abs(tmp.x(1) - tmp.x(0))   ; save original pixel size for default mesh
	tmp.x = xslope*tmp.x + xint
	tmp.y = yslope*tmp.y + yint
	CurBuf = 0
	tmp.dl = 'xyC ' + tmp.dl

; ------------ interpolate to a standard mesh size ---------------
	pix_siz = 0.001*get_num(Prompt='Pixels (nm)',val=pix_siz, group = axis_id)
	nx = fix(abs(tmp.x(n_elements(tmp.x)-1) - tmp.x(0)) /pix_siz)
	ny = fix(abs(tmp.y(n_elements(tmp.y)-1) - tmp.y(0)) /pix_siz)
	print, 'Congrid cut_data to ', nx, ny
	xn = congrid(tmp.x,nx,/interp)
	yn = congrid(tmp.y,ny,/interp)
	dn = congrid(tmp.d,nx,ny,/interp)
	test = tag_names(tmp)
	q = where(test EQ 'E',count)
	if count EQ 0 then energy = 0 else energy = tmp.E
	tmp = create_struct('t','2d','x',xn,'y',yn,'d',dn, $
		'xl',tmp.xl,'yl',tmp.yl,'dl',tmp.dl, 'E', energy)
	HANDLE_VALUE, Data(CurBuf), tmp, /set
	Label(CurBuf) = tmp.dl
	PlotBuf,CurBuf

; ------------- cut image to standard size - (save values in common) -------------
	print, 'select data range.'
	if cll(0) EQ 0 then cll(0) = min(tmp.x)
	if cur(0) EQ 0 then cur(0) = max(tmp.x)
	if cll(1) EQ 0 then cll(1) = min(tmp.y)
	if cur(1) EQ 0 then cur(1) = max(tmp.y)
	cll(0) = get_num(prompt='X-min',val=cll(0), group = axis_id)
	cur(0) = get_num(prompt='X-max',val=cur(0), group = axis_id)
	cll(1) = get_num(prompt='Y-min',val=cll(1), group = axis_id)
	cur(1) = get_num(prompt='Y-max',val=cur(1), group = axis_id)
	Ilo = DIndex(cll(0),cll(1),tmp)
	Ihi = DIndex(cur(0),cur(1),tmp)
   	xn = tmp.x(Ilo(0):Ihi(0))	; cut out the zoomed data from tmp
	yn = tmp.y(Ilo(1):Ihi(1))
	dn = tmp.d(Ilo(0):Ihi(0),Ilo(1):Ihi(1))

; ------------ regenerate data structure ---------------------------
	tmp = create_struct('t','2d','x',xn,'y',yn,'d',dn, $
		'xl',tmp.xl,'yl',tmp.yl,'dl',tmp.dl,'E', tmp.E)
	HANDLE_VALUE, Data(CurBuf), tmp, /set
	Label(CurBuf) = tmp.dl
	PlotBuf,CurBuf
	text = string(format='("Calibrate XY",/,"       slope     intercept",/,"X:  ",F8.3,"  ",F8.3,/,"Y:  ",F8.3,"  ",F8.3)', $
	       xslope, xint, yslope, yint)
	WIDGET_CONTROL, Uprompt,  Bad_ID=badID, SET_VALUE= text
 endif else WIDGET_CONTROL, Uprompt, Bad_ID=badID, SET_VALUE='Calib XY: only for images'
END
