; Copyright (c) 1998-2015 A.P. Hitchcock  All rights reserved
;+
; NAME:
;	ZSTACK_ALIGN.PRO
;
; LAST CHANGED: ------------------  03-Aug-15
;
; AUTHORS:
;	Carl G. Zimba (Photons UnLimited)
;	Chris Jacobsen (SUNY - Stonybrook)
;   Adam Hitchcock (McMaster)
; PURPOSE:
;	Alignment of images abtained on an x-ray microscope.
;	Called by ZSTACK_ANALYZE.PRO
; CATEGORY:
;	Data analysis.
; CALLING SEQUENCE:
;	zstack_align
; INPUTS:
;	filename_list,ev_list,msec_list,filename_display_list
;    *******  and image_stack of zstack_common must be previously defined via ZSTACK_ANALYZE.PRO
;
; KEYWORD PARAMETERS:
;	filename_shift = name of file containing alignment shifts saved during a previous alignment
;	realign = set to redo alignment with existing dragbox
;	low_mem = set to reduce required memory allocation
; OUTPUTS:
;	NONE
;	x_shift, y_shift, corr_dim_stack, corr_stack, shifted_image_stack of zstack_align_common
;		are computed as output
; COMMON BLOCKS:
;	zstack_common	:
;		data_source				:	type of x-ray microscopy data: STXM:1, SXM:2, SM:3, ALS:4, POLY:5
;		data_directory				:	directory of data files
;		image_stack				:	3-D matrix of multiple x-ray microscope images
;		filename_list				:	list of filename corresponding to images in image_stack
;		ev_list					:	list of x-ray energies corresponding to images in image_stack
;		msec_list					:	list of dwell times corresponding to images in image_stack
;		filename_display_list			:	list of filename, x-ray energy, and dwell time corresponding to images in image_stack
;		displayed_file_index			:	index in image_stack, filename_list, msec_list, and filename_display_list currently being displayed or processed
;		n_files					:	number of images
;		list_filename				:	name of file to save or retrieve list of data files
;		shift_filename				:	filename of alignment shifts
;		x_shift					:	array of x-coordinate alignment shifts
;		y_shift					:	array of y-coordinate alignment shifts
;		data_shifted				:	0: data was not shifted and should not be clipped, 1: data was shifted and should be clipped, -1: denotes ZSTACK_PROFILE.PRO is being run as a stand-alone procedure
;		n_clipped_cols				:	number of columns in clipped image
;		n_clipped_rows				:	number of rows in clipped image
;		clipbox					:	vector of four points defining dimensions of region unclipped by alignment: [xleft,xright,ybot,ytop]
;	zstack_align_common
;		zstack_align_par			:	variables controlling ZSTACK Align dialog window
;		file_num					:	vector of file numbers of image files
;		dragbox					:	vector of four points defining dimensions of region selected for alignment: [xleft,xright,ybot,ytop]
;		edge_enhance				:	edge enhancement parameter: 0: none, 1: sobel, 2: roberts
;		edgegauss_pixels			:	number of pixels used for edgeguass smoothing in ZSTACK_ALIGN_IMAGES.PRO, default = 3
;		edgefill					:	type of filling to occur at edges of shifted images: mean, median, max, min, zero
;		image_match				:	Image to align to: -1: preceding image, 0: constant image, 1: following image
;		constant_file_index			:	image of index to use as reference when aligning to a constant image
;		corr_max					:	0: use 3-pt fitted maximum of correlation function, 1: use center of mass of correlation function
;		maxshift					:	2-point vector of minimum and maximum values of x-shift and y_shift, and temp_x_shift and temp_y_shift within ZSTACK_ALIGN_TUNE
;		doalign_complete			:	-1: alignment in progress, 0: alignment not started, 1: alignment finished, 2: using alignment from stored file
;		low_memory					:	Reflects keyword LOW_MEM: 0: use full memory allocation, 1: use reduced memory allocation
;		corr_stack					:	3-D matrix of correlation functions corresponding to image_stack
;		shifted_image_stack			:	3-D matrix of shifted images corresponding to image_stack
;		corr_dim_stack				:	3-D matrix (i,j,k) of maxima of correlation functions: i: x maximum, j: y maximum, k: image file
;		shift_threshold				:	mimimum shift required to actually shift the image
;	zstack_tune_common
;		zstack_tune_par				:	variables controlling ZSTACK Tune Alignment dialog window
;		temp_x_shift				:	vector of alignment shifts along x-coordinate for images in image_stack, obtained within ZSTACK_ALIGN_TUNE
;		temp_y_shift				:	vector of alignment shifts along y-coordinate for images in image_stack, obtained within ZSTACK_ALIGN_TUNE
;		init_x_shift				:	vector of initial alignment shifts along x-coordinate for images in image_stack
;		init_y_shift				:	vector of initial alignment shifts along y-coordinate for images in image_stack
;		image_center				:	array of pixel coordinates specifying the center (in pixels) of each image
;		corr_center				:	array of pixel coordinates specifying the center (in pixels) of each correlation function image
;		shifted_center				:	array of pixel coordinates specifying the center (in pixels) of each shifted image
;		subimage_center				:	array of pixel coordinates specifying the center (in pixels) of each subimage
;		subcorr_center				:	array of pixel coordinates specifying the center (in pixels) of each correlation function subimage
;		subshifted_center			:	array of pixel coordinates specifying the center (in pixels) of each shifted subimage
;		subimage_pixels				:	size of subimages in pixels
;		fid_pt					:	pixel coordinates of present fiducial point(s)
;		n_fid_pt					:	number of fiducial points
;		all_fid_pt					:	array of all fiducial points
;		fid_pt_index				:	index of fiducial point(s)
;	zstack_display_common
;		zstack_display_par			:	variables controlling ZSTACK Display dialog window
;		image_zoom					:	zoom factor for displaying images
;		subimage_zoom				:	zoom factor for subimages
;		movie_delay				:	delay used to display movie images of data stacks, dependent upon machine speed
;		disp_min					:	minimum percentage intensity for display of images
;		disp_max					:	maximum percentage intensity for display of images
;		disp_gamma					:	gamma factor for display of images
;		spectrum_display			:	Display spectra as: 1: Single Beam, 2: Percent Transmittance, 3: Absorbance
;		spectrum_offset				:	Offset used to plot spectra
;		init_zoom					:	initial zoom factor for displaying images (used in ZSTACK_SAVE and ZSTACK_TUNE)
;		movie_active				:	movie of images is active: 0: NO, 1: YES
;		profile_zoom				:	zoom factor for file number axis on profile images
;		image_range				:	scale images using: 0: intensity range of each image, 1: intensity range of full image stack
;		image_ratio				:	Display images normalized by: 0: inv_image_stack, 1: i0 spectrum
;		ratio_image_index			:	index of image to use when ratio images to a constant image
;		image_scale				:	Display images normalized by: 0: inv_image_stack, 1: i0 spectrum
;		image_invert				:	invert color bar: 0: NO, 1: YES
;		temp_old_display			:	initial array of display parameters, set at beginning of ZSTACK_DISPLAY
;		temp_new_display			:	array of display parameters updated as display options are changed
;		zstack_subroutine			:	subroutine from which ZSTACK_DISPLAY was called
;		spectra_x_min				:	mimimum x-ray energy value to plot spectra
;		spectra_x_max				:	maximum x-ray energy value to plot spectra
;		spectra_y_min				:	mimimum intensity value to plot spectra
;		spectra_y_max				:	maximum intensity value to plot spectra
;		x_autoscale				:	autoscale x-ray energy scale: 0: NO, 1: YES
;		y_autoscale				:	autoscale spectra intensity scale: 0: NO, 1: YES
;	zstack_color_common
;		bottom_color_index			:	index of lowermost color of gradient colorscale
;		top_color_index				:	index of uppermost color of gradient colorscale
;		black_color_index			:	index of black color
;		white_color_index			:	index of white color
;		plot_bkgd_color_index			:	color index for plot background, either black or white
;		plot_axes_color_index			:	color index for plot axes, either whilte or black
;		image_border_color_index		:	color index for image border in zstack_buildlist and zstack_profile dialog windows
;		dragbox_color_index			:	color index for dragbox used to define subregion for alignment
;		corr_ctr_color_index			:	color index for crosshair showing center of correlation function
;		corr_max_color_index			:	color index for crosshair showing maximum of correlation function
;		x_shift_color_index			:	color index for plotting of x-shift
;		y_shift_color_index			:	color index for plotting of y-shift
;		shift_cursor_color_index		:	color index for cursor in shift plot, indicating file number
;		tune_fiducial_color_index		:	color index for fiducial points in closeup of shifted image in zstack_tune dialog window
;		spectra_color_index			:	color indices (14) for plotting of spectra
;		spectra_cursor_color_index		:	color index for cursor in spectra plot, indicating x-ray energy
;		profile_color_index			:	color index for plotting of intensity profile and cursor in profile image indicating row or column
;		profile_cursor_color_index		:	color index for cursor in profile image, indicating x-ray energy
;		profile_spectrum_color_index	:	color index for plotting of profile spectrum
;		test1_color_index			:	color index #1 for testing
;		test2_color_index			:	color index #2 for testing
;		test3_color_index			:	color index #3 for testing
; SIDE EFFECTS:
;
; RESTRICTIONS:
;	Used as ZSTACK suite of routines
; PROCEDURE:
;	Called by ZSTACK_ANALYZE.PRO
; EXAMPLE:
;
; MODIFICATION HISTORY:
; Modified 25-mar-1998 to deal with 24 bit graphics, CJJ
; Modified July 11 and 13, 1998 to deal with changes to align.pro, CJJ
; Modified 28-aug-1998 to work with corrected 24 bit graphics. CJJ
; Modified 31-Aug-1998 to add x_shift, y_shift to argument list, and
;   remove shift_filename!, CJJ
;
; Modified 20feb99, CGZ
; Extensively modified and rewritten STACK_ALIGN.PRO to form ZSTACK_ALIGN.PRO
; Changes and additions are numerous:
;
; All procedures and common variables starting with 'stack' were changed to 'zstack'
; so that the existing routine, STACK_ALIGN.PRO, can be run in parallel
;
; Added the following procedures:
;	zstack_align_prep		:	sets common variables, color table, and color indices
;	zstack_align_imgdisp		:	displays images and shift plot
;	zstack_align_save_shift	:	saves alignment shift into MAPPER file, *.aln
;	zstack_align_read_shift	:	reads alignment shifts from MAPPER file, *.aln
;
; Rewrote stack_align_sensitive to be two separate procedures with better control
;	zstack_align_sensitive	:	activate features on Stack Align dialog window
;	zstack_align_desensitive	:	deactivate features on Stack Align dialog window
;
; Pre-existing procedures
;	zstack_align_doalign		:	controls alignment of image stack with active display
;	zstack_align_event		:	event routine for zstack_align
;	zstack_align			:	main procedure for alignment of STXM images
;
; Modified user interface window to include
;	display and movie of image, correlation function, shifted image
;		dragbox is plotted on both image and shifted image
;		center of correlation function displayed as crosshair overlay (same as CJJ)
;		maximum of correlation function displayed as 1-pixel box overlay (same as CJJ)
;	modified plot of alignment shifts
;		- use actual file numbers instead of file sequence number (relative number)
; ***** APH (23-may-04) - undo this change ! ************************
;		- added plot_x_min and plot_x_max
;		? is it useful to plot vs x-ray energy instead - would require considerable work
;			might be able to plot both using upper and lower x-axes
;	movie can be played before and after alignment to inspect position of dragbox
;		and quality of alignment
;	cursor bar added to plot of alignment shifts highlighting shift and file
;		during movie or static display
;	displayed file can be selected either using file list or alignment plot
;		clicking on alignment plot, prints file info and alignment shift in Output Log
;	text fields added to display image and shift information during movie or static display
;	added "Load New Color Table" to change color table of image
;	saving and retrieving of file of alignment shifts
;	added ability to redo alignment
;		- can now do multiple alignments using different conditions, saving each
;
; Changed zstack_align_par.dragbox_label routine in zstack_align_event
;	Replaced getbox routine with box_cursor routine, more robust on multiple platforms, CGZ
;
; Adapted display routines to use zstack_align_imgdisp
;	One display algorithm which can be easily modified
;	Only exception is real-time plotting of alignment shift in zstack_align_doalign
;
; Changed the way the color table is specified: zstack_align_prep
;	- much simpler now, only executed once, allows multiple colors easily
;
; New variables:
;	corr_stack			:	stack of correlation functions
;	shift_image_stack	:	stack of shifted images
;	corr_dim_stack		:	array of dimensions specifying center and maxima of
;							correlation function
;							used for displaying correlation function
;	edgefill			:	type of filling to occur at edges of shifted images
;							(edges can contain no data due to shifting)
;							set within zstack_align_doalign
;		meanfill 		:	replace with mean of image
;		medianfill 	:	replace with median of image
;		maxfill 		:	replace with maximum of image
;		minfill 		:	replace with minimum of image
;		zero			:	replace with zero (default)
; 	doalign_complete	:	specifies state of alignment
;							(modified from use in stack_align.pro)
;		-1			:	alignment in progress
;		 0			:	alignment not started
;		 1			:	alignment finished
;		 2			:	using alignment from stored file
;
;		-2			:	manual alignment in progress
;		-1			:	auto-alignment in progress
;		 0			:	alignment not started
;		 1			:	auto-alignment finished
;		 2			:	manual alignment finished
;		 3			:	using alignment from stored file
;
; Restored shift_filename to argument list
;
; Changed dragbox conditional from
;	IF ((dragbox(0) NE 0) AND (dragbox(1) NE 0) AND $
;		(dragbox(2) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
;	to IF ((dragbox(2) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
;	to accomodate dragbox = [0,0,*,*], i.e., lower left corner
;
; Save alignment / Do not save alignment choice wasn't working in CJJ version - fixed
;
; Stack_align would give non-zero shift for first image
;	This is fixed with modification of call to zstack_align_images (updated version of align.pro)
;
; Added dragbox coordinates to header of MAPPER file of alignment shifts
;
; Added zstack_align_tune to interactively adjust alignment shifts
;	essentially superceding stack_manalign.pro.
;	This can be improved upon to incorporate features of stack_manalign.pro
;
; Moved nearly all widget_control,var,sensitive = 0/1 statements to
;	zstack_align_sensitive and zstack_align_desensitive for more reliable operation
;	and better organization of code (instead of being widely dispersed)
;	zstack_align_sensitive has situation-dependent conditionals to control appearance of window
;
; Need to restore virtual memory allocation when working with large data arrays
; 	so corr_stack, shift_image_stack, and corr_dim_stack) set to zero at end
;
; Added alignment to following image - useful if image quality is better at high energy
;	This is in addition to existing alignment to preceding image and to a constant image
;	Eliminated variable, zstack_align_par.constant_match
;	Added variable, image_match with valid values:
;		-1			:	alignment using preceding image
;		 0			:	alignment using constant image
;		 1			:	alignment using following image
;
; Added low_mem keyword to STACK_ANALYZE.PRO and STACK_ALIGN.PRO
;	If set, then shifted_image_stack is not formed with STACK_ALIGN.PRO
;	This reduces memory use by 1/3 and is useful when large arrays are being processed.
;		This comes at some reduction in speed for displaying new images,
;		most noticeable during playing of image movies
;	If set, display of shifted images within STACK_ALIGN.PRO is done by calculating
;		shifted image from x_shift, y_shift, and image_stack
;		every time an image is displayed.
;	With low_mem set, IDL partition should be approx. >9 times n_elements(image_stack)
;	With low_mem not set, IDL partition should be approx. >13 times n_elements(image_stack)
;		(based on tests on a Macintosh)
;
; Modified COMMON block structure so that common variables are shared with all zstack routines
;	i.e., zstack_common contains variables used by
;		ZSTACK_ANALYZE.PRO, ZSTACK_READLIST.PRO, ZSTACK_BUILDLIST.PRO, and ZSTACK_ALIGN.PRO
; Common variables are now defined only once in each file, not repetitively as before.
; Common variables for data are now determined within ZSTACK_BUILDLIST.PRO or ZSTACK_READLIST.PRO:
;	image_stack, filename_list, ev_list, msec_list, filename_display_list
;	This requires that files be read only once, eliminated time-intensive duplicate calls of
;		STXM_READ.PRO or SXM_READ.PRO
;
; Modified zstack_align_par, zstack_align_tune_par
;	so that they only contain only variables associated with dialog window.
;	All other variables have been moved to zstack_align_common
;
; Added n_files, list_filename, and shift_filename variables to zstack_common variable
;
; Divided align and tune functions into two separate procedures: ZSTACK_ALIGN.PRO and ZSTACK_TUNE.PRO
; ZSTACK_TUNE.PRO could be used as a replacement for ZSTACK_MANALIGN.PRO
;
; Modified so that zoom can be changed after alignment is complete
;	added /new_zoom option to ZSTACK_ALIGN.PRO and slightly altered button naming routine
;
; End of Modifications 20feb99, CGZ
;
; Fixed display of alignment shifts for alignment using following image.  CGZ 12aug99
;
; Added EXIT button to exit ZSTACK package directly from zstack_align dialog, CGZ 12aug99
; Removed CGZ, 12aug99
;
; Changed default value of image_match to -1, i.e., will use preceding image for aligment
;	CGZ, 09sep99
;
; Added optional sections to plot maximum of correlation function and
;	points used to determine center of mass,  commented out for routine use
;	Useful in troubleshooting
;	CGZ, 28sep99
;
; Changed header of file of alignment shifts (*.aln) to include alignment conditions
;	CGZ, 28sep99
;
; Modified to optimize use of memory
;	Each correlation function, corr_stack(*,*,i), is now only as large as region
;	defined by dragbox.  Formerly, each correlation function had the same dimensions
;	as the image.  So if a 50x50 pixel dragbox is used with 200x200 pixel images,
;	this uses only 7% of the memory used if the entire image is used for the alignment.
;
; (06oct00 cgz) Moved dragbox from zstack_align_common to zstack_common
;	so that it can be used in zstack_save to select subregion of interest
;
; (13oct00 cgz) Altered definition of dragbox so that it is now [xleft,xright,ybot,ytop]
;		This makes it consistent with definition of other cursor boxes
;		and eliminates need for min and max testing
;		Changed logic statement from:	IF ((dragbox(2) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
;							to:	IF ((dragbox(1) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
;
; (29oct00 cgz) Modified !version.os routines to use !version.os_family variable
; (31oct00 cgz)
;		Modified zstack_buildlist_savelist to include dialog_pickfile so directory can be selected
;		Replaced platform-dependent code with call to zstack_analyze_extract_filename
; (10nov00 cgz)
;		Fixed hourglass cursor problem with time-intensive alignments
; (28nov00 cgz) migrated zstack_profile_colorbar routine to zstack_analyze.pro
; (26-mar-01 aph) change BOX_CURSOR to BX_CURSOR
; (13-apr-01 aph) tried Zimba suggested fix
; (23-may-04 aph) get plot of alignment shifts to work
; (03-Mar-08 MJ)  Keyword /SCROLL in widget_base() needs X_SCROLL_SIZE.
;                 Took out initial size and placement of base widget.
;                 Put back in temporary filenumber array to get plot of shifts.
; (13-apr-08 aph) turn on pre-set window size (X_Scroll_size, Y_Scroll_size) only for non-Windows OS
; (07-mar-09 aph) added binary_filenmane to zstack_common
;                set default align filename to stack name (.aln) NB was done before ! (shift_filename)
; (27-Jul-09 aph) external common
; (02-Aug-15 aph) when exit this program, pass back the folder of the stack (previously only the filename)
; (02-aug-15 aph) ensure DefPath is defined correctly as exit Zstack_spectra; added @axis_com to all routines
; (03-Aug-15 aph) changed label to zlabel since label is an array in axis_com
;-
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRO zstack_align_prep

; This routine sets up COMMON variables, color maps, and graphics parameters
;print,'zstack_align_prep'

@axis_com
@bsif_common
@zstack_common
@zstack_analyze_common
@zstack_build_list_common
@zstack_align_common
@zstack_tune_common
@zstack_spectra_common
@zstack_profile_common
@zstack_save_common
@zstack_display_common
@zstack_color_common

zstack_color

return
END

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRO zstack_align_desensitive

;print,'zstack_align_desensitive'

@axis_com
@bsif_common
@zstack_common
@zstack_analyze_common
@zstack_build_list_common
@zstack_align_common
@zstack_tune_common
@zstack_spectra_common
@zstack_profile_common
@zstack_save_common
@zstack_display_common
@zstack_color_common

widget_control, zstack_align_par.align_raw_label, sensitive = 0
widget_control, zstack_align_par.align_displayed_label, sensitive = 0
widget_control, zstack_align_par.precede_match_label, sensitive = 0
widget_control, zstack_align_par.follow_match_label, sensitive = 0
widget_control, zstack_align_par.constant_match_label, sensitive = 0
widget_control, zstack_align_par.constant_filename_display_list_label, sensitive = 0
widget_control, zstack_align_par.sobel_edge_label, sensitive = 0
widget_control, zstack_align_par.roberts_edge_label, sensitive = 0
widget_control, zstack_align_par.no_edge_label, sensitive = 0
widget_control, zstack_align_par.xcor_peak_label, sensitive = 0
widget_control, zstack_align_par.xcor_cm_label, sensitive = 0
widget_control, zstack_align_par.xcor_maxshift_label, sensitive = 0
widget_control, zstack_align_par.xcor_shift_threshold_label, sensitive = 0
widget_control, zstack_align_par.xcor_edgegauss_label, sensitive = 0
widget_control, zstack_align_par.dragbox_label, sensitive = 0
widget_control, zstack_align_par.reset_dragbox_label, sensitive = 0
widget_control, zstack_align_par.doit_label, sensitive = 0
widget_control, zstack_align_par.skipit_label, sensitive = 0
widget_control, zstack_align_par.redoit1_label, sensitive = 0
widget_control, zstack_align_par.redoit2_label, sensitive = 0
widget_control, zstack_align_par.tune_align_label, sensitive = 0
;widget_control, zstack_align_par.refine_label, sensitive = 0
widget_control, zstack_align_par.filename_display_list_label, sensitive = 1
widget_control, zstack_align_par.prev_image_label, sensitive = 0
widget_control, zstack_align_par.next_image_label, sensitive = 0
widget_control, zstack_align_par.play_movie_label, sensitive = 0
widget_control, zstack_align_par.display_parameters_label, sensitive = 0
widget_control, zstack_align_par.plot_parameters_label, sensitive = 0
widget_control, zstack_align_par.shift_filename_label, sensitive = 0
widget_control, zstack_align_par.save_shift_doit_label, sensitive = 0
widget_control, zstack_align_par.read_shift_doit_label, sensitive = 0
widget_control, zstack_align_par.browse_shift_label, sensitive = 0
widget_control, zstack_align_par.shift_plot_label, sensitive = 0

return
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRO zstack_align_sensitive

;print,'zstack_align_sensitive'

@axis_com
@bsif_common
@zstack_common
@zstack_analyze_common
@zstack_build_list_common
@zstack_align_common
@zstack_tune_common
@zstack_spectra_common
@zstack_profile_common
@zstack_save_common
@zstack_display_common
@zstack_color_common

IF (doalign_complete GT 0) THEN BEGIN
	widget_control, zstack_align_par.align_raw_label, sensitive = 0
	widget_control, zstack_align_par.align_displayed_label, sensitive = 0
	widget_control, zstack_align_par.precede_match_label, sensitive = 0
	widget_control, zstack_align_par.follow_match_label, sensitive = 0
	widget_control, zstack_align_par.constant_match_label, sensitive = 0
	widget_control, zstack_align_par.constant_filename_display_list_label, sensitive = 0
	widget_control, zstack_align_par.sobel_edge_label, sensitive = 0
	widget_control, zstack_align_par.roberts_edge_label, sensitive = 0
	widget_control, zstack_align_par.no_edge_label, sensitive = 0
	widget_control, zstack_align_par.xcor_peak_label, sensitive = 0
	widget_control, zstack_align_par.xcor_cm_label, sensitive = 0
	widget_control, zstack_align_par.xcor_maxshift_label, sensitive = 0
	widget_control, zstack_align_par.xcor_shift_threshold_label, sensitive = 0
	widget_control, zstack_align_par.xcor_edgegauss_label, sensitive = 0
	widget_control, zstack_align_par.dragbox_label, sensitive = 0
	widget_control, zstack_align_par.reset_dragbox_label, sensitive = 0
	widget_control, zstack_align_par.doit_label, sensitive = 1
	widget_control, zstack_align_par.skipit_label, sensitive = 1
	widget_control, zstack_align_par.redoit1_label, sensitive = 1
	IF ((dragbox(1) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
		widget_control, zstack_align_par.redoit2_label, sensitive = 1
	ENDIF
	widget_control, zstack_align_par.tune_align_label, sensitive = 1
;	widget_control, zstack_align_par.refine_label, sensitive = 1
	widget_control, zstack_align_par.filename_display_list_label, sensitive = 1
	widget_control, zstack_align_par.prev_image_label, sensitive = 1
	widget_control, zstack_align_par.next_image_label, sensitive = 1
	widget_control, zstack_align_par.play_movie_label, sensitive = 1
	widget_control, zstack_align_par.display_parameters_label, sensitive = 1
	IF (doalign_complete GT 0) THEN BEGIN
		widget_control, zstack_align_par.plot_parameters_label, sensitive = 1
	ENDIF ELSE BEGIN
		widget_control, zstack_align_par.plot_parameters_label, sensitive = 0
	ENDELSE
	widget_control, zstack_align_par.shift_filename_label, sensitive = 1
	IF (strlen(strtrim(shift_filename,2)) NE 0) THEN BEGIN
		widget_control, zstack_align_par.save_shift_doit_label, sensitive = 1
		widget_control, zstack_align_par.read_shift_doit_label, sensitive = 1
	ENDIF ELSE BEGIN
		widget_control, zstack_align_par.save_shift_doit_label, sensitive = 0
		widget_control, zstack_align_par.read_shift_doit_label, sensitive = 0
	ENDELSE
	widget_control, zstack_align_par.browse_shift_label, sensitive = 1
	widget_control, zstack_align_par.shift_plot_label, sensitive = 1
ENDIF ELSE BEGIN
	widget_control, zstack_align_par.align_raw_label, sensitive = 0 	; disabled
	widget_control, zstack_align_par.align_displayed_label, sensitive = 0 	; disabled
	widget_control, zstack_align_par.precede_match_label, sensitive = 1
	widget_control, zstack_align_par.follow_match_label, sensitive = 1
	widget_control, zstack_align_par.constant_match_label, sensitive = 1
	IF (image_match EQ 0) THEN BEGIN
		widget_control, zstack_align_par.constant_filename_display_list_label, sensitive = 1
	ENDIF ELSE BEGIN
		widget_control, zstack_align_par.constant_filename_display_list_label, sensitive = 0
	ENDELSE
	widget_control, zstack_align_par.sobel_edge_label, sensitive = 1
	widget_control, zstack_align_par.roberts_edge_label, sensitive = 1
	widget_control, zstack_align_par.no_edge_label, sensitive = 1
	widget_control, zstack_align_par.xcor_peak_label, sensitive = 1
	widget_control, zstack_align_par.xcor_cm_label, sensitive = 1
	widget_control, zstack_align_par.xcor_maxshift_label, sensitive = 1
	widget_control, zstack_align_par.xcor_shift_threshold_label, sensitive = 1
	widget_control, zstack_align_par.xcor_edgegauss_label, sensitive = 1
	widget_control, zstack_align_par.dragbox_label, sensitive = 1
	IF ((dragbox(1) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
		widget_control, zstack_align_par.reset_dragbox_label, sensitive = 1
	ENDIF ELSE BEGIN
		widget_control, zstack_align_par.reset_dragbox_label, sensitive = 0
	ENDELSE
	IF ((image_match EQ 0) AND (constant_file_index EQ -1)) THEN BEGIN
		widget_control, zstack_align_par.doit_label, sensitive = 0
	ENDIF ELSE BEGIN
		widget_control, zstack_align_par.doit_label, sensitive = 1
	ENDELSE
	widget_control, zstack_align_par.skipit_label, sensitive = 1
	widget_control, zstack_align_par.redoit1_label, sensitive = 0
	widget_control, zstack_align_par.redoit2_label, sensitive = 0
	widget_control, zstack_align_par.tune_align_label, sensitive = 1
;	widget_control, zstack_align_par.refine_label, sensitive = 0
	widget_control, zstack_align_par.filename_display_list_label, sensitive = 1
	widget_control, zstack_align_par.prev_image_label, sensitive = 1
	widget_control, zstack_align_par.next_image_label, sensitive = 1
	widget_control, zstack_align_par.play_movie_label, sensitive = 1
	widget_control, zstack_align_par.display_parameters_label, sensitive = 1
	IF (doalign_complete GT 0) THEN BEGIN
		widget_control, zstack_align_par.plot_parameters_label, sensitive = 1
	ENDIF ELSE BEGIN
		widget_control, zstack_align_par.plot_parameters_label, sensitive = 0
	ENDELSE
	widget_control, zstack_align_par.shift_filename_label, sensitive = 1
	widget_control, zstack_align_par.save_shift_doit_label, sensitive = 0
	IF (strlen(strtrim(shift_filename,2)) NE 0) THEN BEGIN
		widget_control, zstack_align_par.read_shift_doit_label, sensitive = 1
	ENDIF ELSE BEGIN
		widget_control, zstack_align_par.read_shift_doit_label, sensitive = 0
	ENDELSE
	widget_control, zstack_align_par.browse_shift_label, sensitive = 1
;	IF (doalign_complete GT 0) THEN BEGIN
;		widget_control, zstack_align_par.shift_plot_label, sensitive = 1
;	ENDIF ELSE BEGIN
		widget_control, zstack_align_par.shift_plot_label, sensitive = 0
;	ENDELSE
ENDELSE

; set values for alignment buttons
IF (doalign_complete EQ 0) THEN BEGIN
	widget_control, zstack_align_par.doit_label, set_value = 'Start auto-alignment'
	widget_control, zstack_align_par.skipit_label, set_value = 'Skip alignment'
	widget_control, zstack_align_par.tune_align_label, set_value='Align images manually'
ENDIF ELSE BEGIN
	widget_control, zstack_align_par.doit_label, $
			set_value = 'Keep alignment -- Go to Stack Spectra'
	widget_control, zstack_align_par.skipit_label, $
			set_value = 'Discard alignment -- Go to Stack Spectra'
	IF ((dragbox(1) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
		widget_control, zstack_align_par.redoit1_label, $
				set_value='Redo alignment -- Reset subregion'
		widget_control, zstack_align_par.redoit2_label, $
				set_value='Redo alignment -- Keep subregion'
	ENDIF ELSE BEGIN
		widget_control, zstack_align_par.redoit1_label, $
				set_value='Redo alignment'
	ENDELSE
	widget_control, zstack_align_par.tune_align_label, $
			set_value='Interactively adjust alignment shifts'
;	widget_control, zstack_align_par.refine_label, set_value='Realign using shifted images'
ENDELSE

return
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRO zstack_align_imgdisp,i_file

;print,'zstack_align_imgdisp'

@axis_com
@bsif_common
@zstack_common
@zstack_analyze_common
@zstack_build_list_common
@zstack_align_common
@zstack_tune_common
@zstack_spectra_common
@zstack_profile_common
@zstack_save_common
@zstack_display_common
@zstack_color_common

; create image ready for display including regions of interest
zstack_analyze_imgprep,i_file,image
zstack_analyze_bytescale, image, byte_image

; Display image, applying zoom factor
wset,zstack_align_par.image_win
IF (image_zoom GE 1.0) THEN BEGIN
	IF ((image_zoom) EQ fix(image_zoom)) THEN BEGIN
		tv,rebin(byte_image,n_cols*image_zoom,n_rows*image_zoom,/sample),0,0
	ENDIF ELSE BEGIN
		tv,congrid(byte_image,n_cols*image_zoom,n_rows*image_zoom),0,0
	ENDELSE
ENDIF ELSE BEGIN
	IF ( ((1./image_zoom) EQ fix(1./image_zoom)) AND $
			((image_zoom*n_cols) EQ fix(image_zoom*n_cols)) AND $
			((image_zoom*n_rows) EQ fix(image_zoom*n_rows)) ) THEN BEGIN
		tv,rebin(byte_image,n_cols*image_zoom,n_rows*image_zoom,/sample),0,0
	ENDIF ELSE BEGIN
		tv,congrid(byte_image,n_cols*image_zoom,n_rows*image_zoom),0,0
	ENDELSE
ENDELSE

;  Plot dragbox (if it exists) over raw image
IF ((dragbox(2) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
    ; Determine dimensions of dragbox
;    xleft = min([dragbox(0),dragbox(2)],max=xright)
;    ybot = min([dragbox(1),dragbox(3)],max=ytop)
    xleft = dragbox(0)>0
    xright = dragbox(1)<n_cols
    ybot = dragbox(2)>0
    ytop = dragbox(3)<n_rows
ENDIF ELSE BEGIN  ; set dimensions of dragbox to entire image
    xleft = 0
    xright = n_cols
    ybot = 0
    ytop = n_rows
ENDELSE

;  Plot dragbox over raw image
IF ((dragbox(1) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
	px = image_zoom*[xleft, xright, xright, xleft, xleft] ;X points
	py = image_zoom*[ybot, ybot, ytop, ytop, ybot] ;Y values
	plots,px,py,/device,color=dragbox_color_index
ENDIF

; Display shift images if alignment is complete
IF (doalign_complete NE 0) THEN BEGIN
	; Display shifted image with dragbox
	IF (low_memory EQ 1) THEN BEGIN
		; Shift image here to form shifted image for display
		; Conserves memory since shifted_image_stack is not formed and used
		IF ((abs(x_shift(i_file)) GT shift_threshold) OR (abs(y_shift(i_file)) GT shift_threshold)) THEN BEGIN
			; Shift the image to form this_image
			zstack_shift,image,x_shift(i_file),y_shift(i_file),shifted_image,edgefill=edgefill
		ENDIF ELSE BEGIN
			; Shift smaller than threshold
			; leave byte_image alone
			shifted_image = image
		ENDELSE
	ENDIF ELSE BEGIN
		; Get shifted image from stored array
		shifted_image = shifted_image_stack(*,*,i_file)
	ENDELSE

	zstack_analyze_bytescale, shifted_image, byte_image

	; Display shifted image, applying zoom factor
	wset,zstack_align_par.shifted_image_win
	IF (image_zoom GE 1.0) THEN BEGIN
		IF ((image_zoom) EQ fix(image_zoom)) THEN BEGIN
			tv,rebin(byte_image,n_cols*image_zoom,n_rows*image_zoom,/sample),0,0
		ENDIF ELSE BEGIN
			tv,congrid(byte_image,n_cols*image_zoom,n_rows*image_zoom),0,0
		ENDELSE
	ENDIF ELSE BEGIN
		IF ( ((1./image_zoom) EQ fix(1./image_zoom)) AND $
				((image_zoom*n_cols) EQ fix(image_zoom*n_cols)) AND $
				((image_zoom*n_rows) EQ fix(image_zoom*n_rows)) ) THEN BEGIN
			tv,rebin(byte_image,n_cols*image_zoom,n_rows*image_zoom,/sample),0,0
		ENDIF ELSE BEGIN
			tv,congrid(byte_image,n_cols*image_zoom,n_rows*image_zoom),0,0
		ENDELSE
	ENDELSE

	;  Plot dragbox (if it exists) over shifted image
	IF ((dragbox(1) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
		px = image_zoom*[xleft-x_shift(i_file), xright-x_shift(i_file), $
					xright-x_shift(i_file), xleft-x_shift(i_file), $
					xleft-x_shift(i_file)] ;X points
		py = image_zoom*[ybot-y_shift(i_file), ybot-y_shift(i_file), $
					ytop-y_shift(i_file), ytop-y_shift(i_file), $
					ybot-y_shift(i_file)] ;Y values
		plots,px,py,/device,color=dragbox_color_index
	ENDIF
ENDIF ;	IF (doalign_complete NE 0) THEN BEGIN

 ; Display image description info
widget_control, zstack_align_par.filename_display_list_label, set_droplist_select = i_file

return
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRO zstack_align_corrdisp,i_file

;print,'zstack_align_corrdisp'

@axis_com
@bsif_common
@zstack_common
@zstack_analyze_common
@zstack_build_list_common
@zstack_align_common
@zstack_tune_common
@zstack_spectra_common
@zstack_profile_common
@zstack_save_common
@zstack_display_common
@zstack_color_common

 ;IF (doalign_complete NE 0) THEN BEGIN
; Display correlation function if available
;IF (abs(doalign_complete) EQ 1) THEN BEGIN		; don't deal with correlation image if using stored shift file


;  Plot dragbox (if it exists) over raw image
IF ((dragbox(2) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
    ; Determine dimensions of dragbox
    xleft = dragbox(0)>0
    xright = dragbox(1)<n_cols
    ybot = dragbox(2)>0
    ytop = dragbox(3)<n_rows
ENDIF ELSE BEGIN  ; set dimensions of dragbox to entire image
    xleft = 0
    xright = n_cols
    ybot = 0
    ytop = n_rows
ENDELSE

; why recalculate the correlation function maximum ?  can this be editted later ?
;	it was already done in zstack_align_images
xcenter = corr_dim_stack(0,i_file)
ycenter = corr_dim_stack(1,i_file)
;print,'Center :',xcenter,ycenter

; determine maximum of correlation function
cleft  = (n_cols/2. - maxshift)>0
cright = (n_cols/2. + maxshift)<(n_cols-1)
cbot   = (n_rows/2. - maxshift)>0
ctop   = (n_rows/2. + maxshift)<(n_rows-1)
;	cm_image = corr_stack(*,*,i_file)
;	cm_image(*,*) = 0
;	cm_image(cleft:cright,cbot:ctop) = corr_stack(cleft:cright,cbot:ctop,i_file)
;	cm_image = fltarr(n_cols,n_rows)
cm_image = corr_stack(*,*,i_file)
max_corr = max(cm_image,max_corr_pixel,min=min_corr)
x_corr = max_corr_pixel mod n_cols
y_corr = max_corr_pixel / n_rows
;print,'1 max_corr_pixel,x_corr,y_corr : ',max_corr_pixel,x_corr,y_corr

; determine points used for finding center of mass
IF (corr_max EQ 1) THEN BEGIN	; align using center of mass of correlation function
	cm_threshold = min_corr + (0.5*(max_corr - min_corr))	; mean intensity of correlation function
	cm_image = corr_stack(*,*,i_file)
	cm_indices=where((corr_stack(*,*,i_file) GE cm_threshold),n_cm)

	; the following works well but probably cuts off some pixels within the correlation peak
	cm_image(*,*) = 0
	cleft  = (x_corr - maxshift)>0
	cright = (x_corr + maxshift)<(n_cols-1)
	cbot   = (y_corr - maxshift)>0
	ctop   = (y_corr + maxshift)<(n_rows-1)
	cm_image(cleft:cright,cbot:ctop) = corr_stack(cleft:cright,cbot:ctop,i_file)
	cm_indices = where((cm_image GE cm_threshold),n_cm)
	x_corr_pts = cm_indices mod n_cols
	y_corr_pts = cm_indices / n_rows
ENDIF ELSE BEGIN
	x_corr_pts = x_corr
	y_corr_pts = y_corr
ENDELSE

; determine maximum of correlation function
max_corr = max(corr_stack(*,*,i_file),max_corr_pixel,min=min_corr)
x_corr = max_corr_pixel mod n_cols
y_corr = max_corr_pixel / n_rows
;print,'2 max_corr_pixel,x_corr,y_corr : ',max_corr_pixel,x_corr,y_corr

; Scale correlation function to fill gray scale range
IF ((dragbox(1) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
	this_image = fltarr(n_cols,n_rows)
	;print,'size(corr_stack) : ',size(corr_stack(*,*,i_file))
	;print,'size(this_image) : ',size(this_image(xleft:xright,ybot:ytop))
	this_image(xleft:xright,ybot:ytop) = corr_stack(*,*,i_file) - min(corr_stack(*,*,i_file))
ENDIF ELSE BEGIN
	this_image = corr_stack(*,*,i_file) - min(corr_stack(*,*,i_file))
ENDELSE
percent_image = 100. * this_image / max(this_image)
display_image = (( ((percent_image - disp_min) $
			/ ((disp_max - disp_min)^disp_gamma)) >0.)<1.)
byte_image = byte( float(bottom_color_index) + $
			float(top_color_index - bottom_color_index) * display_image)

; Display correlation function, applying zoom factor
wset,zstack_align_par.corr_image_win
IF (image_zoom GE 1.0) THEN BEGIN
	IF ((image_zoom) EQ fix(image_zoom)) THEN BEGIN
		tv,rebin(byte_image,n_cols*image_zoom,n_rows*image_zoom,/sample),0,0
	ENDIF ELSE BEGIN
		tv,congrid(byte_image,n_cols*image_zoom,n_rows*image_zoom),0,0
	ENDELSE
ENDIF ELSE BEGIN
	IF ( ((1./image_zoom) EQ fix(1./image_zoom)) AND $
			((image_zoom*n_cols) EQ fix(image_zoom*n_cols)) AND $
			((image_zoom*n_rows) EQ fix(image_zoom*n_rows)) ) THEN BEGIN
		tv,rebin(byte_image,n_cols*image_zoom,n_rows*image_zoom,/sample),0,0
	ENDIF ELSE BEGIN
		tv,congrid(byte_image,n_cols*image_zoom,n_rows*image_zoom),0,0
	ENDELSE
ENDELSE

; Draw cross hair to note center of correlation function
corr_zoom = image_zoom>1
IF ((dragbox(1) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
	; define center of correlation function
	cxcenter = xleft+((xright-xleft)/2.)
	cycenter = ybot+((ytop-ybot)/2.)
	; draw cross hair to note center of correlation function
	plots,cxcenter*image_zoom+[-10*corr_zoom,-5*corr_zoom],$
		cycenter*image_zoom+[0,0],$
		/device,color=corr_ctr_color_index
	plots,cxcenter*image_zoom+[5*corr_zoom,10*corr_zoom],$
		cycenter*image_zoom+[0,0],$
		/device,color=corr_ctr_color_index
	plots,cxcenter*image_zoom+[0,0],$
		cycenter*image_zoom+[-10*corr_zoom,-5*corr_zoom],$
		/device,color=corr_ctr_color_index
	plots,cxcenter*image_zoom+[0,0],$
		cycenter*image_zoom+[5*corr_zoom,10*corr_zoom],$
		/device,color=corr_ctr_color_index
;			; draw diamond for pixel of maximum correlation intensity (shifts with alignment)
;			plots,[fix(0.5+x_corr*image_zoom)],$
;				[fix(0.5+y_corr*image_zoom)],/device,$
;				color=test1_color_index,psym=4
;			; draw points for pixels used for center of mass determination
;			plots,[fix(0.5+x_corr_pts*image_zoom)],$
;				[fix(0.5+y_corr_pts*image_zoom)],/device,$
;				color=test2_color_index,psym=3
			; draw box for pixel of correlation maximum from zstack_align_images (shifts with alignment)
;			plots,[fix(0.5+xcenter*image_zoom)],$
;				[fix(0.5+ycenter*image_zoom)],/device,$
;				color=corr_max_color_index,psym=6
;			plots,[0.5+xcenter*image_zoom],$
;				[0.5+ycenter*image_zoom],/device,$
;				color=corr_max_color_index,psym=6

;			plots,xcenter*image_zoom+[-5*corr_zoom,5*corr_zoom],ycenter*image_zoom, $
;				/device,color=corr_max_color_index
;			plots,xcenter*image_zoom,ycenter*image_zoom+[-5*corr_zoom,5*corr_zoom], $
;				/device,color=corr_max_color_index
	plots,(xleft+xcenter)*image_zoom+[-5*corr_zoom,5*corr_zoom],(ybot+ycenter)*image_zoom, $
		/device,color=corr_max_color_index
	plots,(xleft+xcenter)*image_zoom,(ybot+ycenter)*image_zoom+[-5*corr_zoom,5*corr_zoom], $
		/device,color=corr_max_color_index
	; Plot dragbox over shifted image
	px = image_zoom*[xleft, xright, xright, xleft, xleft] ;X points
	py = image_zoom*[ybot, ybot, ytop, ytop, ybot] ;Y values
	plots,px,py,/device,color=dragbox_color_index
ENDIF ELSE BEGIN
	; draw cross hair to note center of correlation function
	plots,(n_cols/2.)*image_zoom+[-10*corr_zoom,-5*corr_zoom],$
		(n_rows/2.)*image_zoom+[0,0],$
		/device,color=corr_ctr_color_index
	plots,(n_cols/2.)*image_zoom+[5*corr_zoom,10*corr_zoom],$
		(n_rows/2.)*image_zoom+[0,0],$
		/device,color=corr_ctr_color_index
	plots,(n_cols/2.)*image_zoom+[0,0],$
		(n_rows/2.)*image_zoom+[-10*corr_zoom,-5*corr_zoom],$
		/device,color=corr_ctr_color_index
	plots,(n_cols/2.)*image_zoom+[0,0],$
		(n_rows/2.)*image_zoom+[5*corr_zoom,10*corr_zoom],$
		/device,color=corr_ctr_color_index
;			; draw diamond for pixel of maximum correlation intensity (shifts with alignment)
;			plots,[fix(0.5+x_corr*image_zoom)],$
;				[fix(0.5+y_corr*image_zoom)],/device,$
;				color=test1_color_index,psym=4
;			; draw points for pixels used for center of mass determination
;			plots,[fix(0.5+x_corr_pts*image_zoom)],$
;				[fix(0.5+y_corr_pts*image_zoom)],/device,$
;				color=test2_color_index,psym=3
			; draw box for pixel of correlation maximum from zstack_align_images (shifts with alignment)
;			plots,[fix(0.5+xcenter*image_zoom)],$
;				[fix(0.5+ycenter*image_zoom)],/device,$
;				color=corr_max_color_index,psym=6
;			plots,[0.5+xcenter*image_zoom],$
;				[0.5+ycenter*image_zoom],/device,$
;				color=corr_max_color_index,psym=6
	plots,xcenter*image_zoom+[-5*corr_zoom,5*corr_zoom],ycenter*image_zoom, $
		/device,color=corr_max_color_index
	plots,xcenter*image_zoom,ycenter*image_zoom+[-5*corr_zoom,5*corr_zoom], $
		/device,color=corr_max_color_index
ENDELSE

return
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRO zstack_align_plotshifts,i_file

;print,'zstack_align_plotshifts'

@axis_com
@bsif_common
@zstack_common
@zstack_analyze_common
@zstack_build_list_common
@zstack_align_common
@zstack_tune_common
@zstack_spectra_common
@zstack_profile_common
@zstack_save_common
@zstack_display_common
@zstack_color_common

; Plot alignment shifts with cursor bar
;	Should only be called if align is complete since
;	display of shifts during alignment is done within zstack_align_doalign

; Plot alignment shift vs file #
wset,zstack_align_par.shift_plot_win

; Determine range of x-values in plot
IF (x_autoscale EQ 1)	 THEN BEGIN	; autoscale x-axis
	!x.range = [min(file_num),max(file_num)]
;!x.range = [0, n_elements(filename_list)]			; APH 23-may-04
ENDIF ELSE BEGIN
	!x.range = [plot_x_min, plot_x_max]
ENDELSE
;dummy = where(file_num GE !x.range[0] AND file_num LE !x.range[1], count)

; Determine range of y-values in plot
IF (y_autoscale EQ 1) THEN BEGIN	; autoscale y-axis
	!y.range = [min([min(x_shift),min(y_shift)]),max([max(x_shift),max(y_shift)])]
;	!y.range = [min([min(x_shift[dummy]),min(y_shift[dummy])]), $
;			max([max(x_shift[dummy]),max(y_shift[dummy])])]
	!y.range[0] = (1.05 * !y.range[0]) < (0.95 * !y.range[0])
	!y.range[1] = (1.05 * !y.range[1]) > (0.95 * !y.range[1])

	; if all shifts are zero, artificially set the range
	IF (!y.range[0] EQ 0) THEN BEGIN
		!y.range[0] = -0.1
	ENDIF
	IF (!y.range[1] EQ 0) THEN BEGIN
		!y.range[1] = 0.1
	ENDIF
ENDIF ELSE BEGIN
	!y.range = [plot_y_min, plot_y_max]
ENDELSE

; Plot alignment shift vs file #
;tmp_file_num = file_num
file_num = indgen(n_elements(filename_list))		; APH 23-may-04, put back in MJ 03-Mar-08

plot,file_num,x_shift,/nodata, $
		xtitle='File #', ytitle='Shift (pixels)',$
		color=plot_axes_color_index, background=plot_bkgd_color_index
oplot,file_num,x_shift,color=x_shift_color_index
oplot,file_num,y_shift,color=y_shift_color_index

; Plot X and Y labels on alignment shift plot
xyouts,3+!x.range[0],(!y.range[0]+0.8*(!y.range[1] - !y.range[0])),/data, $
		color=x_shift_color_index,charthick=2,'X'
xyouts,3+!x.range[0],(!y.range[0]+0.2*(!y.range[1] - !y.range[0])),/data, $
		color=y_shift_color_index,charthick=2,'Y'

; Plot a indicator bar marking shift for displayed image
oplot,file_num(i_file)+[0.,0.],!y.crange,color=shift_cursor_color_index
; End of plot of alignment shift vs file number

;file_num = tmp_file_num

; KEEP THIS - DO NOT DELETE - OPTIONAL PORTION OF CODE
; Plot alignment shift vs x-ray energy (just like spectra)
;	plot,ev_list,x_shift,/nodata, $
;		xtitle='X-ray Energy (eV)', ytitle='Shift (pixels)',$
;		color=plot_axes_color_index, background=plot_bkgd_color_index
;	oplot,ev_list,x_shift,color=x_shift_color_index
;	oplot,ev_list,y_shift,color=y_shift_color_index
;	xyouts,3+!x.range[0],(!y.range[0]+0.8*(!y.range[1] - !y.range[0])),/data, $
;		color=x_shift_color_index,charthick=2,'X'
;	xyouts,3+!x.range[0],(!y.range[0]+0.2*(!y.range[1] - !y.range[0])),/data, $
;		color=y_shift_color_index,charthick=2,'Y'
;	oplot,ev_list(i_file)+[0.,0.],!y.crange,color=shift_cursor_color_index

return
END

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRO zstack_align_trial_shift,trial_shift,trial_dragbox

;print,'zstack_align_doalign'

@axis_com
@bsif_common
@zstack_common
@zstack_analyze_common
@zstack_build_list_common
@zstack_align_common
@zstack_tune_common
@zstack_spectra_common
@zstack_profile_common
@zstack_save_common
@zstack_display_common
@zstack_color_common

; Deliberately use only one image with a shift for testing purposes
IF ((trial_shift[0] NE 0) OR (trial_shift[0] NE 0)) THEN BEGIN
	print,'data shifted for testing'
	FOR i_file = 0,(n_files-1) DO BEGIN
		ref_fft = shift(image_stack(*,*,0),i_file*trial_shift[0],i_file*trial_shift[1])
		image_stack(*,*,i_file) = ref_fft
	ENDFOR
ENDIF

IF (n_elements(trial_dragbox) EQ 4) THEN BEGIN
	dragbox = trial_dragbox
	print,'dragbox for testing =',dragbox
ENDIF

return
END

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRO zstack_align_doalign

;print,'zstack_align_doalign'

@axis_com
@bsif_common
@zstack_common
@zstack_analyze_common
@zstack_build_list_common
@zstack_align_common
@zstack_tune_common
@zstack_spectra_common
@zstack_profile_common
@zstack_save_common
@zstack_display_common
@zstack_color_common

; Set sobel and roberts variables for subsequent use in zstack_align_images
sobel = 0
roberts = 0
IF (edge_enhance EQ 1) THEN sobel = 1
IF (edge_enhance EQ 2) THEN roberts = 1

; Initialize plot of alignment shifts
;	so that alignment shifts can be plotted as alignment is being done
wset,zstack_align_par.shift_plot_win
!x.range = [min(file_num),max(file_num)]
;!x.range = [0, n_elements(filename_list)]		; (23-may-04 APH)
!y.range = [-maxshift,maxshift]

;tmp_file_num = file_num	; STORE in case used elsewhere as the actual number of file acquired
;file_num = indgen(n_elements(filename_list))		; APH 23-may-04

plot,file_num,x_shift,/nodata, $
	xtitle='File #', ytitle='Shift (pixels)',$
	color=plot_axes_color_index, background=plot_bkgd_color_index
xyouts,3+!x.range[0],0.6*maxshift,/data, $
		color=x_shift_color_index,charthick=2,'X'
xyouts,3+!x.range[0],-0.6*maxshift,/data, $
		color=y_shift_color_index,charthick=2,'Y'

widget_control,hourglass=1

; To test alignment algorithm with a single preshifted image
;zstack_align_trial_shift,[1,0],[5,25,70,55]
;zstack_align_trial_shift,[0,0],[28,74,24,68]
;zstack_align_trial_shift,[0,0],[8,49,7,52]

start_time = systime(1.)

CASE image_match OF
	-1 : ref_fft = image_stack(*,*,0)	; align to preceding image
	 0 : ref_fft = image_stack(*,*,constant_file_index)	; align to constant image
	 1 : ref_fft = image_stack(*,*,n_files-1)	; align to following image
ENDCASE

IF ((dragbox(1) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
	; prepare dimensions of dragbox: xleft,xright,ytop,ybot
;	xleft = min([dragbox(0),dragbox(2)],max=xright)
;	ybot = min([dragbox(1),dragbox(3)],max=ytop)
	xleft = dragbox(0)>0
	xright = dragbox(1)<(n_cols-1)
	ybot = dragbox(2)>0
	ytop = dragbox(3)<(n_rows-1)
	n_corr_cols = 1 + xright - xleft	; number of columns in dragbox
	n_corr_rows = 1 + ytop - ybot	; number of rows in dragbox
	; reduce size of image to the dragbox area,  CGZ
	dragbox_image = ref_fft(xleft:xright,ybot:ytop)
	ref_fft = dragbox_image
	CASE image_match OF
		-1 : ref_fft = image_stack(xleft:xright,ybot:ytop,0)	; align to preceding image
		 0 : ref_fft = image_stack(xleft:xright,ybot:ytop,constant_file_index)	; align to constant image
		 1 : ref_fft = image_stack(xleft:xright,ybot:ytop,n_files-1)	; align to following image
	ENDCASE
ENDIF ELSE BEGIN  ; set dimensions of dragbox to entire image
	xleft = 0
	xright = n_cols-1
	ybot = 0
	ytop = n_rows-1
	n_corr_cols = n_cols
	n_corr_rows = n_rows
	CASE image_match OF
		-1 : ref_fft = image_stack(*,*,0)	; align to preceding image
		 0 : ref_fft = image_stack(*,*,constant_file_index)	; align to constant image
		 1 : ref_fft = image_stack(*,*,n_files-1)	; align to following image
	ENDCASE
ENDELSE

corr_stack = fltarr(n_corr_cols,n_corr_rows,n_files)

;; What we're doing here is to prepare the reference
;; image in a way that is made to be indentical to
;; how the sequence of images will be prepared.  We
;; don't care about the fact that "align" will assume
;; that its first argument is an image which has already
;; been Fourier transformed.
this_image = ref_fft

zstack_align_images,this_image,ref_fft,this_x_shift,this_y_shift, $
	edgegauss=edgegauss_pixels,sobel=sobel, roberts=roberts, $
	cm=corr_max,maxshift=5	;,dragbox=dragbox
	; added cm=corr_max to fix non-zero shift on initial file
	; when doing center of mass alignment
; Object of this first stack_align_images is to get the FFT of reference image
;	(with the appropriate edge enhancement and edgegauss smoothing)
;	It is important that the reference image get the same treatment as subsequent ones.

print,'prealignment done'

doalign_complete = -1		; alignment in progress

; Set up limits of FOR-DO loop
CASE image_match OF
	-1 : BEGIN	; align to preceding image
		for_initial = 0
		for_last = n_files-1
		for_increment = 1
	END
	 0 : BEGIN	; align to constant image
		for_initial = 0
		for_last = n_files-1
		for_increment = 1
	END
	 1 : BEGIN	; align to following image
		for_initial = n_files-1
		for_last = 0
		for_increment = -1
	END
ENDCASE

FOR i_file = for_initial,for_last,for_increment DO BEGIN
	widget_control,hourglass=1		; added to keep hourglass cursor on during alignment

	;  Reduce size of this_image to dragbox area, CGZ
	IF ((dragbox(1) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
		this_image = image_stack(xleft:xright,ybot:ytop,i_file)
	ENDIF ELSE BEGIN
		this_image = image_stack(*,*,i_file)
	ENDELSE

	; Align current image (this_image) and reference image (ref_fft)
	;	By saying /fftpass we assume that the first image has
	;	already been Fourier transformed, and also we get
	;	"this_image" back Fourier transformed.

	zstack_align_images,ref_fft,this_image, $
		this_x_shift,this_y_shift,corr_image,corr_dims, $
		/fftpass, sobel = sobel, roberts=roberts, edgegauss=edgegauss_pixels,  $
		cm=corr_max, maxshift=maxshift	;, dragbox=dragbox

	IF (image_match NE 0) THEN BEGIN
        ref_fft=this_image
	ENDIF

	; Create image stack of correlation functions and maxima and center of correlation function
	corr_dim_stack(*,i_file) = corr_dims
	corr_stack(*,*,i_file) = temporary(corr_image)

	; create x_shift and y_shift files
	CASE image_match OF
		-1 : BEGIN	; align to preceding image
			IF (i_file GT 0) THEN BEGIN
				this_x_shift = this_x_shift + x_shift(i_file-1)
				this_y_shift = this_y_shift + y_shift(i_file-1)
			ENDIF
		END
		 0 : BEGIN	; align to constant image
		END
		 1 : BEGIN	; align to following image
			IF (i_file LT (n_files-1)) THEN BEGIN
				this_x_shift = this_x_shift + x_shift(i_file+1)
				this_y_shift = this_y_shift + y_shift(i_file+1)
			ENDIF
		END
	ENDCASE

	; save individual x and y alignment shifts into two separate arrays
	x_shift(i_file) = this_x_shift
	y_shift(i_file) = this_y_shift

	IF (low_memory EQ 0) THEN BEGIN
		; Shift the image
		IF ((abs(this_x_shift) GT shift_threshold) OR (abs(this_y_shift) GT shift_threshold)) THEN BEGIN
			zstack_shift,image_stack(*,*,i_file),this_x_shift,this_y_shift,shifted_image,edgefill=edgefill
		ENDIF ELSE BEGIN
			shifted_image = image_stack(*,*,i_file)
		ENDELSE
		; Create shifted_image_stack to temporarily save shifted image files
		shifted_image_stack(*,*,i_file) = shifted_image
	ENDIF

	; Update display of image, correlation funtion, and shifted image
	;	won't plot alignment shifts since alignment is incomplete
	zstack_align_imgdisp,i_file
	; Display correlation function
;	IF (abs(doalign_complete) EQ 1) THEN BEGIN		; will only display if noy using stored shift file
		zstack_align_corrdisp,i_file
;		print,'doalign_complete I : ',doalign_complete
;	ENDIF

	; plot alignment shifts in progress
	wset,zstack_align_par.shift_plot_win
	CASE image_match OF
		-1 : BEGIN	; align to preceding image
			IF (i_file GT 0) THEN BEGIN
				plots,[file_num(i_file-1),file_num(i_file)],x_shift(i_file-1:i_file),/data,$
					color=x_shift_color_index
				plots,[file_num(i_file-1),file_num(i_file)],y_shift(i_file-1:i_file),/data,$
					color=y_shift_color_index
			ENDIF
		END
		 0 : BEGIN	; align to constant image
			IF (i_file GT 0) THEN BEGIN
				plots,[file_num(i_file-1),file_num(i_file)],x_shift(i_file-1:i_file),/data,$
					color=x_shift_color_index
				plots,[file_num(i_file-1),file_num(i_file)],y_shift(i_file-1:i_file),/data,$
					color=y_shift_color_index
			ENDIF
		END
		 1 : BEGIN	; align to following image
			IF (i_file LT (n_files-1)) THEN BEGIN
				plots,[file_num(i_file),file_num(i_file+1)],x_shift(i_file:i_file+1),/data,$
					color=x_shift_color_index
				plots,[file_num(i_file),file_num(i_file+1)],y_shift(i_file:i_file+1),/data,$
					color=y_shift_color_index
			ENDIF
		END
	ENDCASE

ENDFOR

; file_num = tmp_file_num		; RESTORE in case used elsewhere

widget_control,hourglass=0
doalign_complete = 1		; auto-alignment is complete

end_time = systime(1.)
; print elapsed time for aligment of all images in data stack
total_time = end_time - start_time
minutes = fix(total_time/60)
seconds = total_time-60.*minutes
IF (minutes GT 0) THEN BEGIN
    print,'Elapsed time for stack alignment: '+$
      strtrim(string(minutes),2)+' minutes '+$
      strtrim(string(seconds,format='(f10.1)'),2)+' seconds.
ENDIF ELSE BEGIN
    print,'Elapsed time for stack alignment: '+$
      strtrim(string(seconds,format='(f10.1)'),2)+' seconds.
ENDELSE

return
END

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRO zstack_align_save_shift,stack_align_filename

;print,'zstack_align_save_shift'

@axis_com
@bsif_common
@zstack_common
@zstack_analyze_common
@zstack_build_list_common
@zstack_align_common
@zstack_tune_common
@zstack_spectra_common
@zstack_profile_common
@zstack_save_common
@zstack_display_common
@zstack_color_common
on_ioerror, zstack_align_save_shift_oops

get_lun,lun
openw,lun,stack_align_filename

printf,lun,'! X-Y Pixel shifts after alignment'

; alignment parameters as text on successive lines
IF ((dragbox(1) NE 0) AND (dragbox(3) NE 0)) THEN BEGIN
	printf,lun,'! Dragbox ['+strtrim(string(dragbox[0],format='(i3)'),2) + ',' $
						+ strtrim(string(dragbox[1],format='(i3)'),2) + ',' $
						+ strtrim(string(dragbox[2],format='(i3)'),2) + ',' $
						+ strtrim(string(dragbox[3],format='(i3)'),2)+'] used'
ENDIF ELSE BEGIN
	printf,lun,'! Full images used'
ENDELSE

CASE image_match OF
	-1 : BEGIN	; aligned to preceding image
		printf,lun,'! Aligned to preceding images'
	END
	 0 : BEGIN	; aligned to constant image
		printf,lun,'! Aligned to constant image, '+filename_list(constant_file_index)
	END
	 1 : BEGIN	; aligned to following image
		printf,lun,'! Aligned to following images'
	END
ENDCASE

CASE corr_max OF
	0 : BEGIN	; aligned using peak maximum of correlation function
		printf,lun,'! Correlation maximum determined by 3-pt quadratic fit'
	END
	1 : BEGIN	; aligned using center of mass of correlation function
		printf,lun,'! Correlation maximum determined by center of mass'
	END
ENDCASE

CASE edge_enhance OF
	0 : BEGIN	; aligned to preceding image
		printf,lun,'! No edge enhancement'
	END
	1 : BEGIN	; aligned to constant image
		printf,lun,'! Sobel edge enhancement'
	END
	2 : BEGIN	; aligned to following image
		printf,lun,'! Roberts edge enhancement'
	END
ENDCASE

printf,lun,'! Maximum allowed shift of '+strtrim(string(maxshift),2)+' pixels'
printf,lun,'! Shift threshold of '+strtrim(string(shift_threshold,format='(f10.2)'),2)+' pixels'
printf,lun,'! Edgegauss smoothing of '+strtrim(string(edgegauss_pixels),2)+' pixels'

; *.sl file of alignment shifts
IF (list_filename NE '') THEN BEGIN
	printf,lun,'! List of image files : '+list_filename
ENDIF

; alignment parameters as a numerical array
printf,lun,'ALIGN('	+ strtrim(string(image_match),2) + ',' $
				+ strtrim(string(constant_file_index),2) + ',' $
				+ strtrim(string(corr_max),2) + ',' $
				+ strtrim(string(edge_enhance),2) + ',' $
				+ strtrim(string(maxshift),2) + ',' $
				+ strtrim(string(shift_threshold,format='(f10.2)'),2) + ',' $
				+ strtrim(string(edgegauss_pixels),2) + ',' $
				+ strtrim(string(dragbox[0],format='(i3)'),2) + ',' $
				+ strtrim(string(dragbox[1],format='(i3)'),2) + ',' $
				+ strtrim(string(dragbox[2],format='(i3)'),2) + ',' $
				+ strtrim(string(dragbox[3],format='(i3)'),2) + ',' $
				+ strtrim(string(image_type,format='(i3)'),2)

; alignment shifts in comma-separated format
svec = size(image_stack)
n_files=svec(3)
printf,lun,'PLOTIT('+strtrim(string(n_files),2)
FOR i=0,(n_files-1) DO BEGIN
    printf,lun,strtrim(string(filename_list(i)),2)+','+$
      strtrim(string(x_shift(i),format='(f10.4)'),2)+','+$
      strtrim(string(y_shift(i),format='(f10.4)'),2)
ENDFOR

print,'Wrote pixel shifts to file "'+data_directory+stack_align_filename+'"'

zstack_align_save_shift_oops :
close,lun
free_lun,lun

;data_directory = temp
;cd,data_directory

return
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRO zstack_align_read_shift,stack_align_filename

;print,'zstack_align_read_shift'

@axis_com
@bsif_common
@zstack_common
@zstack_analyze_common
@zstack_build_list_common
@zstack_align_common
@zstack_tune_common
@zstack_spectra_common
@zstack_profile_common
@zstack_save_common
@zstack_display_common
@zstack_color_common

; Check validity of stack_align_filename
dummy = findfile(stack_align_filename, count=count)
IF (count EQ 0) THEN BEGIN
	print,string(7B),'Shift file, '+stack_align_filename+', not found',string(7B)
	return
ENDIF

; if using a file of shifts from a previous alignment
; What we want to do is to read in the shifts and apply them.

temp_x_shift = x_shift
temp_y_shift = y_shift
zstack_read_mapper,stack_align_filename, indices, shifts, parameters
;	print,'indices : ',indices
;	print,'shifts  : ',shifts
x_shift = shifts(0,*)
y_shift = shifts(1,*)

; Data for alignment parameters,  added CGZ
;	used to display alignment parameters on ZSTACK Align dialog
;	when previously saved alignment shifts are used
; If no parameters are stored with alignment shifts, ELSE condition is followed
IF (size(parameters,/n_dimensions) NE 0) THEN BEGIN
	image_match = byte(parameters[0])
	constant_file_index = fix(parameters[1])
	corr_max = fix(parameters[2])
	edge_enhance = fix(parameters[3])
	maxshift = parameters[4]
	shift_threshold = parameters[5]
	edgegauss_pixels = fix(parameters[6])
	dragbox[0] = fix(parameters[7])
	dragbox[1] = fix(parameters[8])
	dragbox[2] = fix(parameters[9])
	dragbox[3] = fix(parameters[10])
IF (n_elements(parameters) GT 11) THEN BEGIN
	image_type = fix(parameters[11])
ENDIF ELSE BEGIN
	image_type = -1
ENDELSE

	CASE image_type OF
		-1 : BEGIN	; align using original data
			widget_control, zstack_align_par.align_raw_label, set_button = 1
;			widget_control, zstack_align_par.align_displayed_label, set_button = 0
		END
		ELSE : BEGIN	; align using data as displayed
;			widget_control, zstack_align_par.align_raw_label, set_button = 0
			widget_control, zstack_align_par.align_displayed_label, set_button = 1
		END
	ENDCASE

	CASE image_match OF
		-1 :	BEGIN
			widget_control, zstack_align_par.precede_match_label, set_button = 1
			widget_control, zstack_align_par.follow_match_label, set_button = 0
			widget_control, zstack_align_par.constant_match_label, set_button = 0
			widget_control, zstack_align_par.constant_filename_display_list_label,$
					set_droplist_select = 0
			displayed_file_index = 0
		END
		 0 :	BEGIN
			widget_control, zstack_align_par.precede_match_label, set_button = 0
			widget_control, zstack_align_par.follow_match_label, set_button = 0
			widget_control, zstack_align_par.constant_match_label, set_button = 1
			displayed_file_index = constant_file_index
			widget_control, zstack_align_par.constant_filename_display_list_label,$
					set_droplist_select = constant_file_index + 1
		END
		 1 : BEGIN
			widget_control, zstack_align_par.precede_match_label, set_button = 0
			widget_control, zstack_align_par.follow_match_label, set_button = 1
			widget_control, zstack_align_par.constant_match_label, set_button = 0
			widget_control, zstack_align_par.constant_filename_display_list_label,$
					set_droplist_select = 0
			displayed_file_index = n_files - 1
		END
	ENDCASE

	CASE edge_enhance OF
		0:	BEGIN
			widget_control, zstack_align_par.sobel_edge_label, set_button = 0
			widget_control, zstack_align_par.roberts_edge_label, set_button = 0
			widget_control, zstack_align_par.no_edge_label, set_button = 1
		END
		1:	BEGIN
			widget_control, zstack_align_par.no_edge_label, set_button = 0
			widget_control, zstack_align_par.roberts_edge_label, set_button = 0
			widget_control, zstack_align_par.sobel_edge_label, set_button = 1
		END
		2:	BEGIN
			widget_control, zstack_align_par.no_edge_label, set_button = 0
			widget_control, zstack_align_par.sobel_edge_label, set_button = 0
			widget_control, zstack_align_par.roberts_edge_label, set_button = 1
		END
	ENDCASE

	CASE corr_max OF
		0:	BEGIN
			widget_control, zstack_align_par.xcor_cm_label, set_button = 0
			widget_control, zstack_align_par.xcor_peak_label, set_button = 1
		END
		1:	BEGIN
			widget_control, zstack_align_par.xcor_peak_label, set_button = 0
			widget_control, zstack_align_par.xcor_cm_label, set_button = 1
		END
	ENDCASE

	widget_control, zstack_align_par.xcor_maxshift_label, $
			set_value = ' '+strtrim(string(maxshift,format='(i6)'),2)
	widget_control, zstack_align_par.xcor_shift_threshold_label, $
			set_value = ' '+strtrim(string(shift_threshold,format='(f6.2)'),2)
	widget_control, zstack_align_par.xcor_edgegauss_label, $
			set_value = ' '+strtrim(string(edgegauss_pixels,format='(i6)'),2)

ENDIF ELSE BEGIN
	widget_control, zstack_align_par.align_raw_label, set_button = 0
	widget_control, zstack_align_par.align_displayed_label, set_button = 0
	widget_control, zstack_align_par.precede_match_label, set_button = 0
	widget_control, zstack_align_par.follow_match_label, set_button = 0
	widget_control, zstack_align_par.constant_match_label, set_button = 0
	widget_control, zstack_align_par.constant_filename_display_list_label,$
			set_droplist_select = 0
	widget_control, zstack_align_par.sobel_edge_label, set_button = 0
	widget_control, zstack_align_par.roberts_edge_label, set_button = 0
	widget_control, zstack_align_par.no_edge_label, set_button = 0

	widget_control, zstack_align_par.xcor_cm_label, set_button = 0
	widget_control, zstack_align_par.xcor_peak_label, set_button = 0

	widget_control, zstack_align_par.xcor_maxshift_label, set_value = ' '
	widget_control, zstack_align_par.xcor_shift_threshold_label, set_value = ' '
	widget_control, zstack_align_par.xcor_edgegauss_label, set_value = ' '

	displayed_file_index = 0
ENDELSE

IF (low_memory EQ 0) THEN BEGIN
	shifted_image_stack = image_stack
ENDIF

; Apply shifts and update display
svec = size(shifts,/dimensions)
dummy = where([n_elements(svec),svec] EQ [2,2,n_files],count)
IF (count EQ 3) THEN BEGIN
	print,'Shifting images using shift values from '+shift_filename
	file_num = fltarr(n_files)
	FOR i=0,(n_files-1) DO BEGIN
		IF (low_memory EQ 0) THEN BEGIN
			xcenter = x_shift(i)
			ycenter = y_shift(i)
;			IF ((abs(xcenter) GT 0.2) OR (abs(ycenter) GT 0.2)) THEN BEGIN
;			IF ((abs(xcenter) GT 0.02) OR (abs(ycenter) GT 0.02)) THEN BEGIN
			IF ((abs(xcenter) GT shift_threshold) OR (abs(ycenter) GT shift_threshold)) THEN BEGIN
				zstack_shift,image_stack(*,*,i),x_shift(i),y_shift(i), $
					shifted_image,edgefill=edgefill
				shifted_image_stack(*,*,i) = shifted_image
			ENDIF
		ENDIF
		file_num(i) = strmid(strtrim(filename_list(i),2),5,3)
	ENDFOR

	doalign_complete = 3
;	zstack_align_sensitive
ENDIF ELSE BEGIN
	print,string(7B),'File sizes do not match - can not apply shifts',string(7B)
	x_shift = temp_x_shift
	y_shift = temp_y_shift
ENDELSE

return
END

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRO zstack_align_clipbox

;print,'zstack_align_clipbox'

@axis_com
@bsif_common
@zstack_common
@zstack_analyze_common
@zstack_build_list_common
@zstack_align_common
@zstack_tune_common
@zstack_spectra_common
@zstack_profile_common
@zstack_save_common
@zstack_display_common
@zstack_color_common

;; This should be called after alignment is complete and after tune is complete

;dummy = where([x_shift,y_shift] EQ 0,count)	; changed to deal with very small non-zero shifts
dummy = where(abs([x_shift,y_shift]) LT shift_threshold,count)
	; if all shifts are less then shift_threshold, count will be 2*n_files
	; and no shifting of images will occur
IF (count LT 2*n_files) THEN BEGIN
	data_shifted = 1	; data was shifted and should be clipped
	; determine size of clipped image - could substitute with clipbox
	max_x_shift = max(x_shift,min=min_x_shift)
	max_y_shift = max(y_shift,min=min_y_shift)
	; min_xy_shift is either zero or negative, never positive. so use floor(min_xy_shift)
	; max_xy_shift is either zero or positive, never negative. so use ceil(max_xy_shift)
	n_clipped_cols = n_cols + floor(min_x_shift) - ceil(max_x_shift)
	n_clipped_rows = n_rows + floor(min_y_shift) - ceil(max_y_shift)
	; clipbox = [xleft,xright,ybot,ytop], defined in similar manner as dragbox
	clipbox = [-floor(min_x_shift),(n_cols-1) - ceil(max_x_shift), $
			-floor(min_y_shift),(n_rows-1) - ceil(max_y_shift)]
ENDIF ELSE BEGIN
	data_shifted = 0	; data was not shifted and should not be clipped
	n_clipped_cols = n_cols
	n_clipped_rows = n_rows
	; clipbox = [xleft,xright,ybot,ytop], defined in similar manner as dragbox
	clipbox = [0, (n_cols-1), 0, (n_rows-1)]
ENDELSE
;print,'official clipbox : ',clipbox
;; need to shift positions of i_roi and i0_roi for proper display in clipped image
;; implemented as part of zstack_spec_imgdisp.pro and zstack_save_imgdisp.pro

return
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRO zstack_align_event,event

;print,'zstack_align_event'

@axis_com
@bsif_common
@zstack_common
@zstack_analyze_common
@zstack_build_list_common
@zstack_align_common
@zstack_tune_common
@zstack_spectra_common
@zstack_profile_common
@zstack_save_common
@zstack_display_common
@zstack_color_common

CASE event.id OF
    zstack_align_par.align_raw_label : BEGIN
        image_type = -1
        zstack_align_sensitive
    END

    zstack_align_par.align_displayed_label : BEGIN
        image_match = image_ratio
        zstack_align_sensitive
    END

    zstack_align_par.precede_match_label : BEGIN
        image_match = -1
        constant_file_index = -1
        widget_control, zstack_align_par.constant_filename_display_list_label,$
				set_droplist_select=0
        zstack_align_sensitive
    END

    zstack_align_par.follow_match_label : BEGIN
        image_match = 1
        constant_file_index = -1
        widget_control, zstack_align_par.constant_filename_display_list_label,$
				set_droplist_select=0
        zstack_align_sensitive
    END

    zstack_align_par.constant_match_label : BEGIN
        image_match = 0
        widget_control, zstack_align_par.constant_filename_display_list_label, sensitive = 1
		zstack_align_sensitive
    END

	zstack_align_par.constant_filename_display_list_label : BEGIN
		constant_file_index = event.index-1
		IF (constant_file_index GE 0) THEN BEGIN
			zstack_align_desensitive
			displayed_file_index = constant_file_index
			zstack_align_imgdisp,displayed_file_index
			; Display correlation function
			IF (abs(doalign_complete) EQ 1) THEN BEGIN		; will only display if noy using stored shift file
				zstack_align_corrdisp,displayed_file_index
			ENDIF
			; Plot alignment shifts with cursor bar
			IF (doalign_complete GT 0) THEN BEGIN		; will only display if align is complete
				zstack_align_plotshifts,displayed_file_index
			ENDIF
		ENDIF
		zstack_align_sensitive
	END

    zstack_align_par.sobel_edge_label : BEGIN
        edge_enhance = 1
    END

    zstack_align_par.roberts_edge_label : BEGIN
        edge_enhance = 2
    END

    zstack_align_par.no_edge_label : BEGIN
        edge_enhance = 0
    END

    zstack_align_par.xcor_peak_label : BEGIN
        ; 0 for xcor_peak (peak maximum), 1 for xcor_cm (center of mass)
        corr_max = 0
    END

    zstack_align_par.xcor_cm_label : BEGIN
        ; 0 for xcor_peak (peak maximum), 1 for xcor_cm (center of mass)
        corr_max = 1
    END

    zstack_align_par.xcor_maxshift_label : BEGIN
        temp_string = ''
        widget_control, zstack_align_par.xcor_maxshift_label, $
          get_value = temp_string
        on_ioerror, xcor_maxshift_label_oops
        IF (strlen(temp_string(0)) EQ 0) THEN GOTO, xcor_maxshift_label_oops
        reads,temp_string(0),maxshift
        IF (maxshift LT 1) THEN maxshift = 1
        IF (maxshift GT min([n_cols/2,n_rows/2])) THEN $
          maxshift = min([n_cols/2,n_rows/2])
        xcor_maxshift_label_oops :
        widget_control, zstack_align_par.xcor_maxshift_label, $
          set_value = ' '+strtrim(string(maxshift,format='(i6)'),2)
    END

    zstack_align_par.xcor_shift_threshold_label : BEGIN
        temp_string = ''
        widget_control, zstack_align_par.xcor_shift_threshold_label, $
          get_value = temp_string
        on_ioerror, xcor_shift_threshold_label_oops
        IF (strlen(temp_string(0)) EQ 0) THEN GOTO, xcor_shift_threshold_label_oops
        reads,temp_string(0),shift_threshold
        IF (shift_threshold GT 1.00) THEN shift_threshold = 1.00
        IF (shift_threshold LT 0.01) THEN shift_threshold = 0.01
        xcor_shift_threshold_label_oops :
        widget_control, zstack_align_par.xcor_shift_threshold_label, $
          set_value = ' '+strtrim(string(shift_threshold,format='(f6.2)'),2)
    END

    zstack_align_par.xcor_edgegauss_label : BEGIN
        temp_string = ''
        widget_control, zstack_align_par.xcor_edgegauss_label, $
          get_value = temp_string
        on_ioerror, xcor_edgegauss_label_oops
        IF (strlen(temp_string(0)) EQ 0) THEN GOTO, xcor_edgegauss_label_oops
        reads,temp_string(0),edgegauss_pixels
        xcor_edgegauss_label_oops :
        widget_control, zstack_align_par.xcor_edgegauss_label, $
          set_value = ' '+strtrim(string(edgegauss_pixels,format='(i6)'),2)
    END

    zstack_align_par.dragbox_label : BEGIN
	;; Dragbox can be used to define a region of high contrast for alignment

        zstack_align_desensitive
		widget_control, zstack_align_par.image_label, sensitive = 1
        wset,zstack_align_par.image_win
        ;	xv	2 point vector of x-coordinate for opposite box corners
        ;	yv	2 point vector of y-coordinate for opposite box corners
        xv=[0,0]
        yv=[0,0]
;        getbox,xv,yv,/device

;  Replaced getbox routine with box_cursor routine, more robust on multiple platforms, CGZ
;  Box_cursor.pro is shipped with IDL, while getbox is shareware from NASA, modified by CJJ
        ;	x0 and y0 give the initial location of lower left corner of  box
        ;	nx and ny give the initial width and height of box
        x0=0
        y0=0
        nx=0
        ny=0
; output instructions for use of box_cursor to Output Log
	print,string(7B)
	print,'To define Region of Interest box:'
	print,'     Left mouse button   :  Move the box by dragging the mouse'
	print,'     Middle mouse button :  Resize the box by dragging the mouse, moving the nearest corner'
	print,'     Right mouse button  :  Exit and save current box dimensions'
;	osname = strupcase(strmid(!Version.os, 0, 3))
	CASE strupcase(!version.os_family) OF
		'VMS' : BEGIN
			; three button mouse assumed
		END
		'WINDOWS' : BEGIN
			print, "Drag  Left   button near a corner to resize box."
			print, "Drag  Middle button (if exists) to move box."
			print, "click Right button when done."
;			print,'IDL supports the use of mice with up to three buttons.'
;			print,'However, many mice used with Microsoft Windows systems have only two buttons. '
;			print,'Hold down the Control key while pressing the left mouse button to simulate a "middle" mouse button press.'
		END
		'MACOS' : BEGIN
			print,'IDL supports the use of mice with up to three buttons. '
			print,'However, the Macintosh mouse has only one button. '
			print,'When pressed, the Macintosh mouse button is interpreted by IDL as the "left" mouse button. '
			print,'Hold down the Option key while pressing the mouse button to simulate a "middle" mouse button press. '
			print,'Hold down the Command key while pressing the mouse button to simulate a "right" mouse button press.'
		END
		'UNIX' : BEGIN
			; three button mouse assumed
		END
		ELSE : BEGIN
			print,'Unrecognized operating system'
		END
	ENDCASE

;		zstack_drawbox_widget, zstack_align_par.image_win
    IF strupcase(!version.os_family) EQ 'WINDOWS' THEN BEGIN
        bx_cursor,x0,y0,nx,ny 				; aph inserted 26-mar-01
 	ENDIF ELSE box_cursor,x0,y0,nx,ny

 ;  calculate xv and yv to flow back into CJJ code,  CGZ
        xv = [x0,x0+nx]
        yv = [y0,y0+ny]

;        Replaced conditional so that dragbox can extend to lower and left edges
;        if ((xv(0) NE 0) and (xv(1) ne 0) and (yv(0) ne 0) and $
;            (yv(1) ne 1)) then begin
        if ((xv(1) ne 0) and (yv(1) ne 0)) then begin		;zzz change
            dragbox = [xv(0),xv(1),yv(0),yv(1)]/image_zoom
            print,'alignment dragbox =',string(dragbox,format='(i6)')
        endif

        zstack_align_imgdisp,displayed_file_index
		; Display correlation function
		IF (abs(doalign_complete) EQ 1) THEN BEGIN		; will only display if noy using stored shift file
			zstack_align_corrdisp,displayed_file_index
		ENDIF
		; Plot alignment shifts with cursor bar
		IF (doalign_complete GT 0) THEN BEGIN		; will only display if align is complete
			zstack_align_plotshifts,displayed_file_index
		ENDIF
        zstack_align_sensitive

    Print, ' Finished defining subregion'
    END

    zstack_align_par.reset_dragbox_label : BEGIN
		zstack_align_desensitive
        dragbox = [0,0,0,0]
        print,'alignment dragbox =',string(dragbox,format='(i6)')
        zstack_align_imgdisp,displayed_file_index
		; Display correlation function
		IF (abs(doalign_complete) EQ 1) THEN BEGIN		; will only display if noy using stored shift file
			zstack_align_corrdisp,displayed_file_index
		ENDIF
		; Plot alignment shifts with cursor bar
		IF (doalign_complete GT 0) THEN BEGIN		; will only display if align is complete
			zstack_align_plotshifts,displayed_file_index
		ENDIF
		zstack_align_sensitive
    END

    zstack_align_par.doit_label : BEGIN
	  	IF (doalign_complete EQ 0) THEN BEGIN
			zstack_align_desensitive
			zstack_align_doalign
			zstack_align_imgdisp,displayed_file_index
			; Display correlation function
			IF (abs(doalign_complete) EQ 1) THEN BEGIN		; will only display if noy using stored shift file
				zstack_align_corrdisp,displayed_file_index
			ENDIF
			; Plot alignment shifts with cursor bar
			IF (doalign_complete GT 0) THEN BEGIN		; will only display if align is complete
				zstack_align_plotshifts,displayed_file_index
			ENDIF
			zstack_align_sensitive
		ENDIF ELSE BEGIN
			IF (low_memory EQ 1) THEN BEGIN
				FOR i_file=0,(n_files-1) DO BEGIN
;					IF ((abs(x_shift(i_file)) GT 0.02) OR (abs(y_shift(i_file)) GT 0.02)) THEN BEGIN
					IF ((abs(x_shift(i_file)) GT shift_threshold) OR (abs(y_shift(i_file)) GT shift_threshold)) THEN BEGIN
						zstack_shift,image_stack(*,*,i_file),x_shift(i_file),y_shift(i_file), $
							shifted_image,edgefill=edgefill
						image_stack(*,*,i_file) = shifted_image
					ENDIF
				ENDFOR
			ENDIF ELSE BEGIN
				image_stack = shifted_image_stack
			ENDELSE
			zstack_align_clipbox
			; restore virtual memory allocation
			corr_dim_stack = 0
			corr_stack = 0
			shifted_image_stack = 0
			widget_control, zstack_align_par.main_base, /destroy
;        zstack_spectra
			IF (axis_call EQ 1) THEN BEGIN
				zstack_spectra
			ENDIF
		ENDELSE
    END

    zstack_align_par.skipit_label : BEGIN
        x_shift = fltarr(n_files)
        y_shift = fltarr(n_files)
		; restore virtual memory allocation
		corr_dim_stack = 0
		corr_stack = 0
		shifted_image_stack = 0
        widget_control, zstack_align_par.main_base, /destroy
;        zstack_spectra
		IF (axis_call EQ 1) THEN BEGIN
			zstack_spectra
		ENDIF
    END

	;Added to redo alignment, CGZ
    zstack_align_par.redoit1_label : BEGIN	; redo alignment from scratch
        print,'play it again, sam 1'
        doalign_complete = 0	; alignment is not started
        dragbox = [0,0,0,0]
        x_shift = fltarr(n_files)
        y_shift = fltarr(n_files)
        temp_x_shift = fltarr(n_files)
        temp_y_shift = fltarr(n_files)
        ; restore virtual memory allocation
        corr_dim_stack = 0
        corr_stack = 0
        shifted_image_stack = 0
        widget_control, zstack_align_par.main_base, /destroy
        zstack_align,/realign
    END

    zstack_align_par.redoit2_label : BEGIN	; retain dragbox and redo alignment
        print,'play it again, sam 2'
        doalign_complete = 0	; alignment is not started
        x_shift = fltarr(n_files)
        y_shift = fltarr(n_files)
        temp_x_shift = fltarr(n_files)
        temp_y_shift = fltarr(n_files)
        ; restore virtual memory allocation
        corr_dim_stack = 0
        corr_stack = 0
        shifted_image_stack = 0
        widget_control, zstack_align_par.main_base, /destroy
        zstack_align,/realign
    END

    zstack_align_par.tune_align_label : BEGIN
		zstack_align_desensitive
;		wshow,zstack_align_par.main_base_win,0
		init_zoom = image_zoom
		IF (doalign_complete EQ 0) THEN BEGIN
			IF (low_memory EQ 0) THEN BEGIN
				shifted_image_stack = image_stack
			ENDIF
			doalign_complete = -2		; manual alignment in progress
			x_shift = fltarr(n_files)
			y_shift = fltarr(n_files)
		ENDIF
		zstack_tune
		wshow,zstack_align_par.main_base_win,0
    END

    zstack_align_par.filename_display_list_label : BEGIN
		zstack_align_desensitive
        displayed_file_index = event.index
        zstack_align_imgdisp,displayed_file_index
		; Display correlation function
		IF (abs(doalign_complete) EQ 1) THEN BEGIN		; will only display if noy using stored shift file
			zstack_align_corrdisp,displayed_file_index
		ENDIF
		; Plot alignment shifts with cursor bar
		IF (doalign_complete GT 0) THEN BEGIN		; will only display if align is complete
			zstack_align_plotshifts,displayed_file_index
		ENDIF
		zstack_align_sensitive
    END

	zstack_align_par.next_image_label : BEGIN
		zstack_align_desensitive
		IF (displayed_file_index LT (n_files-1)) THEN BEGIN
			displayed_file_index = displayed_file_index+1
		ENDIF ELSE BEGIN
			displayed_file_index = 0
		ENDELSE
		zstack_align_imgdisp,displayed_file_index
		; Display correlation function
		IF (abs(doalign_complete) EQ 1) THEN BEGIN		; will only display if noy using stored shift file
			zstack_align_corrdisp,displayed_file_index
		ENDIF
		; Plot alignment shifts with cursor bar
		IF (doalign_complete GT 0) THEN BEGIN		; will only display if align is complete
			zstack_align_plotshifts,displayed_file_index
		ENDIF
		zstack_align_sensitive
	END

	zstack_align_par.prev_image_label : BEGIN
		zstack_align_desensitive
		IF (displayed_file_index GT 0) THEN BEGIN
			displayed_file_index = displayed_file_index-1
		ENDIF ELSE BEGIN
			displayed_file_index = n_files-1
		ENDELSE
		zstack_align_imgdisp,displayed_file_index
		; Display correlation function
		IF (abs(doalign_complete) EQ 1) THEN BEGIN		; will only display if noy using stored shift file
			zstack_align_corrdisp,displayed_file_index
		ENDIF
		; Plot alignment shifts with cursor bar
		IF (doalign_complete GT 0) THEN BEGIN		; will only display if align is complete
			zstack_align_plotshifts,displayed_file_index
		ENDIF
		zstack_align_sensitive
	END

	zstack_align_par.play_movie_label : BEGIN
		zstack_align_desensitive
		FOR i=0,(n_files-1) DO BEGIN
			IF (displayed_file_index LT (n_files-1)) THEN BEGIN
				displayed_file_index = displayed_file_index+1
			ENDIF ELSE BEGIN
				displayed_file_index = 0
			ENDELSE
			zstack_align_imgdisp, displayed_file_index
			; Display correlation function
			IF (abs(doalign_complete) EQ 1) THEN BEGIN		; will only display if noy using stored shift file
				zstack_align_corrdisp,displayed_file_index
			ENDIF
			; Plot alignment shifts with cursor bar
			IF (doalign_complete GT 0) THEN BEGIN		; will only display if align is complete
				zstack_align_plotshifts,displayed_file_index
			ENDIF
			wait,movie_delay
		ENDFOR
		zstack_align_sensitive
	END

	zstack_align_par.display_parameters_label : BEGIN
		zstack_align_desensitive
		wshow,zstack_align_par.main_base_win,0
		zstack_display,'align'
	END

	zstack_align_par.plot_parameters_label : BEGIN
		zstack_align_desensitive
		wshow,zstack_align_par.main_base_win,0
		zstack_plot,'align'
	END

	; Added to print eV locations of x and y shifts to Output Log, CGZ
	; Also updates display of image, corr_image, shifted_image and related text fields
	zstack_align_par.shift_plot_label : BEGIN
		;; only act if alignment is complete, added, CGZ
		IF (doalign_complete GT 0) THEN BEGIN
			;; only act on a down click of the mouse
			IF (event.type EQ 0) THEN BEGIN
				zstack_align_desensitive
				wset,zstack_align_par.shift_plot_win
				this_file_shift = convert_coord(event.x,event.y,/device,/to_data)
				this_file = this_file_shift(0)
					dummy = min(abs(this_file-file_num),this_i_file)
				print,'You clicked at File # '+$
					strtrim(string(file_num(this_i_file),format='(i3)'),2)+$
					', '+filename_display_list(this_i_file)+$
					', dx = '+strtrim(string(x_shift(this_i_file),format='(f10.2)'),2)+$
					', dy = '+strtrim(string(y_shift(this_i_file),format='(f10.2)'),2)
				displayed_file_index = (this_i_file>0)<(n_files-1)
				widget_control, zstack_align_par.filename_display_list_label,$
					set_list_select=displayed_file_index
				zstack_align_imgdisp, displayed_file_index
				; Display correlation function
				IF (abs(doalign_complete) EQ 1) THEN BEGIN		; will only display if noy using stored shift file
					zstack_align_corrdisp,displayed_file_index
				ENDIF
				; Plot alignment shifts with cursor bar
				IF (doalign_complete GT 0) THEN BEGIN		; will only display if align is complete
					zstack_align_plotshifts,displayed_file_index
				ENDIF
				zstack_align_sensitive
			ENDIF
		ENDIF
	END

	zstack_align_par.shift_filename_label : BEGIN
		temp_string = ''
		widget_control, zstack_align_par.shift_filename_label, get_value = temp_string
		on_ioerror, shift_filename_label_oops
		shift_filename = strtrim(temp_string(0),2)
		IF (strlen(shift_filename) NE 0) THEN BEGIN
			dotpos = strpos(shift_filename,'.')
			IF (dotpos EQ -1) THEN BEGIN
				shift_filename = shift_filename+'.aln'
			ENDIF ELSE BEGIN 	; this forces extension to be '.aln'
				IF (strpos(strlowcase(shift_filename),'.aln') EQ -1) THEN BEGIN
;					shift_filename = shift_filename+'aln'
					shift_filename = str_sep(shift_filename,'.')
					shift_filename = shift_filename(0)+'.aln'
				ENDIF
			ENDELSE
		ENDIF

		shift_filename_label_oops :
		widget_control, zstack_align_par.shift_filename_label, $
				set_value = ' '+shift_filename
		zstack_align_sensitive
	END

	zstack_align_par.save_shift_doit_label : BEGIN
		on_ioerror, save_shift_doit_label_oops
		zstack_align_desensitive

		cd,current=current_directory
		dummy = dialog_pickfile(filter='*.aln', /write, /fix_filter, $
				file=shift_filename, path=data_directory, get_path=data_directory, $
				title='Save alignment file as :')
		IF (dummy EQ '') THEN BEGIN
			data_directory = current_directory
				; sets data_directory to initial directory if CANCEL is chosen during dialog
				; without this, data_directory becomes null string
			GOTO, save_shift_doit_label_oops
				; trap if CANCEL is chosen in dialog
		ENDIF

		zstack_analyze_extract_filename, dummy, stack_align_filename
		widget_control, zstack_align_par.shift_filename_label, $
				set_value = ' '+shift_filename

		zstack_align_save_shift,shift_filename

		save_shift_doit_label_oops :
		zstack_align_sensitive
	END

	zstack_align_par.read_shift_doit_label : BEGIN
		; Check validity of shift_filename
		dummy = findfile(shift_filename, count=count)
		IF (count EQ 0) THEN BEGIN	; if shift_filename is not valid
			print,string(7B),'Shift file, '+shift_filename+', not found',string(7B)
;			shift_filename = ''
		ENDIF ELSE BEGIN	; if shift_filename is valid
			zstack_align_desensitive

			widget_control, hourglass=1
			dragbox = [0,0,0,0]
			; reset correlation function paramaters
			corr_stack = 0
			corr_dim_stack = 0
			svec = size(image_stack)
			corr_dim_stack = fltarr(2,svec(3))
			corr_stack = fltarr(svec(1),svec(2),svec(3))
			wset,zstack_align_par.corr_image_win
			erase
			IF (low_memory EQ 0) THEN BEGIN
				shifted_image_stack = fltarr(svec(1),svec(2),svec(3))
			ENDIF
			zstack_align_read_shift,shift_filename
			widget_control, hourglass=0
			zstack_align_imgdisp,displayed_file_index
			; Display correlation function
			IF (abs(doalign_complete) EQ 1) THEN BEGIN		; will only display if noy using stored shift file
				zstack_align_corrdisp,displayed_file_index
				print,'doalign_complete A : ',doalign_complete
			ENDIF
			; Plot alignment shifts with cursor bar
			IF (doalign_complete GT 0) THEN BEGIN		; will only display if align is complete
				zstack_align_plotshifts,displayed_file_index
			ENDIF
			zstack_align_sensitive
		ENDELSE
	END

	zstack_align_par.browse_shift_label : BEGIN
		on_ioerror, browse_shift_label_oops
		cd,current=current_directory
		dummy = dialog_pickfile(filter='*.aln', /read, /fix_filter, /must_exist, $
				path=data_directory, get_path=data_directory, $
				title='Select alignment shift file :')
		IF (dummy EQ '') THEN BEGIN
			data_directory = current_directory
				; sets data_directory to initial directory if CANCEL is chosen during dialog
				; without this, data_directory becomes null string
			GOTO, browse_shift_label_oops
				; trap if CANCEL is chosen in dialog
		ENDIF

		zstack_align_desensitive
		widget_control, hourglass=1

		zstack_analyze_extract_filename, dummy, shift_filename
		widget_control, zstack_align_par.shift_filename_label, $
				set_value = ' '+shift_filename

		dragbox = [0,0,0,0]
		; reset correlation function paramaters
		corr_stack = 0
		corr_dim_stack = 0
		corr_dim_stack = fltarr(2,n_files)
		svec = size(image_stack)
		corr_stack = fltarr(svec(1),svec(2),svec(3))
		wset,zstack_align_par.corr_image_win
		erase
		IF (low_memory EQ 0) THEN BEGIN
			shifted_image_stack = fltarr(svec(1),svec(2),svec(3))
		ENDIF
		zstack_align_read_shift,shift_filename

		browse_shift_label_oops :
		widget_control, hourglass=0
		zstack_align_imgdisp,displayed_file_index
		; Display correlation function
		IF (abs(doalign_complete) EQ 1) THEN BEGIN		; will only display if noy using stored shift file
			zstack_align_corrdisp,displayed_file_index
			print,'doalign_complete B : ',doalign_complete
		ENDIF
		; Plot alignment shifts with cursor bar
		IF (doalign_complete GT 0) THEN BEGIN		; will only display if align is complete
			zstack_align_plotshifts,displayed_file_index
		ENDIF
		zstack_align_sensitive

	END

ELSE: print, ' Zstack_Align_Event cannot process ', event.ID
ENDCASE

return
END

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRO zstack_align_dialog, Group_Leader=groupLeader

;print,'zstack_align_dialog'

@axis_com
@bsif_common
@zstack_common
@zstack_analyze_common
@zstack_build_list_common
@zstack_align_common
@zstack_tune_common
@zstack_spectra_common
@zstack_profile_common
@zstack_save_common
@zstack_display_common
@zstack_color_common

; Initialize variables if they have no value
;	needed when running zstack_align_dialog as stand-alone prior to running zstack_align
;	i.e., when programming dialog window
IF (n_elements(n_cols) EQ 0) THEN n_cols = 100
IF (n_elements(n_rows) EQ 0) THEN n_rows = 100
IF (n_elements(image_zoom) EQ 0) then image_zoom = 1
IF (n_elements(doalign_complete) EQ 0) then doalign_complete = 0

IF (n_tags(zstack_align_par) EQ 0) THEN BEGIN
    zstack_align_par = $
      {	zstack_align_par					    , $
		main_base							: 0L, $
		align_raw_label						: 0L, $
		align_displayed_label					: 0L, $
		precede_match_label					: 0L, $
		follow_match_label					: 0L, $
		constant_match_label					: 0L, $
		constant_filename_display_list_label		: 0L, $
		sobel_edge_label					: 0L, $
		roberts_edge_label					: 0L, $
		no_edge_label						: 0L, $
		xcor_peak_label						: 0L, $
		xcor_cm_label						: 0L, $
		xcor_maxshift_label					: 0L, $
		xcor_shift_threshold_label				: 0L, $
		xcor_edgegauss_label					: 0L, $
		dragbox_label						: 0L, $
		reset_dragbox_label					: 0L, $
		doit_label							: 0L, $
		skipit_label						: 0L, $
		redoit1_label						: 0L, $
		redoit2_label						: 0L, $
		tune_align_label					: 0L, $
		image_label						: 0L, $
		corr_image_label					: 0L, $
		shifted_image_label					: 0L, $
		colorbar_label						: 0L, $
		filename_display_list_label			: 0L, $
		next_image_label					: 0L, $
		prev_image_label					: 0L, $
		play_movie_label					: 0L, $
		display_parameters_label				: 0L, $
		plot_parameters_label					: 0L, $
		shift_plot_label					: 0L, $
		shift_filename_label					: 0L, $
		save_shift_doit_label					: 0L, $
		read_shift_doit_label					: 0L, $
		browse_shift_label					: 0L, $
		main_base_win						: 0L, $
		image_win							: 0L, $
		corr_image_win						: 0L, $
		shifted_image_win					: 0L, $
		colorbar_win						: 0L, $
		shift_plot_win						: 0L  $
      }
ENDIF

comp_screen_res=GET_SCREEN_SIZE()

; Create the widgets. TLB is MODAL or BLOCKING.
IF N_Elements(groupLeader) EQ 0 THEN BEGIN
	IF !version.os_family EQ 'Windows' then begin
		zstack_align_par.main_base = widget_base(title='ZSTACK Align', /row, /scroll)
	ENDIF else begin
		zstack_align_par.main_base = widget_base(title='ZSTACK Align', /row, /scroll, $
			X_SCROLL_SIZE=comp_screen_res(0)*.90,Y_SCROLL_SIZE=comp_screen_res(1)*.90)
	ENDELSE
ENDIF ELSE BEGIN
	zstack_align_par.main_base = widget_base(title='ZSTACK Align', /row, $
			/Modal, Group_Leader=groupLeader )
ENDELSE

; Start of dialog window for image alignment
;zstack_align_par.main_base = widget_base(title='ZSTACK Align', /row, /scroll )
col1 = widget_base(zstack_align_par.main_base,/column)
col2 = widget_base(zstack_align_par.main_base,/column)

; Left-hand column of dialog window
frame = widget_base(col1,/column,/frame,space=0)
row = widget_base(frame,/row)
zlabel = widget_label(row,value='Align images using : ', /align_left)
base = widget_base(frame,/column,/exclusive)
zstack_align_par.align_raw_label = widget_button( base, value='  Original data');
zstack_align_par.align_displayed_label = widget_button( base, value='  Data as displayed');

frame = widget_base(col1,/column,/frame,space=0)
row = widget_base(frame,/row)
zlabel = widget_label(row,value='Reference image for alignment : ', /align_left)
base = widget_base(frame,/column,/exclusive)
zstack_align_par.precede_match_label = widget_button( base, value='  Each Preceding Image');
zstack_align_par.follow_match_label = widget_button( base, value='  Each Following Image');
zstack_align_par.constant_match_label = widget_button( base, value='  Constant Image'); (select one from below)');
row = widget_base(frame,/row)
zlabel = widget_label(row,value=' ')
zstack_align_par.constant_filename_display_list_label = widget_droplist( row, $
			value = 'Select File', /align_right,/dynamic_resize)
;			value = 'Select File', scr_xsize=240, scr_ysize=20,/align_right,/dynamic_resize)

frame = widget_base(col1,/column,/frame,space=0)
row = widget_base(frame,/row)
zlabel = widget_label(row,value='Edge enhancement before alignment: ', /align_left)
base = widget_base(frame,/row,/exclusive)
zstack_align_par.sobel_edge_label = widget_button( base, value=' Sobel')
zstack_align_par.roberts_edge_label = widget_button( base, value=' Roberts')
zstack_align_par.no_edge_label = widget_button( base, value=' None')

frame = widget_base(col1,/column,/frame,space=0)
row = widget_base(frame,/row)
zlabel = widget_label(row,value='Cross-correlation determination :', /align_left)
base = widget_base(frame,/row,/exclusive)
zstack_align_par.xcor_peak_label = widget_button( base, value=' Correlation maximum') ;
zstack_align_par.xcor_cm_label = widget_button( base, value=' Center of mass') ;
row = widget_base( frame, /row )
zlabel = widget_label( row, value=' Maximum image shift (pixels):',xsize=175,/align_left)
zstack_align_par.xcor_maxshift_label = widget_text( row, xsize=10, /editable, value=' ')

row = widget_base( frame, /row )
zlabel = widget_label( row, value=' Image shift threshold (pixels):',xsize=175,/align_left)
zstack_align_par.xcor_shift_threshold_label = widget_text( row, xsize=10, /editable, value=' ')

row = widget_base( frame, /row )
zlabel = widget_label( row, value=' Edgegauss smoothing (pixels) :',xsize=175,/align_left)
zstack_align_par.xcor_edgegauss_label = widget_text( row, xsize=10, /editable, value=' ')


frame = widget_base(col1,/col,/frame,xsize=270)
zstack_align_par.dragbox_label = $
    widget_button(frame, value='Select a subregion for alignment')
zstack_align_par.reset_dragbox_label = $
    widget_button(frame, value='Reset subregion')

row = widget_base(col1, /row )

zstack_align_par.doit_label = widget_button(col1,value=' ')
zstack_align_par.skipit_label = widget_button(col1,value=' ')
zstack_align_par.redoit1_label = widget_button(col1,value=' ')
zstack_align_par.redoit2_label = widget_button(col1,value=' ')
zstack_align_par.tune_align_label = widget_button(col1,value='  ')

base = widget_base(col2,/row,/frame,/align_center)
col2a = widget_base(base,/column)
zlabel = widget_label(col2a, value='STXM Image',/align_center)
zstack_align_par.image_label = widget_draw(col2a, $
		xsize=n_cols*image_zoom,ysize=n_rows*image_zoom,retain=2,/align_center,/button_events)

IF (doalign_complete LE 1) THEN BEGIN		; don't plot if using manual alignment shifts or stored shift file
	col2b = widget_base(base,/column)
	zlabel = widget_label(col2b, value='Correlation Fn',/align_center)
	zstack_align_par.corr_image_label = widget_draw(col2b, $
			xsize=n_cols*image_zoom,ysize=n_rows*image_zoom,retain=2,/align_center)
ENDIF

col2c = widget_base(base,/column)
zlabel = widget_label(col2c, value='Shifted Image',/align_center)
zstack_align_par.shifted_image_label = widget_draw(col2c, $
		xsize=n_cols*image_zoom,ysize=n_rows*image_zoom, retain=2,/align_center)

col2d = widget_base(base,/column)
zlabel = widget_label(col2d, value='I',/align_center)
zstack_align_par.colorbar_label = widget_draw(col2d, $
		xsize=10*(image_zoom>1), ysize=n_rows*image_zoom, $
		retain=2, sensitive=0, /align_center)

zstack_align_par.filename_display_list_label = widget_droplist( col2, $
		value = 'Select File', /align_center, scr_xsize=250)
zstack_align_par.prev_image_label = widget_button(col2, value='Display Previous Image')
zstack_align_par.next_image_label = widget_button(col2, value='Display Next Image')
zstack_align_par.play_movie_label = widget_button(col2,value='Play movie')
row = widget_base( col2, /row ,/align_center)
zstack_align_par.display_parameters_label = widget_button(row,value='Display Parameters')
zstack_align_par.plot_parameters_label = widget_button(row,value=' Plot  Parameters ')

frame = widget_base(col2,/row,/frame,/align_center)
base = widget_base(frame,/col)
row = widget_base(base,/row)

zstack_align_par.shift_plot_label = $
		widget_draw(row,xsize=((3*n_cols*image_zoom+25)>250)<500, $
					ysize=((n_rows*image_zoom)>150)<250,retain=2,/button_events)
row = widget_base(base,/row,/align_center)
zlabel = widget_label( row, value='Alignment Shift Filename (*.aln) :' )
zstack_align_par.shift_filename_label = widget_text( row, value='', xsize=20, /editable)
row = widget_base(base,/row,/align_center)
zstack_align_par.save_shift_doit_label = widget_button( row, value='Save shifts')
zstack_align_par.read_shift_doit_label = widget_button( row, value='Read shifts')
zstack_align_par.browse_shift_label = widget_button( row, value='Browse *.aln')

;;;;;;;;;;

Device, get_screen_size=screen_size
screen_center = [ screen_size(0) / 2 , screen_size(1) / 2 ]
geom = Widget_Info(zstack_align_par.main_base, /Geometry)
base_size = [geom.scr_xsize,geom.scr_ysize]
x_base_size = (fix(0.90*screen_size[0]) < base_size[0])
y_base_size = (fix(0.95*screen_size[1]) < base_size[1])
halfsize = [ x_base_size / 2 , y_base_size / 2 ]
;; widget_control, zstack_align_par.main_base, $
;; 	XOffset = screen_center[0] - halfsize[0], $
;; 	YOffset = screen_center[1] - halfsize[1], $
;; 	scr_xsize = x_base_size, $
;; 	scr_ysize = y_base_size

widget_control, zstack_align_par.main_base, /realize

zstack_align_par.main_base_win = !d.window
widget_control,zstack_align_par.image_label, get_value = window
zstack_align_par.image_win = window
IF (doalign_complete LE 1) THEN BEGIN		; don't plot if using manual alignment shifts or stored shift file
	widget_control,zstack_align_par.corr_image_label, get_value = window
	zstack_align_par.corr_image_win = window
ENDIF
widget_control,zstack_align_par.shifted_image_label, get_value = window
zstack_align_par.shifted_image_win = window
widget_control,zstack_align_par.colorbar_label, get_value = window
zstack_align_par.colorbar_win = window
widget_control,zstack_align_par.shift_plot_label, get_value = window
zstack_align_par.shift_plot_win = window

; make image and plot widgets inactive
widget_control, zstack_align_par.image_label, sensitive = 0
IF (doalign_complete LE 1) THEN BEGIN		; don't plot if using manual alignment shifts or stored shift file
	widget_control, zstack_align_par.corr_image_label, sensitive = 0
ENDIF
widget_control, zstack_align_par.shifted_image_label, sensitive = 0
widget_control, zstack_align_par.shift_plot_label, sensitive = 0

; set inactive until implemented
widget_control, zstack_align_par.align_displayed_label, sensitive = 0

return
END

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRO zstack_align, filename_shift, $
	realign=realign, low_mem=low_mem, new_zoom=new_zoom, Group_Leader=groupLeader

;print,'zstack_align'

@axis_com
@bsif_common
@zstack_common
@zstack_analyze_common
@zstack_build_list_common
@zstack_align_common
@zstack_tune_common
@zstack_spectra_common
@zstack_profile_common
@zstack_save_common
@zstack_display_common
@zstack_color_common
on_error,2

IF NOT(keyword_set(new_zoom)) THEN BEGIN
	; Check validity of image_stack file
	svec = size(image_stack)
	IF (svec(0) NE 3) THEN BEGIN
		print,'Not a valid stack'
		return
	ENDIF
	IF ((svec(1) NE n_cols) OR (svec(2) NE n_rows)) THEN BEGIN
		print,'Discrepancy between stack dimensions and n_cols, n_rows'
		return
	ENDIF

	IF keyword_set(low_mem) THEN BEGIN
		low_memory = 1
		print,'Using reduced memory allocation'
	ENDIF ELSE BEGIN
		low_memory = 0
	ENDELSE
;print, 'setting memory use'
;		low_memory = 1 	; trial  - why is this here ?????  profile ????

	; Create image stacks of correlation functions and shifted images, CGZ
	;	If returning from ZSTACK_TUNE with different zoom, skip this
	corr_dim_stack = fltarr(2,svec(3))
	corr_stack = fltarr(svec(1),svec(2),svec(3))
	IF (low_memory EQ 0) THEN BEGIN
		shifted_image_stack = fltarr(svec(1),svec(2),svec(3))
	ENDIF

	; Create alignment shift files
	n_files=svec(3)
	x_shift = fltarr(n_files)
	y_shift = fltarr(n_files)
	temp_x_shift = fltarr(n_files)
	temp_y_shift = fltarr(n_files)

	IF (keyword_set(realign)) THEN BEGIN	; if realignment with same dragbox
;        print,'play it again, sam 3'
		doalign_complete = 0		; alignment is not started
		IF (n_elements(dragbox) EQ 0) THEN BEGIN
			; need to set dragbox to zero if using an existing files of shifts,
			; i.e., filename_shift is specified in zstack_analyze
			dragbox = [0,0,0,0]
		ENDIF
	ENDIF ELSE BEGIN	; if the intial alignment OR realignment with new dragbox
;        print,'play it again, sam 4'
		doalign_complete = 0		; alignment is not started
		dragbox=[0,0,0,0]

	image_type = -1						; use original data as default for image alignment
	image_match = -1					; use preceding image as default for image alignment
	edge_enhance = 0					; use no edge enhancement as default for image alignment
	corr_max = 0						; use peak maximum as default for image alignment
	maxshift = min([n_cols/2,n_rows/2,10])	; use 10 pixels as default for image alignment
	shift_threshold = 0.01				; use 0.01 pixels as default for image alignment
	edgegauss_pixels = 3					; use 3 pixels as default for image alignment

	constant_file_index = -1
	movie_active = 0

;  Create file_num to use as x-axis coordinate corresponding to file number, CGZ
; 23-may-04 aph:  modified to work with all common XRM filenaming conventions
	file_num = ax_sort_names(filename_list, /number)

	ENDELSE

; set initial value of shift_filename if list_filename exists and shift_filename is not already defined
;	IF ( (strlen(shift_filename) EQ 0) AND (strlen(list_filename) NE 0) )THEN BEGIN
;		shift_filename = str_sep(list_filename,'.')
;		shift_filename = shift_filename(0)+'.aln'
;	ENDIF

; replace above with forced name
	print, 'stack-name = ', binary_filename
	t  =ax_name(binary_filename)
	shift_filename = t(0)+t(1)+'.aln'

; ---------- save folder & name Zimba is using in the axis_com paramters
	DefPath = data_directory & print, 'DefPath changed to ', DefPath
	t=ax_name(data_Directory)
	lpath = t(0)   & print, 'Last Path (lpath) changed to ', lPath
	lfile = binary_filename & print, 'Last file (lfile) changed to ', lfile
;
ENDIF

IF keyword_set(filename_shift) THEN BEGIN	; if using a stored set of alignment shifts
	doalign_complete = 3
ENDIF

zstack_align_dialog, Group_Leader=groupLeader
widget_control, zstack_align_par.constant_filename_display_list_label, $
		set_value = [['Select file'],filename_display_list]
widget_control, zstack_align_par.filename_display_list_label, $
		set_value = filename_display_list
widget_control, zstack_align_par.xcor_maxshift_label, $
		set_value = ' '+strtrim(string(maxshift,format='(i6)'),2)
widget_control, zstack_align_par.xcor_shift_threshold_label, $
		set_value = ' '+strtrim(string(shift_threshold,format='(f6.2)'),2)
widget_control, zstack_align_par.xcor_edgegauss_label, $
		set_value = ' '+strtrim(string(edgegauss_pixels,format='(i6)'),2)
widget_control, zstack_align_par.shift_filename_label, $
		set_value = ' '+shift_filename

IF (keyword_set(new_zoom) OR keyword_set(realign)) THEN BEGIN	; set existing values of buttons
	CASE image_type OF
		-1 : BEGIN	; align using original data
			widget_control, zstack_align_par.align_raw_label, set_button = 1
;			widget_control, zstack_align_par.align_displayed_label, set_button = 0
		END
		ELSE : BEGIN	; align using data as displayed
;			widget_control, zstack_align_par.align_raw_label, set_button = 0
			widget_control, zstack_align_par.align_displayed_label, set_button = 1
		END
	ENDCASE

	CASE edge_enhance OF
		0 : BEGIN	; no edge enhancement
			widget_control, zstack_align_par.sobel_edge_label, set_button = 0
			widget_control, zstack_align_par.roberts_edge_label, set_button = 0
			widget_control, zstack_align_par.no_edge_label, set_button = 1
		END
		1 : BEGIN	; sobel edge enhancement
			widget_control, zstack_align_par.sobel_edge_label, set_button = 1
			widget_control, zstack_align_par.roberts_edge_label, set_button = 0
			widget_control, zstack_align_par.no_edge_label, set_button = 0
		END
		2 : BEGIN	; roberts edge enhancement
			widget_control, zstack_align_par.sobel_edge_label, set_button = 0
			widget_control, zstack_align_par.roberts_edge_label, set_button = 1
			widget_control, zstack_align_par.no_edge_label, set_button = 0
		END
	ENDCASE
	CASE image_match OF
		-1 :	BEGIN	; align to preceding image
			widget_control, zstack_align_par.precede_match_label, set_button = 1
			widget_control, zstack_align_par.follow_match_label, set_button = 0
			widget_control, zstack_align_par.constant_match_label, set_button = 0
		END
		 0 : BEGIN	; align to constant image
			widget_control, zstack_align_par.precede_match_label, set_button = 0
			widget_control, zstack_align_par.follow_match_label, set_button = 0
			widget_control, zstack_align_par.constant_match_label, set_button = 1
			widget_control, zstack_align_par.constant_filename_display_list_label,$
						set_droplist_select=constant_file_index+1
		END
		 1 : BEGIN	; align to following image
			widget_control, zstack_align_par.precede_match_label, set_button = 0
			widget_control, zstack_align_par.follow_match_label, set_button = 1
			widget_control, zstack_align_par.constant_match_label, set_button = 0
		END
	ENDCASE
	CASE corr_max OF
		0 : BEGIN	; align using peak maximum of correlation function
			widget_control, zstack_align_par.xcor_cm_label, set_button = 0
			widget_control, zstack_align_par.xcor_peak_label, set_button = 1
		END
		1 : BEGIN	; align using center of mass of correlation function
			widget_control, zstack_align_par.xcor_cm_label, set_button = 1
			widget_control, zstack_align_par.xcor_peak_label, set_button = 0
		END
	ENDCASE
ENDIF ELSE BEGIN
	IF (doalign_complete EQ 0) THEN BEGIN		; set initial values of buttons to defaults
		; since image_to_align = 0, i.e., align to original raw data
		widget_control, zstack_align_par.align_raw_label, set_button = 1
;		widget_control, zstack_align_par.align_displayed_label, set_button = 0

		; since edge_enhance = 0, i.e., no edge enhamcement
		widget_control, zstack_align_par.sobel_edge_label, set_button = 0
		widget_control, zstack_align_par.roberts_edge_label, set_button = 0
		widget_control, zstack_align_par.no_edge_label, set_button = 1

		; since image_match = -1, i.e., align to preceding image
		widget_control, zstack_align_par.precede_match_label, set_button = 1
		widget_control, zstack_align_par.follow_match_label, set_button = 0
		widget_control, zstack_align_par.constant_match_label, set_button = 0

		; since corr_max = 0, i.e., align using peak maximum of correlation function
		widget_control, zstack_align_par.xcor_cm_label, set_button = 0
		widget_control, zstack_align_par.xcor_peak_label, set_button = 1
	ENDIF
ENDELSE

; Get alignment shifts from saved file (if valid filename_shift is given)
IF NOT(keyword_set(new_zoom)) THEN BEGIN
	; Check validity of filename_shift
	IF keyword_set(filename_shift) THEN BEGIN
		dummy = findfile(filename_shift, count=count)
		IF (count EQ 0) THEN BEGIN
			print,string(7B),'Shift file, '+filename_shift+', not found',string(7B)
		ENDIF ELSE BEGIN
			print,'Will use existing shift file '+filename_shift
			doalign_complete = 2
			zstack_align_read_shift,filename_shift
		ENDELSE
	ENDIF
ENDIF

zstack_align_sensitive

zstack_align_imgdisp,displayed_file_index
; Display correlation function
IF (abs(doalign_complete) EQ 1) THEN BEGIN		; will only display if noy using stored shift file
	zstack_align_corrdisp,displayed_file_index
	print,'doalign_complete I : ',doalign_complete
ENDIF
; Plot alignment shifts with cursor bar
IF (doalign_complete GT 0) THEN BEGIN		; will only display if align is complete
	zstack_align_plotshifts,displayed_file_index
ENDIF
zstack_analyze_colorbar, zstack_align_par.colorbar_win

xmanager, 'zstack_align', zstack_align_par.main_base, $
  group_leader = zstack_align_par.main_base

return
END
