; Copyright (c) 1998-2015 C. Zimba & A.P. Hitchcock  All rights reserved
;+
; NAME:
;	ZSTACK_PROFILE.PRO
;
; LAST CHANGED: ----------------------------------- 27-Jul-15
;
; AUTHORS:
;	Carl G. Zimba (NIST)
; PURPOSE:
;	Alignment of images abtained on an x-ray microscope.
;	Called by ZSTACK_ANALYZE.PRO
; CATEGORY:
;	Data analysis.
; CALLING SEQUENCE:
;	zstack_profile
; INPUTS:
;	NONE
;	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_spectra_common
;		zstack_spectra_par			:	variables controlling ZSTACK Spectra dialog window
;		zstack_save_par				:	variables controlling ZSTACK Save dialog window
;		roi_index					:	vector of pixels corresponding to regions of interest for all i spectra
;		i_roi						:	vector of pixels corresponding to region of interest for current i spectrum
;		n_roi						:	number of regions of interest defined for i spectra
;		i0_roi					:	vector of pixels defining region of interest for i0 spectrum
;		is_i0_roi					:	Type of region of interest: 0: i0, 1: i
;		spectrum					:	2-D matrix (j,k) of spectra corresponding to defined regions of interest, j=0: i0 spectrum, j=1-14: i spectra, k corresponds to x-ray energy of image
;		save_spectra_type			:	Type of file to save spectra as:
;		spectra_filename_header		:	base filename of spectra and regions of interest to be saved on ZSTACK Spectra dialog window
;		roi_filename				:	filename for storage and retrieval of regions of interest points
;		save_filename_header			:	base filename of images to be saved on ZSTACK Save dialog window
;		i0_filename				:	base filename of i0 spectrum to be retrieved
;		i0_filetype				:	Type of file of retrieved I0 spectrum:	RAW, XAS, CSV
;		i_roi_color_index			:	vector of indices of colors for display of regions of interest for i spectra
;		i0_roi_color_index			:	color index for display of region of interest for i0 spectrum
;		nonintegral_zoom_data			:	scaled byte image used when image_zoom is non-integral
;	zstack_profile_common
;		zstack_profile_par			:	variables controlling ZSTACK Profile dialog window
;		profile_direction			:	0: along the column direction, 1: along the row direction
;		profile_pixel				:	pixel actively used to generate profile image and plot
;		profile_x_pixel				:	x pixel used to construct profile image
;		profile_y_pixel				:	y pixel used to construct profile image
;		profile_win_pixels			:	number of pixels for profile image window
;		profile_image				:	image of profile intensity and image number
;		profile_spectrum			:	spectrum arising from single pixel at center of cursor crosshairs in profile image
;		profile_y_min				:	mimimum of all profile spectra
;		profile_y_max				:	maximum of all profile spectra
;		profile_filename_header		:	base filename of profile intensity plot to be saved on ZSTACK Profile dialog window
;		profile_filename			:	filename of profile intensity plot to be saved on ZSTACK Profile dialog window
;		spectrum_filename_header		:	base filename of profile spectrum to be saved on ZSTACK Profile dialog window
;		spectrum_filename			:	filename of profile spectrum to be saved on ZSTACK Profile dialog window
;		spectra_filename			:	filename of profile spectra to be saved on ZSTACK Profile dialog window
;		profile_use				:	0: ZSTACK_PROFILE used as a subroutine, 1: ZSTACK_PROFILE used as a stand-alone application
;	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
;		plot_x_min					:	mimimum x-ray energy value to plot spectra
;		plot_x_max					:	maximum x-ray energy value to plot spectra
;		plot_y_min					:	mimimum intensity value to plot spectra
;		plot_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:
;	Stand-alone procedure, also called from within ZSTACK_SPECTRA.PRO
; EXAMPLE:
;
; MODIFICATION HISTORY:
;
; Columns and rows were mixed up in the display of the profile image, in the profile plot, and the saved profile output
;	Fixed, CGZ 13aug99
; Shifted images were incorrectly labeled as unshifted.  Conditional with data_shifted variable was using wrong value
;	Fixed, CGZ 13aug99
;
; (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
; (31oct00 cgz)
;		Modified zstack_buildlist_savelist to include dialog_pickfile so directory can be selected
;		Added platform-dependent code with call to zstack_analyze_extract_filename
; (16nov00 cgz)
;		Separated routines to display images and profile image
;		Added new_zoom option to call of zstack_profile
;			for better interaction with zstack_display when a new zoom factor is selected
; (28nov00 cgz) migrated zstack_profile_colorbar routine to zstack_analyze.pro
; (03-Mar-08 MJ) Keyword /SCROLL in widget_base() needs X_SCROLL_SIZE.
;                Use of /SCROLL and /MODAL at the same time not allowed.
; (13-apr-08 aph) turn on pre-set window size (X_Scroll_size, Y_Scroll_size) only for non-Windows OS
; (07mar09 aph)  added binary_filename to zstack_common
; (27-jul-09 aph) external common
; (03-Aug-09 aph) change from base-10 to natural log for spectra (Larry Nitler Carnegie)
; (27-Jul-14 aph) change () to [] with specified ranges
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_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
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_desensitive
;print,'zstack_profile_desensitive'

@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 (movie_active EQ 0) THEN BEGIN
	widget_control, zstack_profile_par.filename_display_list_label, sensitive = 0
ENDIF ELSE BEGIN
	widget_control, zstack_profile_par.filename_display_list_label, sensitive = 1
ENDELSE
widget_control, zstack_profile_par.row_label, sensitive = 0
widget_control, zstack_profile_par.column_label, sensitive = 0
widget_control, zstack_profile_par.column_pixel_label, sensitive = 0
widget_control, zstack_profile_par.column_down_arrow_label, sensitive = 0
widget_control, zstack_profile_par.column_up_arrow_label, sensitive = 0
widget_control, zstack_profile_par.row_pixel_label, sensitive = 0
widget_control, zstack_profile_par.row_down_arrow_label, sensitive = 0
widget_control, zstack_profile_par.row_up_arrow_label, sensitive = 0
widget_control, zstack_profile_par.image_range_label, sensitive = 0
widget_control, zstack_profile_par.stack_range_label, sensitive = 0
widget_control, zstack_profile_par.profile_base_filename_label, sensitive = 0
widget_control, zstack_profile_par.profile_filename_label, sensitive = 0
widget_control, zstack_profile_par.save_profile_label, sensitive = 0
widget_control, zstack_profile_par.spectra_base_filename_label, sensitive = 0
widget_control, zstack_profile_par.save_profile_spectra_label, sensitive = 0
widget_control, zstack_profile_par.save_pixel_spectra_label, sensitive = 0
widget_control, zstack_profile_par.spectrum_filename_label, sensitive = 0
widget_control, zstack_profile_par.spectra_filename_label, sensitive = 0
widget_control, zstack_profile_par.prev_image_label, sensitive = 0
widget_control, zstack_profile_par.next_image_label, sensitive = 0
widget_control, zstack_profile_par.play_image_movie_label, sensitive = 0
widget_control, zstack_profile_par.prev_profile_label, sensitive = 0
widget_control, zstack_profile_par.next_profile_label, sensitive = 0
widget_control, zstack_profile_par.play_profile_movie_label, sensitive = 0
widget_control, zstack_profile_par.display_parameters_label, sensitive = 0
widget_control, zstack_profile_par.plot_parameters_label, sensitive = 0
widget_control, zstack_profile_par.exit_label, sensitive = 0
widget_control, zstack_profile_par.image_label, sensitive = 0
widget_control, zstack_profile_par.profile_image_label, sensitive = 0
widget_control, zstack_profile_par.profile_plot_label, sensitive = 0
;dummy = where(spectrum NE 0, count)
;IF (count NE 0) THEN BEGIN	; if some spectra exist
	widget_control, zstack_profile_par.spectra_plot_label, sensitive = 0
;ENDIF
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_sensitive
;print,'zstack_profile_sensitive'

@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_profile_par.filename_display_list_label, sensitive = 1
widget_control, zstack_profile_par.row_label, sensitive = 1
widget_control, zstack_profile_par.column_label, sensitive = 1
widget_control, zstack_profile_par.column_pixel_label, sensitive = 1
widget_control, zstack_profile_par.column_down_arrow_label, sensitive = 1
widget_control, zstack_profile_par.column_up_arrow_label, sensitive = 1
widget_control, zstack_profile_par.row_pixel_label, sensitive = 1
widget_control, zstack_profile_par.row_down_arrow_label, sensitive = 1
widget_control, zstack_profile_par.row_up_arrow_label, sensitive = 1
widget_control, zstack_profile_par.image_range_label, sensitive = 1
widget_control, zstack_profile_par.stack_range_label, sensitive = 1
widget_control, zstack_profile_par.profile_base_filename_label, sensitive = 1
widget_control, zstack_profile_par.profile_filename_label, sensitive = 1
IF (strlen(strtrim(profile_filename,2)) NE 0) THEN BEGIN
	widget_control, zstack_profile_par.save_profile_label, sensitive = 1
ENDIF ELSE BEGIN
	widget_control, zstack_profile_par.save_profile_label, sensitive = 0
ENDELSE
widget_control, zstack_profile_par.spectra_base_filename_label, sensitive = 1
widget_control, zstack_profile_par.spectrum_filename_label, sensitive = 1
widget_control, zstack_profile_par.spectra_filename_label, sensitive = 1
IF (strlen(strtrim(spectra_filename,2)) NE 0) THEN BEGIN
	widget_control, zstack_profile_par.save_profile_spectra_label, sensitive = 1
	widget_control, zstack_profile_par.save_pixel_spectra_label, sensitive = 1
ENDIF ELSE BEGIN
	widget_control, zstack_profile_par.save_profile_spectra_label, sensitive = 0
	widget_control, zstack_profile_par.save_pixel_spectra_label, sensitive = 0
ENDELSE
widget_control, zstack_profile_par.prev_image_label, sensitive = 1
widget_control, zstack_profile_par.next_image_label, sensitive = 1
widget_control, zstack_profile_par.play_image_movie_label, sensitive = 1
widget_control, zstack_profile_par.prev_profile_label, sensitive = 1
widget_control, zstack_profile_par.next_profile_label, sensitive = 1
widget_control, zstack_profile_par.play_profile_movie_label, sensitive = 1
widget_control, zstack_profile_par.display_parameters_label, sensitive = 1
widget_control, zstack_profile_par.plot_parameters_label, sensitive = 1
widget_control, zstack_profile_par.exit_label, sensitive = 1
widget_control, zstack_profile_par.image_label, sensitive = 1
widget_control, zstack_profile_par.profile_image_label, sensitive = 1
widget_control, zstack_profile_par.profile_plot_label, sensitive = 1
;dummy = where(spectrum NE 0, count)
;IF (count NE 0) THEN BEGIN	; if some spectra exist
	widget_control, zstack_profile_par.spectra_plot_label, sensitive = 1
;ENDIF
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_imgdisp,i_file
;print,'zstack_profile_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

; Display shifted image
; create image ready for display including regions of interest
zstack_analyze_imgprep,i_file,image
zstack_analyze_bytescale, image, byte_image
; Draw line across row or column used to construct profile image
IF (profile_direction EQ 0) THEN BEGIN	; use single row of image
	byte_image(*,profile_y_pixel) = profile_color_index
	byte_image(profile_x_pixel,*) = profile_cursor_color_index
	widget_control, zstack_profile_par.row_pixel_label,$
		set_value=' '+strtrim(string(profile_y_pixel,format='(i5)'),2)
ENDIF ELSE BEGIN					; use single column of image
	byte_image(profile_x_pixel,*) = profile_color_index
	byte_image(*,profile_y_pixel) = profile_cursor_color_index
	widget_control, zstack_profile_par.column_pixel_label,$
		set_value=' '+strtrim(string(profile_x_pixel,format='(i5)'),2)
ENDELSE
; Display image, applying zoom factor
wset,zstack_profile_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
; Display image description info
	widget_control, zstack_profile_par.filename_display_list_label,$
		set_droplist_select = i_file
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_profprep, prof_byte_image
;print,'zstack_profile_profprep'

@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

; Prepare and display profile image, i.e., image of a single line from each image vs eV
IF (profile_direction EQ 0) THEN BEGIN	; use single row of image for profile
	IF (image_range EQ 0) THEN BEGIN	; scale profile image using range of each image
		profile_image = fltarr(n_rows,n_files)
		prof_byte_image = fltarr(n_rows,n_files)
		FOR i=0,n_files-1 DO BEGIN
			; create image ready for display including regions of interest
			zstack_analyze_imgprep,i,image
			zstack_analyze_bytescale, image, byte_image, do_byte_roi='no'
;			profile_image(*,(n_files-1-i)) = byte_image(*,profile_y_pixel)
			profile_image(*,(n_files-1-i)) = image[*,profile_y_pixel]
			prof_byte_image(*,(n_files-1-i)) = byte_image(*,profile_y_pixel)
		ENDFOR
;		byte_image = profile_image
;		byte_image = dummy
	ENDIF ELSE BEGIN	; scale profile image using range of entire image stack
		profile_image = fltarr(n_rows,n_files)
		FOR i=0,n_files-1 DO BEGIN
			profile_image(*,(n_files-1-i)) = image_stack(*,profile_y_pixel,i)
		ENDFOR

		; Scale profile image to fill gray scale range
		;	Important: This is NOT the same scale as image
		IF (image_range EQ 0) THEN BEGIN
			min_image = min(profile_image(where(finite(profile_image))))
			this_image = profile_image - min_image
			max_image = max(profile_image(where(finite(profile_image))))
		ENDIF ELSE BEGIN
			min_image = min(image_stack(where(finite(image_stack))))
			this_image = profile_image - min_image
			max_image = max(image_stack(where(finite(image_stack))))
		ENDELSE
		percent_image = 100. * this_image / max_image
		display_image = (( ((percent_image - disp_min) $
					/ ((disp_max - disp_min)^disp_gamma)) >0.)<1.)
		prof_byte_image = byte( float(bottom_color_index) + $
					float(top_color_index - bottom_color_index) * $
					display_image)
		; refill clipped edges of profile image 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(profile_image,/nan),count)
				IF (clipped_edge[0] NE -1) THEN prof_byte_image(clipped_edge) = image_blgd_color_index
			END
			'infinity' : BEGIN
			;	print,'bytescale edgefill : Infinity'
				clipped_edge = where(finite(profile_image,/infinity),count)
				IF (clipped_edge[0] NE -1) THEN prof_byte_image(clipped_edge) = image_blgd_color_index
			;	IF (clipped_edge[0] NE -1) THEN prof_byte_image(clipped_edge) = spectra_color_index(7)
			END
			ELSE : BEGIN
			;	print,'bytescale edgefill : else'
			END
		ENDCASE
	ENDELSE
ENDIF ELSE BEGIN					; use single column of image for profile
	IF (image_range EQ 0) THEN BEGIN	; scale profile image using range of each image
		profile_image = fltarr(n_files,n_cols)
		prof_byte_image = fltarr(n_files,n_cols)
		FOR i=0,n_files-1 DO BEGIN
			; create image ready for display including regions of interest
			zstack_analyze_imgprep,i,image
			zstack_analyze_bytescale, image, byte_image, do_byte_roi='no'
;			profile_image(i,*) = byte_image(profile_x_pixel,*)
			profile_image(i,*) = image[profile_x_pixel,*]
			prof_byte_image(i,*) = byte_image(profile_x_pixel,*)
		ENDFOR
;		byte_image = profile_image
;		byte_image = dummy
	ENDIF ELSE BEGIN	; scale profile image using range of entire image stack
		profile_image = fltarr(n_files,n_cols)
		FOR i=0,n_files-1 DO BEGIN
			profile_image(i,*) = image_stack(profile_x_pixel,*,i)
		ENDFOR

		; Scale profile image to fill gray scale range
		;	Important: This is NOT the same scale as image
		IF (image_range EQ 0) THEN BEGIN
			min_image = min(profile_image(where(finite(profile_image))))
			this_image = profile_image - min_image
			max_image = max(profile_image(where(finite(profile_image))))
		ENDIF ELSE BEGIN
			min_image = min(image_stack(where(finite(image_stack))))
			this_image = profile_image - min_image
			max_image = max(image_stack(where(finite(image_stack))))
		ENDELSE
		percent_image = 100. * this_image / max_image
		display_image = (( ((percent_image - disp_min) $
					/ ((disp_max - disp_min)^disp_gamma)) >0.)<1.)
		prof_byte_image = byte( float(bottom_color_index) + $
					float(top_color_index - bottom_color_index) * $
					display_image)
		; refill clipped edges of profile image 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(profile_image,/nan),count)
				IF (clipped_edge[0] NE -1) THEN prof_byte_image(clipped_edge) = image_blgd_color_index
			END
			'infinity' : BEGIN
			;	print,'bytescale edgefill : Infinity'
				clipped_edge = where(finite(profile_image,/infinity),count)
				IF (clipped_edge[0] NE -1) THEN prof_byte_image(clipped_edge) = image_blgd_color_index
			;	IF (clipped_edge[0] NE -1) THEN prof_byte_image(clipped_edge) = spectra_color_index(7)
			END
			ELSE : BEGIN
			;	print,'bytescale edgefill : else'
			END
		ENDCASE
	ENDELSE
ENDELSE
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_profdisp,byte_image
;print,'zstack_profile_profdisp'

@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

; Display profile image, i.e., image of a single line from each image vs eV
wset,zstack_profile_par.profile_image_win
; Prepare and display profile image, i.e., image of a single line from each image vs eV
IF (profile_direction EQ 0) THEN BEGIN	; use single row of image for profile
	xleft = fix( image_zoom*(profile_win_pixels - n_rows)/2.)
	xright = xleft + image_zoom*n_rows
	ybot = fix( image_zoom*(profile_win_pixels - profile_zoom*n_files)/2.)
	ytop = ybot + image_zoom*profile_zoom*n_files
	IF (image_zoom GE 1.0) THEN BEGIN
		IF ((image_zoom) EQ fix(image_zoom)) THEN BEGIN
			tv,rebin(byte_image,n_rows*image_zoom,n_files*image_zoom*profile_zoom,/sample), xleft ,ybot
		ENDIF ELSE BEGIN
			tv,congrid(byte_image,n_rows*image_zoom,n_files*image_zoom*profile_zoom),xleft ,ybot
		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_rows*image_zoom,n_files*image_zoom*profile_zoom,/sample), xleft ,ybot
		ENDIF ELSE BEGIN
			tv,congrid(byte_image,n_rows*image_zoom,n_files*image_zoom*profile_zoom),xleft ,ybot
		ENDELSE
	ENDELSE
	; Plot line indicating row used for intensity profile
	plots,xleft-1,ybot+(0.5+n_files-1-displayed_file_index)*image_zoom*profile_zoom, $
			/device,thick=2, color=profile_color_index
	plots,xright+1,ybot+(0.5+n_files-1-displayed_file_index)*image_zoom*profile_zoom, $
			/device,thick=2, color=profile_color_index,/continue

	; Plot line indicating cursor position along row used for intensity profile
	plots,xleft+profile_x_pixel*image_zoom,ybot-1,/device,color=profile_cursor_color_index
	plots,xleft+profile_x_pixel*image_zoom,ytop+1,/device,color=profile_cursor_color_index,/continue
	; Plot boundary lines showing edges (at top and bottom) of profile image
	plots,xleft-1,ytop+1,/device,color=image_border_color_index
	plots,xright+1,ytop+1,/device,color=image_border_color_index,/continue
	plots,xright+1,ybot-1,/device,color=image_border_color_index,/continue
	plots,xleft-1,ybot-1,/device,color=image_border_color_index,/continue
	plots,xleft-1,ytop+1,/device,color=image_border_color_index,/continue
ENDIF ELSE BEGIN					; use single column of image for profile
	xleft = fix( image_zoom*(profile_win_pixels - profile_zoom*n_files)/2.)
	xright = xleft + image_zoom*profile_zoom*n_files
	ybot = fix( image_zoom*(profile_win_pixels - n_cols)/2.)
	ytop = ybot + image_zoom*n_cols
	IF (image_zoom GE 1.0) THEN BEGIN
		IF ((image_zoom) EQ fix(image_zoom)) THEN BEGIN
			tv,rebin(byte_image,n_files*image_zoom*profile_zoom,n_cols*image_zoom,/sample), xleft, ybot
		ENDIF ELSE BEGIN
			tv,congrid(byte_image,n_files*image_zoom*profile_zoom,n_cols*image_zoom), xleft, ybot
		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_files*image_zoom*profile_zoom,n_cols*image_zoom,/sample), xleft, ybot
		ENDIF ELSE BEGIN
			tv,congrid(byte_image,n_files*image_zoom*profile_zoom,n_cols*image_zoom), xleft, ybot
		ENDELSE
	ENDELSE
	; Plot line indicating column used for intensity profile
	plots,xleft+(0.5+displayed_file_index)*image_zoom*profile_zoom,ybot-1, $
			/device, thick=2, color=profile_color_index
	plots,xleft+(0.5+displayed_file_index)*image_zoom*profile_zoom,ytop+1, $
			/device, thick=2, color=profile_color_index,/continue
	; Plot line indicating cursor position along column used for intensity profile
	plots,xleft-1,ybot+profile_y_pixel*image_zoom,/device,color=profile_cursor_color_index
	plots,xright+1,ybot+profile_y_pixel*image_zoom,/device,color=profile_cursor_color_index,/continue

	; Plot boundary lines showing edges (at left and right) of profile image
	plots,xleft-1,ytop+1,/device,color=image_border_color_index
	plots,xright+1,ytop+1,/device,color=image_border_color_index,/continue
	plots,xright+1,ybot-1,/device,color=image_border_color_index,/continue
	plots,xleft-1,ybot-1,/device,color=image_border_color_index,/continue
	plots,xleft-1,ytop+1,/device,color=image_border_color_index,/continue
ENDELSE
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_plotprofile,i_file
;print,'zstack_profile_plotprofile'

@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 intensity profile with cursor bar
IF (profile_direction EQ 0) THEN BEGIN	; use single row of image
	; Calculate minimum and maximum values of shift for plotting of cursor bar,  CGZ
	!x.range = [0,n_cols-1]
	!y.range = [0,1.05*max(profile_image(where(finite(profile_image))))]
;		min_image = min(image(where(finite(image))))
;print,'!y.range 1: ',!y.range
;	!y.range = [0,1.05*max(image_stack)]
	;  Create plot_x to use as x-axis coordinate corresponding to file number, CGZ
	plot_x = fltarr(n_cols)
	FOR i = 0,n_cols-1 DO BEGIN
		plot_x(i) = i
	ENDFOR
	; Plot axes and intensity profile
	wset,zstack_profile_par.profile_plot_win
	erase
	plot,profile_image[*,n_files-1-i_file],/nodata, $
			xtitle='Row #', ytitle='Image Intensity', ticklen = -0.02, $
			color=plot_axes_color_index, background=plot_bkgd_color_index
	; Plot line indicating row used for intensity profile
	IF (data_shifted EQ 1) THEN BEGIN
		; find clipped edges in profile and set to NaN
		;	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
		profile = profile_image[*,n_files-1-i_file]
		clipped_edge = where(profile EQ min(image_stack(*,*,i_file)),count)
		IF (clipped_edge(0) NE -1) THEN BEGIN
			profile(clipped_edge) = !values.f_nan
		ENDIF
	ENDIF ELSE BEGIN
		profile = profile_image[*,n_files-1-i_file]
	ENDELSE
;print,'profile 1: ',profile
	oplot,plot_x,profile,color=profile_color_index
	; Plot line indicating cursor position along row used for intensity profile
	oplot,profile_x_pixel+[0.,0.],!y.crange,color=profile_cursor_color_index
ENDIF ELSE BEGIN					; use single column of image
	; Calculate minimum and maximum values of shift for plotting of cursor bar,  CGZ
	!x.range = [0,n_rows-1]
	!y.range = [0,1.05*max(profile_image(where(finite(profile_image))))]
;print,'!y.range 2: ',!y.range
;	!y.range = [0,1.05*max(image_stack)]
	;  Create plot_x to use as x-axis coordinate corresponding to file number, CGZ
	plot_x = fltarr(n_rows)
	FOR i = 1,n_rows DO BEGIN
		plot_x(i-1) = i
	ENDFOR

	; Plot axes and intensity profile
	wset,zstack_profile_par.profile_plot_win
	erase
	plot,profile_image[i_file,*],/nodata, $
			xtitle='Column #', ytitle='Image Intensity', ticklen = -0.02, $
			color=plot_axes_color_index, background=plot_bkgd_color_index
	; Plot line indicating column used for intensity profile
	IF (data_shifted EQ 1) THEN BEGIN
		; find clipped edges in profile and set to NaN
		;	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
		profile = profile_image[i_file,*]
		clipped_edge = where(profile EQ min(image_stack(*,*,i_file)),count)
		IF (clipped_edge(0) NE -1) THEN BEGIN
			profile(clipped_edge) = !values.f_nan
		ENDIF
	ENDIF ELSE BEGIN
		profile = profile_image[i_file,*]
	ENDELSE
;print,'profile 2: ',profile
	oplot,plot_x,profile,color=profile_color_index
	; Plot line indicating cursor position along column used for intensity profile
	oplot,profile_y_pixel+[0.,0.],!y.crange,color=profile_cursor_color_index
ENDELSE
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_plotspectrum, i_file
;print,'zstack_profile_plotspectrum'

@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 (strupcase(!d.name) NE 'Z') THEN BEGIN
	wset,zstack_profile_par.spectra_plot_win
ENDIF ELSE BEGIN
	print,'Z profile'
ENDELSE
erase
;dummy = where(spectrum NE 0,count)	; if no spectra exist, leave window erased
;IF (count EQ 0) THEN BEGIN
;	return
;ENDIF
; Determine range of x-values in plot
IF (x_autoscale EQ 1)	 THEN BEGIN	; autoscale x-axis
	!x.range = [min(ev_list),max(ev_list)]
ENDIF ELSE BEGIN
	!x.range = [plot_x_min, plot_x_max]
ENDELSE
x_index = where(ev_list GE !x.range[0] AND ev_list LE !x.range[1], count)
; Determine single beam spectrum of pixel selected in image profile
profile_spectrum = reform(image_stack(profile_x_pixel,profile_y_pixel,*))
; clip edges of profile spectrum to reflect clipped edges of aligned images
IF (data_shifted EQ 1) THEN BEGIN
	; find clipped edges in profile and set to NaN
	;	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
;	profile_spectrum = reform(profile_spectrum)
	clipped_edge = profile_spectrum
	FOR i=0,n_files-1 DO BEGIN
		clipped_edge(i) = profile_spectrum(i) EQ min(image_stack(*,*,i))
	ENDFOR
	clipped_edge = clipped_edge * indgen(n_elements(clipped_edge))
	dummy = where(clipped_edge NE 0,count)
	IF (count NE 0) THEN BEGIN
		clipped_edge = clipped_edge(dummy)
		profile_spectrum(clipped_edge) = !values.f_nan
	ENDIF
ENDIF
; should alter to work with range within plot_x_min and plot_x_max
	; have to establish limits of index of ev_list: i_min, i_max
; Find y limits of all potential profile spectra
IF (profile_y_max EQ 0) THEN BEGIN
		CASE spectrum_display OF	; Single Beam vs Percent Transmittance vs Absorbance
			1 : BEGIN		; single beam spectra
				dummy = image_stack(*,*,x_index)
				profile_y_min = min(dummy(where(finite(dummy))), max=profile_y_max, subscript)
				p_spectrum_y_min = min(spectrum[0,x_index], max=p_spectrum_y_max)
				y_min = profile_y_min
				y_max = profile_y_max
			END
			2 : BEGIN		; percent transmittance spectra
				dummy = where(spectrum[0,*] NE 0,count)
				IF (count NE 0) THEN BEGIN	; if i0 spectrum exists
					FOR i=0,n_elements(x_index)-1 DO BEGIN
						IF (finite(spectrum[0,i]) EQ 1) THEN BEGIN
							dummy = 100.*(image_stack(*,*,x_index(i))/spectrum[0,x_index(i)])
							profile_y_min = min(dummy(where(finite(dummy))), max=profile_y_max, subscript)
							IF (i EQ 0) THEN BEGIN
								y_min = profile_y_min
								y_max = profile_y_max
							ENDIF
							IF (profile_y_min LT y_min) THEN y_min = profile_y_min
							IF (profile_y_max GT y_max) THEN y_max = profile_y_max
						ENDIF
					ENDFOR
				ENDIF ELSE BEGIN	; if i0 spectrum does not exist
					dummy = image_stack(*,*,x_index)
					profile_y_min = min(dummy(where(finite(dummy))), max=profile_y_max, subscript)
					y_min = profile_y_min
					y_max = profile_y_max
				ENDELSE
			END
			3 : BEGIN		; absorbance spectra
				dummy = where(spectrum[0,*] NE 0,count)
				IF (count NE 0) THEN BEGIN	; if i0 spectrum exists
					FOR i=0,n_elements(x_index)-1 DO BEGIN
						IF (finite(spectrum[0,i]) EQ 1) THEN BEGIN
							dummy = -alog(image_stack(*,*,x_index(i))/spectrum[0,x_index(i)])
							profile_y_min = min(dummy(where(finite(dummy))), max=profile_y_max, subscript)
							IF (i EQ 0) THEN BEGIN
								y_min = profile_y_min
								y_max = profile_y_max
							ENDIF
							IF (profile_y_min LT y_min) THEN y_min = profile_y_min
							IF (profile_y_max GT y_max) THEN y_max = profile_y_max
						ENDIF
					ENDFOR
				ENDIF ELSE BEGIN	; if i0 spectrum does not exist
					dummy = image_stack(*,*,x_index)
					profile_y_min = min(dummy(where(finite(dummy))), max=profile_y_max, subscript)
					y_min = profile_y_min
					y_max = profile_y_max
				ENDELSE
			END
			ELSE : BEGIN
				print,'spectrum_display not specified'
			END
		ENDCASE
ENDIF
; profile_y_min and profile_y_max are the minimum and maximum values of all potential profile spectra
; i.e., the range in intensity of all profile spectra
;profile_y_min = 0
;profile_y_max = 0
;profile_spectrum = fltarr(n_files)
;profile_y_min = 0.1
;profile_y_max = 0.1
;profile_spectrum = make_array(n_files, /float, value = 0.1)
; Calculate spectra (Single Beam vs Percent Transmittance vs Absorbance)
; Add in offset
CASE spectrum_display OF	; Single Beam vs Percent Transmittance vs Absorbance
	1 : BEGIN		; plot single beam spectra
		dummy = where(spectrum[0,*] NE 0,count)
		IF (count NE 0) THEN BEGIN	; if i0 spectrum exists
			dummy = where(spectrum[1:14,*] NE 0,count)
			IF (count GT 0) THEN BEGIN	; if both i0 and some i spectra exist
;				print,'SB :  SB, i0, i, profile'
				spectra = spectrum[0:n_roi,*]				; [i0,i1,i2,i3,...]
				IF (spectrum_offset NE 0) THEN BEGIN	; add in offset to spectra
					FOR i=0,n_roi DO BEGIN
						spectra[i,*] = (spectrum_offset * (i+1)) + spectra[i,*]
					ENDFOR
					dummy = spectra[0:n_roi,*]
					y_min = min(dummy[where(finite(dummy))],max=y_max)
					y_min = (1.05 * y_max) < (0.95 * y_min)
					y_max = (1.05 * y_max) > (0.95 * y_min)
					IF (y_min LT profile_y_min) THEN  profile_y_min = y_min
					IF (y_max GT profile_y_max) THEN  profile_y_max = y_max
				ENDIF
				IF (y_autoscale EQ 1) THEN BEGIN	; autoscale y-axis
					!y.range = [profile_y_min,profile_y_max]
					!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])
				ENDIF ELSE BEGIN
					!y.range = [plot_y_min, plot_y_max]
				ENDELSE
				plot,ev_list,spectra,/nodata, $
						xtitle='eV',ytitle='Single Beam Intensity', $
						xtick_get = xticks, ytick_get = yticks, $
						color=plot_axes_color_index, background=plot_bkgd_color_index
				FOR i=0,n_roi DO BEGIN
					oplot,ev_list,spectra[i,*],color=spectra_color_index(i)
				ENDFOR
				oplot,ev_list,profile_spectrum,color=plot_axes_color_index
				IF (spectrum_offset NE 0) THEN BEGIN	; plot offset label
					label = 'Offset = '+strtrim(string(spectrum_offset,format='(f10.2)'),2)
					xyouts,5,5, /device, color=plot_axes_color_index, charthick=1, $
							alignment=0.0,label
				ENDIF
			ENDIF ELSE BEGIN	; if only i0 spectrum exists
;				print,'SB :  SB, i0,  , profile'
				IF (y_autoscale EQ 1) THEN BEGIN	; autoscale y-axis
					!y.range = [profile_y_min,profile_y_max]
					!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])
				ENDIF ELSE BEGIN
					!y.range = [plot_y_min, plot_y_max]
				ENDELSE
				plot,ev_list,spectrum[0,*],/nodata,xtitle='eV',ytitle='Single Beam Intensity', $
						xtick_get = xticks, ytick_get = yticks, $
						color=plot_axes_color_index, background=plot_bkgd_color_index
				oplot,ev_list,spectrum[0,*]+spectrum_offset,color=spectra_color_index(0)
				oplot,ev_list,profile_spectrum,color=plot_axes_color_index
			ENDELSE
		ENDIF ELSE BEGIN	; if i0 spectrum does not exist
			dummy = where(spectrum[1:14,*] NE 0,count)
			IF (count EQ 0) THEN BEGIN	; if no i spectrum exist
;				print,'SB : SB,   ,  , profile'
				IF (y_autoscale EQ 1) THEN BEGIN	; autoscale y-axis
					!y.range = [profile_y_min,profile_y_max]
					!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])
				ENDIF ELSE BEGIN
					!y.range = [plot_y_min, plot_y_max]
				ENDELSE
				plot,ev_list,profile_spectrum,/nodata,xtitle='eV',ytitle='Single Beam Intensity', $
						xtick_get = xticks, ytick_get = yticks, $
						color=plot_axes_color_index, background=plot_bkgd_color_index
				oplot,ev_list,profile_spectrum,color=plot_axes_color_index
			ENDIF ELSE BEGIN; if some i spectra exist
;				print,'SB : SB,   , i, profile'
				spectra = spectrum[1:n_roi,*]				; [i1,i2,i3,...]
				IF (spectrum_offset NE 0) THEN BEGIN	; add in offset to spectra
					FOR i=1,n_roi-1 DO BEGIN
						spectra[i,*] = (spectrum_offset * (i)) + spectra[i,*]
					ENDFOR
					dummy = spectra[1:n_roi-1,*]
					y_min = min(dummy[where(finite(dummy))],max=y_max)
					y_min = (1.05 * y_max) < (0.95 * y_min)
					y_max = (1.05 * y_max) > (0.95 * y_min)
					IF (y_min LT profile_y_min) THEN  profile_y_min = y_min
					IF (y_max GT profile_y_max) THEN  profile_y_max = y_max
				ENDIF
				IF (y_autoscale EQ 1) THEN BEGIN	; autoscale y-axis
					!y.range = [profile_y_min,profile_y_max]
					!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])
				ENDIF ELSE BEGIN
					!y.range = [plot_y_min, plot_y_max]
				ENDELSE
				plot,ev_list,spectra,/nodata, $
						xtitle='eV',ytitle='Single Beam Intensity', $
						xtick_get = xticks, ytick_get = yticks, $
						color=plot_axes_color_index, background=plot_bkgd_color_index
				FOR i=0,n_roi-1 DO BEGIN
					oplot,ev_list,spectra[i,*],color=spectra_color_index(i+1)
				ENDFOR
				oplot,ev_list,profile_spectrum,color=plot_axes_color_index
				IF (n_roi GT 1) AND (spectrum_offset NE 0) THEN BEGIN	; plot offset label
						label = 'Offset = '+strtrim(string(spectrum_offset,format='(f10.2)'),2)
						xyouts,5,5, /device, color=plot_axes_color_index, charthick=1, $
								alignment=0.0,label
				ENDIF
			ENDELSE
		ENDELSE
	END
	2 : BEGIN		; plot percent transmittance spectra
		dummy = where(spectrum[0,*] NE 0,count)
		IF (count NE 0) THEN BEGIN	; if i0 spectrum exists
			temp_profile_spectrum = 100.*(profile_spectrum / spectrum[0,*])
			dummy = where(spectrum[1:14,*] NE 0,count)
			IF (count GT 0) THEN BEGIN	; if both i0 and some i spectra exist
;				print,'TXM: TXM,   , i, profile'
				spectra = fltarr(n_roi,n_files)
				FOR i=1,n_roi DO BEGIN	; calculate percent transmittance spectra
					spectra[i-1,*] = 100.*spectrum[i,*]/spectrum[0,*]	; [i1/i0,i2/i0,i3/i0,...]
				ENDFOR
				IF (spectrum_offset NE 0) THEN BEGIN	; add in offset to spectra
					FOR i=0,n_roi-1 DO BEGIN
						spectra[i,*] = (spectrum_offset * (i+1)) + spectra[i,*]
					ENDFOR
					dummy = spectra[0:n_roi-1,*]
					y_min = min(dummy[where(finite(dummy))],max=y_max)
					y_min = (1.05 * y_max) < (0.95 * y_min)
					y_max = (1.05 * y_max) > (0.95 * y_min)
					IF (y_min LT profile_y_min) THEN  profile_y_min = y_min
					IF (y_max GT profile_y_max) THEN  profile_y_max = y_max
				ENDIF
				IF (y_autoscale EQ 1) THEN BEGIN	; autoscale y-axis
					!y.range = [profile_y_min,profile_y_max]
					!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])
				ENDIF ELSE BEGIN
					!y.range = [plot_y_min, plot_y_max]
				ENDELSE
				plot,ev_list,spectra,/nodata, $
						xtitle='eV',ytitle='Percent Tranmittance', $
						xtick_get = xticks, ytick_get = yticks, $
						color=plot_axes_color_index, background=plot_bkgd_color_index
				FOR i=0,n_roi-1 DO BEGIN
					oplot,ev_list,spectra[i,*],color=spectra_color_index(i+1)
				ENDFOR
				oplot,ev_list,temp_profile_spectrum,color=plot_axes_color_index
				IF (spectrum_offset NE 0) THEN BEGIN	; plot offset label
					label = 'Offset = '+strtrim(string(spectrum_offset,format='(f10.2)'),2)
					xyouts,5,5, /device, color=plot_axes_color_index, charthick=1, $
							alignment=0.0,label
				ENDIF
			ENDIF ELSE BEGIN	; if only i0 spectrum exists
;				print,'TXM: TXM,   ,  , profile'
				IF (y_autoscale EQ 1) THEN BEGIN	; autoscale y-axis
					!y.range = [profile_y_min,profile_y_max]
					!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])
				ENDIF ELSE BEGIN
					!y.range = [plot_y_min, plot_y_max]
				ENDELSE
				plot,ev_list,spectrum[0,*],/nodata,xtitle='eV',ytitle='Percent Transmittance', $
						xtick_get = xticks, ytick_get = yticks, $
						color=plot_axes_color_index, background=plot_bkgd_color_index
				oplot,ev_list,spectrum[0,*]+spectrum_offset,color=spectra_color_index(0)
				oplot,ev_list,temp_profile_spectrum,color=plot_axes_color_index
			ENDELSE
		ENDIF ELSE BEGIN	; if i0 spectrum does not exist
			dummy = where(spectrum[1:14,*] NE 0,count)
			IF (count EQ 0) THEN BEGIN	; if no i spectrum exist
;				print,'TXM: SB,   ,  , profile'
				IF (y_autoscale EQ 1) THEN BEGIN	; autoscale y-axis
					!y.range = [profile_y_min,profile_y_max]
					!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])
				ENDIF ELSE BEGIN
					!y.range = [plot_y_min, plot_y_max]
				ENDELSE
				plot,ev_list,profile_spectrum,/nodata,xtitle='eV',ytitle='Single Beam Intensity', $
						xtick_get = xticks, ytick_get = yticks, $
						color=plot_axes_color_index, background=plot_bkgd_color_index
				oplot,ev_list,profile_spectrum,color=plot_axes_color_index
			ENDIF ELSE BEGIN; if some i spectra exist
;				print,'TXM: SB,   , i, profile'
				spectra = spectrum[1:n_roi,*]				; [i1,i2,i3,...]
				IF (spectrum_offset NE 0) THEN BEGIN	; add in offset to spectra
					FOR i=1,n_roi-1 DO BEGIN
						spectra[i,*] = (spectrum_offset * (i)) + spectra[i,*]
					ENDFOR
					dummy = spectra[0:n_roi-1,*]
					y_min = min(dummy[where(finite(dummy))],max=y_max)
					y_min = (1.05 * y_max) < (0.95 * y_min)
					y_max = (1.05 * y_max) > (0.95 * y_min)
					IF (y_min LT profile_y_min) THEN  profile_y_min = y_min
					IF (y_max GT profile_y_max) THEN  profile_y_max = y_max
				ENDIF
				IF (y_autoscale EQ 1) THEN BEGIN	; autoscale y-axis
					!y.range = [profile_y_min,profile_y_max]
					!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])
				ENDIF ELSE BEGIN
					!y.range = [plot_y_min, plot_y_max]
				ENDELSE
				plot,ev_list,spectra,/nodata, $
						xtitle='eV',ytitle='Single Beam Intensity', $
						xtick_get = xticks, ytick_get = yticks, $
						color=plot_axes_color_index, background=plot_bkgd_color_index
				FOR i=0,n_roi-1 DO BEGIN
					oplot,ev_list,spectra[i,*],color=spectra_color_index(i+1)
				ENDFOR
				oplot,ev_list,profile_spectrum,color=plot_axes_color_index
				IF (n_roi GT 1) AND (spectrum_offset NE 0) THEN BEGIN	; plot offset label
						label = 'Offset = '+strtrim(string(spectrum_offset,format='(f10.2)'),2)
						xyouts,5,5, /device, color=plot_axes_color_index, charthick=1, $
								alignment=0.0,label
				ENDIF
			ENDELSE
		ENDELSE
	END
	3 : BEGIN		; plot absorbance spectra
		dummy = where(spectrum[0,*] NE 0,count)
		IF (count NE 0) THEN BEGIN	; if i0 spectrum exists
			temp_profile_spectrum = - alog(profile_spectrum / spectrum[0,*])
			dummy = where(spectrum[1:14,*] NE 0,count)
			IF (count GT 0) THEN BEGIN	; if both i0 and some i spectra exist
;				print,'ABS: ABS,   , i, profile'
				spectra = fltarr(n_roi,n_files)
				FOR i=1,n_roi DO BEGIN	; calculate absorbance spectra
					spectra[i-1,*] = -alog(spectrum[i,*]/spectrum[0,*])	; [i1/i0,i2/i0,i3/i0,...]
				ENDFOR
				IF (spectrum_offset NE 0) THEN BEGIN	; add in offset to spectra
					FOR i=0,n_roi-1 DO BEGIN
						spectra[i,*] = (spectrum_offset * (i+1)) + spectra[i,*]
					ENDFOR
				ENDIF
					dummy = spectra[0:n_roi-1,*]
					y_min = min(dummy[where(finite(dummy))],max=y_max)
					y_min = (1.05 * y_max) < (0.95 * y_min)
					y_max = (1.05 * y_max) > (0.95 * y_min)
;	print,'1 y_min, y_max : ', y_min, y_max
					IF (y_min LT profile_y_min) THEN  profile_y_min = y_min
					IF (y_max GT profile_y_max) THEN  profile_y_max = y_max
;	print,'2 y_min, y_max : ', y_min, y_max
;	print,'3 y_min, y_max : ', profile_y_min, profile_y_max
;				ENDIF
				IF (y_autoscale EQ 1) THEN BEGIN	; autoscale y-axis
					!y.range = [profile_y_min,profile_y_max]
					!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])
				ENDIF ELSE BEGIN
					!y.range = [plot_y_min, plot_y_max]
				ENDELSE
				plot,ev_list,spectra,/nodata, $
						xtitle='eV',ytitle='Absorbance', $
						xtick_get = xticks, ytick_get = yticks, $
						color=plot_axes_color_index, background=plot_bkgd_color_index
				FOR i=0,n_roi-1 DO BEGIN
					oplot,ev_list,spectra[i,*],color=spectra_color_index(i+1)
				ENDFOR
				oplot,ev_list,temp_profile_spectrum,color=plot_axes_color_index
				IF (spectrum_offset NE 0) THEN BEGIN	; plot offset label
					label = 'Offset = '+strtrim(string(spectrum_offset,format='(f10.2)'),2)
					xyouts,5,5, /device, color=plot_axes_color_index, charthick=1, $
							alignment=0.0,label
				ENDIF
			ENDIF ELSE BEGIN	; if only i0 spectrum exists
;				print,'ABS: ABS,   ,  , profile'
				IF (y_autoscale EQ 1) THEN BEGIN	; autoscale y-axis
					!y.range = [profile_y_min,profile_y_max]
					!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])
				ENDIF ELSE BEGIN
					!y.range = [plot_y_min, plot_y_max]
				ENDELSE
				plot,ev_list,spectrum[0,*],/nodata,xtitle='eV',ytitle='Absorbance', $
						xtick_get = xticks, ytick_get = yticks, $
						color=plot_axes_color_index, background=plot_bkgd_color_index
				oplot,ev_list,spectrum[0,*]+spectrum_offset,color=spectra_color_index(0)
				oplot,ev_list,temp_profile_spectrum,color=plot_axes_color_index
			ENDELSE
		ENDIF ELSE BEGIN	; if i0 spectrum does not exist
			dummy = where(spectrum[1:14,*] NE 0,count)
			IF (count EQ 0) THEN BEGIN	; if no i spectrum exist
;				print,'ABS: SB,   ,  , profile'
				IF (y_autoscale EQ 1) THEN BEGIN	; autoscale y-axis
					!y.range = [profile_y_min,profile_y_max]
					!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])
				ENDIF ELSE BEGIN
					!y.range = [plot_y_min, plot_y_max]
				ENDELSE
				plot,ev_list,profile_spectrum,/nodata,xtitle='eV',ytitle='Single Beam Intensity', $
						xtick_get = xticks, ytick_get = yticks, $
						color=plot_axes_color_index, background=plot_bkgd_color_index
				oplot,ev_list,profile_spectrum,color=plot_axes_color_index
			ENDIF ELSE BEGIN; if some i spectra exist
;				print,'ABS: SB,   , i, profile'
				spectra = spectrum[1:n_roi,*]				; [i1,i2,i3,...]
				IF (spectrum_offset NE 0) THEN BEGIN	; add in offset to spectra
					FOR i=1,n_roi-1 DO BEGIN
						spectra[i,*] = (spectrum_offset * (i)) + spectra[i,*]
					ENDFOR
					dummy = spectra[0:n_roi-1,*]
					y_min = min(dummy[where(finite(dummy))],max=y_max)
					y_min = (1.05 * y_max) < (0.95 * y_min)
					y_max = (1.05 * y_max) > (0.95 * y_min)
					IF (y_min LT profile_y_min) THEN  profile_y_min = y_min
					IF (y_max GT profile_y_max) THEN  profile_y_max = y_max
				ENDIF
				IF (y_autoscale EQ 1) THEN BEGIN	; autoscale y-axis
					!y.range = [profile_y_min,profile_y_max]
					!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])
				ENDIF ELSE BEGIN
					!y.range = [plot_y_min, plot_y_max]
				ENDELSE
				plot,ev_list,spectra,/nodata, $
						xtitle='eV',ytitle='Single Beam Intensity', $
						xtick_get = xticks, ytick_get = yticks, $
						color=plot_axes_color_index, background=plot_bkgd_color_index
				FOR i=0,n_roi-1 DO BEGIN
					oplot,ev_list,spectra[i,*],color=spectra_color_index(i+1)
				ENDFOR
				oplot,ev_list,profile_spectrum,color=plot_axes_color_index
				IF (n_roi GT 1) AND (spectrum_offset NE 0) THEN BEGIN	; plot offset label
					label = 'Offset = '+strtrim(string(spectrum_offset,format='(f10.2)'),2)
					xyouts,5,5, /device, color=plot_axes_color_index, charthick=1, $
							alignment=0.0,label
				ENDIF
			ENDELSE
		ENDELSE
	END
	ELSE : BEGIN
		print,'spectrum_display not specified'
	END
ENDCASE
!x.range = [min(xticks),max(xticks)]
!y.range = [min(yticks),max(yticks)]
;	print,'2 !y.range : ',!y.range
IF (ev_list(i_file) GT !x.range[0]) AND (ev_list(i_file) LT !x.range[1]) THEN BEGIN
	plots,ev_list(i_file)+[0.,0.],!y.crange,color=spectra_cursor_color_index
ENDIF
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_read_shift,stack_align_filename
;print,'zstack_profile_read_shift'

@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 using a file of shifts from a previous alignment
; What we want to do is to read in the shifts and apply them.
zstack_read_mapper,stack_align_filename, indices, shifts, parameters
x_shift = shifts(0,*)
y_shift = shifts(1,*)
shifted_image_stack = image_stack
; 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 to stored shift values'
	file_num = fltarr(n_files)
	FOR i=0,(n_files-1) DO BEGIN
		xcenter = x_shift(i)
		ycenter = y_shift(i)
		IF ((abs(xcenter) GT 0.2) OR (abs(ycenter) GT 0.2)) THEN BEGIN
			zstack_shift,image_stack(*,*,i),x_shift(i),y_shift(i), $
					shifted_image,edgefill='minfill'
			shifted_image_stack(*,*,i) = shifted_image
		ENDIF
		file_num(i) = strmid(strtrim(filename_list(i),2),5,3)
	ENDFOR
	data_shifted = 2
	image_stack = shifted_image_stack

ENDIF ELSE BEGIN
	print,string(7B),'File sizes do not match - can not apply shifts',string(7B)
ENDELSE
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_readfile,stackdata_filename
;print,'zstack_profile_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_oops
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_oops :
print,'Error reading stack data file "'+stackdata_filename+'"'
close,lun
free_lun,lun
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_linescan_filename,i_file
;print,'zstack_profile_linescan_filename'

@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 ( (strlen(strtrim(profile_filename_header,2)) EQ 0) AND (strlen(list_filename) NE 0) )THEN BEGIN
	profile_filename_header = str_sep(list_filename,'.')
	profile_filename_header = profile_filename_header(0)
	widget_control, zstack_profile_par.profile_base_filename_label, set_value = ' '+profile_filename_header
	num = profile_filename_header
ENDIF ELSE BEGIN
	num = profile_filename_header
ENDELSE
CASE profile_direction OF	; add X or Y notation and column/row number
	0:	BEGIN
		num = num + '_Y'
		CASE strlen(strtrim(profile_y_pixel,2)) OF
			1:	num = num + '00'+strtrim(profile_y_pixel,2)
			2:	num = num + '0'+strtrim(profile_y_pixel,2)
			3:	num = num + strtrim(profile_y_pixel,2)
			ELSE:	num = num + strtrim(profile_y_pixel,2)
		ENDCASE
	END
	1:	BEGIN
		num = num + '_X'
		CASE strlen(strtrim(profile_x_pixel,2)) OF
			1:	num = num + '00'+strtrim(profile_x_pixel,2)
			2:	num = num + '0'+strtrim(profile_x_pixel,2)
			3:	num = num + strtrim(profile_x_pixel,2)
			ELSE:	num = num + strtrim(profile_x_pixel,2)
		ENDCASE
	END
ENDCASE
profile_filename = num + '.pfl'
widget_control, zstack_profile_par.profile_filename_label, $
			set_value = ' '+profile_filename
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_save_profile, filename
;print,'zstack_profile_save_profile'

@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_profile_save_profile_oops
widget_control, hourglass=1
get_lun,lun
openw,lun,filename
; Plot intensity profile with cursor bar
IF (profile_direction EQ 0) THEN BEGIN	; use single row of image
	printf,lun,'! Profile Intensity from Row '+strtrim(profile_y_pixel,2)+' of Image '+filename_list(displayed_file_index)
	IF (data_shifted EQ 1) THEN BEGIN
		printf,lun,'! Data aligned and shifted : '+list_filename+', '+shift_filename
		IF (list_filename EQ '') THEN BEGIN
			printf,lun,'! ',filename_list
		ENDIF
		IF (shift_filename EQ '') THEN BEGIN
			printf,lun,'! X shifts :',x_shift
			printf,lun,'! Y shifts :',y_shift
		ENDIF
	ENDIF ELSE BEGIN
		printf,lun,'! Raw data - unaligned : '+list_filename
		IF (list_filename EQ '') THEN BEGIN
			printf,lun,'! ',filename_list
		ENDIF
	ENDELSE
	printf,lun,'! Column, Intensity
	FOR i = 0,n_cols-1 DO BEGIN
		printf,lun,strtrim(string(i),2)+','+$
			strtrim(string(profile_image[i,n_files-1-displayed_file_index]),2)
	ENDFOR
ENDIF ELSE BEGIN	; use single column of images
	printf,lun,'! Profile Intensity from Column '+strtrim(profile_x_pixel,2)+' of Image '+filename_list(displayed_file_index)
	IF (data_shifted EQ 1) THEN BEGIN
		printf,lun,'! Data aligned and shifted : '+list_filename+', '+shift_filename
		IF (list_filename EQ '') THEN BEGIN
			printf,lun,'! ',filename_list
		ENDIF
		IF (shift_filename EQ '') THEN BEGIN
			printf,lun,'! X shifts :',x_shift
			printf,lun,'! Y shifts :',y_shift
		ENDIF
	ENDIF ELSE BEGIN
		printf,lun,'! Raw data - unaligned : '+list_filename
		IF (list_filename EQ '') THEN BEGIN
			printf,lun,'! ',filename_list
		ENDIF
	ENDELSE
	printf,lun,'! Row, Intensity
	FOR i = 0,n_rows-1 DO BEGIN
		printf,lun,strtrim(string(i),2)+','+$
			strtrim(string(profile_image[displayed_file_index,i]),2)
	ENDFOR
ENDELSE
print,'Wrote profile intensity to file "'+data_directory+filename+'"'
zstack_profile_save_profile_oops :
widget_control, hourglass=0
close,lun
free_lun,lun
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_spectrum_filename, i_file
;print,'zstack_profile_spectrum_filename'

@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 ( (strlen(strtrim(spectrum_filename_header,2)) EQ 0) AND (strlen(list_filename) NE 0) )THEN BEGIN
	spectrum_filename_header = str_sep(list_filename,'.')
	spectrum_filename_header = spectrum_filename_header(0)
	widget_control, zstack_profile_par.spectra_base_filename_label, set_value = ' '+spectrum_filename_header
	num = spectrum_filename_header
ENDIF ELSE BEGIN
	num = spectrum_filename_header
ENDELSE
numx = '_X'
CASE strlen(strtrim(profile_x_pixel,2)) OF
	1:	numx = numx + '00'+strtrim(profile_x_pixel,2)
	2:	numx = numx + '0'+strtrim(profile_x_pixel,2)
	3:	numx = numx + strtrim(profile_x_pixel,2)
	ELSE:	numx = numx + strtrim(profile_x_pixel,2)
ENDCASE
numy = '_Y'
CASE strlen(strtrim(profile_y_pixel,2)) OF
	1:	numy = numy + '00'+strtrim(profile_y_pixel,2)
	2:	numy = numy + '0'+strtrim(profile_y_pixel,2)
	3:	numy = numy + strtrim(profile_y_pixel,2)
	ELSE:	numy = numy + strtrim(profile_y_pixel,2)
ENDCASE
IF (profile_direction EQ 0) THEN BEGIN	; use single row of image
	spectra_filename = num + numx + '.spc'
	widget_control, zstack_profile_par.spectra_filename_label, $
			set_value = ' '+spectra_filename
ENDIF ELSE BEGIN
	spectra_filename = num + numy + '.spc'
	widget_control, zstack_profile_par.spectra_filename_label, $
			set_value = ' '+spectra_filename
ENDELSE
spectrum_filename = num + numx + numy + '.spc'
widget_control, zstack_profile_par.spectrum_filename_label, $
			set_value = ' '+spectrum_filename
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_save_profile_spectra, filename
;print,'zstack_profile_save_profile_spectra'

@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

; generate variable with spectra for each pixel in linescan
; if I0 exists, ratio to create absorbance   (change file header to note this)
; ??? display spectra in real time as a function of pixel position
; need to update profile display with scrolling bar
; move 'addition to core' to zstack_profile_plotspectrum
init_x_pixel = profile_x_pixel
init_y_pixel = profile_y_pixel
;profile_spectrum = fltarr(n_files)
get_lun,lun
widget_control, hourglass=1
on_ioerror,zstack_profile_save_profile_spectra_oops
print,'n_cols = ',n_cols
IF (profile_direction EQ 0) THEN BEGIN	; use single row of image
	temp_array = fltarr(n_files,n_cols)
	print,'Writing set of linescan spectra to file "'+filename+'"'
	openw,lun,filename, width=2000
	printf,lun,'! Spectrum from Columns (X) 0 to '+strtrim(n_cols-1,2)+ $
					' and Row (Y) '+strtrim(profile_y_pixel,2)
	IF (data_shifted EQ 1) THEN BEGIN
		printf,lun,'! Data aligned and shifted : '+list_filename+', '+shift_filename
		IF (list_filename EQ '') THEN BEGIN
			printf,lun,'! ',filename_list
		ENDIF
		IF (shift_filename EQ '') THEN BEGIN
			printf,lun,'! X shifts :',x_shift
			printf,lun,'! Y shifts :',y_shift
		ENDIF
	ENDIF ELSE BEGIN
		printf,lun,'! Raw data - unaligned : '+list_filename
		IF (list_filename EQ '') THEN BEGIN
			printf,lun,'! ',filename_list
		ENDIF
	ENDELSE
	dummy = where(spectrum[0,*] NE 0,count)
	IF (count NE 0) THEN BEGIN	; if i0 spectrum exists, use absorbance spectrum
		printf,lun,'! Energy, Absorbance'
	ENDIF ELSE BEGIN
		printf,lun,'! Energy, Intensity'
	ENDELSE
	FOR j = 0,n_cols-1 DO BEGIN
		profile_x_pixel = j
		zstack_profile_imgdisp,displayed_file_index
;		zstack_profile_profprep,byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_plotspectrum, displayed_file_index
		temp_array[*,j] = reform(transpose(profile_spectrum))
	ENDFOR
	dummy = strtrim(string(ev_list),2) + [replicate(',',n_elements(ev_list)-1),'']
	printf,lun,['Energy , ', dummy]
	FOR j = 0,n_cols-1 DO BEGIN
		dummy = strtrim(string(temp_array[*,j]),2) + $
				[replicate(',',n_elements(temp_array[*,j])-1),'']
		printf,lun,['Pixel ' + strtrim(string(j),2) + ', ', dummy]
	ENDFOR
ENDIF ELSE BEGIN	; use single column of image
	temp_array = fltarr(n_files,n_rows)
	print,'Writing set of linescan spectra to file "'+filename+'"'
	openw,lun,filename, width=2000
	printf,lun,'! Spectrum from Rows (Y) 0 to '+strtrim(n_rows-1,2)+ $
					' and Column (X) '+strtrim(profile_x_pixel,2)
	IF (data_shifted EQ 1) THEN BEGIN
		printf,lun,'! Data aligned and shifted : '+list_filename+', '+shift_filename
		IF (list_filename EQ '') THEN BEGIN
			printf,lun,'! ',filename_list
		ENDIF
		IF (shift_filename EQ '') THEN BEGIN
			printf,lun,'! X shifts :',x_shift
			printf,lun,'! Y shifts :',y_shift
		ENDIF
	ENDIF ELSE BEGIN
		printf,lun,'! Raw data - unaligned : '+list_filename
		IF (list_filename EQ '') THEN BEGIN
			printf,lun,'! ',filename_list
		ENDIF
	ENDELSE
	dummy = where(spectrum[0,*] NE 0,count)
	IF (count NE 0) THEN BEGIN	; if i0 spectrum exists, use absorbance spectrum
		printf,lun,'! Energy, Absorbance'
	ENDIF ELSE BEGIN
		printf,lun,'! Energy, Intensity'
	ENDELSE
	FOR j = 0,n_rows-1 DO BEGIN
		profile_y_pixel = j
		zstack_profile_imgdisp,displayed_file_index
;		zstack_profile_profprep,byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_plotspectrum, displayed_file_index
		temp_array[*,j] = reform(transpose(profile_spectrum))
	ENDFOR
	dummy = strtrim(string(ev_list),2) + [replicate(',',n_elements(ev_list)-1),'']
	printf,lun,['Energy , ', dummy]
	FOR j = 0,n_cols-1 DO BEGIN
		dummy = strtrim(string(temp_array[*,j]),2) + $
				[replicate(',',n_elements(temp_array[*,j])-1),'']
		printf,lun,['Pixel ' + strtrim(string(j),2) + ', ', dummy]
	ENDFOR
ENDELSE
print,'Wrote multiple profile spectra to file "'+data_directory+filename+'"'
zstack_profile_save_profile_spectra_oops :
widget_control, hourglass=0
close,lun
free_lun,lun
profile_x_pixel = init_x_pixel
profile_y_pixel = init_y_pixel
zstack_profile_imgdisp,displayed_file_index
;zstack_profile_profprep,byte_image
zstack_profile_profdisp,profile_byte_image
zstack_profile_plotprofile, displayed_file_index
zstack_profile_plotspectrum, displayed_file_index
zstack_profile_spectrum_filename,displayed_file_index
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_save_pixel_spectra, filename
;print,'zstack_profile_save_pixel_spectra'

@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

; generate variable with spectra for each pixel in linescan
; if I0 exists, ratio to create absorbance   (change file header to note this)
; ??? display spectra in real time as a function of pixel position
; need to update profile display with scrolling bar
; move 'addition to core' to zstack_profile_plotspectrum
;profile_spectrum = fltarr(n_files)
widget_control, hourglass=1
get_lun,lun
on_ioerror,zstack_profile_save_pixel_spectra_oops
; start of core
;print,'spectrum_filename : ',spectrum_filename
openw,lun,filename, width=2000


; Plot intensity profile with cursor bar
printf,lun,'! Spectrum from Column (X) '+strtrim(profile_x_pixel,2)+ $
				' and Row (Y) '+strtrim(profile_y_pixel,2)
IF (data_shifted EQ 1) THEN BEGIN
	printf,lun,'! Data aligned and shifted : '+list_filename+', '+shift_filename
	IF (list_filename EQ '') THEN BEGIN
		printf,lun,'! ',filename_list
	ENDIF
	IF (shift_filename EQ '') THEN BEGIN
		printf,lun,'! X shifts :',x_shift
		printf,lun,'! Y shifts :',y_shift
	ENDIF
ENDIF ELSE BEGIN
	printf,lun,'! Raw data - unaligned : '+list_filename
	IF (list_filename EQ '') THEN BEGIN
		printf,lun,'! ',filename_list
	ENDIF
ENDELSE
dummy = where(spectrum[0,*] NE 0,count)
IF (count NE 0) THEN BEGIN	; if i0 spectrum exists, use absorbance spectrum
	printf,lun,'! Energy, Absorbance'
ENDIF ELSE BEGIN
	printf,lun,'! Energy, Intensity'
ENDELSE
;print,profile_spectrum
FOR i = 0,n_files-1 DO BEGIN
	printf,lun,strtrim(string(ev_list[i]),2)+','+$
			strtrim(string(profile_spectrum[i]),2)
ENDFOR
print,'Wrote single pixel spectra to file "'+data_directory+filename+'"'
zstack_profile_save_pixel_spectra_oops :
widget_control, hourglass=0
close,lun
free_lun,lun
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_event,event
;print,'zstack_profile_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_profile_par.filename_display_list_label : BEGIN
;		zstack_profile_desensitive
		displayed_file_index = event.index
		zstack_profile_imgdisp, displayed_file_index
;		zstack_profile_profprep,byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_plotspectrum, displayed_file_index
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
;		zstack_profile_sensitive
	END
	zstack_profile_par.row_label : BEGIN
;		zstack_profile_desensitive
		profile_direction = 0
		widget_control, zstack_profile_par.row_label, set_button = 1
		widget_control, zstack_profile_par.column_label, set_button = 0
		wset,zstack_profile_par.profile_image_win
		erase
		zstack_profile_imgdisp, displayed_file_index
		zstack_profile_profprep,profile_byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
;		zstack_profile_sensitive
	END
	zstack_profile_par.column_label : BEGIN
;		zstack_profile_desensitive
		profile_direction = 1
		widget_control, zstack_profile_par.row_label, set_button = 0
		widget_control, zstack_profile_par.column_label, set_button = 1
		wset,zstack_profile_par.profile_image_win
		erase
		zstack_profile_imgdisp, displayed_file_index
		zstack_profile_profprep,profile_byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
;		zstack_profile_sensitive
	END
	zstack_profile_par.row_pixel_label : BEGIN
;		zstack_profile_desensitive
		temp_string = ''
		widget_control, zstack_profile_par.row_pixel_label,get_value = temp_string
		on_ioerror, row_pixel_label_oops
		reads,temp_string(0),profile_y_pixel
		row_pixel_label_oops :
		widget_control, zstack_profile_par.row_pixel_label, $
			set_value = ' '+strtrim(string(profile_y_pixel,format='(i5)'),2)
		erase
		zstack_profile_imgdisp, displayed_file_index
;		zstack_profile_profprep,byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_plotspectrum, displayed_file_index
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
;		zstack_profile_sensitive
	END
	zstack_profile_par.row_down_arrow_label : BEGIN
;		zstack_profile_desensitive
		IF (profile_y_pixel GT 0) THEN BEGIN
			profile_y_pixel = profile_y_pixel - 1
		ENDIF ELSE BEGIN
			profile_y_pixel = n_rows - 1
		ENDELSE
		widget_control, zstack_profile_par.row_pixel_label, $
			set_value = ' '+strtrim(string(profile_y_pixel,format='(i5)'),2)
		zstack_profile_imgdisp, displayed_file_index
;		zstack_profile_profprep,byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_plotspectrum, displayed_file_index
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
;		zstack_profile_sensitive
	END
	zstack_profile_par.row_up_arrow_label : BEGIN
;		zstack_profile_desensitive
		IF (profile_y_pixel LT (n_rows -1)) THEN BEGIN
			profile_y_pixel = profile_y_pixel + 1
		ENDIF ELSE BEGIN
			profile_y_pixel = 0
		ENDELSE
		widget_control, zstack_profile_par.row_pixel_label, $
			set_value = ' '+strtrim(string(profile_y_pixel,format='(i5)'),2)
		zstack_profile_imgdisp, displayed_file_index
;		zstack_profile_profprep,byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_plotspectrum, displayed_file_index
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
;		zstack_profile_sensitive
	END

	zstack_profile_par.column_pixel_label : BEGIN
;		zstack_profile_desensitive
		temp_string = ''
		widget_control, zstack_profile_par.column_pixel_label,get_value = temp_string
		on_ioerror, column_pixel_label_oops
		reads,temp_string(0),profile_x_pixel
		column_pixel_label_oops :
		widget_control, zstack_profile_par.column_pixel_label, $
			set_value = ' '+strtrim(string(profile_x_pixel,format='(i5)'),2)
		erase
		zstack_profile_imgdisp, displayed_file_index
;		zstack_profile_profprep,byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_plotspectrum, displayed_file_index
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
;		zstack_profile_sensitive
	END
	zstack_profile_par.column_down_arrow_label : BEGIN
;		zstack_profile_desensitive
		IF (profile_x_pixel GT 0) THEN BEGIN
			profile_x_pixel = profile_x_pixel - 1
		ENDIF ELSE BEGIN
			profile_x_pixel = n_cols - 1
		ENDELSE
		widget_control, zstack_profile_par.column_pixel_label, $
			set_value = ' '+strtrim(string(profile_x_pixel,format='(i5)'),2)
		zstack_profile_imgdisp, displayed_file_index
;		zstack_profile_profprep,byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_plotspectrum, displayed_file_index
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
;		zstack_profile_sensitive
	END

	zstack_profile_par.column_up_arrow_label : BEGIN
;		zstack_profile_desensitive
		IF (profile_x_pixel LT (n_cols -1)) THEN BEGIN
			profile_x_pixel = profile_x_pixel + 1
		ENDIF ELSE BEGIN
			profile_x_pixel = 0
		ENDELSE
		widget_control, zstack_profile_par.column_pixel_label, $
			set_value = ' '+strtrim(string(profile_x_pixel,format='(i5)'),2)
		zstack_profile_imgdisp, displayed_file_index
;		zstack_profile_profprep,byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_plotspectrum, displayed_file_index
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
;		zstack_profile_sensitive
	END
	zstack_profile_par.next_image_label : BEGIN
;		zstack_profile_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_profile_imgdisp, displayed_file_index
;		zstack_profile_profprep,byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_plotspectrum, displayed_file_index
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
;		zstack_profile_sensitive
	END

	zstack_profile_par.prev_image_label : BEGIN
;		zstack_profile_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_profile_imgdisp, displayed_file_index
;		zstack_profile_profprep,byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_plotspectrum, displayed_file_index
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
;		zstack_profile_sensitive
	END

	zstack_profile_par.play_image_movie_label : BEGIN
		movie_active = 1
		zstack_profile_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_profile_imgdisp, displayed_file_index
;			zstack_profile_profprep,byte_image
			zstack_profile_profdisp,profile_byte_image
			zstack_profile_plotprofile,displayed_file_index
			zstack_profile_plotspectrum,displayed_file_index
			wait,movie_delay
		ENDFOR
		movie_active = 0
		zstack_profile_sensitive
	END
	zstack_profile_par.next_profile_label : BEGIN
;		zstack_profile_desensitive
		IF (profile_direction EQ 0) THEN BEGIN	; use single row of image
			IF (profile_x_pixel LT (n_cols-1)) THEN BEGIN
				profile_x_pixel = profile_x_pixel+1
			ENDIF ELSE BEGIN
				profile_x_pixel = 0
			ENDELSE
		ENDIF ELSE BEGIN	; use single column of image
			IF (profile_y_pixel LT (n_rows-1)) THEN BEGIN
				profile_y_pixel = profile_y_pixel+1
			ENDIF ELSE BEGIN
				profile_y_pixel = 0
			ENDELSE
		ENDELSE
		zstack_profile_imgdisp, displayed_file_index
;		zstack_profile_profprep,byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_plotspectrum, displayed_file_index
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
;		zstack_profile_sensitive
	END

	zstack_profile_par.prev_profile_label : BEGIN
;		zstack_profile_desensitive
		IF (profile_direction EQ 0) THEN BEGIN	; use single row of image
			IF (profile_x_pixel GT 0) THEN BEGIN
				profile_x_pixel = profile_x_pixel-1
			ENDIF ELSE BEGIN
				profile_x_pixel = n_cols-1
			ENDELSE
		ENDIF ELSE BEGIN	; use single column of image
			IF (profile_y_pixel GT 0) THEN BEGIN
				profile_y_pixel = profile_y_pixel-1
			ENDIF ELSE BEGIN
				profile_y_pixel = n_rows-1
			ENDELSE
		ENDELSE
		zstack_profile_imgdisp, displayed_file_index
;		zstack_profile_profprep,byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
		zstack_profile_plotspectrum, displayed_file_index
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
;		zstack_profile_sensitive
	END

	zstack_profile_par.play_profile_movie_label : BEGIN
		zstack_profile_desensitive
		IF (profile_direction EQ 0) THEN BEGIN	; use single row of image
			init_x_pixel = profile_x_pixel
			FOR i=0,(n_cols-1) DO BEGIN
				IF (profile_x_pixel LT (n_cols-1)) THEN BEGIN
					profile_x_pixel = profile_x_pixel+1
				ENDIF ELSE BEGIN
					profile_x_pixel = 0
				ENDELSE
				zstack_profile_imgdisp, displayed_file_index
;				zstack_profile_profprep,byte_image
				zstack_profile_profdisp,profile_byte_image
				zstack_profile_plotprofile,displayed_file_index
				zstack_profile_plotspectrum,displayed_file_index
				wait,movie_delay
			ENDFOR
			profile_x_pixel = init_x_pixel
			zstack_profile_imgdisp, displayed_file_index
;			zstack_profile_profprep,byte_image
			zstack_profile_profdisp,profile_byte_image
			zstack_profile_plotprofile,displayed_file_index
			zstack_profile_plotspectrum,displayed_file_index
		ENDIF ELSE BEGIN					; use single column of image

			init_y_pixel = profile_y_pixel
			FOR i=0,(n_rows-1) DO BEGIN
				IF (profile_y_pixel LT (n_rows-1)) THEN BEGIN
					profile_y_pixel = profile_y_pixel+1
				ENDIF ELSE BEGIN
					profile_y_pixel = 0
				ENDELSE
				zstack_profile_imgdisp, displayed_file_index
;				zstack_profile_profprep,byte_image
				zstack_profile_profdisp,profile_byte_image
				zstack_profile_plotprofile,displayed_file_index
				zstack_profile_plotspectrum,displayed_file_index
				wait,movie_delay
			ENDFOR
			profile_y_pixel = init_y_pixel
			zstack_profile_imgdisp, displayed_file_index
;			zstack_profile_profprep,byte_image
			zstack_profile_profdisp,profile_byte_image
			zstack_profile_plotprofile,displayed_file_index
			zstack_profile_plotspectrum,displayed_file_index

		ENDELSE

		zstack_profile_sensitive
	END
	zstack_profile_par.display_parameters_label : BEGIN
		zstack_profile_desensitive
		wshow,zstack_profile_par.main_base_win,0
		zstack_display,'profile'
	END
	zstack_profile_par.plot_parameters_label : BEGIN
		zstack_profile_desensitive
		wshow,zstack_profile_par.main_base_win,0
		zstack_plot,'profile'
	END
	zstack_profile_par.image_range_label : BEGIN
;		zstack_profile_desensitive
		image_range = 0		; use intensity range of each image
		zstack_profile_imgdisp,displayed_file_index
		zstack_profile_profprep,profile_byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
;		zstack_profile_sensitive
	END

	zstack_profile_par.stack_range_label : BEGIN
;		zstack_profile_desensitive
		image_range = 1		; use intensity range of full image stack
		zstack_profile_imgdisp,displayed_file_index
		zstack_profile_profprep,profile_byte_image
		zstack_profile_profdisp,profile_byte_image
		zstack_profile_plotprofile, displayed_file_index
;		zstack_profile_sensitive
	END
	zstack_profile_par.profile_base_filename_label : BEGIN
		temp_string = ''
		widget_control, zstack_profile_par.profile_base_filename_label,$
				get_value = temp_string
		on_ioerror, profile_filename_label_oops
		profile_filename_header = strtrim(temp_string(0),2)
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
		profile_filename_label_oops :
		zstack_profile_sensitive
	END

	zstack_profile_par.save_profile_label : BEGIN
		on_ioerror, save_profile_label_oops
		zstack_profile_desensitive
		cd,current=current_directory
		dummy = dialog_pickfile(filter='*.pfl', /write, /fix_filter, $
				file=profile_filename, path=data_directory, get_path=data_directory, $
				title='Save intensity profile 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_profile_label_oops
				; trap if CANCEL is chosen in dialog
		ENDIF
		zstack_analyze_extract_filename, dummy, profile_filename
		widget_control, zstack_profile_par.profile_filename_label, $
				set_value = ' '+profile_filename
		zstack_profile_save_profile, profile_filename
		save_profile_label_oops :
		zstack_profile_sensitive
	END
	zstack_profile_par.spectra_base_filename_label : BEGIN
		on_ioerror, spectra_filename_label_oops
		temp_string = ''
		widget_control, zstack_profile_par.spectra_base_filename_label,$
				get_value = temp_string
		spectrum_filename_header = strtrim(temp_string(0),2)
		zstack_profile_linescan_filename, displayed_file_index
		zstack_profile_spectrum_filename, displayed_file_index
		spectra_filename_label_oops :
		zstack_profile_sensitive
	END

	zstack_profile_par.save_pixel_spectra_label : BEGIN
		on_ioerror, save_pixel_spectra_label_oops
		cd,current=current_directory
		dummy = dialog_pickfile(filter='*.spc', /write, /fix_filter, $
				file=spectrum_filename, path=data_directory, get_path=data_directory, $
				title='Save spectrum of current pixel 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_pixel_spectra_label_oops
				; trap if CANCEL is chosen in dialog
		ENDIF
		zstack_analyze_extract_filename, dummy, spectrum_filename
		widget_control, zstack_profile_par.spectrum_filename_label, $
				set_value = ' '+spectrum_filename
		zstack_profile_save_pixel_spectra, spectrum_filename
		save_pixel_spectra_label_oops :
		zstack_profile_sensitive
	END
	zstack_profile_par.save_profile_spectra_label : BEGIN
		on_ioerror, save_profile_spectra_label_oops
		cd,current=current_directory
		dummy = dialog_pickfile(filter='*.spc', /write, /fix_filter, $
				file=spectra_filename, path=data_directory, get_path=data_directory, $
				title='Save spectrum of current profile 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_profile_spectra_label_oops
				; trap if CANCEL is chosen in dialog
		ENDIF
		zstack_analyze_extract_filename, dummy, spectra_filename
		widget_control, zstack_profile_par.spectra_filename_label, $
				set_value = ' '+spectra_filename
		zstack_profile_save_profile_spectra, spectra_filename
		save_profile_spectra_label_oops :
		zstack_profile_sensitive
	END
	zstack_profile_par.image_label : BEGIN
		IF (event.press EQ 1) THEN BEGIN
;			zstack_profile_desensitive
			profile_x_pixel = round(event.x / image_zoom)-1
			profile_y_pixel = round(event.y / image_zoom)-1
			widget_control, zstack_profile_par.row_pixel_label, $
				set_value = ' '+strtrim(string(profile_y_pixel,format='(i5)'),2)
			widget_control, zstack_profile_par.column_pixel_label, $
				set_value = ' '+strtrim(string(profile_x_pixel,format='(i5)'),2)
			zstack_profile_imgdisp, displayed_file_index
;			zstack_profile_profprep,byte_image
			zstack_profile_profdisp,profile_byte_image
			zstack_profile_plotprofile, displayed_file_index
			zstack_profile_plotspectrum, displayed_file_index
			zstack_profile_linescan_filename, displayed_file_index
			zstack_profile_spectrum_filename, displayed_file_index
;			zstack_profile_sensitive
		ENDIF
	END
	zstack_profile_par.profile_image_label : BEGIN
		IF (event.press EQ 1) THEN BEGIN
;			zstack_profile_desensitive
			IF (profile_direction EQ 0) THEN BEGIN	; use single row of image
				ybot = fix( image_zoom*(profile_win_pixels - profile_zoom*n_files)/2.)
				profile_x_pixel = fix(event.x / image_zoom)
				displayed_file_index = (n_files-1) - fix((event.y-ybot)/(image_zoom*profile_zoom))
			ENDIF ELSE BEGIN					; use single column of image
				xleft = fix( image_zoom*(profile_win_pixels - profile_zoom*n_files)/2.)
				displayed_file_index = fix((event.x-xleft)/(image_zoom*profile_zoom))
				profile_y_pixel = fix(event.y / image_zoom)
			ENDELSE
			widget_control, zstack_profile_par.row_pixel_label, $
				set_value = ' '+strtrim(string(profile_y_pixel,format='(i5)'),2)
			widget_control, zstack_profile_par.column_pixel_label, $
				set_value = ' '+strtrim(string(profile_x_pixel,format='(i5)'),2)
			IF (displayed_file_index GT (n_files-1)) THEN displayed_file_index = n_files-1
			IF (displayed_file_index LT 0) THEN displayed_file_index = 0
			zstack_profile_imgdisp, displayed_file_index
;			zstack_profile_profprep,byte_image
			zstack_profile_profdisp,profile_byte_image
			zstack_profile_plotprofile, displayed_file_index
			zstack_profile_plotspectrum, displayed_file_index
			zstack_profile_linescan_filename, displayed_file_index
			zstack_profile_spectrum_filename, displayed_file_index
;			zstack_profile_sensitive
		ENDIF
	END
	zstack_profile_par.profile_plot_label : BEGIN
;		zstack_profile_plotprofile,displayed_file_index
		;; only act on a down click of the mouse
		IF (event.press EQ 1) THEN BEGIN
;			zstack_profile_desensitive
			profile_intensity = convert_coord(event.x,event.y,/device,/to_data)
;			print,'profile  : ',event.x,event.y,profile_intensity
			IF (profile_direction EQ 0) THEN BEGIN	; use single row of image
				profile_x_pixel = round(profile_intensity(0))>0<(n_cols-1)
			ENDIF ELSE BEGIN					; use single column of image
				profile_y_pixel = round(profile_intensity(0))>0<(n_rows-1)
			ENDELSE
			print,'You clicked at File # '+$
				filename_list(displayed_file_index)+', '+$
				strtrim(string(ev_list(displayed_file_index),format='(f10.2)'),2)+' eV'+$
				', x = '+strtrim(string(profile_x_pixel,format='(i3)'),2)+$
				', y = '+strtrim(string(profile_y_pixel,format='(i3)'),2)+$
				', I = '+strtrim(string(image_stack(profile_x_pixel,profile_y_pixel,displayed_file_index),format='(f10.3)'),2)
			widget_control, zstack_profile_par.row_pixel_label, $
				set_value = ' '+strtrim(string(profile_y_pixel,format='(i5)'),2)
			widget_control, zstack_profile_par.column_pixel_label, $
				set_value = ' '+strtrim(string(profile_x_pixel,format='(i5)'),2)
			zstack_profile_imgdisp,displayed_file_index
;			zstack_profile_profprep,byte_image
			zstack_profile_profdisp,profile_byte_image
			zstack_profile_plotprofile,displayed_file_index
			zstack_profile_plotspectrum, displayed_file_index
			zstack_profile_linescan_filename, displayed_file_index
			zstack_profile_spectrum_filename, displayed_file_index
			zstack_profile_plotprofile,displayed_file_index
;			zstack_profile_sensitive
		ENDIF
	END
	zstack_profile_par.spectra_plot_label : BEGIN
;		zstack_profile_spectrum_filename, displayed_file_index
		;; only act on a down click of the mouse
		IF (event.press EQ 1) THEN BEGIN
;			zstack_profile_desensitive
			this_ev_abs = convert_coord(event.x,event.y,/device,/to_data)
;			print,'spectrum : ',event.x,event.y,this_ev_abs
			this_ev = this_ev_abs(0)
			dummy = min(abs(this_ev - ev_list),this_i_ev)
			print,'You clicked at '+$
				strtrim(string(ev_list(this_i_ev),format='(f10.2)'),2)+' eV, '+$
				strtrim(string(12398.52/ev_list(this_i_ev),format='(f10.3)'),2)+' A'
			displayed_file_index = (this_i_ev>0)<(n_files-1)
			widget_control,zstack_profile_par.filename_display_list_label,$
				set_list_select=displayed_file_index
			zstack_profile_imgdisp, displayed_file_index
;			zstack_profile_profprep,byte_image
			zstack_profile_profdisp,profile_byte_image
			zstack_profile_plotprofile, displayed_file_index
			zstack_profile_plotspectrum, displayed_file_index
			zstack_profile_linescan_filename, displayed_file_index
			zstack_profile_spectrum_filename, displayed_file_index
;			zstack_profile_sensitive
		ENDIF
	END
    	zstack_profile_par.exit_label : BEGIN
    		profile_image = 0
    		profile_byte_image = 0
		IF (profile_use EQ 1) THEN BEGIN
			widget_control,zstack_profile_par.main_base,/destroy
		ENDIF ELSE BEGIN
;			widget_control,zstack_profile_par.main_base,/destroy
			wshow,zstack_spectra_par.main_base_win
			IF (init_zoom EQ image_zoom) THEN BEGIN
				zstack_spectra_imgdisp, displayed_file_index
				zstack_spectra_plotspectrum, displayed_file_index
				zstack_spectra_sensitive
			ENDIF ELSE BEGIN
				widget_control, zstack_spectra_par.main_base, /destroy
				zstack_spectra, /new_zoom
			ENDELSE
			widget_control,zstack_profile_par.main_base,/destroy
		ENDELSE
	END
ENDCASE
return
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile_dialog, Group_Leader=groupLeader
;print,'zstack_profile_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

; 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(profile_win_pixels) EQ 0) THEN profile_win_pixels = 100
IF (n_elements(profile_zoom) EQ 0) THEN profile_zoom = 4
;IF (n_elements(doalign_complete) EQ 0) then doalign_complete = 0
IF (n_elements(spectrum) EQ 0) THEN spectrum = fltarr(15,2)
IF (n_elements(data_shifted) EQ 0) then data_shifted = 0
;IF (n_tags(zstack_profile_par) EQ 0) THEN BEGIN
	zstack_profile_par = $
	   {	zstack_profile_par				    , $
		main_base						: 0L, $
		filename_display_list_label		: 0L, $
		row_label						: 0L, $
		column_label					: 0L, $
		row_pixel_label					: 0L, $
		row_down_arrow_label				: 0L, $
		row_up_arrow_label				: 0L, $
		column_pixel_label				: 0L, $
		column_down_arrow_label			: 0L, $
		column_up_arrow_label				: 0L, $
		next_image_label				: 0L, $
		prev_image_label				: 0L, $
		play_image_movie_label			: 0L, $
		next_profile_label				: 0L, $
		prev_profile_label				: 0L, $
		play_profile_movie_label			: 0L, $
		display_parameters_label			: 0L, $
		plot_parameters_label				: 0L, $
		image_range_label				: 0L, $
		stack_range_label				: 0L, $
		profile_base_filename_label		: 0L, $
		save_profile_label				: 0L, $
		profile_filename_label			: 0L, $
		spectra_base_filename_label		: 0L, $
		save_profile_spectra_label			: 0L, $
		save_pixel_spectra_label			: 0L, $
		spectrum_filename_label			: 0L, $
		spectra_filename_label			: 0L, $
		image_label					: 0L, $
		colorbar_label					: 0L, $
		profile_image_label				: 0L, $
		profile_colorbar_label			: 0L, $
		profile_plot_label				: 0L, $
		spectra_plot_label				: 0L, $
		exit_label						: 0L, $
		main_base_win					: 0L, $
		image_win						: 0L, $
		colorbar_win					: 0L, $
		profile_image_win				: 0L, $
		profile_colorbar_win				: 0L, $
		profile_plot_win				: 0L, $
		spectra_plot_win				: 0L  $
      }
;ENDIF

comp_screen_res=GET_SCREEN_SIZE()
; Start of dialog window for spectral analysis
IF N_Elements(groupLeader) EQ 0 THEN BEGIN
IF !version.os_family EQ 'Windows' then begin
	zstack_profile_par.main_base = widget_base(title='Image Profile', /col, /scroll)
ENDIF else begin
	zstack_profile_par.main_base = widget_base(title='Image Profile', /col, $
                  X_SCROLL_SIZE=comp_screen_res(0)*.85,Y_SCROLL_SIZE=comp_screen_res(1)*.95 )
ENDELSE
ENDIF ELSE BEGIN
	zstack_profile_par.main_base = widget_base(title='Image Profile', /col, $
			/Modal, Group_Leader=groupLeader )
ENDELSE
;zstack_profile_par.main_base = widget_base(title='Image Profile', /column, /scroll )
row1 = widget_base(zstack_profile_par.main_base,/row)
col1 = widget_base(row1,/column)
col2 = widget_base(row1,/column)
col3 = widget_base(row1,/column)
; Left column of dialog window
frame = widget_base(col1,/column,/frame,space=0)
label = widget_label(frame, value='Generate intensity profile using: ')
base = widget_base(frame,/row)
col1a = widget_base(base,/col,/exclusive)
zstack_profile_par.column_label = widget_button(col1a, value='Column (X)',ysize=30)
zstack_profile_par.row_label = widget_button(col1a, value='Row (Y)',ysize=30)
col1b = widget_base(base,/col)
row = widget_base(col1b,/row)
zstack_profile_par.column_pixel_label = widget_text(row, /editable, xsize=5)
zstack_profile_par.column_down_arrow_label = widget_button(row, value='<')
zstack_profile_par.column_up_arrow_label = widget_button(row, value='>')
row = widget_base(col1b,/row)
zstack_profile_par.row_pixel_label = widget_text(row, /editable, xsize=5)
zstack_profile_par.row_down_arrow_label = widget_button(row, value='<')
zstack_profile_par.row_up_arrow_label = widget_button(row, value='>')
label = widget_label(frame, value='YELLOW line is intensity profile')
label = widget_label(frame, value='RED line is cursor')
label = widget_label(frame, value='Bottom Left corner is (0,0)')
base = widget_base(col1,/column,/frame,space=0)
row = widget_base(base,/row)
label = widget_label(row,value = 'Scale image intensity using:',/align_left)
row = widget_base(base, /row)
col = widget_base(row, /col, /exclusive)
zstack_profile_par.image_range_label = widget_button(col, value = 'Intensity range of each image')
zstack_profile_par.stack_range_label = widget_button(col, value = 'Intensity range of entire image stack')
base = widget_base(col1,/column,/frame,space=0)
row = widget_base(base,/row)
label = widget_label( row, value = "Profile base filename:")
;row = widget_base(base,/row)
zstack_profile_par.profile_base_filename_label = widget_text(row,/editable,xsize=13)
row = widget_base(base,/row)
zstack_profile_par.save_profile_label = $
	widget_button(base,value='Save Profile Intensity as')
row = widget_base(base,/row)
zstack_profile_par.profile_filename_label = widget_text(row,xsize=35)
base = widget_base(col1,/column,/frame,space=0)
row = widget_base(base,/row)
label = widget_label( row, value = "Spectra base filename:")
;row = widget_base(base,/row)
zstack_profile_par.spectra_base_filename_label = widget_text(row,/editable,xsize=13)
row = widget_base(base,/row)
zstack_profile_par.save_pixel_spectra_label = $
	widget_button(base,value='Save Spectra of Current Pixel as')
row = widget_base(base,/row)
zstack_profile_par.spectrum_filename_label = widget_text(row,xsize=35)
row = widget_base(base,/row)
zstack_profile_par.save_profile_spectra_label = $
	widget_button(base,value='Save Spectra along Profile Line as')
row = widget_base(base,/row)
zstack_profile_par.spectra_filename_label = widget_text(row,xsize=35)
; Center column of dialog window
zstack_profile_par.filename_display_list_label = widget_droplist( col2, $
			value = 'Select File', /align_center, scr_xsize=200, scr_ysize=20)
zstack_profile_par.prev_image_label = widget_button(col2, value='Display Previous Image')
zstack_profile_par.next_image_label = widget_button(col2, value='Display Next Image')
zstack_profile_par.play_image_movie_label = widget_button(col2,value='Play Movie of Images')
row = widget_base(col2, /row,/align_center, space=0)
col = widget_base(row, /col,/align_center)
zstack_profile_par.display_parameters_label = widget_button(col,value='Display Parameters')
zstack_profile_par.plot_parameters_label = widget_button(col,value=' Plot  Parameters ')
;row = widget_base(col2, /row,/align_center,ysize = 50 + n_rows*(image_zoom - 1))
row = widget_base(col2, /row,/align_center,ysize = n_rows*image_zoom)
;	0.5*n_rows*image_zoom)
row = widget_base(col2, /row,/align_center)
zstack_profile_par.prev_profile_label = widget_button(col2, value='Display Previous Profile')
zstack_profile_par.next_profile_label = widget_button(col2, value='Display Next Profile')
zstack_profile_par.play_profile_movie_label = widget_button(col2,value='Play Movie of Profile')
row = widget_base(col2, /row,/align_center)
row = widget_base(col2, /row,/align_center)
;zstack_profile_par.display_parameters_label = widget_button(row,value='Display Parameters')
;row = widget_base(col2, /row,/align_center,ysize = n_rows*image_zoom)
row = widget_base(col2, /row,/align_center,ysize = n_rows*image_zoom)
;	0.5*n_rows*image_zoom)
row = widget_base(col2, /row,/align_center)
IF (data_shifted EQ -1) THEN BEGIN
	zstack_profile_par.exit_label = $
		widget_button(col2,value='Exit ZSTACK Profile')
ENDIF ELSE BEGIN
	zstack_profile_par.exit_label = $
		widget_button(col2,value='Return to ZSTACK Spectra')
ENDELSE
; Right-hand column of dialog window
base = widget_base(col3,/row,/frame,/align_center)
col3a = widget_base(base,/col)
IF (data_shifted EQ 1) THEN BEGIN
	label = widget_label(col3a, value='Shifted Image',/align_center)
ENDIF ELSE BEGIN
	label = widget_label(col3a, value='Unshifted Image',/align_center)
ENDELSE
zstack_profile_par.image_label = widget_draw(col3a,$
		xsize=n_cols*image_zoom, $
		ysize=n_rows*image_zoom, $
		retain=2,/button_events,/align_center)
col3b = widget_base(base,/col,/align_center)
label = widget_label(col3b, value='Profile Image',/align_center)
zstack_profile_par.profile_image_label = widget_draw(col3b, $
		xsize=profile_win_pixels*image_zoom, $
		ysize=n_rows*image_zoom,$
		retain = 2, /button_events,/align_center)
col3c = widget_base(base,/col,/align_center)
label = widget_label(col3c, value='I',/align_center)
zstack_profile_par.colorbar_label = widget_draw(col3c, $
		xsize=10*(image_zoom>1), ysize=n_rows*image_zoom,$
		retain = 2, sensitive=0, /align_center)
row = widget_base(col3,/row,/align_center)
zstack_profile_par.profile_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(col3,/row,/align_center)
zstack_profile_par.spectra_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)
;;;;;;;;;;
Device, get_screen_size=screen_size
screen_center = [ screen_size(0) / 2 , screen_size(1) / 2 ]
geom = Widget_Info(zstack_profile_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_profile_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_profile_par.main_base, /realize
; initialize image and profile windows
zstack_profile_par.main_base_win = !d.window
widget_control,zstack_profile_par.image_label,get_value=window
zstack_profile_par.image_win = window
widget_control,zstack_profile_par.profile_image_label,get_value=window
zstack_profile_par.profile_image_win = window
widget_control,zstack_profile_par.colorbar_label,get_value=window
zstack_profile_par.colorbar_win = window
widget_control,zstack_profile_par.profile_plot_label,get_value=window
zstack_profile_par.profile_plot_win = window
widget_control,zstack_profile_par.spectra_plot_label,get_value=window
zstack_profile_par.spectra_plot_win = window
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO zstack_profile, saved_list_filename, saved_shift_filename, $
                   median=median, despike=despike, zoom=zoom, $
                   passed_data=passed_data, new_zoom=new_zoom, $
                   stackdata_filename=stackdata_filename, $
                   stxm=stxm, sxm=sxm, sm=sm, als=als, poly=poly, help=help, Group_Leader=groupLeader
;print,'zstack_profile'

@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 keyword_set(help) THEN BEGIN
    print,'zstack_profile,[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,median=,/despike,'
    print,'    stackdata_filename= to read in a prealigned, saved stack'
    print,'    /stxm,/sxm,/sm,/als,/poly for different data file types'
    return
ENDIF
; Initialize variables for using ZSTACK_PROFILE as either a stand-alone routine or a subroutine
profile_filename_header = ''
profile_filename = ''
spectrum_filename_header = ''
spectra_filename = ''
profile_spectrum = fltarr(n_files)
profile_direction = 0	; 0 for row, 1 for column
profile_y_min = 0
profile_y_max = 0
IF NOT(keyword_set(passed_data)) THEN BEGIN	; zstack_profile is being used as a stand-alone procedure
	; 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 = ''
		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
	zstack_profile_prep	; load color table and define common variables
	; Determine type of data:  STXM:1, SXM:2, SM:3, ALS:4, POLY:5
	key_vec = [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 +1
	ENDELSE
	; Initialize variables for using ZSTACK_PROFILE as a stand-alone routine
	n_files = 0
	save_filename_header = ''
	disp_min = 0
	disp_max = 110
	disp_gamma = 1
	movie_delay = 0.02
	displayed_file_index = 0
	data_shifted = 0
	spectrum = 0
	profile_use = 1	; set this to denote that zstack_profile is being used as a stand-alone procedure

	IF keyword_set(zoom) THEN BEGIN
		image_zoom = zoom
	ENDIF ELSE BEGIN
		image_zoom = 1.00
	ENDELSE
	init_zoom = image_zoom
;	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
	IF keyword_set(stackdata_filename) THEN BEGIN
		zstack_profile_readfile,stackdata_filename
		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
		profile_x_pixel = n_cols/2
		profile_y_pixel = n_rows/2
		profile_win_pixels = max([n_rows,n_cols,n_files])
		profile_zoom = floor(profile_win_pixels/n_files)
	ENDIF ELSE BEGIN
		IF (strlen(list_filename) EQ 0) THEN BEGIN	; if no filename is given
			zstack_buildlist, filename_list
		ENDIF ELSE BEGIN		; if valid filename is given
			zstack_readlist, list_filename
		ENDELSE

		n_files = n_elements(filename_list)
		profile_x_pixel = n_cols/2
		profile_y_pixel = n_rows/2
		profile_win_pixels = max([n_rows,n_cols,n_files])
		profile_zoom = floor(profile_win_pixels/n_files)
		IF (n_files LT 2) THEN BEGIN
			print,'No files in list for analyzing!'
			return
		ENDIF
		; Despike data using X1A function, DESPIKE.PRO
		IF keyword_set(despike) THEN BEGIN
			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
			FOR i=0,(n_files-1) DO BEGIN
				khz = image_stack(*,*,i)
				IF (median EQ 1) THEN BEGIN
					khz = median(khz,3)
				ENDIF ELSE BEGIN
					khz = median(khz,median)
				ENDELSE
				image_stack(*,*,i) = temporary(khz)
			ENDFOR
		ENDIF

		IF (strlen(shift_filename) GT 0) THEN BEGIN		; do auto alignment from scratch
			zstack_profile_read_shift,shift_filename
		ENDIF
	ENDELSE
ENDIF ELSE BEGIN
	; Initialize variables for using ZSTACK_PROFILE as a subroutine of ZSTACK_SPECTRA
	IF NOT(keyword_set(new_zoom)) THEN BEGIN
		init_zoom = image_zoom
		profile_x_pixel = n_cols/2
		profile_y_pixel = n_rows/2
		profile_win_pixels = max([n_rows,n_cols,n_files])
		profile_zoom = floor(profile_win_pixels/n_files)
		profile_use = 0	; set this to denote that zstack_profile is being used as a subroutine procedure
	ENDIF
ENDELSE
zstack_profile_dialog, Group_Leader=groupLeader
widget_control, zstack_profile_par.filename_display_list_label, $
		set_value = filename_display_list
widget_control, zstack_profile_par.row_pixel_label, $
	set_value = ' '+strtrim(string(profile_y_pixel,format='(i5)'),2)
widget_control, zstack_profile_par.column_pixel_label, $
	set_value = ' '+strtrim(string(profile_x_pixel,format='(i5)'),2)
IF (profile_direction EQ 0) THEN BEGIN
	widget_control, zstack_profile_par.row_label, set_button = 1
ENDIF ELSE BEGIN
	widget_control, zstack_profile_par.column_label, set_button = 1
ENDELSE
IF (image_range EQ 0) THEN BEGIN
	widget_control, zstack_profile_par.image_range_label, set_button = 1
ENDIF ELSE BEGIN
	widget_control, zstack_profile_par.stack_range_label, set_button = 1
ENDELSE
zstack_profile_imgdisp, displayed_file_index
zstack_profile_profprep, profile_byte_image
zstack_profile_profdisp, profile_byte_image
zstack_analyze_colorbar, zstack_profile_par.colorbar_win
zstack_profile_plotprofile, displayed_file_index
zstack_profile_plotspectrum, displayed_file_index
zstack_profile_linescan_filename, displayed_file_index
zstack_profile_spectrum_filename, displayed_file_index
xmanager, 'zstack_profile', zstack_profile_par.main_base, $
		group_leader = zstack_profile_par.main_base
return
end
