; Copyright (c) 1998-2009 C. Zimba & A.P. Hitchcock  All rights reserved
;+
; NAME:
;	ZSTACK_ANALYZE.PRO
;
; LAST CHANGED: ------------------  03-Aug-09
;
; AUTHORS:
;	Carl G. Zimba (NIST), Chris Jacobsen (SUNY - Stonybrook), Adam Hitchcock (McMaster)
;
; PURPOSE:
;	Analysis of images and spectra abtained from a series of images from an x-ray microscope.
;
; CATEGORY:
;	Data analysis.
;
; CALLING SEQUENCE:
;	zstack_analyze,saved_list_filename, saved_shift_filename
; INPUTS:
;	saved_list_filename = list of images to be aligned (optional)
;		(developed by zstack_buildlist within zstack_analyze)
;	saved_shift_filename = list of alignment shifts to be used on list_filename (optional)
;		(developed by zstack_align within zstack_analyze)
; KEYWORD PARAMETERS:
;	median = set for median smoothing of image with width = 3
;	despike = set for removing intensity spikes in the images
;	zoom = zoom factor for image display.  Default = 1.  Must be integral or 1/integral.
;	manual_align = set to use manual alignment of images with ZSTACK_MANALIGN.PRO
;	stackdata_filename = name of previously stored file of stackdata
;	stxm = data obtained from STXM of Beamline X1A at NSLS
;	sxm = data obtained from cryo-STXM of Beamline X1A at NSLS
;	sm = data obtained from ???
;	als = data obtained from Beamline 7 at ALS
;	poly = data obtained from Polymer STXM
;	low_mem = set to conserve memory use during alignment
;	help = set to print how-to-use message
; OUTPUTS:
;	NONE
; 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_analyze_common
;		zstack_analyze_par			:	variables controlling ZSTACK Analyze dialog window
;		do_edge_clip				:	Clip edges of null data created by image alignment:	0: NO, 1: YES
;		do_despike					:	Despike data before alignment:	0: NO, 1: YES
;		do_median_filter			:	Median filter data before alignment:	0: NO, 1: YES
;		do_save_memory				:	Conserve memory by not creating duplicate arrays: 0: NO, 1: YES
;	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_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:
;
; PROCEDURE:
;   Complicated.
; EXAMPLE:
;
; MODIFICATION HISTORY:
;   25-Mar-1998 - now works with 24 bit graphics, CJJ
;   24-Jul-1998 - two changes (based on suggestions by Adam
;     Hitchcock, but the implementations here are my own) CJJ :
;     1. allow user to read in i0 files from an ascii file of
;        (line by line) values of ev, khz.  The file is used
;        only if it spans a larger range of eV values than the
;        images in the stack span.
;     2. Click on the spectrum to change the file which is displayed
;   14-Aug-1998 - now if there's an alignment file, read it in and
;     apply it but STILL give the user the chance to align the stack.
;     This allows one to (for example) first align a stack manually,
;     and then do an automatic alignment over a restricted shift
;     range to "refine" the alignment. CJJ
;   28-Aug-1998: with IDL 5.1 the way 24 bit graphics is handled is
;     now different - need to invoke device,decomposed=0, CJJ
;   31-Aug-1998: Allow saving and reading of stack files as XDR data,
;     don't read ROI file by default on startup, use zoom=1 unless
;     explicitly told otherwise, have alignment shifts saved by
;     this program rather than by alignment programs, allow clipping
;     of data to exclude shift boundaries, CJJ
;   27-sep-1998: but tvrd() works differently on different devices
;     so need to write images for GIF files to Z buffer, CJJ
;   13-oct-1998: Save many images at once, start to work on
;     ratio image stuff, CJJ
;
; Modified 20feb99, CGZ
; Extensively modified and rewritten STACK_ANALYZE.PRO to form ZSTACK_ANALYZE.PRO
; Changes and additions are numerous:
;
; All procedures and common variables starting with 'stk' were changed to 'zstack'
; so that the existing routine, STACK_ANALYZE.PRO, can be run in parallel
;
; Reorganized STACK_ANALYZE.PRO so that it is only a short control function
;	spectral analysis is done completely within ZSTACK_SPECTRA.PRO
;		spectra and regions of interest are saved with ZSTACK_SPECTRA.PRO
;	saving of image data is done within ZSTACK_SAVE.PRO
;
; Procedures have been modified, added, eliminated as below:
;	zstack_analyze_prep		:	formerly stk_anl_graphics
;	zstack_analyze			:	formerly stack_analyze
;
; Functions of procedures are now:
;	zstack_analyze_prep		:	sets color table and color indices and defines common variables
;	zstack_analyze			:	main procedure for analysis of STXM images
;
; Changed the way the color table is specified:
;	- calls ZSTACK_COLOR.PRO from within zstack_analyze_prep
;	- much simpler now, only executed once, allows multiple colors easily
;
; Deleted unused variables
;	char_ypix,charsize,textregion_nlines,textregion_ypix,
;	i_images_color_index,i0_images_color_index,i0_images_list,i_images_list
;
; 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.
;	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)
;
; Renamed ev to ev_list, and msec to msec_list
;
; Added option for data from Polymer STXM
;	/poly keyword and stxm1_sxm2_sm3_als4_poly5 variable
;	Made stxm1_sxm2_sm3_als4_poly5 part of zstack_common variable
;
; 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 (in zstack_analyze_prep), 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
;
; Added zstack_analyze_readfile procedure to read in saved image stack (*.stk)
;	Saved image stack has a format slightly different from CJJ code since it includes the filename_list
;		so the file structure of the two different file formats makes them incompatible
;
; (05oct00 cgz)
;	Created zstack_save_common to include variables for saving various image and movie formats
;		Moved zstack_save_par and save_filename_header from zstack_spectra_common
;
; (05nov00 cgz) modified values of image_ratio to reflect new options
; (28nov00 cgz) migrated zstack_analyze_colorbar routine from all other zstack routine except zstack_buildlist.pro
; (07mar09 aph)  added binary_filename to zstack_common
; (27-jul-09 aph) external common
; (03-aug-09 aph) change base-10 log to natural log (as noted byLarry Nittler, Carnegie)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_analyze_prep
;print,'zstack_analyze_prep'

@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
print,'kilroy 1'
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_analyze_extract_directory, input_string, output_string
;print,'zstack_analyze_extract_directory'
; this function extracts the directory from the input_string
; directory text is returned as output_string
; usually used after dialog_pickfile request for directory
last_char = strmid(input_string,strlen(input_string)-1,1)
CASE strupcase(!version.os_family) OF
	'VMS' : BEGIN
		IF (last_char NE ']') THEN BEGIN
			output_string = input_string+']'
		ENDIF
	END
	'WINDOWS' : BEGIN
		IF (last_char NE '\') THEN BEGIN
			output_string = input_string+'\'
		ENDIF
	END
	'MACOS' : BEGIN
		IF (last_char NE ':') THEN BEGIN
			output_string = input_string+':'
		ENDIF
	END
	'UNIX' : BEGIN
		IF (last_char NE '/') THEN BEGIN
			output_string = input_string+'/'
		ENDIF
	END
	ELSE : BEGIN
		print,'Unrecognized operating system'
	END
ENDCASE
IF (firstpos EQ -1) THEN BEGIN
	stripped_filelist(i) = filelist(i)
	IF (i EQ 0) THEN stripped_directory = ''
ENDIF ELSE BEGIN
	stripped_filelist(i) = $
	strmid(filelist(i), firstpos, (strlen(temp_filename)-firstpos))
	IF (i EQ 0) THEN stripped_directory = strmid(temp_filename,0,firstpos)
ENDELSE
IF (strupcase(!version.os_family) EQ 'VMS') THEN BEGIN
	semipos = rstrpos(stripped_filelist(i), ';')
	IF (semipos GT 1) THEN BEGIN
		stripped_filelist(i) = strmid(stripped_filelist(i),0,semipos)
	ENDIF
ENDIF
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_analyze_extract_filename, input_string, output_string
;print,'zstack_analyze_extract_filename'
; this function extracts the directory from the input_string
; directory text is returned as output_string
; usually used after dialog_pickfile request for directory
CASE strupcase(!version.os_family) OF
	'VMS' : BEGIN
		firstpos = strpos(input_string, ']')+1
	END
	'WINDOWS' : BEGIN
		firstpos = rstrpos(input_string, '\')+1
	END
	'MACOS' : BEGIN
		firstpos = rstrpos(input_string, ':')+1
	END
	'UNIX' : BEGIN
		firstpos = rstrpos(input_string, '/')+1
	END
	ELSE : BEGIN
		print,'Unrecognized operating system'
	END
ENDCASE
IF (firstpos EQ -1) THEN BEGIN
	output_string = input_string
ENDIF ELSE BEGIN
	output_string = strmid(input_string, firstpos, (strlen(input_string)-firstpos))
ENDELSE

IF (strupcase(!version.os_family) EQ 'VMS') THEN BEGIN
	semipos = rstrpos(output_string, ';')
	IF (semipos GT 1) THEN BEGIN
		output_string = strmid(output_string,0,semipos)
	ENDIF
ENDIF
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_analyze_imgprep,i,image
;print,'zstack_save_imgdisp'

@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 current image
CASE image_ratio OF
	0 : BEGIN	; if original data is being displayed
		image = image_stack(*,*,i)
	END
	1 : BEGIN	; if (image/current image) is being displayed
		image = image_stack(*,*,i) / image_stack(*,*,ratio_image_index)
	END
	2 : BEGIN	; if -log(image/current image) is being displayed	CHANGE to USE LOG-base 10 (03-Aug-09 aph)
		image = -alog(image_stack(*,*,i) / image_stack(*,*,ratio_image_index))
	END
	3 : BEGIN	; if (image - current image) is being displayed
		image = image_stack(*,*,i) - image_stack(*,*,ratio_image_index)
	END
	4 : BEGIN	; if (image/i0 spectrum) is being displayed
		image = image_stack(*,*,i) / spectrum[0,i]
	END
	5 : BEGIN	; if -log(image/i0 spectrum) is being displayed	CHANGE to USE LOG-base 10 (03-Aug-09 aph
		image = -alog(image_stack(*,*,i) / spectrum[0,i])
	END
	6 : BEGIN	; if (image - i0 spectrum) is being displayed
		image = image_stack(*,*,i) - spectrum[0,i]
	END
	7 : BEGIN	; if (stack - reference stack) is being displayed
		print,'Stack normalization is not currently implemented - will display raw data'
		image = image_stack(*,*,i)
;		image = image_stack(*,*,i) - spectrum[0,i]
	END
	ELSE : BEGIN	; if original data is being displayed
		image = image_stack(*,*,i)
	END
ENDCASE
IF (data_shifted EQ 1) THEN BEGIN
; do we need to be here if image_ratio EQ 0, i.e., image = image_stack(*,*,i)  ?????
;		clipped edges should already be set from zstack_shift during alignment
	;reset clipped edges of image to minimum intensity of image
	;	this only works if clipped edges are set to zero or minimum intensity of image
	;	during alignment using zstack_shift
	;	In the future, edgefill option could be option on display dialog
;print,'image_ratio test edgefill : ',edgefill
	CASE edgefill OF
		'meanfill' : BEGIN
;			print,'imgprep edgefill : meanfill'
			clipped_edge = where(image_stack(*,*,i) EQ mean(image_stack(*,*,i)),count)
			clipped_edge = [clipped_edge,where(image_stack(*,*,ratio_image_index) EQ mean(image_stack(*,*,ratio_image_index)),count)]
			clipped_edge = clipped_edge(uniq(clipped_edge,sort(clipped_edge)))
			image(clipped_edge) = mean(image(clipbox[0]:clipbox[1],clipbox[2]:clipbox[3]))
		END
		'medianfill' : BEGIN
;			print,'imgprep edgefill : medianfill'
			clipped_edge = where(image_stack(*,*,i) EQ median(image_stack(*,*,i)),count)
			clipped_edge = [clipped_edge,where(image_stack(*,*,ratio_image_index) EQ median(image_stack(*,*,ratio_image_index)),count)]
			clipped_edge = clipped_edge(uniq(clipped_edge,sort(clipped_edge)))
			image(clipped_edge) = median(image(clipbox[0]:clipbox[1],clipbox[2]:clipbox[3]))
		END
		'maxfill' : BEGIN
;			print,'imgprep edgefill : maxfill'
			clipped_edge = where(image_stack(*,*,i) EQ max(image_stack(*,*,i)),count)
			clipped_edge = [clipped_edge,where(image_stack(*,*,ratio_image_index) EQ max(image_stack(*,*,ratio_image_index)),count)]
			clipped_edge = clipped_edge(uniq(clipped_edge,sort(clipped_edge)))
			image(clipped_edge) = 1.01*max(image(clipbox[0]:clipbox[1],clipbox[2]:clipbox[3]))
		END
		'minfill' : BEGIN
;			print,'imgprep edgefill : minfill'
			clipped_edge = where(image_stack(*,*,i) EQ min(image_stack(*,*,i)),count)
			clipped_edge = [clipped_edge,where(image_stack(*,*,ratio_image_index) EQ min(image_stack(*,*,ratio_image_index)),count)]
			clipped_edge = clipped_edge(uniq(clipped_edge,sort(clipped_edge)))
			image(clipped_edge) = 0.99*min(image(clipbox[0]:clipbox[1],clipbox[2]:clipbox[3]))
		END
		'zero' : BEGIN
;			print,'imgprep edgefill : zero'
			clipped_edge = where(image_stack(*,*,i) EQ 0,count)
			clipped_edge = [clipped_edge,where(image_stack(*,*,ratio_image_index) EQ 0,count)]
			clipped_edge = clipped_edge(uniq(clipped_edge,sort(clipped_edge)))
			image(clipped_edge) = 0
		END
		'NaN' : BEGIN
;			print,'imgprep edgefill : NaN'
			clipped_edge = where(finite(image_stack(*,*,ratio_image_index),/nan),count)
			IF (clipped_edge[0] NE -1) THEN BEGIN
				clipped_edge = [clipped_edge,where(finite(image_stack(*,*,i),/nan),count)]
				clipped_edge = clipped_edge(uniq(clipped_edge,sort(clipped_edge)))
			ENDIF ELSE BEGIN
				clipped_edge = where(finite(image_stack(*,*,i),/nan),count)
			ENDELSE
			IF (clipped_edge[0] NE -1) THEN image(clipped_edge) = !values.f_nan
		END
		'infinity' : BEGIN
;			print,'imgprep edgefill : Infinity'
			clipped_edge = where(finite(image_stack(*,*,ratio_image_index),/infinity),count)
			IF (clipped_edge[0] NE -1) THEN BEGIN
				clipped_edge = [clipped_edge,where(finite(image_stack(*,*,i),/infinity),count)]
				clipped_edge = clipped_edge(uniq(clipped_edge,sort(clipped_edge)))
			ENDIF ELSE BEGIN
				clipped_edge = where(finite(image_stack(*,*,i),/infinity),count)
			ENDELSE
			IF (clipped_edge[0] NE -1) THEN image(clipped_edge) = !values.f_infinity
		END
		ELSE : BEGIN
;			print,'imgprep edgefill : else'
			clipped_edge = where(image_stack(*,*,i) EQ min(image_stack(*,*,i)),count)
			clipped_edge = [clipped_edge,where(image_stack(*,*,ratio_image_index) EQ min(image_stack(*,*,ratio_image_index)),count)]
			clipped_edge = clipped_edge(uniq(clipped_edge,sort(clipped_edge)))
			image(clipped_edge) = 0.99*min(image(clipbox[0]:clipbox[1],clipbox[2]:clipbox[3]))
		END
	ENDCASE
ENDIF
;zstack_analyze_bytescale, image, byte_image
;image = byte_image
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_analyze_bytescale, image, byte_image, do_byte_roi=do_byte_roi
;print,'zstack_analyze_bytescale'

@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 byte-scaled image
IF (n_elements(do_byte_roi) EQ 0) THEN BEGIN
	do_byte_roi = ''
ENDIF
; Scale image intensity to minimum and maximum values
IF (image_scale EQ 0) THEN BEGIN	; scale image using entire image field including i0 region
	IF (image_range EQ 0) THEN BEGIN
		min_image = min(image(where(finite(image))))
		image = temporary(image) - min_image
		max_image = max(image(where(finite(image))))
	ENDIF ELSE BEGIN
		min_image = min(image_stack(where(finite(image_stack))))
		image = temporary(image) - min_image
		max_image = max(image_stack(where(finite(image_stack))))
	ENDELSE
ENDIF ELSE BEGIN	; scale image exclusive of area corresponding to i0 region (extended to entire hole)
	IF ((image_ratio EQ 1) OR (image_ratio EQ 2)) AND $
					(displayed_file_index EQ ratio_image_index) THEN BEGIN
				; trap in the case when image is ratioed to itself,
				;			i.e., displayed_file_index EQ ratio_image_index
				; so must scale image using entire image field
				; otherwise error occurs since it can't find a hole in the image
		IF (image_range EQ 0) THEN BEGIN
			min_image = min(image(where(finite(image))))
			image = temporary(image) - min_image
			max_image = max(image(where(finite(image))))
		ENDIF ELSE BEGIN
			min_image = min(image_stack(where(finite(image_stack))))
			image = temporary(image) - min_image
			max_image = max(image_stack(where(finite(image_stack))))
		ENDELSE
	ENDIF ELSE BEGIN	; scale image exclusive of area corresponding to i0 hole
		i0_svec = size(i0_roi)
		IF (i0_svec(0) NE 0) THEN BEGIN
			IF (image_range EQ 0) THEN BEGIN
				min_image = min(image(where(finite(image))))
				image = temporary(image) - min_image
				hole_threshold = 0.9 * mean(image(i0_roi))
					; set intensity threshold to slightly less than average intensity of io region
				no_hole = where(image LT hole_threshold,no_hole_count)
					; indices of image pixels having intensity lower than threshold
				hole = where(image GE hole_threshold,hole_count)
					; indices of image pixels having intensity greater than or equal to threshold
;				hole_threshold = 0.5*(mean(image(no_hole)) + mean(image(hole)))
				hole_threshold = mean(image(no_hole)) + 2.0 * stddev(image(no_hole))
					; reset intensity threshold to better-determined value
				no_hole = where(image LT hole_threshold,no_hole_count)
					; indices of image pixels having intensity lower than threshold
				hole = where(image GE hole_threshold,hole_count)
					; indices of image pixels having intensity greater than or equal to threshold
				dummy = image(no_hole)
				max_image = max(dummy(where(finite(dummy))))
			ENDIF ELSE BEGIN
				min_image = min(image_stack(where(finite(image_stack))))
				image = temporary(image) - min_image
				hole_threshold = 0.9 * mean(image(i0_roi))
					; set intensity threshold to slightly less than average intensity of io region
				no_hole = where(image LT hole_threshold,no_hole_count)
					; indices of image pixels having intensity lower than threshold
				hole = where(image GE hole_threshold,hole_count)
					; indices of image pixels having intensity greater than or equal to threshold
;				hole_threshold = 0.5*(mean(image(no_hole)) + mean(image(hole)))
				hole_threshold = mean(image(no_hole)) + 2.0 * stddev(image(no_hole))
					; reset intensity threshold to better-determined value
				no_hole = where(image LT hole_threshold,no_hole_count)
					; indices of image pixels having intensity lower than threshold
				hole = where(image GE hole_threshold,hole_count)
					; indices of image pixels having intensity greater than or equal to threshold
				dummy = image(no_hole)
				max_image = max(dummy(where(finite(dummy))))
			ENDELSE
		ENDIF
	ENDELSE
ENDELSE
; Scale image to fill gray scale range
percent_image = 100. * image / max_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)
percent_image = 0
display_image = 0
; refill clipped edges of images so they appear with image_bkgd_color
CASE edgefill OF
	'meanfill' : BEGIN
;		print,'bytescale edgefill : meanfill'
	END
	'medianfill' : BEGIN
;		print,'bytescale edgefill : medianfill'
	END
	'maxfill' : BEGIN
;		print,'bytescale edgefill : maxfill'
	END
	'minfill' : BEGIN
;		print,'bytescale edgefill : minfill'
	END
	'zero' : BEGIN
;		print,'bytescale edgefill : zero'
	END
	'NaN' : BEGIN
;		print,'bytescale edgefill : NaN'
		clipped_edge = where(finite(image,/nan),count)
		IF (clipped_edge[0] NE -1) THEN byte_image(clipped_edge) = image_blgd_color_index
	END
	'infinity' : BEGIN
;		print,'bytescale edgefill : Infinity'
		clipped_edge = where(finite(image,/infinity),count)
		IF (clipped_edge[0] NE -1) THEN byte_image(clipped_edge) = image_blgd_color_index
;		IF (clipped_edge[0] NE -1) THEN byte_image(clipped_edge) = spectra_color_index(7)
	END
	ELSE : BEGIN
;		print,'bytescale edgefill : else'
	END
ENDCASE
IF (do_byte_roi NE 'no') THEN BEGIN	; Change color of roi regions
	i_svec = size(i_roi)
	i0_svec = size(i0_roi)
	IF ((i0_svec(0) NE 0) AND (i0_roi[0] NE -1)) THEN BEGIN
		byte_image(i0_roi) = spectra_color_index(0)
	ENDIF
	IF (i_svec(0) NE 0) THEN BEGIN
		FOR j=1,n_roi DO BEGIN
			roi = i_roi[roi_index[j-1]:roi_index[j]-1]
			byte_image(roi) = spectra_color_index(j)
		ENDFOR
	ENDIF
ENDIF
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_analyze_colorbar, window_name
;print,'zstack_analyze_colorbar'

@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

wset, window_name
colorbar, color = zstack_black_color_index, $	;plot_bkgd_color_index, $
	bottom = bottom_color_index, top = top_color_index, $
	ncolors = top_color_index - bottom_color_index, $
	position = [0.0,0.0,0.99,0.9], ticklen = 0.0, $
	/vertical, divisions = 1, range = [0,255]
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_analyze_readfile,stackdata_filename
;print,'zstack_analyze_readfile'

@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,stack_data_readfile_bailout
get_lun,lun
openr,lun,stackdata_filename,/xdr
n_cols = long(0)
n_rows = long(0)
n_files = long(0)
readu,lun,n_cols,n_rows,n_files
filename_list = strarr(n_files)
readu,lun,filename_list
x_dist = fltarr(n_cols)
y_dist = fltarr(n_rows)
ev_list = fltarr(n_files)
msec_list = fltarr(n_files)
readu,lun,x_dist,y_dist,ev_list,msec_list
image_stack = fltarr(n_cols,n_rows,n_files)
readu,lun,image_stack
x_start = min(x_dist,max=x_stop)
y_start = min(y_dist,max=y_stop)
print,'Read stack data file "'+stackdata_filename+'"'
close,lun
free_lun,lun
return
stack_data_readfile_bailout:
print,'Error reading stack data file "'+stackdata_filename+'"'
close,lun
free_lun,lun
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_analyze_clip_data
print,'zstack_analyze_clip_data'

@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([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_analyze_init_event, event
;print,'zstack_analyze_init_event

@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_analyze_par.browse_directory_label : BEGIN
        cd,current = current_directory
        dummy = dialog_pickfile(get_path=data_directory,title='Select File within Desired Directory')
        widget_control, zstack_analyze_par.directory_label, $
          set_value = ' '+data_directory
        IF (dummy EQ '') THEN data_directory = current_directory
			; sets data_directory to initial directory if CANCEL is chosen during dialog
			; without this, data_directory becomes null string
        on_ioerror, browse_directory_label_oops
        browse_directory_label_oops:
        cd,data_directory	; change directory to data_directory, CGZ
;        last_char = strmid(data_directory,strlen(data_directory)-1,1)
;        osname = strupcase(strmid(!version.os,0,3))
;		CASE osname OF
;			'VMS' : BEGIN
;				IF (last_char NE ']') THEN BEGIN
;					data_directory = data_directory+']'
;				ENDIF
;			END
;			'WIN' : BEGIN
;				IF (last_char NE '\') THEN BEGIN
;					data_directory = data_directory+'\'
;				ENDIF
;			END
;			'MAC' : BEGIN
;				IF (last_char NE ':') THEN BEGIN
;					data_directory = data_directory+':'
;				ENDIF
;			END
;			'UNIX' : BEGIN
;				IF (last_char NE '/') THEN BEGIN
;					data_directory = data_directory+'/'
;				ENDIF
;			END
;			ELSE : BEGIN
;				print,'Unrecognized operating system'
;			END
;		ENDCASE
        widget_control, zstack_analyze_par.directory_label, $
          set_value = ' '+data_directory
	END

	zstack_analyze_par.directory_label : BEGIN
        temp_string = ''
        widget_control, zstack_analyze_par.directory_label, $
          get_value = temp_string
        on_ioerror, directory_label_oops
        data_directory = temp_string(0)
        directory_label_oops:
        last_char = strmid(data_directory,strlen(data_directory)-1,1)
        osname = strupcase(strmid(!version.os,0,3))
		CASE osname OF
			'VMS' : BEGIN
				IF (last_char NE ']') THEN BEGIN
					data_directory = data_directory+']'
				ENDIF
			END
			'WIN' : BEGIN
				IF (last_char NE '\') THEN BEGIN
					data_directory = data_directory+'\'
				ENDIF
			END
			'MAC' : BEGIN
				IF (last_char NE ':') THEN BEGIN
					data_directory = data_directory+':'
				ENDIF
			END
			'UNIX' : BEGIN
				IF (last_char NE '/') THEN BEGIN
					data_directory = data_directory+'/'
				ENDIF
			END
			ELSE : BEGIN
				print,'Unrecognized operating system'
			END
		ENDCASE
        widget_control, zstack_analyze_par.directory_label, $
          set_value = ' '+data_directory
		cd,data_directory	; change directory to data_directory, CGZ
	END

	zstack_analyze_par.list_filename_label : BEGIN
		temp_string = ''
		widget_control, zstack_analyze_par.save_list_filename_label, get_value = temp_string
		on_ioerror, list_filename_label_oops
		list_filename = strtrim(temp_string(0),2)
		IF (strlen(list_filename) NE 0) THEN BEGIN
			dotpos = strpos(list_filename,'.')
			IF (dotpos EQ -1) THEN BEGIN
				list_filename = list_filename+'.sl'
			ENDIF ELSE BEGIN
				IF (strpos(strlowcase(list_filename),'.sl') EQ -1) THEN BEGIN
					list_filename = list_filename+'sl'
				ENDIF
			ENDELSE
		ENDIF
		list_filename_label_oops:
		widget_control, zstack_analyze_par.save_list_filename_label, $
				set_value = ' '+list_filename
	END
	zstack_analyze_par.browse_list_filename_label : BEGIN
;		IF (data_directory EQ '') THEN cd,current=data_directory
		dummy = dialog_pickfile(filter='*.sl',path=data_directory,/read,$
				get_path=data_directory, title='Select STACK list File')
		on_ioerror, browse_list_label_oops
		IF (strlen(dummy) EQ 0) THEN GOTO, browse_list_label_oops
			; trap if CANCEL is chosen in dialog
		widget_control,zstack_analyze_par.main_base,hourglass=1
		; strip the directory from dummy to get list_filename
		osname = strupcase(strmid(!Version.os, 0, 3))
		CASE osname OF
			'VMS' : BEGIN
				firstpos = strpos(dummy, ']')+1
			END
			'WIN' : BEGIN
				firstpos = rstrpos(dummy, '\')+1
			END
			'MAC' : BEGIN
				firstpos = rstrpos(dummy, ':')+1
			END
			'UNIX' : BEGIN
				firstpos = rstrpos(dummy, '/')+1
			END
			ELSE : BEGIN
				print,'Unrecognized operating system'
			END
		ENDCASE
		IF (firstpos EQ -1) THEN BEGIN
			list_filename = dummy
			stripped_directory = ''
		ENDIF ELSE BEGIN
			list_filename = strmid(dummy, firstpos, (strlen(dummy)-firstpos))
			stripped_directory = strmid(dummy,0,firstpos)
		ENDELSE
		IF (osname EQ 'VMS') THEN BEGIN
			semipos = rstrpos(list_filename, ';')
			IF (semipos GT 1) THEN BEGIN
				list_filename = strmid(list_filename,0,semipos)
			ENDIF
		ENDIF
		widget_control, zstack_analyze_par.list_filename_label, $
				set_value = ' '+list_filename
		widget_control, zstack_analyze_par.directory_label, $
				set_value = ' '+stripped_directory
		browse_list_label_oops:
	END
	zstack_analyze_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
				IF (strpos(strlowcase(shift_filename),'.aln') EQ -1) THEN BEGIN
					shift_filename = shift_filename+'aln'
				ENDIF
			ENDELSE
		ENDIF
		shift_filename_label_oops:
		widget_control, zstack_align_par.shift_filename_label, $
			set_value = ' '+shift_filename
	END
	zstack_analyze_par.browse_shift_filename_label : BEGIN
		dummy = dialog_pickfile(filter='*.aln',path=data_directory,/read, $
				title='Select Alignment Shift File')
		on_ioerror, browse_shift_label_oops
		IF (strlen(dummy) EQ 0) THEN GOTO, browse_shift_label_oops
			; trap if CANCEL is chosen in dialog
		widget_control,zstack_analyze_par.main_base,hourglass=1
		; strip the directory from dummy to get list_filename
		osname = strupcase(strmid(!Version.os, 0, 3))
		CASE osname OF
			'VMS' : BEGIN
				firstpos = strpos(dummy, ']')+1
			END
			'WIN' : BEGIN
				firstpos = rstrpos(dummy, '\')+1
			END
			'MAC' : BEGIN
				firstpos = rstrpos(dummy, ':')+1
			END
			'UNIX' : BEGIN
				firstpos = rstrpos(dummy, '/')+1
			END
			ELSE : BEGIN
				print,'Unrecognized operating system'
			END
		ENDCASE
		IF (firstpos EQ -1) THEN BEGIN
			shift_filename = dummy
			stripped_directory = ''
		ENDIF ELSE BEGIN
			shift_filename = strmid(dummy, firstpos, (strlen(dummy)-firstpos))
			stripped_directory = strmid(dummy,0,firstpos)
		ENDELSE
		IF (osname EQ 'VMS') THEN BEGIN
			semipos = rstrpos(shift_filename, ';')
			IF (semipos GT 1) THEN BEGIN
				shift_filename = strmid(shift_filename,0,semipos)
			ENDIF
		ENDIF
		widget_control, zstack_analyze_par.shift_filename_label, $
				set_value = ' '+shift_filename
		browse_shift_label_oops:
	END
	zstack_analyze_par.stackdata_filename_label : BEGIN
	END
	zstack_analyze_par.browse_stackdata_filename_label : BEGIN
	END
	zstack_analyze_par.NSLS_stxm_source_label : BEGIN
		data_source = 1
	END
	zstack_analyze_par.NSLS_cryo_source_label : BEGIN
		data_source = 2
	END
	zstack_analyze_par.sm_data_source_label : BEGIN
		data_source = 3
	END
	zstack_analyze_par.ALS_BL7_source_label : BEGIN
		data_source = 4
	END
	zstack_analyze_par.ALS_Poly_source_label : BEGIN
		data_source = 5
	END
	zstack_analyze_par.other_source_label : BEGIN
	END
	zstack_analyze_par.despike_yes_label : BEGIN
		do_despike = 1
	END
	zstack_analyze_par.despike_no_label : BEGIN
		do_despike = 0
	END
	zstack_analyze_par.median_yes_label : BEGIN
		do_median_filter = 1
	END
	zstack_analyze_par.median_no_label : BEGIN
		do_median_filter = 0
	END
	zstack_analyze_par.median_level_label : BEGIN
;		IF (median EQ 1) THEN BEGIN
;			median = 3
;		ENDIF ELSE BEGIN
;			median = median
;		ENDELSE
	END
	zstack_analyze_par.memory_yes_label : BEGIN
		low_memory = 1
	END
	zstack_analyze_par.memory_no_label : BEGIN
		low_memory = 0
	END
	zstack_analyze_par.update_label : BEGIN
print,'pressed the continue button'
		widget_control,zstack_analyze_par.main_base,/destroy
		print,'do_despike : ',do_despike
		return
;		zstack_analyze, list_filename, shift_filename, $
 ;                  median=median, despike=despike, low_mem=low_mem, $
  ;                 stackdata_filename=stackdata_filename, $
   ;                ztrace=ztrace
	END
	zstack_analyze_par.close_label : BEGIN
print,'pressed the stop button'
		widget_control,zstack_analyze_par.main_base,/destroy
		retall
	END
ENDCASE
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_analyze_modal_dialog
print,'zstack_analyze_modal_dialog'
IF (n_tags(zstack_analyze_par) EQ 0) THEN BEGIN
    	zstack_analyze_par = $
    	{	zstack_analyze_par, $
		main_base: 0L, $
		directory_label: 0L, $
		browse_directory_label: 0L, $
		list_filename_label: 0L, $
		browse_list_filename_label: 0L, $
		shift_filename_label: 0L, $
		browse_shift_filename_label: 0L, $
		stackdata_filename_label: 0L, $
		browse_stackdata_filename_label: 0L, $
		median_yes_label: 0L, $
		median_no_label: 0L, $
		median_level_label: 0L, $
		despike_yes_label: 0L, $
		despike_no_label: 0L, $
		NSLS_stxm_source_label: 0L, $
		NSLS_cryo_source_label: 0L, $
		sm_data_source_label: 0L, $
		ALS_BL7_source_label: 0L, $
		ALS_Poly_source_label: 0L, $
		other_source_label: 0L, $
		memory_yes_label: 0L, $
		memory_no_label: 0L, $
		cpu_label: 0L, $
		opsys_label: 0L, $
		platform_label: 0L, $
		screen_size_label: 0L, $
		update_label: 0L, $
		close_label: 0L, $
		main_base_win: 0L $
	}
ENDIF
;   self.tlb = Widget_Base(Group_Leader=parent, Modal=1, Title=self.title, $
 ;     Column=1, Base_Align_Center=1, Floating=1)
zstack_analyze_par.main_base = widget_base(title='ZSTACK Analyze Modal Widget', /col, /scroll)
label = widget_label(zstack_analyze_par.main_base,value='ZSTACK Analyze Modal Widget')
widget_control, zstack_analyze_par.main_base, /realize
zstack_analyze_par.main_base_win = !d.window
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_analyze_init_dialog
print,'zstack_analyze_init_dialog'

@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

scr_dims = get_screen_size()
IF (n_tags(zstack_analyze_par) EQ 0) THEN BEGIN
    	zstack_analyze_par = $
    	{	zstack_analyze_par, $
		main_base: 0L, $
		directory_label: 0L, $
		browse_directory_label: 0L, $
		list_filename_label: 0L, $
		browse_list_filename_label: 0L, $
		shift_filename_label: 0L, $
		browse_shift_filename_label: 0L, $
		stackdata_filename_label: 0L, $
		browse_stackdata_filename_label: 0L, $
		median_yes_label: 0L, $
		median_no_label: 0L, $
		median_level_label: 0L, $
		despike_yes_label: 0L, $
		despike_no_label: 0L, $
		NSLS_stxm_source_label: 0L, $
		NSLS_cryo_source_label: 0L, $
		sm_data_source_label: 0L, $
		ALS_BL7_source_label: 0L, $
		ALS_Poly_source_label: 0L, $
		other_source_label: 0L, $
		memory_yes_label: 0L, $
		memory_no_label: 0L, $
		cpu_label: 0L, $
		opsys_label: 0L, $
		platform_label: 0L, $
		screen_size_label: 0L, $
		update_label: 0L, $
		close_label: 0L, $
		main_base_win: 0L $
	}
ENDIF
;saved_list_filename, saved_shift_filename, $
;                   median=median, despike=despike, $
;                   stackdata_filename=stackdata_filename, $
;                   stxm=stxm, sxm=sxm, sm=sm, als=als, poly=poly, low_mem=low_mem, $
;                   ztrace=ztrace, help=help
zstack_analyze_par.main_base = widget_base(title='ZSTACK Initialization', /col,/scroll )
row1 = widget_base(zstack_analyze_par.main_base,/row,/frame,/align_center)
row2 = widget_base(zstack_analyze_par.main_base,/row,/frame,/align_center)
row3 = widget_base(zstack_analyze_par.main_base,/row,/align_center)
row4 = widget_base(zstack_analyze_par.main_base,/row,/align_center)
;col = widget_base(row1,/col)
;row = widget_base(col,/row)
zstack_analyze_par.browse_directory_label = widget_button(row1,value='Directory:')
;label = widget_label(row,value='Current directory :',xsize=150,/align_left)
zstack_analyze_par.directory_label = widget_text(row1,value='', xsize=90, /editable)
;zstack_analyze_par.browse_directory_label = widget_button(row,value='Browse')
col = widget_base(row2,/col)
row = widget_base(col,/row)
label = widget_label(row, value='File of image list :',xsize=150,/align_left)
zstack_analyze_par.list_filename_label = widget_text(row,value='', xsize=50, /editable)
zstack_analyze_par.browse_list_filename_label = widget_button(row, value='Browse')
row = widget_base(col,/row)
label = widget_label(row, value='File of alignment shifts :',xsize=150,/align_left)
zstack_analyze_par.shift_filename_label = widget_text(row,value='', xsize=50, /editable)
zstack_analyze_par.browse_shift_filename_label = widget_button(row, value='Browse')
row = widget_base(col,/row)
label = widget_label(row, value='Binary stack data file :',xsize=150,/align_left)
zstack_analyze_par.stackdata_filename_label = widget_text(row,value='', xsize=50, /editable)
zstack_analyze_par.browse_stackdata_filename_label = widget_button(row, value='Browse')
col2b = widget_base(row3,/col,/frame)
row = widget_base(col2b,/row)
label = widget_label(row, value='Primary data source ?',xsize=150,/align_left)
row = widget_base(col2b,/row)
col = widget_base(row,/col,/exclusive)
zstack_analyze_par.NSLS_stxm_source_label = widget_button(col, value='NSLS STXM (*.nc)')
zstack_analyze_par.NSLS_cryo_source_label = widget_button(col, value='NSLS Cryo-STXM (*.sxm)')
zstack_analyze_par.sm_data_source_label = widget_button(col, value='*.sm')
zstack_analyze_par.ALS_BL7_source_label = widget_button(col, value='ALS BL7 STXM (*.dat)')
zstack_analyze_par.ALS_Poly_source_label = widget_button(col, value='ALS Polymer STXM (not implemented)')
;zstack_analyze_par.other_source_label = widget_button(col, value='Other')
col2a = widget_base(row3,/col,/frame,space=0)
row = widget_base(col2a,/row)
label = widget_label(row, value='Remove spikes from data ?',xsize=150,/align_left)
row = widget_base(col2a,/row,/exclusive,/align_center)
zstack_analyze_par.despike_yes_label = widget_button(row, value='Yes')
zstack_analyze_par.despike_no_label = widget_button(row, value='No')
row = widget_base(col2a,/row)
label = widget_label(row, value='Median filter data ?',xsize=150,/align_left)
row = widget_base(col2a,/row,/exclusive,/align_center)
zstack_analyze_par.median_yes_label = widget_button(row, value='Yes')
zstack_analyze_par.median_no_label = widget_button(row, value='No')
row = widget_base(col2a,/row)
label = widget_label(row, value='Median level ?',xsize=100)
zstack_analyze_par.median_level_label = widget_text(row,value='', xsize=5, /editable)
row = widget_base(col2a,/row)
label = widget_label(row, value='Conserve memory ?',xsize=150,/align_left)
row = widget_base(col2a,/row,/exclusive,/align_center)
zstack_analyze_par.memory_yes_label = widget_button(row, value='Yes')
zstack_analyze_par.memory_no_label = widget_button(row, value='No')
col2c = widget_base(row3,/col,/frame,space=0)
label = widget_label(col2c, value='Computer platform :',xsize=150,/align_left)
zstack_analyze_par.cpu_label = widget_label(col2c, value=!version.arch)
label = widget_label(col2c, value='Operating System :',xsize=150,/align_left)
zstack_analyze_par.opsys_label = widget_label(col2c, value=!version.os)
label = widget_label(col2c, value='Screen size :',xsize=150,/align_left)
zstack_analyze_par.screen_size_label = widget_label(col2c, $
	value=strtrim(string(fix(scr_dims[0])),2)+' x '+ $
		strtrim(string(fix(scr_dims[1])),2)+' pixels')
zstack_analyze_par.update_label = widget_button(row4,value='Continue')
zstack_analyze_par.close_label = widget_button(row4,value='Stop')
widget_control, zstack_analyze_par.main_base, /realize
zstack_analyze_par.main_base_win = !d.window
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_analyze_init
print,'zstack_analyze_init'

@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_analyze_init_dialog
widget_control, zstack_analyze_par.directory_label, $
			set_value = ' '+data_directory
widget_control, zstack_analyze_par.list_filename_label, $
			set_value = ' '+list_filename
widget_control, zstack_analyze_par.shift_filename_label, $
			set_value = ' '+shift_filename
;widget_control, zstack_analyze_par.stackdata_filename_label, $
;			set_value = ' '+stackdata_filename
CASE data_source OF
	1 : BEGIN	; X1A STXM data
		widget_control, zstack_analyze_par.NSLS_stxm_source_label, set_button = 1
 	END
	2 : BEGIN	; X1A cryo-STXM data
		widget_control, zstack_analyze_par.NSLS_cryo_source_label, set_button = 1
	END
	3 : BEGIN	; sm data
		widget_control, zstack_analyze_par.sm_data_source_label, set_button = 1
	END
	4 : BEGIN	; BL7 (ALS) data
		widget_control, zstack_analyze_par.sm_data_source_label, set_button = 1
	END
	5 : BEGIN	; Polymer STXM (ALS) data
		widget_control, zstack_analyze_par.ALS_Poly_source_label, set_button = 1
	END
	ELSE : BEGIN	; X1A STXM data assumed
		widget_control, zstack_analyze_par.NSLS_stxm_source_label, set_button = 1
	END
ENDCASE
IF (do_despike EQ 0) THEN BEGIN
	despike = 0
	widget_control, zstack_analyze_par.despike_no_label, set_button = 1
ENDIF ELSE BEGIN
	despike = 1
	widget_control, zstack_analyze_par.despike_yes_label, set_button = 1
ENDELSE
IF (do_median_filter NE 0) THEN BEGIN
	widget_control, zstack_analyze_par.median_yes_label, set_button = 1
	widget_control, zstack_analyze_par.median_level_label, $
				set_value = ' '+strtrim(string(do_median_filter),2)
ENDIF ELSE BEGIN
	widget_control, zstack_analyze_par.median_no_label, set_button = 1
	widget_control, zstack_analyze_par.median_level_label, sensitive = 0
ENDELSE
IF (do_save_memory EQ 0) THEN BEGIN
	widget_control, zstack_analyze_par.memory_no_label, set_button = 1
ENDIF ELSE BEGIN
	widget_control, zstack_analyze_par.memory_yes_label, set_button = 1
ENDELSE
xmanager, 'zstack_analyze_init', zstack_analyze_par.main_base, $
		group_leader = zstack_analyze_par.main_base
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_analyze_initial_zoom
;n_cols = 100.
;print,'n_cols :', n_cols
screen_size = get_screen_size()
print,screen_size[0]
CASE 1 OF
	screen_size[0] LE 900 : BEGIN
		print,'max image = 100'
	END

	(screen_size[0] LT 1100) : BEGIN
		print,'max image = 150'
	END
	(screen_size[0] LT 1200) : BEGIN
		print,'max image = 200'
	END
	(screen_size[0] LT 1300) : BEGIN
		print,'max image = 250'
	END
	screen_size[0] LT 1700 : BEGIN
		print,'max image = 350'
	END
	screen_size[0] GE 1700 : BEGIN
		print,'max image = 400'
	END
ENDCASE
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_analyze_align
IF keyword_set(ztrace) THEN print,'ZTRACE: zstack_despike_filter'

@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

;help,/memory
    n_files = n_elements(filename_list)
print,'zstack_analyze : n_files : ', n_files
    IF (n_files LT 2) THEN BEGIN
        print,'No files in list for analyzing!'
        GOTO, zstack_analyze_align_bailout
    ENDIF
	; Despike data using X1A function, DESPIKE.PRO
;	IF keyword_set(despike) THEN BEGIN
	IF (do_despike NE 0) THEN BEGIN
		IF keyword_set(ztrace) THEN print,'ZTRACE: despike'
		print,'despike'
		FOR i=0,(n_files-1) DO BEGIN
			khz = image_stack(*,*,i)
			despike,khz
			image_stack(*,*,i) = temporary(khz)
		ENDFOR
	ENDIF
; should rewrite this so median keyword is the same as number used by median command
; if number isn't given, default to 3
; if no keyword, then no median smoothing

	; Smooth data using median filter
;	IF keyword_set(median) THEN BEGIN
	IF (do_median_filter NE 0) THEN BEGIN
		IF keyword_set(ztrace) THEN print,'ZTRACE: median filter'
		FOR i=0,(n_files-1) DO BEGIN
			khz = image_stack(*,*,i)
			khz = median(khz,do_median_filter)
			image_stack(*,*,i) = temporary(khz)
		ENDFOR
	ENDIF
;help,/memory
; Align the images
	IF (strlen(shift_filename) EQ 0) THEN BEGIN		; do auto alignment from scratch
		IF keyword_set(ztrace) THEN print,'ZTRACE: zstack_align'
		zstack_align, low_mem = do_save_memory
			; added low_mem option to conserve memory use in zstack_align.pro
	ENDIF ELSE BEGIN			; do alignment using pre-existing *.aln file
		IF keyword_set(ztrace) THEN print,'ZTRACE: zstack_align, realign'
;		zstack_align, filename_shift=shift_filename, low_mem=low_mem;, /realign
		zstack_align, shift_filename, low_mem = do_save_memory;, /realign
			; added low_mem option to conserve memory use in zstack_align.pro
	ENDELSE

zstack_analyze_align_bailout :
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_analyze, saved_list_filename, saved_shift_filename, $
                   init=init, median=median, despike=despike, low_mem=low_mem, zoom=zoom, $
                   stackdata_filename=stackdata_filename, $
                   stxm=stxm, sxm=sxm, sm=sm, als=als, poly=poly, source=source, $
                   compile=compile, ztrace=ztrace, help=help, $
                   called_by_axis=called_by_axis, group_leader_ID=groupLeader
;help,/memory
IF keyword_set(ztrace) THEN print,'ZTRACE: zstack_analyze'

@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

; @bsif_common	; needed for X1A STXM
; @sxm_common	; needed for X1A cryo-STXM
on_error,2
IF keyword_set(help) THEN BEGIN
    print,'zstack_analyze,[saved_list_filename,saved_shift_filename]'
    print,'  where [saved_list_filename] is an optional list of files'
    print,'        [saved_shift_filename] is a MAPPER-type file for pixel shifts'
    print,'  Options include:'
    print,'    zoom=integer or 1/integer,text_height=pixels,/median,/despike,/manual_align'
    print,'    stackdata_filename= to read in a prealigned, saved stack'
    print,'    /stxm,/sxm,/sm,/als,/poly for different data file types'
    return
ENDIF
; Get current directory/folder with path
cd,current = data_directory
; if called from AXIS2000, set axis2000 to 1, otherwise 0
axis_call = 0
IF keyword_set(called_by_axis) THEN axis_call = 1
; Check validity of list_filename
IF (n_elements(saved_list_filename) EQ 0) THEN BEGIN
	list_filename = ''
ENDIF ELSE BEGIN
	dummy = findfile(saved_list_filename, count=count)
	IF (count EQ 0) THEN BEGIN
		print,string(7B),'List file, '+saved_list_filename+', not found',string(7B)
		list_filename = ''
		saved_shift_filename = ''
	ENDIF ELSE BEGIN
		list_filename = saved_list_filename
	ENDELSE
ENDELSE
; Check validity of shift_filename
IF (n_elements(saved_shift_filename) EQ 0) THEN BEGIN
	shift_filename = ''
ENDIF ELSE BEGIN
	dummy = findfile(saved_shift_filename, count=count)
	IF (count EQ 0) THEN BEGIN
		print,string(7B),'Shift file, '+saved_shift_filename+', not found',string(7B)
		shift_filename = ''
	ENDIF ELSE BEGIN
		shift_filename = saved_shift_filename
	ENDELSE
ENDELSE
; Check validity of stackdata_filename
IF keyword_set(stackdata_filename) THEN BEGIN
	IF (n_elements(stackdata_filename) EQ 0) THEN BEGIN
		stackdata_filename = ''
	ENDIF ELSE BEGIN
		dummy = findfile(stackdata_filename, count=count)
		IF (count EQ 0) THEN BEGIN
			print,string(7B),'Stack data file, '+stackdata_filename+', not found',string(7B)
			stackdata_filename = ''
		ENDIF
	ENDELSE
ENDIF ELSE BEGIN
	stackdata_filename = ''
ENDELSE
; Determine type of data:  STXM:1, SXM:2, SM:3, ALS:4, POLY:5
key_vec = [keyword_set(source),keyword_set(stxm),keyword_set(sxm),keyword_set(sm),keyword_set(als),keyword_set(poly)]
dummy = where(key_vec EQ 1,count)
IF (count EQ 0) THEN BEGIN
    print,'Assuming files are /stxm type'
    data_source = 1
ENDIF ELSE BEGIN
	IF (count NE 1) THEN BEGIN
		print,'Can not specify multiple data types - halting execution'
		return
	ENDIF
	data_source = dummy
	IF (data_source EQ 0) THEN BEGIN
		dummy = where(strlowcase(strtrim(string(source),2)) EQ ['stxm','stm','sm','als','poly'], count)
		IF (count NE 0) THEN BEGIN
			data_source = dummy
		ENDIF ELSE BEGIN
			dummy = where(source EQ [1,2,3,4,5], count)
			IF (count NE 0) THEN BEGIN
				data_source = dummy
			ENDIF
		ENDELSE
	ENDIF
ENDELSE
; Despike data using X1A function, DESPIKE.PRO
IF keyword_set(despike) THEN BEGIN
	do_despike = 1
ENDIF ELSE BEGIN
	do_despike = 0
ENDELSE
; if number isn't given, default to 3
; if no keyword, then no median smoothing

; Smooth data using median filter
IF keyword_set(median) THEN BEGIN
	IF (median EQ 1) THEN BEGIN
		do_median_filter = 3
	ENDIF ELSE BEGIN
		do_median_filter = median
	ENDELSE
ENDIF ELSE BEGIN
	do_median_filter = 0
ENDELSE
; Conserve memory by not creating duplicate arrays
; Set do_save_memory variable here for use later in ZSTACK_ALIGN
IF keyword_set(low_mem) THEN BEGIN
	do_save_memory = 1
ENDIF ELSE BEGIN
	do_save_memory = 0
ENDELSE
IF keyword_set(init) THEN BEGIN
	zstack_analyze_init
ENDIF
IF keyword_set(ztrace) THEN print,'ZTRACE: zstack_color'
;zstack_analyze_prep	; load color table and define common variables
IF (axis_call NE 1) THEN BEGIN
	zstack_color
ENDIF ELSE BEGIN
	zstack_color,/no_load
ENDELSE
; Initialize zstack_spectra_common variables
;	i_roi = 0
;	i0_roi = 0
;	n_roi = 0
;	roi_index = 0
;	spectrum = 0
;	i0_filename = ''
;	i0_filetype = ''
;	spec_filename_header = ''
;	save_filename_header = ''
; Initialize zstack_common variables
cd,current = data_directory
n_files = 0
displayed_file_index = 0
data_shifted = 0
edgefill = 'infinity'  				; use minimum intensity as default for image alignment
;	edgefill = 'min'  				; use minimum intensity as default for image alignment
; Initialize zstack_display_common variables
IF keyword_set(zoom) THEN BEGIN
	image_zoom = zoom
ENDIF ELSE BEGIN
	image_zoom = 1.
ENDELSE
n_cols = 0
n_rows = 0
dragbox = [0,0,0,0]
clipbox = [0,0,0,0]
;image_zoom = 1.
subimage_zoom = 4.
movie_delay = 0.1	; This is machine-dependent
disp_min = 0.
disp_max = 100.
disp_gamma = 1.
spectrum_display = 3	; Spectra displayed as absorbance
spectrum_offset = 0.
init_zoom = image_zoom
movie_active = 0
profile_zoom = 1.
image_range = 0
image_ratio = 0
ratio_image_index = 0	; Images displayed as raw data
image_scale = 0
image_invert = 0
plot_x_min = 0.
plot_x_max = 0.
plot_y_min = 0
plot_y_max = 0
x_autoscale = 1
y_autoscale = 1
i_roi = ''
i0_roi = ''
reference_spectrum = ''
reference_image = ''
reference_stack = ''
;idl_major_version_string = $
;  strmid(!version.release,0,strpos(!version.release,'.'))
;idl_major_version = fix(0)
;reads,idl_major_version_string,idl_major_version
; Read in the data and construct zstack_common
;help,/memory
IF keyword_set(stackdata_filename) THEN BEGIN
;	print,'will read in '+stackdata_filename+', not implemented'

	IF keyword_set(ztrace) THEN print,'ZTRACE: zstack_analyze_readfile'
	zstack_analyze_readfile,stackdata_filename		;, Group_Leader_ID=groupLeader
	n_files = n_elements(filename_list)
	filename_display_list = strarr(n_files)
	FOR i=0,(n_files-1) DO BEGIN
		filename_display_list(i) = $
			filename_list(i)+': '+$
			strtrim(string(ev_list(i),format='(f10.2)'),2)+' eV '+$
			strtrim(string(msec_list(i),format='(i6)'),2)+' msec'
	ENDFOR
	x_shift = fltarr(n_files)	; set to null vector
	y_shift = fltarr(n_files)	; set to null vector

	IF (axis_call EQ 1) THEN BEGIN
		return
	ENDIF
ENDIF ELSE BEGIN
	IF (strlen(list_filename) EQ 0) THEN BEGIN	; if no filename is given
		filename_list = ''
		IF keyword_set(ztrace) THEN print,'ZTRACE: zstack_buildlist'
		zstack_buildlist, filename_list		;, Group_Leader_ID=groupLeader
	ENDIF ELSE BEGIN		; if valid filename is given
		IF keyword_set(ztrace) THEN print,'ZTRACE: zstack_readlist'
		zstack_readlist, list_filename		;, Group_Leader_ID=groupLeader
	ENDELSE

	IF (axis_call EQ 1) THEN BEGIN
		return
	ENDIF
    n_files = n_elements(filename_list)
    IF (n_files LT 2) THEN BEGIN
        print,'No files in list for analyzing!'
        return
    ENDIF
	; Despike data using X1A function, DESPIKE.PRO
	IF (do_despike NE 0) THEN BEGIN
		IF keyword_set(ztrace) THEN print,'ZTRACE: despike'
		print,'despike'
		FOR i=0,(n_files-1) DO BEGIN
			khz = image_stack(*,*,i)
			despike,khz
			image_stack(*,*,i) = temporary(khz)
		ENDFOR
	ENDIF
; should rewrite this so median keyword is the same as number used by median command
; if number isn't given, default to 3
; if no keyword, then no median smoothing

	; Smooth data using median filter
	IF (do_median_filter NE 0) THEN BEGIN
		IF keyword_set(ztrace) THEN print,'ZTRACE: median filter'
		FOR i=0,(n_files-1) DO BEGIN
			khz = image_stack(*,*,i)
			khz = median(khz,do_median_filter)
			image_stack(*,*,i) = temporary(khz)
		ENDFOR
	ENDIF
; Align the images
	IF (strlen(shift_filename) EQ 0) THEN BEGIN		; do auto alignment from scratch
		IF keyword_set(ztrace) THEN print,'ZTRACE: zstack_align'
		zstack_align, low_mem = do_save_memory	;, Group_Leader_ID=groupLeader
			; added low_mem option to conserve memory use in zstack_align.pro
	ENDIF ELSE BEGIN			; do alignment using pre-existing *.aln file
		IF keyword_set(ztrace) THEN print,'ZTRACE: zstack_align, realign'
;		zstack_align, filename_shift=shift_filename, low_mem=low_mem;, /realign
		zstack_align, shift_filename, low_mem = do_save_memory	;, Group_Leader_ID=groupLeader
			; added low_mem option to conserve memory use in zstack_align.pro
	ENDELSE
;	; Clip edges of data
;	IF keyword_set(ztrace) THEN print,'ZTRACE: zstack_analyze_clip_data'
;	zstack_analyze_clip_data

ENDELSE
; ZSTACK_SPECTRA is now invoked through ZSTACK_ALIGN at end of alignment
; Extract spectra
IF keyword_set(ztrace) THEN print,'ZTRACE: zstack_spectra analyze'
zstack_spectra		;, Group_Leader_ID=groupLeader
; reset variables at end of zstack, this is also done within zstack_spectra
image_zoom = 1
n_cols = 0
n_rows = 0
xmanager, 'zstack_analyze', zstack_analyze_par.main_base, $
  group_leader = zstack_analyze_par.main_base
return
end