; Copyright (c) 1998-2019  A.P. Hitchcock  All rights reserved
;+
;NAME:
;	AXIS_C
;
;LAST CHANGED: ----------------------------------- 21-Jan-19 (aph)
;
;PURPOSE:
;	This file contains three procedures (AXIS_C, AXIS_EVENT, AXIS_MENU_EVENT)
; which execute all menu items and displays for the AXIS2000 widget.
; It is the core of the aXis2000 widget.
;
;CATEGORY:
;	AXIS: data analysis
;
;CALLING SEQUENCE:
;	AXIS_C [, start_file = start_file, group = group, spin=spin]
;
; ROUTINES
;	PRO AXISMENU_EVENT, Event
;	PRO AXIS_EVENT, Event
;	PRO AXIS_C, start_file = start_file, GROUP=Group
;
;INPUTS:
;	EVENT - ID of event code (button push)
;
;KEYWORDS:
;	START_FILE 	name of initial parameters (default = AXIS.INI)
;	GROUP 		group name (AXIS_ID - stored in AXIS_COM)
;	SPIN		spin the globe on start-up; activate web links
;
;OUTPUTS: none
;
;COMMON BLOCKS:
;	@AXIS_COM	standard set of common blocks
;   @sdf_com
;   @AX_PEEM_COM  common for PEEM widget read-in
;   COMMON tif_convert_common   - common for Tif convert (PEEM stacks)
;	@ptycho_com
;   @nexus_com
;
;PROCEDURE:
;  HELP for using aXis2000 is given in AXIS.PDF which can be accessed
; by the AXIS help button which starts Adobe Acrobat to view that file.
;  If this does not come up, you may not have the Adobe reader on your
;  system and/or, the system level command to run Acrobat may not be correct.
;  To fix this:
;       1. Download Adobe Acroreader from www.adobe.com (it is freeware)
;       2. change the command to execute Acrobat in the axis.ini file
;          (use the Windows RUN command to determine the correct syntax)
;       3. restart aXis2000
;  The source of AXIS.PDF is a Word97 document, axis2000.doc
;
; HELP for coding aXis2000 and a file-by-file description of the code
; is contained in AXIS_PROGRAMS.HTML which can be viewed with a web browser.
;
;MODIFICATION HISTORY:
; ***** for detailed history please see the top of the source file (AXIS_C.PRO) *****
;-

;
; *******************   AXIS 2000 ********************************************
;
;  IDL WIDGET to process X-ray spectromicroscopy images and spectra
;
;  HELP for AXIS uses Adobe Acroreader to view AXIS.PDF.
;  If this does not come up, you may not have the Adobe reader on your
;  system and/or, the system level command to run Acrobat may not be correct.
;  To fix this:
;       1. Download Adobe Acroreader from www.adobe.com (it is freeware)
;       2. change the command to execute Arobat in the menu
;       3. restart AXIS
;  The source of axis.pdf is axis.doc, a Word document
;
; ------------------- REVISION HISTORY (UPDATE PLEASE!) --------------
; (28-jun-98 aph) (print_file, location) added to enable spooler printing
;		axis_ini.pro started
; (3-Dec-98 aph) (axis_c, ax_mesh, ...)
;		- interpolate to common mesh on ratio; subtract
;		- add warp function (NOT WORKING as of 01-Jan-99)
; (12-Dec-98 aph).... VERSION 1.6  (axis_c, axis_com, axis_ini, ...
;		- adapt widget to IDL-5 vs. IDL-4 (axis.ini .. switches)
;		- modify BUFFER widget (proper layout; Cancel)
;		- modify GET_TEXT widget (define 'val'; scroll; SWITCHED by IDL version !)
;		- modify MBUF widget (proper layout; all, Cancel)
;		- AXIS_C: add 'Utility.Set preferences'
;				- revise layout; buffer info list
;				- Zmin, Zmax controls
; (28-Dec-98 aph)
;		- AXIS_OPTIONS, AXIS_OPTIONS_EVENTCB - GUI approach to defaults
;		- Write.ALS, Write.NSLS fixed to handle small dynamic range data
;		- AX_ZOOM - explicit positioning, use Get_Num for scale changes
;  (31-Dec-98 aph)
; SWITCH to aaa_axis.pro so the file is always first up on select
;		- AAA_AXIS: revise pull-down menu
;					move out LN_add, LN_subsp, LN_norm to allow IDL 4.0 to run
;		- ALS_SPECTRA - GUI approach to read and process ALS spectral files
; (03-Jan-99 aph) Zmin, Zmax also for spectra
;		- ALS_SPECTRA - switched explicitly on IDL 5.2 only
; (08-Jan-99 aph) fixed Zmin, Zmax display on overplot (Refresh)
; (16-Jan-99 aph) put tif, gif format images into data buffers
; (22-Jan-99 aph) close/all added to all clear functions to allow release
; (19-Apr-99 aph) printing using customized window.pro for ALS (need to generalize!)
; (10-May-99 aph) Deglitch (removed hourglass - froze IDL when cursor used)
; (11-May-99 aph) print procedure - added PR_command to axis.ini
; (12-May-99 aph) Added SPEM - image, XPS and NEXAFS readin routines (klugy !)
; (13-May-99 aph) Added PEEM - image (tif), spectra (AXIS-ascii) and stack routines
; (14-May-99 aph) auto-PEEM convert with white correction etc
; (15-May-99 aph) spectra.ALS-PEEM
; (22-May-99 aph) binary stack data format (stack_rb, stack_wb)
; (24-May-99 aph) NOSHELL added to print spawn commands
; (07-jun-99 aph) size problem for IDL 4.0 !; removed img_warp
; (08-jun-99 aph) added group=axis_id to all calls to get_num to cure modal warning
;	------------ THIS MAKES IDL 4.0 NO LONGER SUPPORTABLE --------------------
; (11-jun-99 aph) generate and display RGB images
; (23-Jun-99 aph) color table that works ! - removed SpecColr ; ImgColr
; (25-Jun-99 aph) put in Zimba_stack codes
; ( 5-jul-99 aph) put spectral color codes low
; ( 6-jul-99 aph) mask/multiply, stack-fit for n-components
; ( 9-jul-99 aph) correct overplot rescaling (.05-.95 of first plot)
; (26-jul-99 aph) plotbuf,thumbs (no update if curbuf=0); version 1.6e
; (12-aug-99 aph) add SVD prcoedure; clean up for 1.7 distribution
; (15-aug-99 aph) 1.7a  real write to NetCDF format as needed
; (08-sep-99 aph) 1.7b - spectra cursor; new zimba; standardizing aaa_axis
; (15-sep-99 aph) add NSLS cryo stxm read-in routine
; (19-sep-99 aph) fixed manual align bug (hourglass frozen); first to first_plot
; (25-sep-99 aph) ax_clear work right; work on colors for Zimba (modified his code !)
; (26-sep-99 aph) remove aloadct (IDL 4.0) ; adapt to axis_start & resolve_all
;				  rename all pros to call name; replace thumbnails with 9x
; (28-sep-99 aph) 1.7d use Thumbs to select new buffers
; (17-Oct-99 aph) consolidate improvements (axis_read_image; SVD, bug corrections; V 1.8
; (28-oct-99 aph) introduce stackscomponents;
;                 remove align call in stack_analyze& binary if no align name
; (12-nov-99 aph) Colorbar draw window and colorbar added
; (16-nov-99 aph) X,Y controls, sensitize, gamma added
; ( 7-dec-99 aph) image rotation added
; (27-dec-99 aph) radial profile completed
; (30-dec-99 aph) AXIS 2000
;streamlined the AXIS_MENU section by removing code to subroutines
;new:	AX_ZOOM_CURSOR
;		AX_ZOOM_PAN  (rename from AX_ZOOM)
;		AX_IMAGE_ADD
;		AX_NC2GIF
;		AX_SPEC_DELETE
;		FILE_OVERWRITE - warns of existance of files on writes
;fixed: AX_MESH (add meshing of spectra)
;		AX_IMG_AVG - average by region.no zeros done properly
;		AXIS_APP - append now works like BAN append - (1), (2), (avg)
; (19-jan-00 aph) gain-divide for spectra
; (24-jan-00 aph) stack_analyze - remove constraints on OD mode for subtract
; (29-jan-00 aph) TIMER on axis_base for logo display
; (01-feb-00 aph) add log base 10
; (20-feb-00 aph) correct logo color
; (27-feb-00 aph) add groupID to get_text
; (06-mar-00 aph) default to no-rotate
; (07-apr-00 aph) force axis.ini to reside in 'codepath' subdirectory
; (11-apr-00 aph) add generate_stack routine
; (16-apr-00 aph) remove modal to xloadct (images); default = no-rotate
; (26-apr-00 aph) add image_resize
; (14-may-00 aph) stacks~princple components; abort corrected
; (20-may-00 aph) add NCDF2ALS - convert from NetCDF (binary) to ALS (ascii)
; (24-jun-00 aph) image append function added; roll-over correction funtion added
; (22-aug-00 aph) keyword to rotate changed to SPIN
; (18-sep-00 aph) add routine to compute cross-link density; remove images~SVD maps
; (24-Oct-00 aph) fix problem in writing stack_lst file from Tif to NetCDF conversion
; (01-Nov-00 aph) add modify_scale to utilities (ax_interp)
; (07-nov-00 aph) correct utilities~set energy
; (04-dec-00 aph) normalize_to_line-(H,V) options
; (06-dec-00 cgz) Changed code determining value of ini_file to CASE structure
; (08-dec-00 cgz) Modified or added choices to CASE structure for
;				'Utilities.Help' :  Help file
;					Help is part of utilities pull-down menu
;				'Quit.Quit' : Quit AXIS, update *.ini file
;				'Quit.Exit' : Quit AXIS, don't update *.ini file
;					Quit and Exit are part of QUIT pull-down menu
;			Moved widget construction and realization to a separate file: axis_dialog.pro
;			Commented out Set-up default grahics properties - not needed
; (30-dec-00 cgz) Moved Quit.Quit, Quit.Exit, Utilities.Help, and Utilities.Copy
;				to a second row of buttons at top of widget
; (29-dec-00 aph) changed submenu items in zoom~thumbnails
; (31-jan-01 aph) neatened top end
; (01-feb-01 cgz) Added Clear Buffer button to second row at top of widget
;				Has the same functionality as Utilities.Clear.Selected
;			Changed name of Copy button to Copy Buffer for consistency
;			Changed code to construct ini_file name during Exit - no need to use ax_name
; (05-feb-01 aph) image~average pixels, utilities~change mesh
; (06-feb-01 aph) convert to B/W for print~annotate to get output
; (11-feb-01 aph) add read beam line 5.3.2 data files
; (13-feb-01 aph) add spectra ~ Curve fit
; (22-feb-01 aph) add read_sdf = self-defining formats
; (25-feb-01 aph) add widget to display details of SDF files
; (19-apr-01 aph) add tif2netCDF~many
; (22-apr-01 aph) force list file name in stacks~convert format to be *.lst
; (08-may-01 aph) correct rotate to stop distortion and preserve centre
; (06-jun-01 aph) allow area-of-interest in peem read-in (temporary)
;    			writetif.dat, tif.image to allow write out of dark tif
; (07-jun-01 aph) incorporate PEEM read-in widget (trial version) - INCOMPLETE !!
; (18-jul-01 aph) adapt for new NSLS STXM IV format
; (29-jul-01 aph) introduce maps~CGO curve fit; get read_sdf for spectra working
; (04-aug-01 aph) get ax_peem_read widget working & integrated to aXis2000
; (12-aug-01 aph) add widget for PEEM TIF to netCDF conversion.
; (21-aug-01 aph) add 5.3.2 stack read in
; (30-sep-01 aph) add nsls STXMIV spectra and stack routines
; (07-oct-01 aph) add G_lbl control; make 3d plot reflect current Z-values
; (14-oct-01 aph) SPECTRAL manipulation: add - peak area;
; (09-nov-01 aph) revise read_sdf; re-order dialog
; (14-oct-01 aph) SPECTRAL manipulation: add - peak area; rotate images in separate file
; (28-dec-01 aph) add line replace for inages
; (08-jan-02 aph) modify to add pixel display (dec31/01) and format X, Y for enough digits
; (16-feb-02 aph) add scale bar
; (27-feb-02 aph) add one more decimal place to X,Y display
; (19-MAR-02 aph) incorporated SGU's'printer' approach to printing -not fully functioning
; (30-mar-02 aph) remove duplicate 'Cl' in clip function;
;                change menu structure to create 'Display' pull-down list
; (28-apr-02 aph) Elmitec binary read-in
; (08-may-02 aph) Elmitec readin & sphinx stack; direct to *.ncb (all peem formats)
; (16-jul-02 aph) fix up Elmitec readin
; (11-aug-02 aph) add Andy Smith's tif_convert
; (09-sep-02 aph) add modify one point to image and spectra processing (ax_one_pt)
; (05-oct-02 aph) set peem stack display to zoom=1
; (30-oct-02 aph) read-in SPHINX spectra
; (12-Feb-03 aph) fix error in Read.Spectra.Sphinx.1
; (15-feb-03 aph) add read.spectra.multi-column
; (17-feb-03 aph) remove double size on peem stack display
; (10-may-03 aph) modify menu for PEEM stack conversion; common
; (25-may-03 aph) fix no-start from zimba without defining path
; (02-jun-03 aph) fix menu links for stacks~convert data~peem
; (20-sep-03 aph) add absolute value to spectra
; (15-nov-03 aph) histogram
; (14-feb-04 aph) add read_all
; (20-feb-04 aph) add stacks.convert.TOF-all to *.ncb
; (26-mar-04 aph) re-arrange XAS read button; modify stack_analyze~binary re align file
; (10-apr-04 aph) add images~remove zeros (stxm532 on x1 gives many dropped points)
; (02-may-04 aph) add debug switch to stack_analyse to help find bug
; (17-may-04 aph) add Lox image and spectra read-in
; (09-jun-04 aph) fix tag-E in multiply, Elmitec read in
; (11-jul-04 aph) change to code-directory on quit or exit
; (14-sep-04 aph) add image~average~whole~non-zero function
; (17-oct-04 aph) change menus (read~ALS_STXM; stacks~analyse), add stack_add
; (29-oct-04 aph) change menus; cancel on exit does NOT end program (axis_ini now a function)
; (21-jan-05 aph) changes to version 2.1q
; (03-feb-05 aph) add REGRESS based spectral curve fit
; (10-feb-05 aph) Io default is image max
; (21-Mar-05 aph) add utilities~write image ascii
; (24-mar-05 aph) correct stack~bin~current  (in this file)
; (25-mar05-aph) images~bin added
; (28-May-05 aph) axis_log incorporated instead of print
; (13-jun-05 aph) version switch on /nowait flag for spawn commands (Ximageviewer, help)
; (14-Jun-05 aph) revise menu for stack~convert~peem; improved tif_convert
; (03-aug-05 aph) add write ALS-litho
; (18-sep-05 aph) add reset color, display~RGB processing
; (16-Oct-05 aph) introduce Read_lox single read-in widget
;            Pre 16-oct-05 read_lox changed to read_lox_spectra
; (03-Nov-05 aph) add read~images~als-xyt
; (13-Nov-05 aph) set axis_ID to 0 when quit or Exit so can use as means to see if AXIS is running
; (15-Dec-05 aph) add stacks~tomography
; (28-jan-06 aph) add read~images~roi
; (04-feb-06 aph) change image~bin to preserve size (increase x, y, pixel size proprtionately)
; (23-Feb-06 aph) add stacks~slicer; re-arrange menus; color; fix errors; XimageViewer start
; (22-Mar-06 aph) make XImageViewer start work; remove ALS_STXM tags
; (26-Apr-06 aph) read JPG images; convert sequence of jpg to *.ncb
; (28-apr-06 gaj) add stacks~convert format~ncb to mrc
; (01-may-06 aph) integrate gaj changes
; (04-may-06 aph) polarisation fits (spectra; stacks)
; (12-jun-06 aph) add images~roi~lox
; (12-jun-06 gaj) add stacks~convert format~mrc to ncb
; (10-jul-06 gaj) fixed some bugs with Stack~Tomography~map
; (01-Aug-06 gaj) add stacks~convert format~ncb to mpg for making movies
; (13-Aug-06 aph) consolidate JSO, GAJ changes
; (22-Sep-06 aph) revise dialog to group conversion routines that make *.ncb
; (10-Nov-06 aph) generate_mask~manual; stacks~append  added
; (15-Jan-07 aph) reverse spectra after convert_to_IP
; (20-Jan-07 aph) add read-in for ALS PEEM3 format images, spectra and stacks
; (19-Feb-07 aph) spectra~curve fit~polarization modified ot allow tolerance, max_iteration adjustment
; (14-Mar-07 aph) add utilities~calculate peptide spectra  - AA_Run.sav file (JSO)
; (01-may-07 aph) re-arranged utilities (change write _reals (spc-save.pro)
; (01-Jun-07 aph) add links to VJJ PCA_GUI and Stack_analyze
; (14-Jul-07 aph) add tomography processing for set of axb files (component maps from SVD)
; (07-Sep-07 aph) search for problem of code_path block to VM version; XImage_Viewer non-window prompt changed
; (13-Sep-07 aph) add ax_cimage to als peem2 read-in - Scholl routine to replace removal of first few columns
; (01-Jan-08 aph) add new ax_RGB_map widget as stacks~'RGB - color composite map'
;                 stacks~convert~OD to transmission
;				  generate masks~auto converted to CW_RSLIDER
; (02-feb-08 aph) fix spectra ~convert to OD (missing interpolation !! - from Aug 2006)
;                 add code to convert OD spectra to OD1 using elemental response
; (03-mar-08 MJ)  For Unix and Mac do not use /NOWAIT in SPAWN
;                 command. Only supported on Windows.
; (20-mar-08 aph) checked back in windows; updated convert_to.OD (post 01feb08 changes)
; (13-apr-08 aph) fix problem of starting with axis2000 logo still displayed
; (20-apr-08 aph) adjust generate mask so it always puts the mask in buffer 0
; (22-may-08 aph) enable multi-column writing in XAS format
; (31-may-08 aph) fix axis2000 ROI read-in (end up in CurBuf=0 at end)
; (04-Jun-08 aph) multi-column spectral write with unequally spaced, random length data
; (17-sep-08 aph) rename stack_analyze (axis2000 version) to stack_process
; (13-Oct-08 aph) read in Bessy stxm images and stacks
; (26-Dec-08 aph) add read_ftir maps (Thermo *.map reader; Nicolet (omnic) version)
; (29-Dec-08 aph) fix up readin-in of ROI file (axis2000 CJJ & CZ format)
; (12-Jan-09 aph) add stack~differentiate (for FTIR map processing)
; (07-Mar-09 aph) allow access to old stack align routine from stacks~anlyse~binary
; (10-Jul-09 aph) fix WritePath problem in stack_alignment
; (31-Jul-09 aph) set norm_value to 500.; update axis_com listing ; add Lox dispersion mode
; (17-Dec-09 aph) add read-in of Twinmic data; bin spectra
; (28-Dec-09 aph) add spectra~fix_rollover; added 10^ and grouped (exp, ln, 10^, log) in power
; (11-Jan-10 aph) changed @aligncom to @stack_process_align_com
; (22-Jan-10 aph) read in STXM_control XRF stacks
; (12-Feb-10 aph) MSA read-in; XRF read-in Amptek MCA, Oxford (MSA) and XGLabs (DTA)
; (14-Feb-10 aph) read in Digital Micrograph exported datacube (pEELS stacks)
; (16-Feb-10 aph) read in inca XRF stacks (element maps from SEM)
;                 removed ax_sdfe() - reding in pre-aug2001 SDF format
; (21-Feb-10 aph) correct aXis_ID variable in call to read_dm_datacube
;				  add read~stacks~XRF~Twinmic
; (26-Feb-10 aph) add routine to convert any *.ncb stack to set of *.cts ascii spectra
; (07-Mar-10 aph) fix spectra.bin to have same number of x,y points (error due to hang over at end)
; (15-Mar-10 aph) fix spectra.bin for non evenly spaced data
; (27-mar-10 aph) set up reading multiple inca XRF maps at once
; (21-Apr-10 aph) correct Inca_stack group ID
;                 add conversion & processing of stack-of-stacks (XAS-XRF)
; (12-Jun-10 aph) read ascii (x,y) images added
; (19-Jun-10 aph) add XRF-map readin for APS and CLS XRF systems
; (19-Jul-10 aph) incorporate XPspec_sim files into aXis2000
; (23-Jul-10 aph) add readin in of XGLabs XRf stacks as HDF5 files
; (29-Jan-11 aph) generate~mask~threshold split; utilities~sf default to transmission
; (03-Feb-11 aph) remove link to Jacobsen's stack analyze (display message)
; (15-feb-11 aph) scale bar position - axis_log, /clear requires text
; (10-Mar-11 aph) automate column selection for Inca XRF map read-in
; (13-Mar-11 aph) get multi-file read in going
; (23-Apr-11 aph) add remove bad lines~auto
; (07-may-11 aph) set default print to B/W; save last print size
; (17-may-11 aph) spectra.bin - replace ~finite()  with finite NE 0
;                              - IDL 5.2 does ont have the ~ operator
; (25-Jul-11 aph) bin (image, spectra) - add option to SUM instead of average; remember user choices
; (28-Jul-11 aph) add read~spectra~alignment  (x,y)alignment files placed in successive buffers
;                 fix read~spectra~nsls~map  to use read_mapper.pro directly
; (31-Jul-11 aph) rationalize stacks~tomography; get working 'read map'
; (29-Oct-11 aph) add capability to read single and multiplle Bessy TXM images
; (31-Oct-11 aph) set default directory to DefPath (nb not always using pickfile2 anymore)
; (22-Nov-11 aph) add Images~Modify X,Y axes
; (24-Nov-11 aph) improve user dialog for stack read in
; (29-Nov-11 aph) change tag for stacks~aXis (stack list)
; (15-Dec-11 aph) remove second 'hist' label; fix-up generate mask~manual to work for any size image
; (15-Jul-12 aph) clip numeric introduced
; (11-Aug-12 aph)  add label when read in *.xas files
; (26-Nov-12 aph) add stacks~rotate
; (02-Dec-12 aph) add read_Ptychography.Shapiro
; (31-Dec-12 aph) correct label for calib
; (28-Apr-13 aph) add TXRM image and stack readin
; (09-May-13 aph) make TXRM read-in more flexible; default to normalize to per-pixel time
; (27-may-13 aph) get to work with arbirary source location
; (16-Jul-13 aph) add NSRRC SPEM read_in
; (22-Jul-13 aph) use GUI for NSRRC SPEM read_in
; (27-Aug-13 aph) add NSRRC PEEM stack read-in
; (15-Oct-13 aph) add tomo~make a list
; (10-nov-13 aph) add stacks~tomography~  (generate stack of all data)
; (14-nov-13 aph) add make_tomo_list
; (14-Jan-14 aph) add @sdf_com to allow ax_sdf to know last file
; (26-Feb-14 aph) correct write.graphics command strings; try fr float (for Jay)
; (21-Apr-14 aph) make histograms reals, so can smooth without loosing sparse image data
; (02-MAy-14 aph) tif_to_ncb introduced (for Sam Kalirai; TXM@SSRL)
; (11-May-14 aph) add line-by-line stack Io conversion
; (24-Jul-14 aph) adapt scale bar to add xl, yl; add Axes switch to allow plotting without axes
;                 adjust scale bar position algorithm (a KLUGE !); flip color for bar off image
; (29-Nov-14 aph) remove fpath from calls to stack_process (it is a IDL function);
;                 used lpath instead, which is transferred in axis_com common
; (01-Dec-14 aph) modifty Image~Multiply buffers to allow ignoring ax_mesh
; (11-Jan-15 aph) fix up image~img_warp
; (15-Jan-15 aph) add ax_display_ptycho
; (28-Jan-15 aph) add read_txm_alba.1  and read_txm_alba.3
; (27-Apr-15 bw ) add read STXM NeXus
; (13-Jul-15 aph) add STXM NeXus read-in (SLS, Bessy-2, Diamond)
; (24-jul-15 aph) force OS dependent default ini file names (axis_win.ini or axis_unix.ini)
; (27-Jul-15 aph) change display_ptycho_com to ptycho_com (variables with 2 '_' only read 1st 2 of 3 parts of name
; (31-Jul-16 aph) change text to texta (text is an IDL program); fix DefPath for Zimba
; (14-Feb-16 aph) add t, d, to the label for SF OD1 output files
; (09-Mar-16 aph) add stacks - Ratio to another stack
; (19-Mar-16 aph) use online_help, book = ' '  procedure to open axs2000.pdf
; (26-mar-16 aph) recovery if last folder or path cannot be found
; (19-Apr-16 aph) add utilities.read.images.ascii
; (26-Apr-16 aph) integrate Jacobsen stack_analyze
; (08-May-16 aph) add ax_nexus_viewer
; (12-May-16 aph) add read~Soleil_PEEM
; (19-Nov-16 aph) add utilities~change dwell
; (18-Dec-16 aph) add utilities~other~[ECHEM plot, ISEELS display, print ISEELS database]
; (26-Feb-17 aph) fix write~images~jpg~data
; (14-Mar-17 aph) add images~FRC - resolution
; (20-Jul-17 aph) add read~stacks~DUV-Raman
;				  modify write~graphics~tif~(data, image) to be able to read from image-J (8 or 16)
; (28-Sep-17 aph) add stacks~y_illumination correct  (for CLS cryo-STXM ZP scanned stacks)
; (03-Apr-18 aph) change stacks~image alignment to work with *.axb files
; (03-Jun-18 aph) add concentration calculator
; (24-Jun-18 aph) add option to stacks~image_align~shift to expand canvas - ABANDONED ---  NOT COMPLETED AS OF 1-July-2018
; (01-Jul-18 aph) add stacks_expand
; (06-Jul-18 aph) fix img_aln so it works - use stack_list to get files to align
; (01-Oct-18 aph) add NSRRC XPEEM images read-in (16-bit unsigned integer tif)
; (13-Nov-18 aph) change prompt for zoom to "Numerical-cut(in data units)" to remind user
; (25-Nov-18 aph) add SGM_Image read-in
; (21-Jan-19 aph) put tags indicating processing AFTER the old label
;-
; --------------------------------------------------------------------
; NAMES AND MEANING OF COMMON VARIABLES
; *************************************************************************
; ***********         AXIS COMMON PARAMETERS   (23-jul-14) ****************
; *************************************************************************
;
; CAUTION - if you use one of these variable names in a subroutine for
; a different purpose and have included @axis_com, this can be a source
; of hard to trace errors in other routines. A common cuplrit is DATA.
;
;COMMON aDRAWID,    Axis_ID, MainWid, MainImg, XZPlot, YZPlot, Thumbnails, AxSpin
;	Axis_ID		ID of AXIS widget base
;	MainWid		graphics window # of draw window (not same as Widget ID !!)
;	MainImg		ID of MainImg draw window
;	XZPlot		graphics window #  of XZ line-out draw window
;	YZPlot		graphics window #  of XZ line-out draw window
;   ColorbarPlot graphics window #  of colorbar draw window
;	Thumbnails	graphics window #  of Thumbnails draw window
;	AxSpin		= 1 if using spinning globe logo; = 0 if single image
;COMMON aBUF, CurBuf, Data, pData, pNum, pBufs, BufStat, ButIDs, BufButs, OptButs
;	CurBuf		number of current buffer (0-12; only 0-9 directly displayable)
;	Data		pointers to the data structures
;	pData		pointers to spectra components for overplotting
;	pNum		number of plots in temporary storage for overplotting
;	pBufs		original buffers of overplot files (order scrambled by user sleection in overplotting)
;	BufStat		status of displayed buffers (multiple buffer display in overplot)
;	ButIDs		ID values of the buffer labels
;	BufButs		ID values of the buffer selection boxes
;	OptButs		ID values of the option buttons
;COMMON BufScal,    Xscl,Yscl, Zscl,  Xmin, Xmax, Ymin, Ymax, Zmin, Zmax, G_slider
;	Xscl		Array of (xmin, xmax) for all 10 buffers
;	Yscl		Array of (ymin, ymax) for all 10 buffers
;	Zscl		Array of (zmin, zmax) for all 10 buffers
;	Xmin		Widget ID for Text box with user selectable Xmin (15-Nov-99)
;	Xmax		Widget ID for Text box with user selectable Xmax (15-Nov-99)
;	Ymin		Widget ID for Text box with user selectable Ymin (15-Nov-99)
;	Ymax		Widget ID for Text box with user selectable Ymax (15-Nov-99)
;	Zmin		Widget ID for Text box with user selectable Zmin (20-Dec-98)
;	Zmax		Widget ID for Text box with user selectable Zmax (20-Dec-98)
;	G_slider	Widget ID for gamma slider control (16-nov-99)
;COMMON aPATHS,  DefPath, WritePath, ini_file, codepath, last_image_ext,location
;	DefPath		path for READING datafiles
;	WritePath	path for Writing data files
;	ini_file	name of program paramaters
;	codepath	path to code files
;   last_image_ext  extension (data type) of last image read by axis (default *.im1)
;	location	physical location (used as switch for some spcific cases)
;COMMON aPRINT,  gr_dev, gr_scale, Print_dev, Pr_Command, print_file
;	gr_dev		IDL device for screen display ('WIN', 'X')
;	gr_scale	graphics scal factor (0.5 to 2.0)
;	Print_dev	IDL device for printing ('PS'=postscript, 'PCL'=HP PCL language)
;	Pr_Command	command to transfer file to printer   (11-May-99)
;	print_file	name of print file
;	Help_cmd	command to load acrobat file (axis.pdf)  (24-may-99)
;   Net_command command to start web browser (31-jan-00)
;COMMON aCURS1,	CursorX, CursorY, CursorZ, PixelX, PixelY, xline, yline, Xval, Yval, Zval
;	CursorX		widget ID for x value display
;	CursorY		widget ID for y value display
;	CursorZ		widget ID for z value display
;	PixelX		widget ID of x pixel value display
;	PixelY		widget ID of y pixel value display
;	xline		[x1, x2] data values for user selected line
;	yline		[y1, y2] data values for user selected line
;	Xval		x value of cursor
;	Yval		y value of cursor
;	Zval		z value of cursor
;COMMON aCURS2,	GraphFrozen, CurFroz, CurX, CurY, Xrng, Yrng, Zrng
;	GraphFrozen	switch indicating MainImg cursor nor active (NO LONGER USED)
;	CurFroz		[x,y] values where MainImg cursor is frozen
;	CurX		x-cursor index (device)
;	CurY		y-cursor index (device)
;	Xrng		[Xmin, Xmax] graph limits (data units)
;	Yrng		[Ymin, Ymax] graph limits (data units)
;	Zrng		[Zmin, Zmax] graph limits (data units)
;COMMON aCURS3,
;	Xold		previous X-cursor value (for del-X computation)
;	Yold		previous Y-cursor value (for del-Y computation)
;	MainCurCol	color of cursor (NOT USED ??)
;	First_Plot	flag to indicate whether ax_color should be called
;	Last_Img	flag indicating last display on MainGraf was image (NOT USED ??)
;COMMON aCURS4,	delX, delY, delR, delZ, DXval, DYval, DRval, DZval, click1
;	delX		widget ID for delta-x value display
;	delY		widget ID for delta-y value display
;	delR		widget ID for delta-R value display (distance between points)
;	delZ		widget ID for delta-z value display (image intensity)
;	DXval		delta-x value
;	DYval		delta-y value
;	DRval		delta-R value
;	DZval		delta-z value
;	click1		0 - cursor free; 1 - first point selected; 2 - second point selected
;COMMON aprompt,
;	Uprompt		index for AXIS communication text window
;	version		version identifier (# (date))  					(10-may-98)
;   profl		profl=1 - extract profile                       (11-may-98)
;COMMON acolor,     ColTbl, bColor, UserR, UserG, UserB
;COMMON aSCALEBAR,  scale_bar, bar_pos
;	scale_bar	flag to plot or not plot bar
;	bar_pos		[bar_x, bar_y] position of start of bar in fraction of plot units
;COMMON aselect,
;	select_flag	flag to switch Thumbs from replot to select mode (28-sep-99)
;   copy_flag   flag to indicate copy operation
;	NewBuf		Number of new buffer
;   img_rep_line  flag to indicate mode to identify a replacement line
;	norm_flag	flag to control if ring current normalization is to be carried out (11-mar-07)
;	norm_value	standard ring current (default = 400 mA - ALS top up target) (07-Aug-08)
;	norm_string	text string defining type of normalization performed  (moved from sdf_com, 21-Jul-14)
;   xy_correct_flag flag to control if xy correction is to be carried out (01-feb-09)
;COMMON axis_color_common,
;	ax_low_color_index, ax_top_color_index, $
;	ax_black_color_index, ax_white_color_index, $
;	ax_color00_index, ax_color01_index, ax_color02_index, ax_color03_index, $
;	ax_color04_index, ax_color05_index, ax_color06_index, ax_color07_index, $
;	ax_color08_index, ax_color09_index, ax_color10_index, ax_color11_index, $
;	ax_color12_index, ax_color13_index, ax_color14_index, ax_color15_index
;COMMON aLBL,       Label, BufLblFont
;	Label			array of 9 labels displayed with file list
;	BufLblFont		font used for widget (system specific !!)
;COMMON aOPTIONS, Axes, Mouse, Line_Sym, pan_smooth, thumb_plot
;	Axes			switch to indicate if axes are to be plotted on 2D graph
;   Mouse		   	switch to indicate if Main_graph is active on mouse MOTION (=1) or click (=0)
;	Line_Sym		switch to determine if symbols are plotted (=1)
;	pan_smooth		switch to indicate if zoom graph updated on mouse MOTION (=1) or click (=0)
;   thumb_plot      switch to indicate that a ThumbZoom (4 or 9) is plotted (aph 10-jul-99)
;COMMON aparam,     (3-mar-98, 11-may-99)
;	X_calib  	X-slope, X-intercept for auto spectral scale setting
;	Y_calib     Y-slope, Y-intercept for auto spectral scale setting
;	constant	add/subtract constant
;	gain_m		multiplicative gain constant
;	gain_d		divisive gain constant
;	factor      constants for conversions
;	Xlock       standard (x1,x2) values (for image alignment)
;	Ylock       standard (y1,y2) values (for image alignment)
;	cll         (x,y) lower left of cutout (Zoom; align images)
;	cur  		(x,y) upper right of cutout (Zoom; align images)
;	pix_siz		size of pixel (for image aligmnment)
;	PrintSize   size in inchess of the printed Main Window in utilities~Print   ; added 7-May-11
;	PrintColor  color switch (1 = B/W, 0 = color for printouts   ; added 7-May-11
;
;COMMON lastpath,	(2-mar-98; 4-jan-00 overwrite_all)
;	lpath			last path accessed in pickfile routine
;	lfile			last file accessed in pickfile routine
;	overwrite_all	switch to indicate ignore overwrite checks in file writes
;COMMON alsRead,	(01-Jan-99)
;	I_process	procedure to massage I_file (none, dark, OSA, both)
;	Io_process	procedure to massage I_file (none, dark, OSA, both)
;	S_file		name of sample data file  (NB I_file used by stacks !!)
;	Io_file		name of reference data file
;	I_col		Column number for sample data
;	Io_col		Column number for reference data
;	als_readin	method of processing sample, ref (data, ratio, absorption)
;   Scan_Par_Update  switch to indicate updating paramaters during Browse
;COMMON ax_logo_com, (29-jan-00)
;	ax_logo		array of logo_num logo images
;	logo_rate	display rate
;	logo_num	number of images
;	logo_now 	current image
;	logo_size	size of image (gr_scale*360)
;   frontpanel	if = 1 then front panel (single or rotating) is up
;	logo_more	if = 1 continue displaying logo
;	logo_win	array of pixmap indices
;	logo_R		red color
;	logo_G
;	logo_B
; COMMON asfcom (25-nov-01)
;	sf_cmpd		formula
;	sf_emin		minimum energy
;	sf_emax		maximum energy
;	sf_mode		tpye of calculation (trans or mass abs)
;	sf_density	density
;	sf_thick	thickness
; COMMON tofcom  (14-feb-04)
;	tofE		photon energy
; 	stop1		stop # 1
;	stop2		stop # 2
;	bin_ns		bin size
;	tof1_min	minimum time for stop 1
;	tof1_max	maximum time for stop 1
;	tof2_min	minimum time for stop 2
;	tof2_max	maximum time for stop 2
; COMMON logtext  (14-sep-04)
;	log_last_line  index of last line in Widget_text box in panel
; COMMON MCF_EVENT, mcf  (26-Oct-04)  for multi-column ascii file read-in
;	MCF_ID		widget ID
;	MCF_Channel_List  list of channels
;	mcf_ext		current file extension
;	MCF_Xcol	column for X
;	MCF_Ycol_I	column for Y_I
;	MCF_Ycol_I0	column for Y_I0
;	convert_OD_flag  set to read I, Io columns from multicolumn file
;	MCF_rows	# of rows to skip
;	MCF_lasfile	name of last file
;	MCF_lastrow	last row
; COMMON aparam2   mesh_x, mesh_y, Io-val, nsmooth
;	mesh_x		#y-pixels to interpolate images to
;	mesh_y		#y-pixels to interpolate images to
;	Io_val		value of Io for converting images to OD
;	nsmooth		number of smooths (Savitsky-Golay or median)
;	xrf_cols_start	first non-zero column in the XRF maps written by INCA
;	xrf_cols_stop	last non-zero column in the XRF maps written by INCA
;	xrf_rows_start	first non-zero rows in the XRF maps written by INCA
;	xrf_rows_stop	last non-zero rows in the XRF maps written by INCA
;	xrf_map_width	size (um) along x-axis
;	xrf_energy		beam energy (eV)
;	xrf_dwell		pixel dwell time (ms)
; Common aparam3,	   img_bin, img_SumAdd, spec_bin, spec_SumAdd
;	img_bin			factor to bin images by
;	img_SumAdd		switch from (Average) to (Sum) when binning images
;	spec_bin		factor to bin spectra by
;	spec_SumAdd		switch from (Average) to (Sum) when binning spectra
;	dist_xy			2-d float - X_factor, Y_factor distortion parameters used by AX_XYDIS
; COMMON aptycho,		ptycho_E, ptycho_pix, ptycho_dwell		(01-Dec-12)
;	ptycho_E		energy of ptycho image
; 	ptycho_pix		pixel size (nm) of ptycho image
;	ptycho_dwell	dwell time used to record ptycho image
; COMMON ansls,		(2-mar-98)
;   SD			ScanData - structure containing info of NSLS image scan
;				sd.wavelength - photon wavelength
;				sd.dwell - pixel dwell for images
;				sd.clock_frequency - something involved with count normalization
;
; KEEP the ansls line THE LAST !! - it is a structure of variable size

; XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX



PRO AxisMenu_Event, Event
@axis_com
@ax_peem_com
@tif_convert_com
@stack_process_com
COMMON volume_data, image_stack
@bsif_com
@sdf_com
@ptycho_com
@nexus_com

on_error,2

CASE Event.Value OF

; *****************************************************************
; ##### STXM_control files (*.sdf) - read ALL data types ##########
; *****************************************************************

 'Read.STXM (sdf)' : BEGIN
 ; ************* read in all types of 5.3.2 imputs (spectra, images, linescans, stacks)
	tmp = ax_sdf(group_leader=axis_ID)
	if  n_tags(tmp) NE 0 THEN BEGIN
     	WIDGET_CONTROL, /Hourglass
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
	 	Plotbuf, CurBuf
	endif
    END

 'Read.STXM (NeXus)' : BEGIN
 ; ************* Implement to read in all types of NeXus imputs (spectra, images, linescans, stacks)
 if n_elements(nexus_lastfile) EQ 1 then tmp = ax_nexus(group_leader=axis_ID, file = nexus_path+nexus_lastfile) $
     else tmp = ax_nexus(group_leader=axis_ID)
  if  n_tags(tmp) NE 0 THEN BEGIN
      WIDGET_CONTROL, /Hourglass
      HANDLE_VALUE, Data(Curbuf), tmp, /SET
      Plotbuf, CurBuf
  endif
  END

 'Read.PEEM (lox)' : BEGIN
 ; ************* read in all types of Lox files (spectra, images, stacks)
	tmp = ax_lox(group_leader=axis_ID)
	if  n_tags(tmp) NE 0 THEN BEGIN
     	WIDGET_CONTROL, /Hourglass
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
	 	Plotbuf, CurBuf
	endif else begin			; read_lox returns an empty string if unsuccessful
		t = size(tmp,/type)
	  	if t EQ 7 then begin
			if strlen(tmp) EQ 0 then return
	  		stack_process, tmp, /no_align, /binary   ;,  zoom=zoom_num
	  	endif
	endelse
    END

; *****************************************************************
; ############### Images - read in image type data ################
; *****************************************************************

 'Read.Images.AXIS' : BEGIN
;  ******************* Read Binary (written from AXIS) *****************
   	WIDGET_CONTROL, /Hourglass
    tmp = axb_load()
    if  n_tags(tmp) NE 0 THEN BEGIN
    	tmp = ax_order(tmp)
		HANDLE_VALUE, Data(CurBuf), tmp, /set
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	endif
    END

  'Read.Images.ALS-xyt' : BEGIN
;  ******************* Read  files for pattern generation (written from aXis2000)*************
  	tmp = Litho_READ(group=axis_ID)
	IF n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
	END

  'Read.Images.text.no_header' : BEGIN
  ;  ******************* Read ascii (x,y) images without header information ********
  	tmp = read_ascii_img(/silent)
	IF n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
	END

'Read.Images.Bessy.STXM (old)' : BEGIN
;  ******************* Read Bessy STXM data (old, Oct-08) *****************
   	norm=300.  ; normalize to standard start-of-fill value (or top-up)
   	t=dialog_message('Normalize to ring current ?',/question)
   	if t EQ 'Yes' then begin
	   	norm = get_num(prompt='standard ring current', val=norm, group = axis_ID)
	   	tmp = read_bessy_stxm(normalize=norm)
   	endif else  tmp = read_bessy_stxm()
	IF n_tags(tmp) NE 0 THEN BEGIN           ; check read worked !
		tmp = ax_order(tmp)
		Label(CurBuf) = tmp.dl
		HANDLE_VALUE, Data(CurBuf), tmp, /set
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.Bessy.TXM' : BEGIN
;  ********** read in a Bessy TXM image (*.spe, *.txt) ******
   	WIDGET_CONTROL, /Hourglass
	tmp = read_Bessy_TXM(FILTER='*.spe')
	IF n_tags(tmp) NE 0 THEN BEGIN           ; check read worked !
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.Graphics.BMP.image' : BEGIN
  ; ************** Read BMP file and treat as image ****
   	WIDGET_CONTROL, /Hourglass
    tmp = img_load(DEFPATH=defpath,/BMP)
	if  n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		PlotBuf, Curbuf
	endif
	END

'Read.Images.Graphics.BMP.data' : BEGIN
  ; ************** Read BMP file and treat as data ****
   	WIDGET_CONTROL, /Hourglass
    tmp = img_load(DEFPATH=defpath,/BMP, /VALUES)
	if  n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		PlotBuf, Curbuf
	endif
	END

  'Read.Images.Graphics.TIF.image' : BEGIN
  ; ************** Read TIF file and treat as image ****
   	WIDGET_CONTROL, /Hourglass
    tmp = img_load(DEFPATH=defpath, /TIF)
	if  n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		PlotBuf, Curbuf
	endif
	END

'Read.Images.Graphics.TIF.data' : BEGIN
  ; ************** Read TIF file and treat as data ****
   	WIDGET_CONTROL, /Hourglass
    tmp = img_load(DEFPATH=defpath, /TIF, /VALUES)
	if  n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		PlotBuf, Curbuf
	endif
	END

  'Read.Images.Graphics.GIF.image' : BEGIN
  ; ************** Read TIF file and treat as image ****
   	WIDGET_CONTROL, /Hourglass
    tmp = img_load(DEFPATH=defpath, /GIF)
	if  n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		PlotBuf, Curbuf
	endif
	END

'Read.Images.Graphics.GIF.data' : BEGIN
  ; ************** Read TIF file and treat as data ****
   	WIDGET_CONTROL, /Hourglass
    tmp = img_load(DEFPATH=defpath, /GIF, /VALUES)
	if  n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		PlotBuf, Curbuf
	endif
	END

 'Read.Images.Graphics.JPG.image' : BEGIN
  ; ************** Read JPG file and treat as image ****
   	WIDGET_CONTROL, /Hourglass
    tmp = img_load(DEFPATH=defpath, /JPG)
	if  n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		PlotBuf, Curbuf
	endif
	END

'Read.Images.Graphics.JPG.data' : BEGIN
  ; ************** Read JPG file and treat as data ****
   	WIDGET_CONTROL, /Hourglass
    tmp = img_load(DEFPATH=defpath, /JPG, /VALUES)
	if  n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		PlotBuf, Curbuf
	endif
	END

'Read.Images.Graphics.PNG.image' : BEGIN
  ; ************** Read PNG file and treat as image ****
   	WIDGET_CONTROL, /Hourglass
    tmp = img_load(DEFPATH=defpath, /PNG)
	if  n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		PlotBuf, Curbuf
	endif
	END

'Read.Images.Graphics.PNG.data' : BEGIN
  ; ************** Read PNG file and treat as data ****
   	WIDGET_CONTROL, /Hourglass
    tmp = img_load(DEFPATH=defpath, /PNG, /VALUES)
	if  n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		PlotBuf, Curbuf
	endif
	END

'Read.Images.MSA' : BEGIN
;  ******************* Read MSA image format *****************
   	tmp = spc_load(typ=msa)
    HANDLE_value, Data(CurBuf),tmp,/set
    Plotbuf,CurBuf
    END

  'Read.Images.NSLS.old (*.nc)' : BEGIN
;  ******************* Read OLD NSLS X1A STXM data (NCF format) *****************
   	WIDGET_CONTROL, /Hourglass
	tmp = READ_BNL()
	IF n_tags(tmp) NE 0 THEN BEGIN           ; check read worked !
		tmp = ax_order(tmp)
		Label(CurBuf) = tmp.dl
		HANDLE_VALUE, Data(CurBuf), tmp, /set
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.NSLS.cryo' : BEGIN
;  ******************* Read new NSLS X1A cryo-STXM data (*.sxm; convert to *.nc) *****************
   	WIDGET_CONTROL, /Hourglass
	tmp = Read_cryo()
	IF n_tags(tmp) NE 0 THEN BEGIN           ; check read worked !
		tmp = ax_order(tmp)
		Label(CurBuf) = tmp.dl
		HANDLE_VALUE, Data(CurBuf), tmp, /set
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.NSLS.stxmIV' : BEGIN
;  ******************* Read new NSLS X1A STXMIV images (*.sxm; convert to *.nc) *****************
   	WIDGET_CONTROL, /Hourglass
	tmp = read_stxm4()
	IF n_tags(tmp) NE 0 THEN BEGIN           ; check read worked !
		tmp = ax_order(tmp)
		Label(CurBuf) = tmp.dl
		HANDLE_VALUE, Data(CurBuf), tmp, /set
		PlotBuf, CurBuf
	ENDIF
    END

; ===================== various PEEM formats =====================
  'Read.Images.PEEM.ALS-PEEM2' : BEGIN
  	tmp = AX_PEEM_READ(/axis)
  	tmp = ax_cimage(tmp)		; remove 2 rows worth of extrema (Scholl routine Sep07)
	IF n_tags(tmp) NE 0 THEN BEGIN
		tmp = ax_order(tmp)
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
	END

  'Read.Images.PEEM.ALS-PEEM3' : BEGIN
;  ----  (20-jan-07)  Adapt to data from Scholls' IDL acquire routine for PEEM2 / PEEM3
	tmp = read_peem3(group=axis_ID)
	IF n_tags(tmp) NE 0 THEN BEGIN
		tmp = ax_order(tmp)
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
	END

  'Read.Images.PEEM.Elmitec.dat' : BEGIN
;  ********** read in a 12-bit image from UVIEW2002 binary format ******
  	tmp = read_uview()
	IF n_tags(tmp) EQ 0 THEN RETURN
	if sd.wavelength EQ 0. then sd.wavelength = 12398.
	energy = 12398./sd.wavelength
	dwell = sd.dwell_time
	energy = get_num(prompt = "Energy (eV)", val = energy, group = axis_ID)
	dwell = get_num(PROMPT = "dwell (s)", Val=dwell, group=axis_ID)
	tmp.xl = string(FORMAT='("x (um)     E = ",f8.3," eV     dwell = ",f7.2," s")', $
  		energy, dwell)
	pix_siz = get_num(prompt = 'ImageSize (um)', val = pix_siz, group=axis_ID)
	max_X = tmp.x(n_elements(tmp.x)-1)
	tmp.x = tmp.x*(pix_siz/max_X)
	tmp.y = tmp.y*(pix_siz/max_X)
	tmp.e = energy
	if energy NE 0 then sd.wavelength = 12398./energy
	sd.dwell_time = dwell
	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf
	END

  'Read.Images.PEEM.Elmitec.tif' : BEGIN
;  ********** read in an 8-bit or 16-bit tif exported from UVIEW2002 ******
  	tmp = img_load(DEFPATH=defpath, /tif, /elmitec, /values)
	IF n_tags(tmp) EQ 0 THEN RETURN
	if sd.wavelength EQ 0. then sd.wavelength = 12398.
	energy = 12398./sd.wavelength
	dwell = sd.dwell_time
	energy = get_num(prompt = "Energy (eV)", val = energy, group = axis_ID)
	dwell = get_num(PROMPT = "dwell (s)", Val=dwell, group=axis_ID)
	tmp.xl = string(FORMAT='("x (um)     E = ",f8.3," eV     dwell = ",f7.2," s")', $
  		energy, dwell)
	pix_siz = get_num(prompt = 'ImageSize (um)', val = pix_siz, group=axis_ID)
	max_X = tmp.x(n_elements(tmp.x)-1)
	tmp.x = tmp.x*(pix_siz/max_X)
	tmp.y = tmp.y*(pix_siz/max_X)
	tmp.e = energy
	if energy NE 0 then sd.wavelength = 12398./energy
	sd.dwell_time = dwell
	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	ax_color
	PlotBuf, CurBuf
	END

  'Read.Images.PEEM.Lox-PEEM.image' : BEGIN
;  ********** read in a 24-bit tif written by Lox ***************
  	tmp = img_load(DEFPATH=defpath, /tif, /lox, /values)
	IF n_tags(tmp) EQ 0 THEN RETURN
	if sd.wavelength EQ 0. then sd.wavelength = 12398.
	energy = 12398./sd.wavelength
	dwell = sd.dwell_time
	energy = get_num(prompt = "Energy (eV)", val = energy, group = axis_ID)
	dwell = get_num(PROMPT = "dwell (s)", Val=dwell, group=axis_ID)
	tmp.xl = string(FORMAT='("x (um)     E = ",f8.3," eV     dwell = ",f7.2," s")', $
  		energy, dwell)
	pix_siz = get_num(prompt = 'ImageSize (um)', val = pix_siz, group=axis_ID)
	max_X = tmp.x(n_elements(tmp.x)-1)
	tmp.x = tmp.x*(pix_siz/max_X)
	tmp.y = tmp.y*(pix_siz/max_X)
	if energy NE 0 then sd.wavelength = 12398./energy
	sd.dwell_time = dwell
	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	ax_color
	PlotBuf, CurBuf
	END

'Read.Images.PEEM.Lox-PEEM.dispersion' : BEGIN
;  ********** read in dispersion mode line-spectra written by UView2000 ***************
	axis_log, 'To be written!'
	END

  'Read.Images.PEEM.ALS-PEEM.12-bit' : BEGIN
;  ********** read in an ALS PEEM-2 Image (as-recorded) ******
   	WIDGET_CONTROL, /Hourglass
	file=PICKFILE2(/Read, FILTER=fltr, title= '12-bit ALS PEEM file',/LPATH, DEFPATH=defpath)
	if file EQ '' then return
   	if dialog_message(/question,title = 'AXIS2000: Read 12-bit ALS-PEEM' $
   	    ,  'Mask with area of interest ?') EQ 'Yes' then  begin
   	    	aoifile = PICKFILE2(/Read, title = 'Area of Interest file', FILTER='*.aoi')
			if strlen(aoifile) NE 0 then begin
				openr, lun, aoifile, /get_lun
				txt = '' &	aoi = intarr(4)
				readf, lun, txt
				close, lun & free_lun, lun
				print, 'input to Area of interest = ', txt
				start = strpos(txt,'Box1')
				txt = strmid (txt, start+5)
				reads, txt, aoi
				print, 'Area of interest = ', aoi
				tmp = Rd_PEEM(file, /bits12,/white, /aoi_data, aoi_box=aoi, /axis)
			endif
   	    endif else tmp = Rd_PEEM(file, /bits12, /white, /axis)
	IF n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.PEEM.ALS-PEEM.16-bit' : BEGIN
;  ********** read in an ALS PEEM-2 Image  ******
   	WIDGET_CONTROL, /Hourglass
	tmp = Rd_PEEM(/white, /axis)
	IF n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.PEEM.Mephisto' : BEGIN
;  ********** 'Read (512x512) binary image data from Mephisto  **************************
   	WIDGET_CONTROL, /Hourglass
	tmp = Read_Mef(DEFPATH=DefPath)
	IF n_tags(tmp) NE 0 THEN BEGIN           ; check read worked !
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.PEEM.NSRRC' : BEGIN
;  ********** read in an NSRRC  XPEEM mage (16-bit unsiged tif)  ******
   	WIDGET_CONTROL, /Hourglass
	tmp = img_load(DEFPATH=defpath, /TIF, /VALUES)
	IF n_tags(tmp) NE 0 THEN BEGIN
		PEEM_energy = get_num(Prompt = ' Photon energy (eV)',title = 'NSRRC X-PEEM reader', group = Axis_ID)
		tmp.e = PEEM_energy
		if n_elements(PEEM_pixel_size) NE 0 then PEEM_pixel_size = 0.02  ; 20 nm default
		PEEM_pixel_size =  0.001*get_num(Prompt = ' pixel size (nm) ', title = 'NSRRC X-PEEM reader', group = Axis_ID)
		if PEEM_pixel_size GT 0 then begin
			tmp.x = PEEM_pixel_size*tmp.x
			tmp.y = PEEM_pixel_size*tmp.y
		endif
		tmp.xl = 'X (um)  E = ' + string(tmp.e, format='(F8.2)')
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.Ptychography.11.0.2-display' : BEGIN
;  ********** Display 11.0.2 2-dwell ptycho data (15-Jan-14)  **************************

	ax_display_ptycho, /axis_on
    END

  'Read.Images.Ptychography.Shapiro' : BEGIN
;  ********** 'Read ptychography result (Shapiro, Nov 2012)  **************************
   	WIDGET_CONTROL, /Hourglass
	tmp = (DEFPATH=DefPath)
	tmp = read_h5_ptycho()
	IF n_tags(tmp) NE 0 THEN BEGIN           ; check read worked !
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.ROI.peem2' : BEGIN
;  ********** read in  peem2 AOI file **********
;   uses existing image  if buffer is an image, or gets file as template
   	WIDGET_CONTROL, /Hourglass
   	HANDLE_VALUE, Data(Curbuf), tmp
   	image_flag=0
   	IF n_tags(tmp) NE 0 then begin
   		IF tmp.t EQ '2d' then image_flag=1
   	ENDIF
   	IF image_flag EQ 0 then tmp = ax_read_roi(roi_type='peem2') ELSE BEGIN
    	tmp = ax_read_roi(template=tmp, roi_type='peem2')
    	CurBuf=0
    ENDELSE
	IF n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.ROI.lox' : BEGIN
;  ********** read in  peem2 AOI file **********
;   uses existing image  if buffer is an image, or gets file as template
   	WIDGET_CONTROL, /Hourglass
   	HANDLE_VALUE, Data(Curbuf), tmp
   	image_flag=0
   	IF n_tags(tmp) NE 0 then begin
   		IF tmp.t EQ '2d' then image_flag=1
   	ENDIF
   	IF image_flag EQ 0 then tmp = ax_read_roi(roi_type='lox') ELSE BEGIN
    	tmp = ax_read_roi(template=tmp, roi_type='lox')
    	CurBuf=0
    ENDELSE
	IF n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.ROI.aXis2000 stack' : BEGIN
;  ********** read in  CJ/CZ format roi file **********
;   uses existing image  if buffer is an image, or gets file as template
   	HANDLE_VALUE, Data(Curbuf), tmp
   	image_flag=0
   	IF n_tags(tmp) NE 0 then begin
   		IF tmp.t EQ '2d' then image_flag=1	; assume image has same row,col dimensions as ROI file
   	ENDIF
   	IF image_flag EQ 0 then BEGIN	; do not have image - let ax_read_roi help user find reference image
   		tmp = ax_read_roi(roi_type='stack')
   	ENDIF ELSE BEGIN
    	tmp = ax_read_roi(template=tmp, roi_type='stack')	; have image - overwrite it
    ENDELSE
	IF n_tags(tmp) EQ 0 THEN RETURN
	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf
    END

; ******************************  SGM Images ************************************
  'Read.Images.SGM_Image.Average fluorescence spectrum' : BEGIN
  	tmp = h5_read_sgm_image(/pfya)
  	IF n_tags(tmp) EQ 0 THEN RETURN
  	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf
    END

  'Read.Images.SGM_Image.Io map' : BEGIN
  	tmp = h5_read_sgm_image(/io)
  	IF n_tags(tmp) EQ 0 THEN RETURN
  	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf
    END

  'Read.Images.SGM_Image.Dwell map' : BEGIN
  	tmp = h5_read_sgm_image(/dwell)
  	IF n_tags(tmp) EQ 0 THEN RETURN
  	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf
    END

  'Read.Images.SGM_Image.Partial yield maps' : BEGIN
	axis_log, 'generate peak limit file to extract PFY maps - e.g.'
	axis_log, '60 80'
	axis_log, '95 115'
  	tmp = h5_read_sgm_image(/pfyr)
  	IF n_tags(tmp) EQ 0 THEN RETURN
  	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf
    END

  'Read.Images.SGM_Image.TEY map' : BEGIN
  	tmp = h5_read_sgm_image(/tey)
  	IF n_tags(tmp) EQ 0 THEN RETURN
  	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf
    END

  'Read.Images.SGM_Image.Transmission map' : BEGIN
  	tmp = h5_read_sgm_image(/diode)
  	IF n_tags(tmp) EQ 0 THEN RETURN
  	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf
    END

  'Read.Images.SGM_Image.SDD data (stack of XRF spectra)' : BEGIN

    axis_log, 'NOT YET WRITTEN'
    END

; ******************************  SGM Images  - END - ************************************

  'Read.Images.SPEM.ALS-SPEM' : BEGIN
;  ********** read in an ALS SPEM Image  ******
   	WIDGET_CONTROL, /Hourglass
	tmp = Rd_SPEM()					; adapted ALS LOADSPEM.PRO
	IF n_tags(tmp) NE 0 THEN BEGIN
		tmp = ax_order(tmp)
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.SPEM.NSRRC SPEM' : BEGIN
;  ********** read in an NSRRC SPEM Image  ******
   	WIDGET_CONTROL, /Hourglass
	tmp = read_nsrrc_spem_gui(group_leader=axis_ID)
	IF n_tags(tmp) NE 0 THEN BEGIN
		tmp = ax_order(tmp)
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.Other.ALS-STXM-7.0' : BEGIN
;  ********** read in an ALS STXM Image (*.im*, *.dat) ******
   	WIDGET_CONTROL, /Hourglass
	tmp = read_als(DEGLITCH=0)
	IF n_tags(tmp) NE 0 THEN BEGIN           ; check read_als worked !
		tmp = ax_order(tmp)
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.Other.ALS-XM1' : BEGIN
;  ********** read in an ALS XM-1 image (*.spe)  ******
   	WIDGET_CONTROL, /Hourglass
	tmp = xm1_load(group=axis_ID)
	IF n_tags(tmp) NE 0 THEN BEGIN           ; check read_als worked !
		tmp = ax_order(tmp)
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.Other.ALS-STXM-7.0.linescan' : BEGIN
;  ********** read in an ALS STXM Line scan (*.xa*, *.dat) ******
   	WIDGET_CONTROL, /Hourglass
	tmp = ln_load(FILTER='*.xa*')
	IF n_tags(tmp) NE 0 THEN BEGIN           ; check read_als worked !
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

'Read.Images.Other.Ascii image.reals' :  BEGIN
; ************* 'Read (1d) or (2d) data to AXIS-format file as REALS' ********************
  	WIDGET_CONTROL, /Hourglass
 	tmp = spc_load()
    IF n_tags(tmp) NE 0 THEN begin
    	HANDLE_value, Data(CurBuf), tmp, /set
 	  	PlotBuf, Curbuf
    ENDIF
   END

'Read.Images.Other.Ascii image.integers' :  BEGIN
; ************* 'Read (1d) or (2d) data to AXIS-format file as REALS' ********************
  	WIDGET_CONTROL, /Hourglass
 	tmp = spc_load(/int_factor)
    IF n_tags(tmp) NE 0 THEN begin
    	HANDLE_value, Data(CurBuf), tmp, /set
 	  	PlotBuf, Curbuf
    ENDIF
   END

  'Read.Images.Text.no_header' : BEGIN
  ;  ******************* Read ascii (x,y) images without header information ********
  	tmp = read_ascii_img(/silent, group = axis_ID)
	IF n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
	END

  'Read.Images.Text.with_header' : BEGIN
  ;  ******************* Read ascii (x,y) images with header information ********
	axis_log, 'Not yet written - 12-Jun-2010 (aph)'
;  	tmp = read_ascii_img(/silent, /header, group = axis_ID)
;	IF n_tags(tmp) NE 0 THEN BEGIN
;		HANDLE_VALUE, Data(Curbuf), tmp, /SET
;		Label(CurBuf) = tmp.dl
;		PlotBuf, CurBuf
;	ENDIF
	END

  'Read.Images.TOF.img' : BEGIN
;  ******************* 'Read (x,y,z) triplet TOF data (Mac) **************************
   	WIDGET_CONTROL, /Hourglass
	tmp = Read_TOF(DEFPATH=DefPath)
	IF n_tags(tmp) NE 0 THEN BEGIN           ; check read worked !
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

'Read.Images.TOF.all (pTA)' : BEGIN
;  ******************* 'Read (x,y,z) triplet TOF data (Mac) **************************
   	WIDGET_CONTROL, /Hourglass
	tmp = Read_ALL(/axis_on, /pipico)
	IF n_tags(tmp) NE 0 THEN BEGIN           ; check read worked !
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.Twinmic.transmission' : BEGIN
;  ********** read in  Twinmic image files (*.ssv) **********
	tmp = load_ssv(/param, group=aXis_ID)
	IF n_tags(tmp) EQ 0 THEN RETURN
	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf
    END

  'Read.Images.Twinmic.fluorescence' : BEGIN
;  ********** read in  Twinmic image files (*.img) **********
	tmp = read_xrf_img(group=aXis_ID)
	IF n_tags(tmp) EQ 0 THEN RETURN
	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf
    END

  'Read.Images.TXRM.Alba.Mistral' : BEGIN
;  ********** read in an ALS SPEM Image  ******
	tmp = read_txm_alba(/one)			;  add /select to enable individual components to be read
	IF n_tags(tmp) NE 0 THEN BEGIN				;  add /no_norm to disable automatic normalization to clock time / pixel
		tmp = ax_order(tmp)
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.TXRM.Xradia' : BEGIN
;  ********** read in an ALS SPEM Image  ******
	tmp = ax_read_txrm(group=aXis_ID)			;  add /select to enable individual components to be read
	IF n_tags(tmp) NE 0 THEN BEGIN				;  add /no_norm to disable automatic normalization to clock time / pixel
		tmp = ax_order(tmp)
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Images.XRF.APS' : BEGIN
;  ********** read in  APS XRF map files  **********
	tmp = read_aps_xrf_maps(group=aXis_ID)
	IF n_tags(tmp) EQ 0 THEN RETURN
	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf
    END

  'Read.Images.XRF.CLS SGM' : BEGIN
;  ********** read in  CLS SGM XRF map files  **********
	tmp = read_cls_sgm_xrf(group=aXis_ID)
	IF n_tags(tmp) EQ 0 THEN RETURN
	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf
    END

  'Read.Images.XRF.Inca (Oxford)' : BEGIN
;  ********** read in  Oxford INCA program elemental map files (*.tsv) **********
;	--- set up to read up to 9 at once
	fnames=dialog_pickfile(filter='*.tsv', /multiple, path = DefPath, get_path=lpath, $
		title='Pick one or more XRF map files')
	DefPath = lpath
;	print, 'default path set to ', DefPath
	print, '# of files to read = ', n_elements(fnames)
	if n_elements(fnames) GT 1 then begin
; process multiple files into buffers starting at Buffer 1, ending at 9
		CurBuf = 1
		if n_elements(fnames) GT 9 then n_buf = 9 else n_buf = n_elements(fnames)
		tmp = read_xrf_img(file = fnames(0), scope = 'inca', group=aXis_ID) ; assume nrow, ncol known
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
		for i = 1, n_buf - 1 do begin
		CurBuf = CurBuf+1
			tmp = read_xrf_img(file = fnames(i), scope = 'inca', group=aXis_ID, /silent) ; assume nrow, ncol known
			HANDLE_VALUE, Data(Curbuf), tmp, /SET
			Label(CurBuf) = tmp.dl
			PlotBuf, CurBuf
		endfor
	endif else begin
		tmp = read_xrf_img(file=fnames(0), scope = 'inca', group=aXis_ID)
		IF n_tags(tmp) EQ 0 THEN RETURN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	ENDELSE
    END

  'Read.Images.XRF.Twinmic' : BEGIN
;  ********** read in  Twinmic image files (*.img) **********
	tmp = read_xrf_img(group=aXis_ID)
	IF n_tags(tmp) EQ 0 THEN RETURN
	HANDLE_VALUE, Data(Curbuf), tmp, /SET
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf
    END

; *****************************************************************
; ############### Spectra - read in spectra type data #############
; *****************************************************************

  'Read.Spectra.AXIS' : BEGIN
; ************** Read file in AXIS format
	tmp = spc_load(filter='*.txt')
	if  n_tags(tmp) NE 0 THEN BEGIN
     	WIDGET_CONTROL, /Hourglass
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		PlotBuf, Curbuf
	endif
	END

  'Read.Spectra.alignment' : BEGIN
; ************** Read file in AXIS format
	read_axm, a_x, a_y
	if  n_tags(a_x) NE 0 THEN BEGIN
		Curbuf_X = 5
		HANDLE_VALUE, Data(Curbuf_X), a_x, /SET
		HANDLE_VALUE, pData(0), a_x, /set
		PlotBuf, Curbuf_X
		Curbuf_Y = 6
		HANDLE_VALUE, Data(Curbuf_Y), a_y, /SET
		HANDLE_VALUE, pData(1), a_y, /set
		PlotBuf, Curbuf_Y
		PlotBuf, Curbuf_X,/same_Scale
; ------------  (27-jul-11 aph - tried to use refresh to generate overlapping plot but does not work)
;		pNum = 2
;		pBufs = [5,6]
;		Refresh
	endif
	END


  'Read.Spectra.multi-column' : BEGIN
; ************** Read file in multi-column ascii format
	tmp = ax_file_load(group = axis_ID)
	if  n_tags(tmp) NE 0 THEN BEGIN
     	WIDGET_CONTROL, /Hourglass
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
		PlotBuf, Curbuf
	endif
	END

 'Read.Spectra.ALS-STXM-7.0' : BEGIN
 	als_spectra, GROUP_LEADER=Axis_ID
 	Plotbuf, CurBuf
    END

 'Read.Spectra.ALS-STXM.5.3' : BEGIN
;	fname = dialog_pickfile(Title='Select SDF Spectral file', Filter = '*.xsp', PATH=DefPath, $
;	  GET_PATH=DefPath, group=axis_ID)
	tmp = ax_sdf(group_leader=axis_ID)
;	help, tmp, /struct
	if  n_tags(tmp) NE 0 THEN BEGIN
     	WIDGET_CONTROL, /Hourglass
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
	 	Plotbuf, CurBuf
	endif
    END

 'Read.Spectra.ALS-SPEM.XPS' : BEGIN
; *************** read als PHI XPS data (single region only) *************
    tmp=load_spm()
    if  n_tags(tmp) NE 0 THEN BEGIN
    	HANDLE_value, Data(CurBuf),tmp,/set
    	Plotbuf,CurBuf
    ENDIF
	END

 'Read.Spectra.ALS-SPEM.NEXAFS' : BEGIN
; *************** read als PHI XPS data (single region only) *************
    tmp=load_nex()
    if  n_tags(tmp) NE 0 THEN BEGIN
    	HANDLE_value, Data(CurBuf),tmp,/set
    	Plotbuf,CurBuf
    ENDIF
	END

 'Read.Spectra.ALS-PEEM' : BEGIN
; *************** read als PEEM-2 nexafs *************
    tmp=pem_load()
    if  n_tags(tmp) NE 0 THEN BEGIN
    	HANDLE_value, Data(CurBuf),tmp,/set
    	Plotbuf,CurBuf
    ENDIF
	END

 'Read.Spectra.Lox-PEEM' : BEGIN
; *************** read als PEEM-2 nexafs *************
    tmp=read_lox_spectra()
    if  n_tags(tmp) NE 0 THEN BEGIN
    	HANDLE_value, Data(CurBuf),tmp,/set
    	Plotbuf,CurBuf
    ENDIF
	END

'Read.Spectra.SPHINX-PEEM.1' : BEGIN
; *************** read sphinx format - multi-column *************
	tmp = spc_load(filter='*.dat')
  	HANDLE_value, Data(CurBuf),tmp,/set
   	Plotbuf,CurBuf
	END

'Read.Spectra.SPHINX-PEEM.all' : BEGIN
; *************** read sphinx format - multi-column *************
	fname = dialog_pickfile(Title='Select Sphinx spectrum', Filter = '*.dat', $
	         PATH=DefPath, GET_PATH=DefPath, group=axis_ID)
	nspec = spc_load(file=fname, /multi)	; find number of columns
	if nspec EQ 1 then begin
		tmp = spc_load(file=fname, xcol = 1, ycol =2)
	  	HANDLE_value, Data(CurBuf),tmp,/set
	   	Plotbuf,CurBuf
	endif else begin
		CurBuf = CurBuf - 1
	    for i = 2, nspec+1 do begin
	    	CurBuf = CurBuf + 1
	    	tmp=spc_load(file=fname, xcol = 1, ycol = i)
		  	HANDLE_value, Data(CurBuf),tmp,/set
		   	Plotbuf,CurBuf
	    endfor
	endelse
	END

'Read.Spectra.MSA' : BEGIN
;  ******************* Read MSA spectra format *****************
   	tmp = spc_load(typ='msa')
    HANDLE_value, Data(CurBuf),tmp,/set
    Plotbuf,CurBuf
    END

'Read.Spectra.NSLS.ascii' : BEGIN
; ********************* read nsls format (ascii) data ****************
    tmp = bnl_load(DEFPATH=DefPath)
    HANDLE_value, Data(CurBuf),tmp,/set
    Plotbuf,CurBuf
	END

  'Read.Spectra.NSLS.nc' : BEGIN
  ; ********************* read nsls format (NC) data ****************
    tmp=read_bsp(DEFPATH=DefPath)
    HANDLE_value, Data(CurBuf),tmp,/set
    Plotbuf,CurBuf
	END

  'Read.Spectra.NSLS.stxmIV' : BEGIN
;  ******************* Read new NSLS X1A STXMIV spectra (*.sm) *****************
   	WIDGET_CONTROL, /Hourglass
	tmp = read_stxm4()
	IF n_tags(tmp) NE 0 THEN BEGIN           ; check read worked !
		Label(CurBuf) = tmp.dl
		HANDLE_VALUE, Data(CurBuf), tmp, /set
		PlotBuf, CurBuf
	ENDIF
    END

  'Read.Spectra.NSLS.map' : BEGIN
  ; ********************* read Mapper format (*.map) data ****************
	filename = pickfile2(/read,filter='*.map', /lpath, DefPath=DefPath)
	read_mapper, filename, x, y
	t=ax_name(filename)
	tmp = {t:'1d', x:x, d:y,dn:y, xl:'Energy (eV)', yl:'NSLS mapper file', dl:t(1)}
    HANDLE_value, Data(CurBuf),tmp,/set
    Plotbuf,CurBuf
	END

  'Read.Spectra.Twinmic.fluorescence' : BEGIN
  ; ********************* read XGLabs fluorescence data ****************
	tmp=read_xrf_spectra(group=aXis_ID)
    HANDLE_value, Data(CurBuf),tmp,/set
    Plotbuf,CurBuf
	END

  'Read.Spectra.Twinmic.transmission' : BEGIN
  ; ********************* read Mapper format (*.map) data ****************
	axis_log, 'read routine for Twinmic spectra not yet written'
;	tmp=read_axm()
;   HANDLE_value, Data(CurBuf),tmp,/set
;    Plotbuf,CurBuf
	END


'Read.Spectra.XAS' : BEGIN
; ********************* read nsls format (*.xas) data ****************
    tmp = ax_read_xas()
    HANDLE_value, Data(CurBuf),tmp,/set
    Plotbuf,CurBuf
	END

'Read.Spectra.XRF.Amptek (*.mca)' : BEGIN
;  ******************* Read MSA spectra format *****************
   	tmp = spc_load(typ='mca')
    HANDLE_value, Data(CurBuf),tmp,/set
    Plotbuf,CurBuf
    END

'Read.Spectra.XRF.Inca (Oxford)' : BEGIN
;  ******************* Read MSA spectra format *****************
   	tmp = spc_load(typ='msa', filter='*.txt')
    HANDLE_value, Data(CurBuf),tmp,/set
    Plotbuf,CurBuf
    END

'Read.Spectra.XRF.XGLabs-text' : BEGIN
;  ******************* Read XRF spectrum written by XGLabs in *.dta format *****************
	tmp=read_xrf_spectra(group=aXis_ID)
    HANDLE_value, Data(CurBuf),tmp,/set
    Plotbuf,CurBuf
	END

'Read.Spectra.XRF.XGLabs-hdf5' : BEGIN
;  ******************* Read XRF spectrum written by XGLabs in hdf5 format *****************
  tmp=read_xrf_spectra(group=aXis_ID, /hdf5)
    HANDLE_value, Data(CurBuf),tmp,/set
    Plotbuf,CurBuf
  END


; *****************************************************************
; ############### Stacks  - read in stack (x,yE)data ##############
; *****************************************************************

'Read.Stacks.Bessy.STXM (old)' : BEGIN
;  ******************* Read stack data from the old Bessy STXM (Oct-08) *****************
   	norm=300.  ; normalize to standard start-of-fill value (or top-up)
   	t=dialog_message('Normalize to ring current ?',/question)
   	if t EQ 'Yes' then begin
	   	norm = get_num(prompt='standard ring current', val=norm, group = axis_ID)
   	endif else  norm = 0
   	tmp = read_bessy_stack(normalize=norm,/silent)
    END

'Read.Stacks.Bessy.TXM' : BEGIN
;  ******************* Read Bessy TXM stacks  *****************
   	norm=300.  ; normalize to standard start-of-fill value (or top-up)
  	t=dialog_message('Normalize to ring current ?',/question)
 	if t EQ 'Yes' then begin
	   	norm = get_num(prompt='standard ring current', val=norm, group = axis_ID)
  	endif else  norm = 0
 	tmp = read_bessy_stack(/txm, normalize=norm)

    END

 'Read.Stacks.DM-datacube' : BEGIN
;  ******************* Read Binary (written from AXIS) *****************
   	WIDGET_CONTROL, /Hourglass
    tmp = read_dm_datacube(group=aXis_ID)
    END

 'Read.Stacks.DUV-Raman' : BEGIN
;  ********** Read Deep UP excited Raman stack (Hailey Sapers)  *********
   	WIDGET_CONTROL, /Hourglass
    tmp = read_duv_stack(group=aXis_ID)
   if  n_tags(tmp) NE 0 THEN BEGIN
   		help, tmp, /struct
 		HANDLE_VALUE, Data(CurBuf), tmp, /set
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	endif
    END

 'Read.Stacks.FTIR' : BEGIN
;  ******************* Read FTIR stack (Paul Dumas)  *****************
   	WIDGET_CONTROL, /Hourglass
    tmp = read_ftir()
   if  n_tags(tmp) NE 0 THEN BEGIN
    	tmp = ax_order(tmp)
		HANDLE_VALUE, Data(CurBuf), tmp, /set
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	endif
    END

 'Read.Stacks.PEEM.NSRRC' : BEGIN
;  ********** read in NSLS PEEM stack (single file '*.pem')  ******
	tmp = read_nsrrc_peem()
   if  n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(CurBuf), tmp, /set
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	endif
    END

  'Read.Stacks.PEEM.Soleil' : BEGIN
 ; ************* read in Soleil XPEEM files (*.nxs)
    tmp = read_nxs()
    if  n_tags(tmp) NE 0 THEN BEGIN
      ;       tmp = ax_order(tmp)
      HANDLE_VALUE, Data(CurBuf), tmp, /set
      Label(CurBuf) = tmp.dl
      PlotBuf, CurBuf
    endif
  END

 'Read.Stacks.PEEM.all other' : BEGIN
;  ********** read in ALS (PEEM2 old & new, PEEM3), Lox, or Sphinx PEEM Images  ******
; ------ same as Stacks.convert format.PEEM'
	tif_convert
    END

'Read.Stacks.TXRM.Alba.Mistral' : BEGIN
;  ******************* Read .Alba-Mistral TXM stacks  *****************
;   	norm=100.  ; normalize to standard start-of-fill value (or top-up)
;  	t=dialog_message('Normalize to ring current ?',/question)
 ;	if t EQ 'Yes' then begin
;	   	norm = get_num(prompt='standard ring current', val=norm, group = axis_ID)
 ; 	endif else  norm = 0
 	tmp = read_txm_alba()

    END

 'Read.Stacks.TXRM.Xradia' : BEGIN
;  ********** read in set of TXRM images (Shanghai STXM format)  ******
	tmp = ax_read_txrm_stack()
	if tmp NE '0' then $
		stack_process, tmp, /no_align, /binary, title = stack_name
    END

 'Read.Stacks.XRF.Inca' : BEGIN
;  *********** Read  XRF(x,y) written by Oxford Inca (export to 'RAW') *****************
   	WIDGET_CONTROL, /Hourglass
    tmp = read_XRF_stack(/inca, group=aXis_ID)
    END

 'Read.Stacks.XRF.STXM_control.one energy' : BEGIN
;  ********** Read XRF(x,y) at one photon energy (written by STXM_control) *************
   	WIDGET_CONTROL, /Hourglass
    tmp = read_XRF_stack(group=aXis_ID)
    END

 'Read.Stacks.XRF.STXM_control.multiple energies' : BEGIN
;  ********** Read XRF(x,y,E) at multipe photon energies (written by STXM_control) ******
   	WIDGET_CONTROL, /Hourglass
    tmp = read_XAS_XRF_stack(group=aXis_ID)
    END

'Read.Stacks.XRF.XGLabs.text (*.dta)' : BEGIN
;   *************** convert 1-channel or sum  XGLabs *.dta without zeros to PYMCA compatible input  *********
	tmp = ax_xrf_convert(group=aXis_ID, /silent)
	if n_tags(tmp) NE 0 then begin
	  	CurBuf = 0
		HANDLE_VALUE, Data(CurBuf), tmp, /set
		PlotBuf,CurBuf
  	ENDIF
    END

'Read.Stacks.XRF.XGLabs.hdf5' : BEGIN
;   *************** convert XGLabs HDF5 XRF maps to aXis2000 stacks (*.ncb,*.dat) *********
  tmp = read_xrf_stack_hdf5(/spect)
  if n_tags(tmp) NE 0 then begin
      CurBuf = 0
    HANDLE_VALUE, Data(CurBuf), tmp, /set
    PlotBuf,CurBuf
    ENDIF
    END

; *****************************************************************
; #################### WRITE to file images and spectra  ##########
; *****************************************************************

'Write.AXIS' : BEGIN
; ************* 'Write (1d) or (2d) data to AXIS-format file' ********************
  	  HANDLE_value, Data(CurBuf), tmp
  	  IF n_tags(tmp) NE 0 THEN begin
     	WIDGET_CONTROL, /Hourglass
 	    CASE tmp.t OF
 	    '1d' : file = spc_save(tmp)
 	    '2d' : file = axb_save(tmp)
 	    else :  axis_log, ' AXIS buffer type not 1d or 2d: no file written '
 	    ENDCASE
 	  	PlotBuf, Curbuf         ; replot to update label on current plot
      endif
    END

  'Write.ALS-xyt' : BEGIN
;	*********** Write GIF file of MainImg *****************
    HANDLE_value, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 THEN return
	IF tmp.t EQ '2d' then test = litho_save(tmp)
    END

  'Write.Graphics.GIF.image' : BEGIN
;	*********** Write GIF file of MainImg *****************
  	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 THEN RETURN
	SetGraf, 'MainImg'
	file = pickfile2(/write,filter='*.gif', /lpath, DefPath=DefPath)
	IF file NE '' then begin
		b = tvrd()
     	WIDGET_CONTROL, /Hourglass
		Write_GIF, file, b
		t = ax_name(file)
   		axis_log, 'wrote image as GIF to ' + t(1)
   	ENDIF
    END

  'Write.Graphics.GIF.data' : BEGIN
;	*********** Write GIF file of data only *****************
  	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 THEN RETURN
	IF tmp.t NE '2d' then RETURN     ; ONLY write out 2d data
	SetGraf, 'MainImg'
	file = pickfile2(/write, filter='*.gif',/lpath, DefPath=DefPath)
	IF file NE '' then begin
	 	WIDGET_CONTROL, /Hourglass
		Write_GIF, file, bytscl(tmp.d)
		t = ax_name(file)
	   	axis_log, 'wrote data as GIF to ' + t(1)
	ENDIF
    END

  'Write.Graphics.JPG.image' : BEGIN
;	*********** Write jpg file of MainImg *****************
  	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 THEN RETURN
	SetGraf, 'MainImg'
	file = pickfile2(/write,filter='*.jpg', /lpath, DefPath=DefPath)
	IF file NE '' then begin
		b = tvrd()
     	WIDGET_CONTROL, /Hourglass
		Write_JPEG, file, b
		t = ax_name(file)
   		axis_log, 'wrote image as jpg  to ' + t(1)
   	ENDIF
    END

  'Write.Graphics.JPG.data' : BEGIN
;	*********** Write jpg file of data only *****************
  	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 THEN RETURN
	IF tmp.t NE '2d' then RETURN     ; ONLY write out 2d data
	SetGraf, 'MainImg'
	file = pickfile2(/write, filter='*.jpgf',/lpath, DefPath=DefPath)
	IF file NE '' then begin
	 	WIDGET_CONTROL, /Hourglass
		Write_JPEG, file, bytscl(tmp.d)
		t = ax_name(file)
	   	axis_log, 'wrote data as jpg to ' + t(1)
	ENDIF
    END

 'Write.Graphics.PNG.image' : BEGIN
;	*********** Write PNG file of complete MainImg *****************
  	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 THEN RETURN
	file = pickfile2(/write,filter='*.png', /lpath, DefPath=DefPath)
	IF file NE '' then begin
     	WIDGET_CONTROL, /Hourglass
		SetGraf, 'MainImg'
		b = tvrd()
		scaled = BytScl(b, Top=ax_top_color_index)
		s = Size(scaled, /Dimensions)
  		image24 = BytArr(3, s[0], s[1])
		TVLCT, r, g, b, /Get
		image24[0, *, *] = r[scaled]
		image24[1, *, *] = g[scaled]
		image24[2, *, *] = b[scaled]
		Write_PNG, file, image24
		axis_log, 'wrote image as 24-bit PNG to ' + file
   	ENDIF
    END

 'Write.Graphics.PNG.data' : BEGIN
;	*********** Write PNG file of data only *****************
  	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 THEN RETURN
	file = pickfile2(/write,filter='*.png', /lpath, DefPath=DefPath)
	IF file NE '' then begin
     	WIDGET_CONTROL, /Hourglass
		scaled = BytScl(tmp.d, Top=ax_top_color_index)
		s = Size(scaled, /Dimensions)
  		image24 = BytArr(3, s[0], s[1])
		TVLCT, r, g, b, /Get
		image24[0, *, *] = r[scaled]
		image24[1, *, *] = g[scaled]
		image24[2, *, *] = b[scaled]
		Write_PNG, file, image24
		t = ax_name(file)
		axis_log, 'wrote data as 24-bit PNG to ' + t(1)
   	ENDIF
    END


'Write.Graphics.TIF.image' : BEGIN
;	*********** Write TIF file of MainImg *****************
  	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp)EQ 0 THEN RETURN
	file = pickfile2(/write,filter='*.tif',/lpath,DefPath=DefPath)
	IF file NE '' then begin
		SetGraf, 'MainImg'
		b = tvrd()
     	WIDGET_CONTROL, /Hourglass
;		Win2Tif, file, /real      ; OLD pre 20-Jul-17
		Write_tiff, file, rotate(b,7)
		t = ax_name(file)
		axis_log, 'wrote image as 8-bit gray scale TIF to ' + t(1)
		ax_wait,/off
	ENDIF
    END

  'Write.Graphics.TIF.data' : BEGIN
;	*********** Write TIF file of MainImg *****************
  	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 THEN RETURN
	IF tmp.t NE '2d' THEN RETURN
	file = pickfile2(/write,filter='*.tif',/lpath,DefPath=DefPath)
	IF file NE '' then begin
;   	WIDGET_CONTROL, /Hourglass			; new version (20-Jul-17, aph)
		scaled = BytScl(tmp.d, Top=ax_top_color_index)
		s = Size(scaled, /Dimensions)
  		image24 = BytArr(3, s[0], s[1])
		TVLCT, r, g, b, /Get
		image24[0, *, *] = r[scaled]
		image24[1, *, *] = g[scaled]
		image24[2, *, *] = b[scaled]
		Write_tiff, file, bytscl(rotate(tmp.d,7))
		t = ax_name(file)
		axis_log, 'wrote data as 8-bit, 3-channel TIF to ' + t(1)
		ax_wait,/off
		ENDIF
; old version, using Win2tif, before 20 July 2017
;		nxp = n_elements(tmp.x)  &  nyp = n_elements(tmp.y)
;		window, xsize = nxp, ysize = nyp
;		ax_color, /noload
;		tvscl, tmp.d
;   	WIDGET_CONTROL, /Hourglass
;		Win2Tif, file, /real, /gray
;		t = ax_name(file)
;		axis_log, 'wrote data as TIF to ' + t(1)
;		wdelete
;		ax_wait,/off
;	ENDIF
    END

'Write.ALS-image' : BEGIN
 ; ************* Write Image to ALS format file (*.im1, *.dat) ********************
  	  HANDLE_value, Data(CurBuf), tmp
  	  IF n_tags(tmp) NE 0 THEN begin
  	     if  tmp.t EQ '2d' THEN BEGIN
  	     	WIDGET_CONTROL, /Hourglass
  	     	file=sav_als(tmp)
  	     endif else axis_log, 'Write.ALS-image: only for images'
      endif
    END


'Write.ascii image.reals' :  BEGIN
; ************* 'Write (1d) or (2d) data to AXIS-format file as REALS' ********************
  	  HANDLE_value, Data(CurBuf), tmp
  	  IF n_tags(tmp) NE 0 THEN begin
     	WIDGET_CONTROL, /Hourglass
 	    file = spc_save(tmp)
 	  	PlotBuf, Curbuf         ; replot to update label on current plot
      endif
    END

'Write.ascii image.integers' :  BEGIN
; ************* 'Write (1d) or (2d) data to AXIS-format file as REALS' ********************
  	  HANDLE_value, Data(CurBuf), tmp
  	  IF n_tags(tmp) NE 0 THEN begin
     	WIDGET_CONTROL, /Hourglass
 	    file = spc_save(tmp, /int_factor)
 	  	PlotBuf, Curbuf         ; replot to update label on current plot
      endif
    END

'Write.NSLS-image (*.nc)' : BEGIN
  ; ************* Write Image to NSLS format file (*.nc)  ********************
 	  HANDLE_value, Data(CurBuf), tmp
 	  IF n_tags(tmp) NE 0 THEN begin
 	     if  tmp.t EQ '2d' THEN BEGIN
	      	WIDGET_CONTROL, /Hourglass
	     	file=sav_nsls(tmp)
      	endif else axis_log, 'Write.NSLS-image: only for images'
    endif
    END

'Write.SDF format' : BEGIN
; ************* 'Write (1d) or (2d) data to AXIS-format file' ********************
  	  HANDLE_value, Data(CurBuf), tmp
  	  IF n_tags(tmp) NE 0 THEN begin
  	    CASE tmp.t OF
 	    '1d' : file = write_sdf(tmp)
 	    '2d' : file = write_sdf(tmp)
 	    else :  axis_log,  ' AXIS buffer type not 1d or 2d: no file written '
 	    ENDCASE
      endif
    END

'Write.XAS single/multiple' : BEGIN
  ; *********** Write 1 or multiple spectra to NSLS XAS format file (*.xas)  ***********
  HANDLE_value, Data(CurBuf), tmp
  IF n_tags(tmp) EQ 0 THEN return
  IF tmp.t EQ '1d' THEN BEGIN
  	  IF pNum EQ 1 then ax_write_xas,tmp else $		; single spectrum  write
           ax_write_xas,tmp, /multi, /nof				; multiple spectrum write
  ENDIF else axis_log, 'Write XAS spectrum: only for spectra'
 END

; *****************************************************************
; ################ ZOOM (and cut) images or spectra ###############
; *****************************************************************

'Zoom.Image.Pan' : BEGIN
; ************************* Zoom image using IDL ZOOM function (pans) *****************
	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) NE 0 THEN BEGIN
	   IF tmp.t EQ '2d' then BEGIN
		   	if pan_smooth EQ 1 then begin
				text = string(format='("Left - set zooom factor",/,"Right - quit zoom",A)','')
				axis_log,  text
			endif else begin
				text = string(format='("Left - replot",/,"Middle - zoom parameters",/,"Right - quit zoom",A)','')
				axis_log,  text
			endelse
		    wset, MainImg
		    wsz = fix(360*gr_scale/1.5)
	        if pan_smooth EQ 1 then ax_zoom_pan,/continuous, /interp, xsize=wsz, ysize=wsz
	        if pan_smooth EQ 0 then ax_zoom_pan, /interp, xsize=wsz, ysize=wsz
	   endif
   endif
   END

'Zoom.Image.Cursor - cut' : BEGIN
; ************* use a marquee (Box cursor) to select & cut zoom region ***********
	AX_ZOOM_CURSOR
END

'Zoom.Image.Numerical-cut(in data units)' : BEGIN
;  ***********'Event for Zoom.Numerical' ******************
 ax_zoom_cut
 END

'Zoom.Spectra.Cursor' : BEGIN
; ************************* Zoom plot using Box Cursor *****************
 HANDLE_VALUE, pData(0), tmp
 IF n_tags(tmp) NE 0 THEN BEGIN
	If tmp.t EQ '1d' then BEGIN
	    SetGraf,'MainImg'     ; restore image (x,y) scaling parameters
		text = string(format='("Left - resize",/,"Middle - move",/,"Right - done",A)','')
		axis_log,  text
		BX_CURSOR, xl, yl, w, h , COLOR = 100   ; define a region to zoom
		ll=CONVERT_COORD(xl, yl, /DEVICE, /TO_DATA)   ;Convert to data coordinates
    	ur=CONVERT_COORD(xl + w, yl + h, /DEVICE, /TO_DATA)
		!y.range(0)=ll(1)    &  !y.range(1)=ur(1)       ;Set the zoom
		!x.range(0)=ll(0)    &  !x.range(1)=ur(0)
		Xrng = !x.range      & 	Yrng = !y.range
		Refresh
	ENDIF  else axis_log, 'Zoom.spectra : not for images'
 ENDIF
 END

'Zoom.Spectra.Normal' : BEGIN
  ; ***********************  Reset spectrum to full (x,y) range ******************
  	SetGraf,'MainImg'     ; restore image (x,y) scaling parameters
    !y.range=0  &  !x.range=0
	Refresh
    END

'Zoom.Spectra.Out x2' : BEGIN
;   ****************** Zoom out spectrum x 2    **********************************
     SetGraf,'MainImg'     ; restore image (x,y) scaling parameters
    !x.range(0) = Xrng(0) - (Xrng(1)-Xrng(0))/2
    !x.range(1) = Xrng(1) + (Xrng(1)-Xrng(0))/2
    !y.range(0) = Yrng(0) - (Yrng(1)-Yrng(0))/2
    !y.range(1) = Yrng(1) + (Yrng(1)-Yrng(0))/2
    Xrng = !x.range
    Yrng = !y.range
    Zrng = !y.range
    Refresh
    END

'Zoom.Spectra.Numerical' : BEGIN
;   ***************** Zoom out spectrum using numerical limits  ****************
	SetGraf,'MainImg'     ; restore image (x,y) scaling parameters
  	!x.range(0) = Get_Num(PROMPT = "X min: ", Val=Xrng(0), group=axis_ID)
  	!x.range(1) = Get_Num(PROMPT = "X max: ", Val=Xrng(1), group=axis_ID)
  	!y.range(0) = Get_Num(PROMPT = "Y min: ", Val=Yrng(0), group=axis_ID)
  	!y.range(1) = Get_Num(PROMPT = "Y max: ", Val=Yrng(1), group=axis_ID)
  	Xrng = !x.range
    Yrng = !y.range
    Zrng = !y.range
  	Refresh
	END


; **************************************************************************
; ###########  FILTER - valid for BOTH images and spectra #################
; **************************************************************************

'Filter.Smooth' : BEGIN
; ********  Smooth Filter - user selects level **********
  HANDLE_VALUE, Data(CurBuf), tmp
  IF n_tags(tmp) NE 0 THEN BEGIN
  	IF N_ELEMENTS(nsmooth) EQ 0 THEN nsmooth = 3
	nsmooth=get_num(Prompt='# of pts.',val=nsmooth, group=axis_ID)
	WIDGET_CONTROL, /Hourglass
    tmp.d = smooth(tmp.d,nsmooth,/edge_truncate, /NaN)
    CurBuf = 0
	tmp.dl =  tmp.dl + ' S' + strtrim(string(fix(nsmooth)),2)
	Label(CurBuf) = tmp.dl
	HANDLE_VALUE, Data(CurBuf), tmp, /set
	PlotBuf,CurBuf
   ENDIF
   END

'Filter.Median' : BEGIN
; ********  Median Filter - user selects level **********
  HANDLE_VALUE, Data(CurBuf), tmp
  IF n_tags(tmp) NE 0 THEN BEGIN
  	IF N_ELEMENTS(nsmooth) EQ 0 THEN nsmooth = 3
	nsmooth=get_num(Prompt='# of pts.',val=nsmooth, group=axis_ID)
	WIDGET_CONTROL, /Hourglass
    tmp.d = median(tmp.d,nsmooth)
    CurBuf = 0
	tmp.dl =  tmp.dl + ' M' +  strtrim(string(fix(nsmooth)),2)
	Label(CurBuf) = tmp.dl
	HANDLE_VALUE, Data(CurBuf), tmp, /set
	PlotBuf,CurBuf
   ENDIF
   END

'Filter.Lee Filter' : BEGIN
; *************     Lee Filter *******************
    HANDLE_VALUE, Data(CurBuf), tmp
    IF n_tags(tmp) NE 0 THEN BEGIN
  	axis_log, 'Size of the filter box is 2N+1. Default=5.'
  	axis_log, 'Estimate of standard deviation. Default=5.'
  	axis_log, 'If SIG is -ve, IDL prompts, TVSCLs until SIG=0.'
   	ml = get_num(Prompt='Filter box', val=5, group=axis_ID)
   	sig = get_num(Prompt='Sigma', val=5, group=axis_ID)
    tmp.d = leefilt(tmp.d, ml(0),sig(0))
    CurBuf = 0
	tmp.dl = tmp.dl + ' LF'
	Label(CurBuf) = tmp.dl
	HANDLE_VALUE, Data(CurBuf), tmp, /set
	PlotBuf,CurBuf
   ENDIF
   END

'Filter.Convol' : BEGIN
; *************  Convolution Filter **************
  HANDLE_VALUE, Data(CurBuf), tmp
  IF n_tags(tmp) NE 0 THEN BEGIN
  	axis_log, 'Digital filtering: '
	axis_log, 'No Filtering: Flow = 0, Fhigh = 1'
	axis_log, 'Low Pass:	  Flow = 0, 0 < Fhigh < 1'
	axis_log, 'High Pass  0 < Flow < 1, Fhigh =1'
	axis_log, 'Band Pass: 0 < Flow < Fhigh < 1'
	axis_log, 'Band Stop: 0 < Fhigh < Flow < 1'
	flo = get_num(prompt='F_low', val= 0.01, group=axis_ID)
    fhi = get_num(prompt='F_high',val= 0.5, group=axis_ID)
    ord = get_num(prompt='Order ',val=5.0, group=axis_ID)
    Coeff = DIGITAL_FILTER(Flo(0), Fhi(0), 50, Ord(0))
    tmp.d = convol(tmp.d,coeff)
    CurBuf = 0
	tmp.dl = tmp.dl + ' Convol'
	Label(CurBuf) = tmp.dl
	HANDLE_VALUE, Data(CurBuf), tmp, /set
	PlotBuf,CurBuf
  ENDIF
  END

'Filter.Clean (FT image filter)' : BEGIN
; ************ implements 2d Fourier filtering to remove low freq. components *********
; -------NB - generate high freq, and subtract to use as high freq. or bandpass filter
  HANDLE_VALUE, Data(CurBuf), tmp
  IF n_tags(tmp) NE 0 THEN BEGIN
  	IF tmp.t EQ '2d' THEN BEGIN
  		t = tmp.d
  		Clean, t
		tmp.d = t
	    CurBuf = 0
		tmp.dl = tmp.dl + ' FT-clean'
		Label(CurBuf) = tmp.dl
		HANDLE_VALUE, Data(CurBuf), tmp, /set
		PlotBuf,CurBuf
  	ENDIF ELSE axis_log, 'Clean: only for images'
  ENDIF
  END


; *****************************************************************
; ########### Image_Process - specific to IMAGES ##################
; *****************************************************************

'Images.Add.Append' : BEGIN
;  ***** Append two images with averaging in common (x,y) region *****************
	AX_IMAGE_APPEND
 END

'Images.Add.Buffer' : BEGIN
;  ***** Add or Subtract two images in common (x,y) region *****************
	AX_IMAGE_ADD
 END

'Images.Add.Constant' : BEGIN
; ******** add or subtract a constant from all pixels (eg for detector offsets) ********
  	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) NE 0 THEN BEGIN
		IF tmp.t EQ '2d' THEN BEGIN
	      constant = get_num(val = constant, prompt='# to add ?', group=axis_ID)
	      tmp.d = tmp.d + constant
	      CurBuf = 0
		  tmp.dl = tmp.dl + ' + ' + STRCOMPRESS(string(constant))
		  HANDLE_VALUE, Data(CurBuf), tmp, /set
		  Label(CurBuf) = tmp.dl
		  PlotBuf,CurBuf
		ENDIF ELSE axis_log,  'Image add: only for images'
   ENDIF
   END

'Images.Average pixels.whole image - all pixels' : BEGIN
; ******** average user-selected region if an image (all pixels) ********
   ax_img_avg, /whole
   END

'Images.Average pixels.whole image - ignore zeros' : BEGIN
; ******** average user-selected region if an image (all pixels) ********
   ax_img_avg, /whole, /nozeros
   END

'Images.Average pixels.region - all pixels' : BEGIN
; ******** average user-selected region if an image (all pixels) ********
   ax_img_avg
   END

'Images.Average pixels.region - ignore zeros' : BEGIN
; ******** average user-selected region if an image (ONLY non-zero pixels) ********
	ax_img_avg, /nozeros
   END

'Images.bin' : BEGIN
;   *************** bin current image *********
	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 THEN RETURN
	IF tmp.t NE '2d' THEN RETURN
	if n_elements(img_bin) LE 0 then img_bin = 2
	img_bin=get_num(Val=img_bin,PROMPT='bin *', group=axis_ID)
	if n_elements(img_SumAvg) LE 0 then img_SumAvg = 'A'
	img_SumAvg = get_text(Val=img_SumAvg,PROMPT='Sum(S) or Average(A)', group=axis_ID)
	n_cols=n_elements(tmp.x)  &  n_rows=n_elements(tmp.y)
	x_start = tmp.x(0)  &  x_stop = tmp.x(n_elements(tmp.x)-1)
	y_start = tmp.y(0)  &  y_stop = tmp.y(n_elements(tmp.y)-1)
	image_data = tmp.d
    if (float(n_cols)/float(img_bin))-fix(n_cols/img_bin) GT 0 $
		OR (float(n_rows)/float(img_bin))-fix(n_rows/img_bin) then begin
        nct =fix(n_cols/img_bin)*img_bin  &  nrt = fix(n_rows/img_bin)*img_bin
        xtra_c = n_cols - nct + 1
        xtra_r = n_rows - nrt + 1
	    x_stop = x_stop*float(nct)/float(n_cols)  ; correct axis length for truncation
        y_stop = y_stop*float(nrt)/float(n_rows)
        axis_log, 'image truncated to ' +  strtrim(string(fix(nct),2)) + strtrim(string(fix(nrt),2))
        tmp2 = tmp.d                      ;force size to integer mutiple of img_bin
        image_data = intarr(nct,nrt)
		image_data = tmp2(0:n_cols-xtra_c,0:n_rows-xtra_r)
    endif
    n_cols = fix(n_cols/img_bin)
    n_rows = fix(n_rows/img_bin)
    axis_log, 'bin image x' + strtrim(string(fix(img_bin),2)) + ' to ' +  strtrim(string(n_cols),2) + '  x ' + strtrim(string(n_rows),2)
    bin_data = fltarr(n_cols,n_rows)
    bin_data = rebin(image_data,n_cols,n_rows)
    if img_SumAvg NE 'A' then bin_data = bin_data*img_bin*img_bin
    x = fltarr(n_cols)  & y = fltarr(n_rows)
    x_step = (x_stop - x_start)/float(n_cols)
    y_step = (y_stop - y_start)/float(n_rows)
    x = x_start + findgen(n_cols)*x_step
    y = y_start + findgen(n_rows)*y_step
    print, 'binned X: min, max:', x(0), x(n_elements(x)-1)
	dl = tmp.dl + ' bin ' + STRCOMPRESS(string(fix(img_bin))) + ' avg'
	if img_SumAvg NE 'A' then dl = tmp.dl + ' bin ' + STRCOMPRESS(string(fix(img_bin)))  + ' sum'
	tmp2 = {t:'2d', d: bin_data, E: tmp.E, x: x, y: y, xl: tmp.xl, yl: tmp.yl, dl: dl}
;	help, tmp2, /struct
  	CurBuf = 0
	HANDLE_VALUE, Data(CurBuf), tmp2, /set
	Label(CurBuf) = tmp2.dl
	PlotBuf,CurBuf
  END

'Images.Calibrate XY.1 point' : BEGIN
;   **************************** Calibrate XY-values of image  *********
	AX_XYCal,/one
  END

'Images.Calibrate XY.2 points' : BEGIN
;   **************************** Calibrate XY-values of image  *********
	AX_XYCal
  END

'Images.Clip signal.histogram' : BEGIN
;  *************************** Clip image or spectra at user limits *********
 	HANDLE_VALUE, Data(CurBuf), tmp
   	IF n_tags(tmp) NE 0 THEN BEGIN
   		IF tmp.t EQ '2d' THEN BEGIN
			SetGraf, 'MainImg'
			tmp = clip(tmp)
		   	CurBuf = 0
		   	Label(CurBuf) = tmp.dl
		   	HANDLE_VALUE, Data(CurBuf), tmp, /set
		   	PlotBuf, CurBuf
		ENDIF ELSE axis_log, 'Clip: only for images'
    ENDIF
    END

'Images.Clip signal.numerical' : BEGIN
;  *************************** Clip image or spectra at user limits *********
 	HANDLE_VALUE, Data(CurBuf), tmp
   	IF n_tags(tmp) NE 0 THEN BEGIN
   		IF tmp.t EQ '2d' THEN BEGIN
			SetGraf, 'MainImg'
			tmp = clip(tmp, /numeric)
		   	CurBuf = 0
		   	Label(CurBuf) = tmp.dl
		   	HANDLE_VALUE, Data(CurBuf), tmp, /set
		   	PlotBuf, CurBuf
		ENDIF ELSE axis_log, 'Clip: only for images'
    ENDIF
    END

'Images.Convert_to_OD' : BEGIN
;  *************************** Convert_to_OD *********
 	HANDLE_VALUE, Data(CurBuf), tmp
   	IF n_tags(tmp) EQ 0 THEN RETURN
	IF tmp.t EQ '2d' THEN BEGIN
		SetGraf, 'MainImg'
		Io=max(tmp.d)
		Io = get_num(prompt = 'Io level',val = Io, group=axis_ID)
		tmp.d = -1.*alog(float(tmp.d)/Io)
; remove NaN and replace with median value
		bad_data = where(finite(tmp.d) EQ 0,count)
		if count gt 0 then begin
			t = moment(tmp.d,/nan)
			tmp.d(bad_data) = t(0)
			text = 'convert_to_OD: WARNING - ' + strcompress(string(count)) + ' NaN or Inf pixels set to mean'
			axis_log, text
		endif
	   	CurBuf = 0
	   	tmp.dl = tmp.dl + ' OD'
	   	Label(CurBuf) = tmp.dl
	   	HANDLE_VALUE, Data(CurBuf), tmp, /set
	   	PlotBuf, CurBuf
	ENDIF ELSE axis_log,  'Convert_to_OD: only for images'
    END

'Images.Cross-link density' : BEGIN
;  *************************** Compute cross-link density from volume fractions *********
 	HANDLE_VALUE, Data(CurBuf), tmp
   	IF n_tags(tmp) NE 0 THEN BEGIN
   		IF tmp.t NE '2d' THEN RETURN
   		WIDGET_CONTROL, Uprompt, $
   		   Set_Value = 'Cross-link evaluation must start with volume fraction image'
		SetGraf, 'MainImg'
		V2 = tmp.d
		CLD = V2
		CLD = -55.5*V2^(-0.3333)*[alog(1-V2)+V2+0.469*V2*V2]
		tmp.d = CLD
	   	CurBuf = 0
	   	tmp.dl = tmp.dl + ' XL'
	   	Label(CurBuf) = tmp.dl
	   	HANDLE_VALUE, Data(CurBuf), tmp, /set
	   	PlotBuf, CurBuf
    ENDIF
    END

'Images.Deglitch' : BEGIN
  ; ***********  glitch removal by excluding extrema (last changed: 10-may-99) ********
  	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) NE 0 THEN BEGIN
		IF tmp.t EQ '2d' THEN BEGIN
			SetGraf, 'MainImg'
			a = tmp.d
			tmp.d = deglitch(tmp.d)
			tmp.d = a
		   	tmp.dl = tmp.dl + ' DeGl'
		   	CurBuf = 0
		   	Label(CurBuf) = tmp.dl
		   	HANDLE_VALUE, Data(CurBuf), tmp, /set
		   	PlotBuf,CurBuf
	  		WIDGET_CONTROL, Uprompt, Set_Value = ''
	   	ENDIF ELSE axis_log,  'Deglitch: only for images'
   	ENDIF
  	END

'Images.Delete region' : BEGIN
;   ******************** delete user-selected region of image  *********
	AX_img_del
  END

'Images.Distort XY scale' : BEGIN
;   ******************** Warp X versus Y pixel size  of image  *********
	AX_XYDis
  END

'Images.Fix rollover.1' : BEGIN
 ; *********************** Fix rollover (add 65535) for PEEM ***************
    HANDLE_VALUE, Data(CurBuf), tmp
     IF n_tags(tmp) EQ 0 THEN RETURN
     IF tmp.t NE '2d' THEN RETURN
     neg_ind = where(tmp.d LT 0, count)
     if count GT 0 then begin
      	tmp.d(neg_ind) = tmp.d(neg_ind)+ 65535.
      	tmp.d(1,1) = tmp.d(1,1) +1e-6*tmp.d(1,1)   ; kluge to force REAL *,nc file !
        CurBuf = 0
	   	tmp.dl = tmp.dl + ' FR'
	   	Label(CurBuf) = tmp.dl
	  	HANDLE_VALUE, Data(CurBuf), tmp, /set
	   	PlotBuf,CurBuf
	 endif else axis_log, 'Fix rollover - no negative numbers'
     END

'Images.Fix rollover.many' : BEGIN
 ; *********************** Fix rollover (add 65535) for PEEM ***************
	 t = ax_fix_rollover()
     END

'Images.FRC - resolution' : BEGIN
;   ********************* compute Fourier Ring Correlation  *********
   HANDLE_VALUE, Data(CurBuf), tmp
   IF n_tags(tmp) NE 0 THEN BEGIN
   	if tmp.t EQ '2d' then begin
		t = ax_frc(image=tmp, group=aXis_ID)
		if n_tags(t) NE 0 THEN BEGIN
	      	CurBuf = 0
	   		HANDLE_VALUE, Data(0), tmp
	   		splot, tmp, thick=4, /zero
	   		HANDLE_VALUE, Data(7), tmp
	   		splot, tmp, /o
	   		HANDLE_VALUE, Data(8), tmp
	   		splot, tmp, /o
	     	HANDLE_VALUE, Data(9), tmp
	   		splot, tmp, /o
	   	endif
   	 endif else axis_log, 'FRC: only for images'
   ENDIF
  END

'Images.Gain.Multiply' : BEGIN
;   **************************** Scale Z-values of image  *********
   HANDLE_VALUE, Data(CurBuf), tmp
   IF n_tags(tmp) NE 0 THEN BEGIN
   	if tmp.t EQ '2d' then begin
   		gain_m = get_num(val = gain_m, prompt='Multiply by ...', group=axis_ID)
    	tmp.d = gain_m*tmp.d
      	CurBuf = 0
   		tmp.dl = tmp.dl + ' * ' + STRCOMPRESS(string(gain_m))
   		HANDLE_VALUE, Data(CurBuf), tmp, /set
   		Label(CurBuf) = tmp.dl
   		PlotBuf,CurBuf
   	  endif else axis_log, 'Z-scale: only for images'
   ENDIF
  END

'Images.Gain.Divide' : BEGIN
;   ********************* Divide Z-values of image by constant  *********
   HANDLE_VALUE, Data(CurBuf), tmp
   IF n_tags(tmp) NE 0 THEN BEGIN
   	if tmp.t EQ '2d' then begin
   		gain_d = get_num(val = gain_d, prompt='Divide by ...', group=axis_ID)
    	tmp.d = tmp.d / gain_d
      	CurBuf = 0
   		tmp.dl = tmp.dl + ' / ' + STRCOMPRESS(string(gain_d))
   		HANDLE_VALUE, Data(CurBuf), tmp, /set
   		Label(CurBuf) = tmp.dl
   		PlotBuf,CurBuf
   	  endif else axis_log, 'Z-scale: only for images'
   ENDIF
  END

'Images.generate mask.threshold.histogram' : BEGIN
 ; *********************** generate Mask (>=1, <=0) ********************
 if float(!version.release) LT 6.3 then begin
	  	test = dialog_message(/info, 'method does not work for IDL versions pre 6.3')
  endif else begin
	  	HANDLE_VALUE, Data(CurBuf), tmp
	    IF n_tags(tmp) EQ 0 THEN RETURN
	  	ax_select
  endelse
  end

'Images.generate mask.threshold.minimum' : BEGIN
 ; *********************** generate Mask (>=1, <=0) ********************
    HANDLE_VALUE, Data(CurBuf), tmp
    IF n_tags(tmp) EQ 0 THEN RETURN
    threshold = get_num(val = 0.5, prompt='threshold value (> set to 1, < set to 0) ?', group=axis_ID)
    low = where(tmp.d LT threshold, lcount)
;    print, 'No. of points lower = ',lcount
    if lcount GT 0 then tmp.d(low) = 0.0
    high = where(tmp.d GE threshold, hcount)
;    print, 'No. of points higher = ',hcount
    if hcount GT 0 then tmp.d(high) = 1.0
	CurBuf = 0
   	tmp.dl = tmp.dl + ' Mask > ' + strcompress(string(threshold, format='(g8.2)'))
   	Label(CurBuf) = tmp.dl
  	HANDLE_VALUE, Data(CurBuf), tmp, /set
   	PlotBuf,CurBuf
   	roi_file = pickfile2(/write, FILTER='*.roi', /LPATH, DEFPATH=defpath)
   	if roi_file NE '' then begin
   		t = ax_name(roi_file)
   		roi_file = t(0)+t(1) + '.roi'
   		openw,lun,roi_file,/xdr, /get_lun
		writeu,lun,n_elements(high),0
		writeu,lun,long(high)
		close,lun & free_lun,lun
		t = ax_name(roi_file)
		axis_log,'Wrote ROI file: ' + t(1)
	endif
  END


'Images.generate mask.manual' : BEGIN
 ; *********************** generate Mask (>=1, <=0) ********************
     HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 THEN RETURN
	IF tmp.t EQ '2d' THEN BEGIN
		SetGraf, 'MainImg'
		erase
		loadct,ColTbl,/silent
		ncol = n_elements(tmp.x) & nrow = n_elements(tmp.y)
		img_size = max([ncol, nrow])
		if img_size GT 360*gr_scale then begin
			img_zoom =  floor(img_size / 360*gr_scale) + 1  ;for images larger than 360*gr_scale
			text = '1/' + string(img_zoom, format='(I2)')
			axis_log, 'image rescaled by  ' + text  + ' before manual mask generation'
			t_img = congrid(tmp.d, fix(ncol/img_zoom), fix(nrow/img_zoom), cubic = -0.5)
			tvscl, t_img
		 	roi = cw_defroi(MainWid, image_size = [ncol/img_zoom, nrow/img_zoom])
			svec = size(roi)
			IF svec(0) EQ 0 then RETURN	; proceed only if roi is real region
			t_img(*,*) = 0
			t_img(roi) = 1		; generate mask
			tmp.d = congrid(t_img, ncol, nrow, cubic = -0.5)
			tmp.d(where(tmp.d GT 0.5)) = 1 	; clean up as congrid does not get values exactly 1
		endif
		if img_size GE 160*gr_scale AND img_size LE 360*gr_scale then begin
		    tvscl, tmp.d
		    roi = cw_defroi(MainWid, image_size = [ncol,nrow])
			svec = size(roi)
			IF svec(0) EQ 0 then RETURN	; proceed only if roi is real region
			tmp.d = 0
			tmp.d(roi) = 1		; generate mask
		endif
		if img_size LT 160*gr_scale then begin
		    img_zoom =  floor(360*gr_scale / img_size)
		    text = string(img_zoom, format='(I2)')
		    axis_log, 'image rescaled by  ' + text  + ' before manual mask generation'
		    tvscl, rebin(tmp.d, img_zoom*ncol,img_zoom*nrow)
		    roi = cw_defroi(MainWid, image_size = [ncol,nrow], zoom =[img_zoom, img_zoom])
			svec = size(roi)
			IF svec(0) EQ 0 then RETURN	; proceed only if roi is real region
			tmp.d = 0
			tmp.d(roi) = 1		; generate mask
		endif

		ax_color
		roi_file = pickfile2(/write, FILTER='*.roi', /LPATH, DEFPATH=defpath)
	   	if roi_file NE '' then begin
	   		t = ax_name(roi_file)
	   		roi_file = t(0)+t(1) + '.roi'
	   		openw,lun,roi_file,/xdr, /get_lun
			writeu,lun,n_elements(roi),0
			writeu,lun,long(roi)
			close,lun & free_lun,lun
			print,'Wrote ROI file: ', roi_file
	   	endif
		CurBuf = 0
		tmp.dl = tmp.dl + ' mask.manual '
		HANDLE_VALUE, Data(CurBuf), tmp, /set
		PlotBuf, CurBuf
		Label(CurBuf) = tmp.dl
	ENDIF ELSE axis_log, 'Images.generate.mask.manual: only for images'
	END

'Images.histogram' : BEGIN
 ; *********************** generate a histogram of the image z-values ********************
     HANDLE_VALUE, Data(CurBuf), tmp
     IF n_tags(tmp) NE 0 THEN BEGIN
		SetGraf, 'MainImg'
		n_bins = 400
		dt = tmp.d
		xt = findgen(n_bins) & xmn = min(dt, max=xmx)
		xt = xmn + xt*(xmx-xmn)/n_bins
		dtz = histogram(double(dt), binsize = double((xmx-xmn)/n_bins), /nan)
		t = size(dtz)  & dtzn = lonarr(t(1))	; KLIGE to get around corrupted descriptor problem
		for i = 0, t(1)-1 do dtzn(i) = dtz(i)
  		tmp = {t:'1d', x:xt, d:float(dtzn),dn:float(dtzn), xl:'value', yl:'number', dl:'histogram '+tmp.dl}
		CurBuf = 0
	   	Label(CurBuf) = tmp.dl + ' histogram'
	  	HANDLE_VALUE, Data(CurBuf), tmp, /set
	   	PlotBuf,CurBuf
     ENDIF else axis_log, 'histogram: only for images'
     END

'Images.Modify one point' : BEGIN
; ************************  modify a single point ***********************
		ax_one_pt
	END

'Images.Modify X,Y axes' : BEGIN
; ************************  modify X, Y axes ***********************
  HANDLE_VALUE, Data(CurBuf), tmp
  IF n_tags(tmp) EQ 0 THEN RETURN
  IF tmp.t EQ '2d' then begin
	   	xfactor = get_num(prompt='X-axis factor', val=1.0, title='Modify XY axes', group = axis_id)
   		yfactor = get_num(prompt='Y-axis factor', val=1.0, title='Modify XY axes', group = axis_id)
   		tmp.x = xfactor*tmp.x
   		tmp.y = yfactor*tmp.y
   		if xfactor NE 1.0 then tmp.dl = tmp.dl + ' Mx ' + strtrim(string(xfactor, format='(F5.2)'))
   		if yfactor NE 1.0 then tmp.dl = tmp.dl + ' My ' + strtrim(string(yfactor, format='(F5.2)'))
		CurBuf = 0
	   	Label(CurBuf) = tmp.dl
	  	HANDLE_VALUE, Data(CurBuf), tmp, /set
	   	PlotBuf,CurBuf
	   	axis_log, 'M-x,y by ' + strtrim(string(xfactor, format='(F5.2)')) $
	   	    + ' , ' + strtrim(string(yfactor, format='(F5.2)'))
  ENDIF ELSE axis_log, 'Modify X,Y axes: only for images'

  END

'Images.Multiply buffers' : BEGIN
 ; *********************** Multiply 2 buffers ********************
  HANDLE_VALUE, Data(CurBuf), tmp
  IF n_tags(tmp) EQ 0 THEN RETURN
  IF tmp.t EQ '2d' then begin
    bt = buffer(group = AXIS_ID)
    IF bt EQ -1 THEN RETURN
	HANDLE_VALUE, Data(bt), div
	IF n_tags(div) EQ 0 THEN RETURN
	IF (div.t EQ '2d') THEN BEGIN     ; for images only
		IF n_elements(div.d) NE n_elements(tmp.d) then begin
			test = dialog_message(/question,'Unequal sized images. Mesh to the matching area ?')
			IF  test EQ 'Yes' then begin
				t = Ax_Mesh(tmp,div,2)    ; match (x,y) scales
				if t EQ 0 then begin
					axis_log,'Incompatible buffers. Size or scale difference too great. Multiply buffers cancelled'
					return
				endif else axis_log, 'Multiply buffers: meshed to common size'
			ENDIF
		ENDIF
 	   	Cnst = get_num(val = factor(0), prompt='scaled by?', group=axis_ID)
	   	factor(0) = cnst
	   	tmp.d = tmp.d * factor(0)*div.d
 	   	CurBuf = 0
		tmp.dl = string(format='(A," *",G10.3," * ",A)',tmp.dl,cnst,div.dl)
   		HANDLE_VALUE, Data(CurBuf), tmp, /set
   		Label(CurBuf) = tmp.dl
   		PlotBuf,CurBuf
    ENDIF ELSE axis_log, 'Multiply buffers: only for images'
   ENDIF ELSE axis_log, 'Multiply buffers: only for images'
  END

'Images.Particle analyze' : BEGIN
;  *********** count and measure size of particles (GENERATE_MASK first !) *******************
	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) NE 0 THEN BEGIN
	    s = ax_particles(simage = tmp,/axis_on)
	    if n_tags(s) ne 0 then begin
           CurBuf = 0
   		   HANDLE_VALUE, Data(CurBuf), s, /set
   		   Label(CurBuf) = s.dl
   		   PlotBuf,CurBuf
	    endif
	ENDIF ELSE axis_log, 'PArticle analyze: only for images'
END

'Images.Power.exp(Z)' : BEGIN
 ; *********************** Exp of data ********************
    HANDLE_VALUE, Data(CurBuf), tmp
     IF n_tags(tmp) NE 0 THEN BEGIN
      	expd = exp(tmp.d)
		tmp.d = expd
        CurBuf = 0
	   	tmp.dl = tmp.dl + ' e^'
	   	Label(CurBuf) = tmp.dl
	  	HANDLE_VALUE, Data(CurBuf), tmp, /set
	   	PlotBuf,CurBuf
     ENDIF
     END

'Images.Power.ln(Z)' : BEGIN
 ; *********************** Naperian Log of data ********************
     HANDLE_VALUE, Data(CurBuf), tmp
     IF n_tags(tmp) NE 0 THEN BEGIN
;		if min(tmp.d) LE 0 THEN tmp.d = tmp.d + min(tmp.d) + 1.
      	logd = alog(tmp.d)
      	bad = where(finite(logd) EQ 0, count)
      	if count GT 0 then $
      	     logd(bad) =  min(logd(where(finite(logd) EQ 1)))
      	tmp.d = logd
		CurBuf = 0
	   	tmp.dl = tmp.dl + ' Ln'
	   	Label(CurBuf) = tmp.dl
	  	HANDLE_VALUE, Data(CurBuf), tmp, /set
	   	PlotBuf,CurBuf
     ENDIF
     END

'Images.Power.10^(Z)' : BEGIN
 ; *********************** Exp of data ********************
    HANDLE_VALUE, Data(CurBuf), tmp
     IF n_tags(tmp) NE 0 THEN BEGIN
      	expd = 10^(tmp.d)
		tmp.d = expd
        CurBuf = 0
	   	tmp.dl = tmp.dl + ' Ln'
	   	Label(CurBuf) = tmp.dl
	  	HANDLE_VALUE, Data(CurBuf), tmp, /set
	   	PlotBuf,CurBuf
     ENDIF
     END

'Images.Power.log10(Z)' : BEGIN
 ; *********************** Naperian Log of data ********************
     HANDLE_VALUE, Data(CurBuf), tmp
     IF n_tags(tmp) NE 0 THEN BEGIN
;		if min(tmp.d) LE 0 THEN tmp.d = tmp.d + min(tmp.d) + 1.
      	logd = alog10(tmp.d)
      	bad = where(finite(logd) EQ 0, count)
      	if count GT 0 then $
      	     logd(bad) =  min(logd(where(finite(logd) EQ 1)))
      	tmp.d = logd
		CurBuf = 0
	   	tmp.dl = tmp.dl + ' Log10'
	   	Label(CurBuf) = tmp.dl
	  	HANDLE_VALUE, Data(CurBuf), tmp, /set
	   	PlotBuf,CurBuf
     ENDIF
     END

 'Images.Profiles.Linear' : BEGIN
;  ************ Generate a lineout on 2d images *************************
HANDLE_VALUE, Data(CurBuf), tmp
IF n_tags(tmp) NE 0 THEN begin
  IF tmp.t EQ '2d' then begin
  	axis_log, 'Profiles: select 1st point'
	profl=1        ; SETS flag to the cursor/mouse processor
   endif else axis_log, 'Profiles: only for images'
ENDIF
END

'Images.Profiles.Radial' : BEGIN
;  ************ Generate a map of radial profiles *************************
AX_PROF_RAD, /axis
END

'Images.Ratio to' : BEGIN
 ; *********************** Ratio Image in CurBuf to image in another buffer ****
    HANDLE_VALUE, Data(CurBuf), tmp
  IF n_tags(tmp) EQ 0 THEN RETURN
  IF tmp.t EQ '2d' then begin
    bt = Buffer(group = AXIS_ID)
    IF bt EQ -1 THEN RETURN
    HANDLE_VALUE, Data(bt), div
	IF (div.t EQ '2d') THEN BEGIN     ; for images only
  		t = Ax_Mesh(tmp,div,2)
  		if t NE 0 then begin
			tmp.d = tmp.d / div.d
			tmp.dl = tmp.dl + ' / ' + div.dl
    		CurBuf = 0
   			Label(CurBuf) = tmp.dl
   			HANDLE_VALUE, Data(CurBuf), tmp, /set
   			PlotBuf,CurBuf
		endif ELSE axis_log, 'Ratio: incompatible files'
	ENDIF else axis_log, 'Image ratio: only for images'
  ENDIF else axis_log, 'Image ratio: only for images'
  END

'Images.Remove zeros' : BEGIN
 ; ***********************  replace zeros with adjacent points ******************
HANDLE_VALUE, Data(CurBuf), tmp
IF n_tags(tmp) EQ 0 THEN RETURN
IF tmp.t EQ '2d' then begin
    tmp.d = remove_zeros(tmp.d)
	CurBuf = 0
	Label(CurBuf) = tmp.dl
	HANDLE_VALUE, Data(CurBuf), tmp, /set
	PlotBuf,CurBuf
  ENDIF else axis_log, 'Image Replace Zeros: only for images'
END

'Images.Replace line.auto' : BEGIN
;  ************ Replace bad horizontal line in images with auto identification *************************
HANDLE_VALUE, Data(CurBuf), tmp
IF n_tags(tmp) EQ 0 THEN RETURN
IF tmp.t NE '2d' THEN RETURN
tmp = remove_lines(tmp)
CurBuf = 0
Label(CurBuf) = tmp.dl
HANDLE_VALUE, Data(CurBuf), tmp, /set
PlotBuf,CurBuf
END


'Images.Replace line.manual' : BEGIN
;  ************ Replace bad horizontal line in the image *************************
HANDLE_VALUE, Data(CurBuf), tmp
IF n_tags(tmp) EQ 0 THEN RETURN
IF tmp.t NE '2d' THEN RETURN
axis_log, 'use cursor to select line to be replaced'
LineClear
img_rep_line=1
END

'Images.Resize' : BEGIN
;  ************ Resize image *************************
HANDLE_VALUE, Data(CurBuf), tmp
IF n_tags(tmp) EQ 0 THEN RETURN
IF tmp.t NE '2d' THEN RETURN
IF factor(0) NE 1. then nx = factor(0) else nx = n_elements(tmp.x)
IF factor(1) NE 1. then ny = factor(1) else ny = n_elements(tmp.y)
old_nx = n_elements(tmp.x)
IF N_ELEMENTS(mesh_x) EQ 0 THEN mesh_x = old_nx
text = string(old_nx, format='("# of X pixels. Old = ",i4)')
nx = get_num(prompt=text,val=mesh_x,group=axis_ID)
old_ny = n_elements(tmp.y)
IF N_ELEMENTS(mesh_y) EQ 0 THEN mesh_y = old_ny
text = string(old_ny, format='("# of Y pixels. Oold = ",i4)')
ny = get_num(prompt=text,val=mesh_y,group=axis_ID)
dn = congrid(tmp.d, nx, ny, /interp, cubic=-0.5)

x_step = (tmp.x(n_elements(tmp.x)-1) - tmp.x(0))/nx
xn = findgen(nx)*x_step + tmp.x(0)
y_step = (tmp.y(n_elements(tmp.y)-1) - tmp.y(0))/ny
yn = findgen(ny)*y_step + tmp.y(0)

tmp = {t:'2d', x:xn, y:yn, e: tmp.e, d:dn, xl:tmp.xl, yl:tmp.yl, dl:tmp.dl + ' RS'}
CurBuf = 0
HANDLE_VALUE, Data(CurBuf), tmp, /set
Label(CurBuf) = tmp.dl
PlotBuf,CurBuf
END

'Images.Rotate' : BEGIN
;   **************************** Rotate image ************************
  ax_rotate
 END

'Images.Set XY scale' : BEGIN
;   **************************** Set X- and Y-scales of image  *********
	AX_XYScl
  END

'Images.Warp' : BEGIN
; ******** Warp image to same scale as a reference image *************
; -------- matching on 4 or more user-selected points
	   Axes = 1		; change display so axes will be displayed
	   WIDGET_CONTROL, OptButs, Set_Value=string(Axes)   ; to allow user to identify ranges to keep
	   PlotBuf, CurBuf
	   img_warp		; STILL BUGGY AS OF 25-NOV-01, BUT PARTLY FUNCTIONING
  END

; ***************************************************************
; ############## Processing specific to  STACKS ###############
; ***************************************************************

'Stacks.Analyze.stack process' : BEGIN
;   ******************** execute stack_process (read-in BINARY - all data) *********
	sa_debug = 0
	ncb_file = pickfile2(/READ, FILTER='*.ncb',/LPATH, DEFPATH=defpath, $
	    TITLE = 'Select binary stack file')
	Write_path = Lpath
	if strlen(ncb_file) EQ 0 THEN RETURN  ; bail-out if no filename
	t=ax_name(ncb_file) & stack_name=t(1)
	test = dialog_message(/question, 'Read an alignment file ?',/default_no)
	if test EQ 'Yes' then begin
		align_file = pickfile2(/READ, FILTER='*.aln',$
		  TITLE= 'Select alignment data file', /LPATH, DEFPATH=defpath)
		if strlen(align_file) GT 0 THEN BEGIN  ; bail-out if no filename
		    WIDGET_CONTROL, /Hourglass
		    stack_process, ncb_file, align_file, /binary, $
		          title = stack_name, debug = sa_debug ;, zoom=zoom_num
		endif else begin
			test2 = dialog_message(/question, 'Align with old Jacobsen stack_align ?')
			if test2 EQ 'Yes' then begin
			 	WIDGET_CONTROL, /Hourglass
			 	stack_rb, ncb_file
				t = ax_name(ncb_file)
			 	shift_filename=t(0)+t(1)+'_cjo.aln'
			 	stack_align,  filename_ev_msec_list, shift_filename, /realign
			endif else begin
			 	stack_process, ncb_file, /no_align, /binary, $
		          title = stack_name, debug = sa_debug ;, zoom=zoom_num
			endelse
		endelse
	endif else stack_process, ncb_file, /no_align, /binary,  $
			          title = stack_name, debug = sa_debug ;, zoom=zoom_num
	ax_color		; restore color scheme
  END

'Stacks.Analyze.stack list input': BEGIN
;   ******************** execute stack_process (to align and extract spectra) *********
	WIDGET_CONTROL, Uprompt, SET_VALUE= 'Select file-list file'
	scan_file = pickfile2(/READ, FILTER='*.sl',/LPATH, DEFPATH=defpath)
	Write_path = Lpath
;	loadct,0, /silent
	if strlen(scan_file) GT 0 THEN BEGIN  ; try BUILD_LIST if no filename
; ------ read in the *.sl file here and rewrite if needed
		test = stack_list(scan_file)
		if test EQ 0 then begin
			axis_log, 'Could not find files in ' + scan_file
			return	; BAIL if no valid SL file
		endif
		align_file = pickfile2(/READ, FILTER='*.aln',$
			  TITLE= 'Select alignment data file', /LPATH, DEFPATH=defpath)
;		zn = get_num(prompt='Zoom *',val=1, group=axis_ID)
;		zoom_num=fix(zn(0))
		WIDGET_CONTROL, /Hourglass
		if strlen(align_file) GT 0 THEN BEGIN  ; bail-out if no filename
		;	print, 'STACK_entry: scan= ', scan_file, '  align_file= ',align_file
			stack_process, scan_file, align_file  ; , ,zoom=zoom_num
		endif else stack_process, scan_file, /no_align ;, zoom=zoom_num
	endif else stack_process
	ax_color		; restore color scheme
  END


'Stacks.Analyze.Jacobsen stack analyze' : BEGIN
;   ******************** execute Jacobsen's stack_analyze.sav  *********
	stack_analyze	;  disabled since it causes write / read *.nc files to fail inVM versions
	ax_color		; restore color scheme
;	text = strarr(2)
;	texta(0) = 'To run the Jacobsen stack_analyse widget'
;	texta(1) = 'exit aXis2000 and double click on c:\aXis2000\stack_analyze.sav'
;	t = dialog_message(texta, /information, dialog_parent=axis_iD)
 END

 'Stacks.Analyze.XRF stack-of-stacks' : BEGIN
;  ********** Process XRF(x,y,E)  ******
	axis_log, 'Extract absorption stack I(x,y,E)'
	axis_log, 'from    XAS-XRF 4d stack I(x,y,xrf,E)'
;	ch_low= get_num(Val=ch_low,PROMPT='lower limit of XRF spectrum (Channel #)', group=axis_ID)
;	ch_hi = get_num(Val=ch_hi, PROMPT='upper limit of XRF spectrum (Channel #)', group=axis_ID)
    tmp = xas_xrf_extract(group=aXis_ID)   ; ch_low=ch_low, ch_hi=ch_hi,
    END

'Stacks.Analyze.Zimba' : BEGIN
;   ******************** execute Zstack_analyze (to align and extract spectra) *********
	t = ax_name(DefPath)					; DefPath is stored without final separator - sometimes!
	print,'Zimba: DefPath = ',  Defpath
;	if strmid(DefPath,(strlen(Defpath)-1),1) NE ax_sep() then begin
;		Defpath = Defpath + ax_sep()
;		print, 'Last path (lpath) changed to ',lpath
;	endif
	test = findfile(Defpath + '*.*')			; avoid error when path not defined
	if test(0) NE '' then cd, DefPath, current=CurrentPath else cd, CodePath
	zstack_analyze, /called_by_axis
  END


'Stacks.Analyze.Remy Coulombe' : BEGIN
;   ******************** execute Stack_analyze (read-in BINARY - all data) *********
	sa_debug = 0
	ncb_file = pickfile2(/READ, FILTER='*.ncb',/LPATH, DEFPATH=defpath, $
	    TITLE = 'Select binary stack file')
	Write_path = Lpath
	if strlen(ncb_file) GT 0 THEN BEGIN  ; bail-out if no filename
		test = dialog_message(/question, 'Read an alignment file ?',/default_no)
		if test EQ 'Yes' then begin
			WIDGET_CONTROL, Uprompt, SET_VALUE= 'Select alignment data file'
			align_file = pickfile2(/READ, FILTER='*.aln',/LPATH, DEFPATH=defpath)
		endif else align_file = ''
;		zn = get_num(prompt='Zoom *',val=1, group=axis_ID)
;		zoom_num=fix(zn)
		WIDGET_CONTROL, /Hourglass
;		loadct,0, /silent
;		print, 'STACK_entry: data= ', ncb_file, '  align_file= ',align_file
		if strlen(align_file) GT 0 THEN BEGIN  ; bail-out if no filename
			Rstack_analyze, ncb_file, align_file, fpath=WritePath, /binary, debug = sa_debug ;, zoom=zoom_num
		endif else Rstack_analyze, ncb_file, /no_align, fpath=WritePath, /binary, debug = sa_debug ;, zoom=zoom_num
	endif
	ax_color		; restore color scheme
  END

'Stacks.Add' : BEGIN
; *************  add 2 stacks of same dimension *******************
	stack_add
  END

'Stacks.Append' : BEGIN
; *************  append 2 stacks of same dimension *******************
	stack_append
  END

'Stacks.bin.energy' : BEGIN
;   *************** bin energy scale of a stored aXis binary stack  *********
	bin_num=2
	bin_num =get_num(Val=bin_num,PROMPT='bin energy scale *', group=axis_ID)
  fileget=''
  ax_bin, fileget, bin = bin_num, /stack, /energy
END

'Stacks.bin.NSLS.1' : BEGIN
;   *************** bin 1 net CDF (BNL) file format *********
	bin_num=2
	bin_num=get_num(Val=bin_num,PROMPT='bin *', group=axis_ID)
	fileget=PICKFILE2(/Read, FILTER='*.nc', /LPATH, DEFPATH=defpath)
	IF strlen(fileget) GT 0 THEN ax_bin,fileget, bin=bin_num, /one
  END

'Stacks.bin.NSLS.file' : BEGIN
;   ********** bin a stack list set of files *********
	bin_num=2
	bin_num=get_num(Val=bin_num,PROMPT='bin *', group=axis_ID)
	fileget=PICKFILE2(/Read, FILTER='*.sl', /LPATH, DEFPATH=defpath)
	IF strlen(fileget) GT 0 THEN ax_bin,fileget, bin=bin_num
  END

'Stacks.bin.stack.*.ncb' : BEGIN
;   *************** bin axis binary stack  *********
	bin_num=2
	bin_num=get_num(Val=bin_num,PROMPT='bin spatially *', group=axis_ID)
	fileget='tttt'
	ax_bin, fileget, bin = bin_num, /stack
  END


'Stacks.bin.stack.lox' : BEGIN
;   *************** bin current image *********2
	bin_num=2
	bin_num=get_num(Val=bin_num,PROMPT='bin *', group=axis_ID)
	fileget=''
	ax_bin, fileget, bin = bin_num, /stack, /lox
  END

'Stacks.change mesh or size' : BEGIN
; *************  change mesh  (to allow appending 2 stacks of different dimension **********
	stack_mesh
  END

'Stacks.convert to OD with line Io' : BEGIN
; ************** normalize a stack on line-by-line basis  ***********
; ----- for slow stacks, with clear Io from bottom to top, correct for Io flux changes (time) --
    tmp = stack_line_io()
    if  n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
	 	Plotbuf, CurBuf
	endif
END

'Stacks.convert format.OD to transmission' : BEGIN
;   ********* convert a stack in *.ncb format from OD to transmission ******************
	file = pickfile2(/READ, FILTER='*.ncb', /LPATH, DEFPATH=defpath)
	stack_rb, file
	image_stack = exp(-1.*image_stack)
	t = ax_name(file)
	file = t(0) + 't' + t(1) + '.' + t(2)
	stack_wb, file
	axis_log, 'OD converted to trans. '+t(1)
  END

'Stacks.convert format.ALS to netCDF.1' : BEGIN
;   ********** convert 1 ALS file  to net CDF (BNL) format *********
	bin_num = get_num(Val=1,PROMPT='smooth by binning:#=? (#=2: 2x2pixels -> 1)', group=axis_ID)
    als2ncdf, bin=bin_num, /one
  END

'Stacks.convert format.ALS to netCDF.many' : BEGIN
;   *******convert 1 or a sequence of ALS to net CDF (BNL) format *********
	t = ax_conv()                         ; separated for code space reasons 3-dec-98
  END

'Stacks.convert format.ALS to netCDF.file' : BEGIN
;   ******convert sequence of ALS to net CDF (BNL) files; names from FILE *********
  WIDGET_CONTROL, Uprompt, SET_VALUE='Select file_list file'
  fileget=PICKFILE2(/Read, FILTER='*.lst', /LPATH, DEFPATH=defpath)
  if strlen(fileget) GT 0 THEN BEGIN
   		WIDGET_CONTROL, Uprompt, SET_VALUE= 'ALS->nc: smooth by binning?'
		bin_num=1				; optional binning of data
		bin_num=get_num(Val=bin_num,PROMPT='bin *', group=axis_ID)
		WIDGET_CONTROL, Uprompt, Bad_ID = badID, SET_VALUE= 'ALS->nc: calibrate E?'
		del_E=0.
		del_E = get_num(Val=del_E,PROMPT='dE(real-meas, eV)', group=axis_ID)
	 	spos = rstrpos(fileget,'.')    ; find last separator
		sl_file =  strmid(fileget,0,spos) + '.sl'
		text = get_text(Prompt = 'stack_list file',val = sl_file, group=axis_ID)
		sl_file = text
;		print, 'writing to stack_list file: ', sl_file
	    als2ncdf,list=fileget,bin=bin_num, outlist=sl_file, delE=del_E
  endif
  END

'Stacks.convert format.ALS 5.3.2 STXM to *.ncb' : BEGIN
;   ******convert ALS 5.3.2 STXM to binary stack (*.ncb)  *********
	tmp = ax_sdf(group_leader=axis_ID)
	if  n_tags(tmp) NE 0 THEN BEGIN
     	WIDGET_CONTROL, /Hourglass
		HANDLE_VALUE, Data(Curbuf), tmp, /SET
	 	Plotbuf, CurBuf
	endif else begin
		t = size(tmp,/type)
	  	if t EQ 7 then begin		; tmp is a string - the name of the stack file
	  		stack_process, tmp, /no_align, /binary ;, zoom=zoom_num
	  	endif
	endelse
  END

'Stacks.convert format.to axis binary from.bmp' : BEGIN
;   ******convert set of *.bmp files to binary stack (*.ncb)  *********
  	stack_file = bmp_to_ncb(group_leader=axis_ID)
  	if strlen(stack_file) GT 0 then $
  		stack_process, stack_file, /no_align, /binary
  END

'Stacks.convert format.to axis binary from.jpg' : BEGIN
;   ******convert set of *.jpg files to binary stack (*.ncb)  *********
  	stack_file = jpg_to_ncb(group_leader=axis_ID)
  	if strlen(stack_file) GT 0 then $
  		stack_process, stack_file, /no_align, /binary
  END

'Stacks.convert format.to axis binary from.mrc' : BEGIN
;   ***************convert MRC stack from disk to ncb format  (GAJ July 2006) *********
  axis_log, 'convert (*.mrc) to (*.ncb)  stack'
  fileget=PICKFILE2(/Read, FILTER='*.*', /LPATH, DEFPATH=defpath)
  if strlen(fileget) GT 0 THEN BEGIN
 	 	t = ax_name(fileget)
		file_name = t(1) + '.' + t(2)				;many possible file extensions: .mrc, .st, .rec, ...
		file_path = t(0)
		read_MRC_file, (file_path + file_name)		;read stack in mrc format
		file_name =  t(1) + '.ncb'
		stack_wb, (file_path + file_name)	; write stack in ncb format (same name, but .ncb)
		stack_process, (file_path + file_name), /no_align, /binary
  endif
END

'Stacks.convert format.to axis binary from.tif' : BEGIN
;   ******convert set of *.tif files to binary stack (*.ncb)  *********
  	stack_file = tif_to_ncb(group_leader=axis_ID)
  	if strlen(stack_file) GT 0 then $
  		stack_process, stack_file, /no_align, /binary
  END

'Stacks.convert format.to axis binary from.TOF-all' : BEGIN
; *************convert sequence of TOF-all files (from disk) to *.ncb stack *********
	file = ax_conv_all(/axis_on)
  END

'Stacks.convert format.to axis binary from.NSLS STXMIV' : BEGIN
;   ******convert ALS 5.3.2 STXM to binary stack (*.ncb)  *********
  	stack_file = stxm4_ncb(group_leader=axis_ID)
  	if strlen(stack_file) GT 0 then $
  		stack_process, stack_file, /no_align, /binary
  END

'Stacks.convert format.from axis binary to.cts (ascii spectra)' : BEGIN
;   ***************convert ncb stack from disk to set of ascii spectra (aph Feb 2010)  *********
  axis_log, 'convert (*.ncb) to set of (*.cts) spectra'
  tmp = write_cts(group = aXis_ID)
  if  n_tags(tmp) NE 0 THEN BEGIN
		HANDLE_VALUE, Data(CurBuf), tmp, /set
		Label(CurBuf) = tmp.dl
		PlotBuf, CurBuf
	endif
 END

'Stacks.convert format.from axis binary to.mpg' : BEGIN
;   ***************convert ncb stack from disk to MRC format *********
  axis_log, 'convert (*.ncb) to (*.mpg)  movie'
  fileget=PICKFILE2(/Read, FILTER='*.ncb', /LPATH, DEFPATH=defpath)
  if strlen(fileget) GT 0 THEN BEGIN
 	 	t = ax_name(fileget)
		file_name = t(1) + '.ncb'
		file_path = t(0)
		ncb_to_mpg, (file_path + file_name)		;convet ncb stack to mpg movie
  endif
END

'Stacks.convert format.from axis binary to.mrc' : BEGIN
;   ***************convert ncb stack from disk to MRC format (GAJ July 2006)  *********
  axis_log, 'convert (*.ncb) to (*.mrc)  stack'
  fileget=PICKFILE2(/Read, FILTER='*.ncb', /LPATH, DEFPATH=defpath)
  if strlen(fileget) GT 0 THEN BEGIN
 	 	t = ax_name(fileget)
		file_name = t(1) + '.ncb'
		file_path = t(0)
		stack_rb, (file_path + file_name)		;read stack in ncb format
		file_name =  t(1) + '.mrc'
		write_MRC_file, (file_path + file_name)	; write stack in mrc format (same name, but .mrc)
  endif
END

'Stacks.convert format.netCDF to ALS.1' : BEGIN
;   ******convert net CDF (BNL) file to ALS *********
  ncdf2als,/one
  END

'Stacks.convert format.netCDF to ALS.file' : BEGIN
;   ******convert sequence of net CDF (BNL) files to ALS; names from FILE *********
  text = 'Select a (*.nc) stack_list file'
  print, text
  WIDGET_CONTROL, Uprompt, SET_VALUE= text
  fileget=PICKFILE2(/Read, FILTER='*.sl', /LPATH, DEFPATH=defpath)
  if strlen(fileget) GT 0 THEN BEGIN
 	 	t = ax_name(fileget)
		lst_file =  t(1) + '.lst'
		text = get_text(Prompt = 'list file',val = lst_file, group=axis_ID)
		lst_file = t(0) + text
		scale = 1.
		scale = get_num(prompt = 'scale factor (ALS format is integer)', val = scale, group =axis_ID)
	    ncdf2als,list=fileget, outlist=lst_file, scale=scale
  endif
  END

 'Stacks.convert format.PEEM' : BEGIN
;  ********** read in ALS (PEEM2 old & new, PEEM3), Lox, or Sphinx PEEM Images  ******
	tif_convert
    END

'Stacks.convert format.PEEM-old.ALS-PEEM.to netCDF' : BEGIN
;   ***************convert ALS PEEM sequence to net CDF (BNL) format *********
;  	col12 = get_num(Prompt = '# of columns to drop in 12-bit mode', val = -1, group=AXIS_ID)
  	col12 = 5
  	tmp = AX_PEEM_READ(/axis, col12 = col12, /multi)
	END

'Stacks.convert format.PEEM-old.ALS-PEEM.to *.ncb' : BEGIN
;   ***************convert ALS PEEM sequence to *.ncb binary stack *********
;  	col12 = get_num(Prompt = '# of columns to drop in 12-bit mode', val = -1, group=AXIS_ID)
  	col12 = 5
  	tmp = AX_PEEM_READ(/axis, col12 = col12, /multi, /ncb)
  	stack_process, tmp, /no_align, /binary
	END

;'Stacks.convert format.PEEM-old.SPHINX.to netCDF' : BEGIN
;   ***************convert SPHINX sequence to net CDF (BNL) format *********
;  	tmp = AX_PEEM_READ(/axis, /sphinx, /multi)
;	END

'Stacks.convert format.PEEM-old.SPHINX' : BEGIN
;   ***************convert SPHINX sequence to *.ncb binary stack *********
  	tmp = AX_PEEM_READ(/axis, /sphinx, /multi, /ncb)
  	if tmp NE 0 then $
     	stack_process, tmp, /no_align, /binary ;, zoom=1
	END

'Stacks.convert format.TIF to netCDF.1' : BEGIN
;   ***************convert 1 ALS file (form disk) to net CDF (BNL) format *********
	bin_num=1
	bin_num=get_num(Val=bin_num,PROMPT='bin *', group=axis_ID)
    tif2ncdf,bin=bin_num, fltr='*.tif'
  END

'Stacks.convert format.TIF to netCDF.many' : BEGIN
;   ***************convert 1 or a sequence of ALS to net CDF (BNL) format *********
	file1=PICKFILE2(/Read, FILTER='*.tif', /LPATH, DEFPATH=defpath, $
		title = 'first file of sequence')
	if strlen(file1) EQ 0 THEN RETURN
	file2=PICKFILE2(/Read, FILTER='*.tif', /LPATH, DEFPATH=defpath, $
		title = 'last file of sequence')
	if strlen(file2) EQ 0 THEN RETURN
	fileroot=strmid(file1, 0, strpos(file1,'#')+1)
	t = ax_name(fileroot) & fileshort=t(1) & tifpath = t(0)
	first = fix(strmid(file1, strpos(file1,'#')+1, strpos(file1,'.')-strpos(file1,'#')-1))
	last  = fix(strmid(file2, strpos(file2,'#')+1, strpos(file2,'.')-strpos(file2,'#')-1))
	filelist = pickfile2(/write,/lpath,filter='*.lst', $
	    title='Write list of files', DEFPATH=defpath)
	t = ax_name(filelist) & filelist = t(0) + t(1) + '.lst'  ; force *.lst ending
;    	print, fileroot,fileshort, first,last, filelist
	openw,unit, filelist,/get_lun
	printf, unit, tifpath
	for i = first, last do begin
		num = strcompress(string(1000 + i))
		num = strmid(num,2,4)
		file=fileshort + num + '.tif'
		printf,unit, strcompress(file)
	endfor
	close, unit & free_lun, unit
	WIDGET_CONTROL, Uprompt, SET_VALUE= 'TIF->nc: smooth by binning?'
	bin_num=1				; optional binning of data
	bin_num=get_num(Val=bin_num,PROMPT='bin *', group=axis_ID)
	WIDGET_CONTROL, Uprompt, Bad_ID = badID, SET_VALUE= 'TIF->nc: calibrate E?'
	del_E=0.
	del_E = get_num(Val=del_E,PROMPT='dE(real-meas, eV)', group=axis_ID)
	t = ax_name(filelist)
	sl_file =  t(0) + t(1) + '.sl'
	sl_file = get_text(Prompt = 'stack_list file',val = sl_file, group=axis_ID)
	tif2ncdf,list=filelist,bin=bin_num, outlist=sl_file, delE=del_E
  END

'Stacks.convert format.TIF to netCDF.file' : BEGIN
; ******convert sequence of TIF to netCDF files; names from FILE *********
  filelist=PICKFILE2(/Read, FILTER='*.lst', /LPATH, DEFPATH=defpath)
  if strlen(filelist) EQ 0 THEN RETURN
	WIDGET_CONTROL, Uprompt, SET_VALUE= 'TIF->nc: smooth by binning?'
	bin_num=1				; optional binning of data
	bin_num=get_num(Val=bin_num,PROMPT='bin *', group=axis_ID)
	WIDGET_CONTROL, Uprompt, Bad_ID = badID, SET_VALUE= 'TIF->nc: calibrate E?'
	del_E=0.
	del_E = get_num(Val=del_E,PROMPT='dE(real-meas, eV)', group=axis_ID)
	t = ax_name(filelist)
	sl_file =  t(0) + t(1) + '.sl'
	sl_file = get_text(Prompt = 'stack_list file',val = sl_file, group=axis_ID)
	tif2ncdf,list=filelist,bin=bin_num, outlist=sl_file, delE=del_E
  END


'Stacks.convert format.aXis binary (*.ncb) to ascii spectra (*.cts)' : BEGIN
; *************convert sequence of NSLS files (from disk) to GIF format *********
	ax_nc2gif
  END
'Stacks.convert format.NSLS-STXMIV to netCDF' : BEGIN
; *************convert sequence of NSLS files (from disk) to GIF format *********
	ax_stxm4nc, /outlist
  END

'Stacks.convert format.NSLS to GIF' : BEGIN
; *************convert sequence of NSLS files (from disk) to GIF format *********
	ax_nc2gif
  END

'Stacks.convert format.NSLS to HDF.1' : BEGIN
;   ***************convert buffer image to net HDF format *********
   HANDLE_VALUE, Data(CurBuf), tmp
   IF n_tags(tmp) NE 0 THEN BEGIN
   	if tmp.t EQ '2d' then begin
   		sav_HDF, tmp
   	  endif else WIDGET_CONTROL, Uprompt, SET_VALUE='Z-scale: only for images'
   ENDIF
  END

'Stacks.convert format.NSLS to HDF.many' : BEGIN
;   ***************convert sequence of NSLS files (from disk) to HDF format *********
  WIDGET_CONTROL, Uprompt, SET_VALUE='pick first file of sequence'
  file1=PICKFILE2(/Read, FILTER='*.nc', /LPATH, DEFPATH=defpath)
  if strlen(file1) GT 0 THEN BEGIN
     WIDGET_CONTROL, Uprompt, SET_VALUE='pick last file of sequence'
     file2=PICKFILE2(/Read, FILTER='*.nc', /LPATH, DEFPATH=defpath)
	 if strlen(file2) GT 0 THEN BEGIN
; assumes all NSLS file names are 12 char. and columns 6-8 are a sequential file number
; convention is YMMDD###.nc for all NSLS X1A  files
        spos=strpos(file1,'.')
		fileroot=strmid(file1, 0, spos-3)
    	fileshort=strmid(file1,spos-8, 5)
    	first = fix(strmid(file1,spos-3, 3))
    	last  = fix(strmid(file2,spos-3, 3))
; allow any extension by picking up ext from pickfile choice (aph 14-feb-98)
		ext = strmid(file1,spos+1,3)    ; take extension
; generate file with list of filenames
		WIDGET_CONTROL, Uprompt, SET_VALUE= 'NSLS->HDF: file-list file'
    	filestore = pickfile2(/write,/lpath,filter='*.sln', DEFPATH=defpath)
     	openw,unit, filestore,/get_lun
   		for i = first, last do begin
      		num = strcompress(string(1000 + i))
      		num = strmid(num,2,4)
      		file=fileroot + num + '.' + ext
			printf,unit, strcompress(file)
    	endfor
   		close,unit & free_lun, unit
	    sav_HDFm,list=filestore
   	endif
  endif
  END

'Stacks.convert format.XRF ((*.dta) to 1-column (*.cts)' : BEGIN
;   *************** convert 1-channel or sum  XGLabs *.dta without zeros to PYMCA compatible input  *********
	tmp = ax_xrf_convert(group=aXis_ID, /silent)
	if n_tags(tmp) NE 0 then begin
	  	CurBuf = 0
		HANDLE_VALUE, Data(CurBuf), tmp, /set
		PlotBuf,CurBuf
  	ENDIF
  END

'Stacks.Differentiate' : BEGIN
; ********************** spectral differentiation of a stack  ***********
	stack_diff
  END

'Stacks.Expand' : BEGIN
; ********************** add a user-defined area around each image  ***********
	ax_stack_expand, group = AXIS_ID
  END

'Stacks.Generate_stack' : BEGIN
; ********************* generate a stack from product of a spectrum and an image *******
  buf_spec = buffer(prompt = 'Spectrum', group = axis_ID)
  HANDLE_VALUE, Data(buf_spec), tmp
  IF n_tags(tmp) EQ 0 THEN RETURN
  buf_spec = buffer(prompt = 'Image', group = axis_ID)
  HANDLE_VALUE, Data(buf_spec), tmp_img
  IF n_tags(tmp_img) EQ 0 THEN RETURN
  IF tmp_img.t NE '2d' then return
  stack_make, tmp, tmp_img
  END

'Stacks.y_illumination correct' : BEGIN
; ********************* correct for non-even vertical illumination *******
  tmp = stack_illumination_correct()
  IF size(tmp,/type) EQ 2 and n_tags(tmp) EQ 0 THEN RETURN	; cancel in stack_illumination_correct
  IF size(tmp,/type) EQ 8 then begin
	  	IF tmp.t NE '2d' then return
		CurBuf = 0
		HANDLE_VALUE, Data(CurBuf), tmp, /set	; display illuminat as f(E)
		PlotBuf,CurBuf
  ENDIF
  END


'Stacks.Image alignment.shift' : BEGIN
; ********************** user selection of 1-alignment point ***********	modified 3-April 2018 (im => axb); 7 Jul 18

   WIDGET_CONTROL, OptButs, Get_Value= spec_bin	 ;	turn on Axes display, stpre last setting in spec_bin parameter
   Axes = 1
   WIDGET_CONTROL, OptButs, Set_Value= Axes

; ---------- get stack list file (FORMAT: folder then 1 lines with name.ext - can be *.axb, *.nc, *.im (pre-2001 ALS !)
   WIDGET_CONTROL, Uprompt, SET_VALUE= 'Select file-list file'
   stack_list_file = pickfile2(/READ, FILTER='*.sl',/LPATH, DEFPATH=defpath)
	Write_path = Lpath
	if strlen(stack_list_file) GT 0 THEN BEGIN
; ------ read in the *.sl file here and rewrite if needed
		test = stack_list(stack_list_file)
		if test EQ 0 then begin
			axis_log, 'Could not find files in ' + stack_list_file
			return	; BAIL if no valid *.sl file
		endif ; else BEGIN		; ----- check the stack list is read properly
;			 print, stack_list_file
 ;			for i= 0, n_elements(filename_list)-1 do  print, filename_list(i)
;		endelse
	endif else return
; ---------------  Document the set of files to align
	n_files = n_elements(filename_list)
    t = ax_name(filename_list(0))
	file_path = t(0)
    fileroot = strmid(t(1), 0, strpos(t(1),'_'))
    ext = t(2)
	print, 'Image alignment - SHIFT only.'
	t = ax_name(filename_list(0))  & first = t(1)
	t = ax_name(filename_list(n_files-1))  & last = t(1)
	print, 'Rootname= ',fileroot,'  Extension= ',ext,' Files from', first,' to ',last
	CurBuf = 1
; ------------ do the alignment
    for i = 0, n_files-1 do begin
    	file = filename_list(i)
  		CASE strlowcase(ext) OF
  			'nc':  tmp = read_bnl(file)
  			'im':  tmp = read_als(file)
  			'axb': tmp = axb_load(file=file)
  		ENDCASE
; ---- check if E is defined; if not ASK use to set
		test=tag_names(tmp)			; check in case energy is not defined
		energy = -500.
		for s_i = 0, n_elements(test)-1 do begin				; CAUTION - reusing index variable inside loop is DANGEROUS !
		    if strlowcase(test(s_i)) EQ 'e' then energy=tmp.e
		endfor
		if energy EQ -500. then energy = get_num(Prompt ='set X-value (E, angle)', Val = energy, group = Axis_ID)
		tmp = {t:'2d',x:tmp.x,y:tmp.y,d:tmp.d,e:energy, xl:tmp.xl,yl:tmp.yl,dl: tmp.dl}

; ------ change to transfer via call, not Data buffers --------
  		HANDLE_VALUE,Data(CurBuf),tmp, /SET
  		PlotBuf,CurBuf
		t = ax_name(file)
		fnm = t(1) & print, i, ' Aligning file ', fnm
		img_algn,tmp, fnm, /one_pt
	endfor
	img_asav, /one_pt			;write-out shifts (*.al) and filename files (*.sl)
	Axes = spec_bin				; reset Axes state to pre-alignment state
	WIDGET_CONTROL, OptButs, Set_Value=Axes
  END

'Stacks.Image alignment.stretch/shift' : BEGIN
; ********************** user selection of 2 alignment points ***********
  text = string(format='("pick first file of sequence",/,a,"(*.im* or *.nc)")',' ')
  WIDGET_CONTROL, Uprompt, SET_VALUE= text
  file1=PICKFILE2(/Read, FILTER='*.*', /LPATH, DEFPATH=defpath)
  if strlen(file1) GT 0 THEN BEGIN
	 dot_pos = rstrpos(file1,'.')
  	 ext = strmid(file1,dot_pos+1,strlen(file1))    ; take extension
     WIDGET_CONTROL, Uprompt, SET_VALUE='pick last file of sequence'
     file2=PICKFILE2(/Read, FILTER='*.'+ext, /LPATH, DEFPATH=defpath)
	 if strlen(file2) GT 0 THEN BEGIN
		t = ax_name(file1)
		WritePath = t(0)
		if !VERSION.OS_FAMILY EQ 'unix' then sep = '/' else sep = '\'
		sep_pos = rstrpos(file1,sep)           ; used by ImgAlgn to put
; pre July-09 version
;  		WritePath = strmid(file1,0,sep_pos)        ; aligned data in same subdirectory
	 	print, 'Path to store aligned files is: ', WritePath
		fileroot=strmid(file1, 0, dot_pos-3)
    	fileshort=strmid(file1,sep_pos+1, dot_pos-sep_pos-1)
     	first = fix(strmid(file1,dot_pos-3, 3))
    	last  = fix(strmid(file2,dot_pos-3, 3))
    	print, 'Image alignment - STRETCH & SHIFT '
    	print, 'Rootname= ',fileroot,'  Extension= ',ext,' Files from', first,' to ',last
    	for i = first, last do begin
      		num = strcompress(string(1000 + i))
      		num = strmid(num,2,4)
      		file=fileroot + num + '.' + ext
      		CASE strlowcase(ext) OF
      			'nc':  tmp = read_bnl(file)
      			'im':  tmp = read_als(file)
      			'axb': tmp = axb_load(file=file)
      		ENDCASE
	  		HANDLE_VALUE,Data(1),tmp, /SET
	  		PlotBuf,1
 			img_algn, tmp, fnm
    	endfor
   	  img_asav			;write-out shifts, stretches (*.al) and filename files (*.sl)
   	  endif
  endif
  END

'Stacks.Image alignment.warp' : BEGIN
; ************** user selection of 4 or more alignment points ***********
WIDGET_CONTROL, Uprompt, SET_VALUE= 'Select file-list file'
file_list = pickfile2(/READ, FILTER='*.sl',/LPATH, DEFPATH=defpath)
img_warp, list = file_list
END

'Stacks.Stack_movie' : BEGIN
;   ***************execute stack_movie (to view sequence) *********
	WIDGET_CONTROL, Uprompt, SET_VALUE= 'Select file-list file'
	scan_file = pickfile2(/READ, FILTER='*.sl',/LPATH, DEFPATH=defpath)
	loadct,0, /silent
	if strlen(scan_file) GT 0 THEN BEGIN  ; bail-out if no filename
	   Stack_movie, scan_file
	endif else Stack_movie
	ax_color		; restore color scheme
  END

'Stacks.maps.SVD' : BEGIN
;   ********** Use AX_SVD procedure to derive component maps from STACK *********
	text = ' Select stack file (*.ncb)'
	print, text
	widget_control, Bad_ID=Bad_ID, Uprompt, SET_VALUE=text
	stack_file =  pickfile2(/read, filter='*.ncb')
	if stack_file NE '' then ax_svd, /axis, stack=stack_file
  END

'Stacks.maps.Stack fit' : BEGIN
;   ******************** execute Stack_fit - fit a stack to 2-8 components *********
	stack_fit, /axis
  END

'Stacks.maps.CGO curve fit' : BEGIN
;   ******************** execute AX_CGO to fit a stack to 2-8 components *********
	ax_CGO, /stack, /axis
  END

'Stacks.maps.polarization fit' : BEGIN
;   ******************** execute AX_pol_map to fit a polarization stack  *********
	ax_pol_map, /axis
  END

'Stacks.Ratio to another stack' : BEGIN
; *************  ratio 2 stacks of the same dimensions *******************
	stack_add, /ratio
  END

'Stacks.RGB - color composite map' : BEGIN
;   ******************** load aX_RGB_MAP WIDGET  *********
	if float(!version.release) GE 6.3 then	ax_rgb_map $
       else axis_log, 'only valide for IDL 6.3 or higher. Please use Display~RGB composite'
  END

'Stacks.Rotate' : BEGIN
; ********************** rotate stack  ***********
	stack_rotate
  END

'Stacks.Slicer (3d viewer)': BEGIN
; ******************** read binary stack into slicer3 ********************************
  ax_slicer3
  END

'Stacks.Statistical analysis.principle components' : BEGIN
;   ******************** compute Principle components - CAN BE SLOW ! *********
	WIDGET_CONTROL, Uprompt, SET_VALUE= 'Select stack data file'
	ncb_file = pickfile2(/READ, FILTER='*.ncb',/LPATH, DEFPATH=defpath)
	if ncb_file EQ '' then return
	Write_path = Lpath
	text = get_text(prompt = 'Standardize ?',val = 'no', group = axis_ID)
	if strlowcase(text) NE 'no' then standardize = 1 else standardize = 0
	if strlen(ncb_file) GT 0 THEN BEGIN
		ax_pc,stack = ncb_file, standardize = standardize, axis=1
	endif else begin
		WIDGET_CONTROL, Uprompt, SET_VALUE= 'Select image list file'
		img_file = pickfile2(/READ, FILTER='*.sl',/LPATH, DEFPATH=defpath)
		if strlen(img_file) GT 0 THEN ax_pc, images = img_file, standardize = standardize, axis=1
	endelse
  END

'Stacks.Statistical analysis.PCA_GUI (CJJ Dec 2005)' : BEGIN
;   ******************** run Jacobsen's PCA_GUI  *********
    pca_gui
  END

'Stacks.Tomography.make tomo list' : BEGIN
; ********************* generate a stack from one image of oriignal SDF files *******
;	axis_log, 'Being written by Juan Wu - 10-Nov-13'
	make_tomo_list
 END

'Stacks.Tomography.angle stack from SDF files.one image' : BEGIN
; ********************* generate a stack from one image of oriignal SDF files *******
  ncb_file = ax_angle_stack(group=axis_ID, channel=1, region=1)
  stack_process, ncb_file, /no_align, /binary
  ax_color		; restore color scheme
 END

'Stacks.Tomography.angle stack from SDF files.map' : BEGIN
; ********* generate a stack from difference of 2 images of an angle scan sequence *******
  ncb_file = ax_angle_stack(/map, group=axis_ID, channel=1, region=1)
  stack_process, ncb_file, /no_align, /binary, debug = sa_debug
  ax_color		; restore color scheme
  END

'Stacks.Tomography.angle stack from SDF files.stack' : BEGIN
; ********************* generate a stack of stacks of an angle scan sequence *******
   ncb_file = ax_angle_stack(/stack, group=axis_ID, channel=1)
   stack_process, ncb_file, /no_align, /binary, debug = sa_debug
   ax_color		; restore color scheme
  END

'Stacks.Tomography.angle stack from images (axb)' : BEGIN
;   ********convert set of images to an angle scan sequence   *********
  ncb_file = ax_tomo_read(/axb, group=axis_ID)
  stack_process, ncb_file, /no_align, /binary, debug = sa_debug
  ax_color		; restore color scheme
END

; ***************************************************************
; ############## Processing specific to LineScans ###############
; ***************************************************************

'Linescans.Add lines.horizontal' : BEGIN
;  ***** select and add horizontal band of lines *********************
   ln_add
   END

'Linescans.Add lines.vertical' : BEGIN
;  ***** select and add horizontal band of lines *********************
   ln_add, /vertical
   END

'Linescans.align.linear' : BEGIN
;  ***** align successive lines *****************************
  LN_align
  END

'Linescans.align.curve' : BEGIN
;  ******************* align successive lines *****************************
  LN_align, /curve
  END

'Linescans.subtract reference' : BEGIN
;  ***** ratio each line to a subset of linescan OR file Io  ***************
  ln_subsp
  END

'Linescans.locate line' : BEGIN
; **************** place line of linescan on user-selected image ************
  ln_locat
  END

'Linescans.normalize to Io' : BEGIN
;  ***** ratio each horizontal line to contents of a buffer *****************
;  ******* ( Io from Add.horizontal OR file Io ) ************
   ln_norm
 END

'Linescans.normalize to line.horizontal' : BEGIN
;  ***** ratio each vertical line to a OR file spectrum  ************
;  ***** (to remove line scan noise ) *******************************
   ln_norm, Horizontal=1
 END

'Linescans.normalize to line.vertical' : BEGIN
;  ***** ratio each vertical line to a OR file spectrum  ************
;  ***** (to remove line scan noise ) *******************************
   ln_norm, Vertical=1
 END

'Linescans.line_fit' : BEGIN
;   ******************** fit a linescan to 1-5 spectral components *********
	line_fit,axis=1
  END


; ***************************************************************
; ############## Processing specific to SPECTRA #################
; ***************************************************************

; ---------------- absolute value ------------------

  'Spectra.Absolute value' : BEGIN
 ; ********* calibrate X-axis with existing slope, intercept **************
 	HANDLE_VALUE, Data(CurBuf), tmp
 	IF n_tags(tmp) ne 0 THEN BEGIN
		test = where(tmp.d LT 0, count)
		if count GT 0 then tmp.d(test) = -1.0*tmp.d(test)
		tmp.dl = tmp.dl + ' abs'
		HANDLE_VALUE, Data(0), tmp, /SET           ;Put the data in temp buffer
  		PlotBuf, 0
  	ENDIF
    END

; ---------------- add (append, buffer, constant)  ------------------

 'Spectra.Add.Append' : BEGIN
  ;  ***************  Append 2 data arrays ***************
    axis_app
	END

 'Spectra.Add.Buffer' : BEGIN
  ; ***********  Sum 2 files:  Interpolates to finest X-scale in common region *****************
	axis_add
    END

  'Spectra.Add.Constant' : BEGIN
  ; *******************  Add a constant to displayed  data **************

    HANDLE_VALUE, Data(Curbuf), tmp
    if n_tags(tmp) NE 0 then begin
        If tmp.t EQ '1d' then begin
    	    constant = Get_Num(val = constant, Prompt = 'Constant:', group=axis_ID)
     		tmp.d=tmp.d + constant
    		tmp.dl = tmp.dl + ' ' + strcompress(string(constant))
    		HANDLE_VALUE, Data(0), tmp, /SET
    		PlotBuf, 0
    	ENDIF ELSE WIDGET_CONTROL, Uprompt, SET_VALUE='Add: only for spectra'
    endif
    END

  'Spectra.Bin' : BEGIN
  ; *******************  reduce dimensionality & smooth by binning **************
    HANDLE_VALUE, Data(Curbuf), tmp
    if n_tags(tmp) NE 0 then begin
        If tmp.t EQ '1d' then begin
        	if n_elements(spec_bin) EQ 0 then spec_bin = 2
        	spec_bin = fix(get_num(prompt='bin', val=spec_bin, group=axis_ID))
        	if spec_bin LT 2 then return
        	if n_elements(spec_SumAvg) LE 0 then spec_SumAvg = 'A'
			spec_SumAvg = get_text(Val=spec_SumAvg,PROMPT='Sum(S) or Average(A)', group=axis_ID)
        	tmpx=tmp.x
     		tmpo = tmp.d
 ;    		print, "min, max data ", min(tmpo), max(tmpo)
     		npts = n_elements(tmpx)/spec_bin	; rounds to lower number
     		x = fltarr(npts-1)
    ; determine reduced spacing		; approximately retains unequal spacing
    		 for i = 0, npts-2 do begin
    		 	for j = 0, spec_bin-1 do x(i) = x(i) + tmpx(spec_bin*i+j)
    		 	x(i) = x(i)/float(spec_bin)
    		 endfor
;    		 print, x
    ; use INTERPOL to mesh the data to the reduced number of x-points
    		d2 = interpol(tmpo,tmpx,x,/quadratic)
;    		print, "min, max interpolated ", min(d2), max(d2)
; 	check for NaN or Inf from floating divides
;			bad = where(~finite(d2), count)   ; DOES NOT WORK for IDL 5.2 !!
			bad = where(finite(d2) EQ 0, count)
			if count GT 0 then begin
				for i = 0, n_elements(bad)-1 do begin
				; replace with local averag e- only works for isolated bad points
					if bad(i) GT 1 AND bad(i) LT n_elements(d2)-2 then  $
				         d2(bad(i)) = (d2(bad(i)-1) + d2(bad(i)+1))/2.
				endfor
			axis_log, 'interpolation errors on ' + strtrim(string(bad),2) + ' pts'
			endif
			if spec_SumAvg NE 'A' then d2 = d2 * spec_bin  ;sum rather than average
			ty=tag_names(tmp)
			yl = ' '
			for i = 0, n_elements(ty)-1 do if ty(i) EQ 'YL' then yl =tmp.yl
			tmp.dl =  tmp.dl + ' bin ' + strtrim(string(spec_bin),2)
			s = {t:'1d', x:x, d:d2, dn:d2, xl:tmp.xl, dl:tmp.dl}
			axis_log, 'bin - ' + strtrim(string(spec_bin),2) + ': '  +  strtrim(string(n_elements(tmp.x)),2) $
			                   + ' to ' + strtrim(string(npts),2) + ' points'
    		HANDLE_VALUE, Data(0), s, /SET
    		PlotBuf, 0
    	ENDIF ELSE WIDGET_CONTROL, Uprompt, SET_VALUE='Bin: only for spectra'
    endif
    END

; ----------------------  X-axis calibration -----------------------------------------

  'Spectra.Calibrate.X.auto' : BEGIN
 ; ********* calibrate X-axis with existing slope, intercept **************
 	HANDLE_VALUE, Data(CurBuf), tmp
 	IF n_tags(tmp) ne 0 THEN BEGIN
 	  If tmp.t EQ '1d' then begin
		txt = 'X.auto: Xnew = Xold*' + STRCOMPRESS(string(X_calib(0))) + ' + ' + STRCOMPRESS(string(X_calib(1)))
		axis_log, txt
		tmp.x = X_calib(0)*tmp.x + X_calib(1)
		tmp.dl =  tmp.dl + ' Cxa'
		HANDLE_VALUE, Data(0), tmp, /SET           ;Put the data in temp buffer
  		PlotBuf, 0
  	  ENDIF else WIDGET_CONTROL, Uprompt, SET_VALUE='Calib.X.2: not for images'
  	ENDIF
    END

  'Spectra.Calibrate.X.1 point' : BEGIN
; ********* calibrate X-axis at 1-point (shift-X) **************
	HANDLE_VALUE, Data(CurBuf), tmp   ;Get the data
	IF n_tags(tmp) ne 0 THEN BEGIN
	  If tmp.t EQ '1d' then begin
	    SetGraf,'MainImg'
		WIDGET_CONTROL, Uprompt, SET_VALUE='Select X-calibration point'
		CURSOR, x, y, /UP, /DATA                ;Get a cursor point
		xn = Get_Num( PROMPT='New X : ', group=axis_ID)    ;Get a new value for that point
		X_calib(0) = 1.0
		X_calib(1) = xn(0) - x
		tmp.x = X_calib(0)*tmp.x + X_calib(1)
		txt = 'X-cal 1: shift = '+ STRCOMPRESS(string(X_calib(1))) + ' eV'
		axis_log, txt
		tmp.dl = tmp.dl + ' Cx1 '
		HANDLE_VALUE, Data(0), tmp, /SET    ;Put the recalibrated data into temp buffer
		PlotBuf, 0
	  ENDIF else WIDGET_CONTROL, Uprompt, SET_VALUE='Calib.X.1: not for images'
	ENDIF
   END

  'Spectra.Calibrate.X.2 point' : BEGIN
 ; ********* calibrate X-axis with 2-points (stretch-X) **************
 	HANDLE_VALUE, Data(CurBuf), tmp
 	IF n_tags(tmp) ne 0 THEN BEGIN
 	  If tmp.t EQ '1d' then begin
 	    SetGraf,'MainImg'
 		WIDGET_CONTROL, Uprompt, SET_VALUE='Select FIRST X-calib.point'
    	CURSOR, x1, y1, /UP, /DATA   				;Get a cursor point
  		xn1 = Get_Num( PROMPT = 'New X1 : ', group=axis_ID)     ;Get the new value for that point
  		WIDGET_CONTROL, Uprompt, SET_VALUE='Select SECOND X-calib.point'
		CURSOR, x2, y2, /UP, /DATA                ;Repeat the process for another point
  		xn2 = Get_Num(PROMPT = 'New X2 : ', group=axis_ID)
 		X_calib(0) = (xn1(0) - xn2(0))/(x1-x2)          ;Recalibrate the data
		X_calib(1) = xn1(0) - X_calib(0)*x1
		tmp.x = X_calib(0)*tmp.x + X_calib(1)
		tmp.dl = tmp.dl + ' Cx2'
		HANDLE_VALUE, Data(0), tmp, /SET           ;Put the data in temp buffer
  		PlotBuf, 0
 		txt = 'X.2: Xnew = Xold*' + STRCOMPRESS(string(X_calib(0))) + ' + ' + STRCOMPRESS(string(X_calib(1)))
		axis_log, txt
  	  ENDIF else WIDGET_CONTROL, Uprompt, SET_VALUE='Calib.X.2: not for images'
  	ENDIF
    END

  'Spectra.Calibrate.X.numerical' : BEGIN
 ; ********* calibrate X-axis with user #'s **************
 	HANDLE_VALUE, Data(CurBuf), tmp
 	IF n_tags(tmp) ne 0 THEN BEGIN
 	  If tmp.t EQ '1d' then begin
		WIDGET_CONTROL, Uprompt, SET_VALUE='Define current value of FIRST X-calib.point'
  		xo1 = Get_Num( PROMPT = 'Old X1 : ', group=axis_ID)     ;Get the old value for that point
		WIDGET_CONTROL, Uprompt, SET_VALUE='Define NEW value of this point'
  		xn1 = Get_Num( PROMPT = 'New X1 : ', group=axis_ID)     ;Get the new value for that point
		xo2 = xo1  & xn2 = xn1  ; kluge to let user set slope =1 fast
 		WIDGET_CONTROL, Uprompt, SET_VALUE='Define current value of SECOND X-calib.point'
 		xo2 = Get_Num( PROMPT = 'Old X2 : ', VAL=xo2(0), group=axis_ID)
		WIDGET_CONTROL, Uprompt, SET_VALUE='Define NEW value of this point'
  		xn2 = Get_Num( PROMPT = 'New X2 : ', VAL=xn2(0), group=axis_ID)
		X_calib(0) = 1.0          ;Recalibrate the data
		if xo1(0) NE xo2(0) then X_calib(0) = (xn1(0) - xn2(0))/(xo1(0)-xo2(0))
		X_calib(1) = xn1(0) - X_calib(0)*xo1(0)
		tmp.x = X_calib(0)*tmp.x+ X_calib(1)
		tmp.dl = tmp.dl + ' Cx_# '
		HANDLE_VALUE, Data(0), tmp, /SET           ;Put the data in temp buffer
  		PlotBuf, 0
 		txt = 'X.#: Xnew = Xold*' + STRCOMPRESS(string(X_calib(0))) + ' + ' + STRCOMPRESS(string(X_calib(1)))
		axis_log, txt
  	  ENDIF else WIDGET_CONTROL, Uprompt, SET_VALUE='Calibrate: not for images'
  	ENDIF
    END

; ----------------------  Y-axis calibration -----------------------------------------

  'Spectra.Calibrate.Y.auto' : BEGIN
 ; ********* calibrate Y-axis with existing slope, intercept **************
 	HANDLE_VALUE, Data(CurBuf), tmp
 	IF n_tags(tmp) ne 0 THEN BEGIN
 	  If tmp.t EQ '1d' then begin
		txt = 'Y.auto: Ynew = Yold*' + STRCOMPRESS(string(Y_calib(0))) + ' + ' + STRCOMPRESS(string(Y_calib(1)))
		WIDGET_CONTROL, Uprompt, SET_VALUE = txt
		tmp.d = Y_calib(0)*tmp.d + Y_calib(1)
		tmp.dl = tmp.dl + ' CyA'
		HANDLE_VALUE, Data(0), tmp, /SET           ;Put the data in temp buffer
  		PlotBuf, 0
  	  ENDIF else WIDGET_CONTROL, Uprompt, SET_VALUE='Calibrate: not for images'
  	ENDIF
    END

  'Spectra.Calibrate.Y.1 point' : BEGIN
 ; ********* calibrate Y-axis at 1-point (shift-Y) **************
 	HANDLE_VALUE, Data(CurBuf), tmp
 	IF n_tags(tmp) ne 0 THEN BEGIN
 	  If tmp.t EQ '1d' then begin
 	    SetGraf,'MainImg'
		WIDGET_CONTROL, Uprompt, SET_VALUE='Select Y-calibration point'
   		CURSOR, x, y, /UP, /DATA
  		yn = Get_Num(PROMPT = 'New Y : ', group=axis_ID)
		Y_calib(0) = 1.0
		Y_calib(1) = yn(0) - y
		tmp.d = Y_calib(0)*tmp.d + Y_calib(1)
		tmp.dl = tmp.dl + ' Cy1'
		HANDLE_VALUE, Data(0), tmp, /SET
  		PlotBuf, 0
      ENDIF else WIDGET_CONTROL, Uprompt, SET_VALUE='Calib.Y.1 not for images'
  	ENDIF
    END

  'Spectra.Calibrate.Y.2 point' : BEGIN
 ; ********* calibrate Y-axis with 2-points (stretch-Y) **************
 	HANDLE_VALUE, Data(CurBuf), tmp
 	IF n_tags(tmp) ne 0 THEN BEGIN
 	  If tmp.t EQ '1d' then begin
 	    SetGraf,'MainImg'
		WIDGET_CONTROL, Uprompt, SET_VALUE='Select FIRST Y-calib.point'
    	CURSOR, x1, y1, /UP, /DATA   				;Get a cursor point
  		yn1 = Get_Num( PROMPT = 'New Y1 : ', group=axis_ID)     ;Get the new value for that point
  		WIDGET_CONTROL, Uprompt, SET_VALUE='Select SECOND Y-calib.point'
		CURSOR, x2, y2, /UP, /DATA                ;Repeat the process for another point
  		yn2 = Get_Num(PROMPT = 'New Y2 : ', group=axis_ID)
		Y_calib(0) = 1.0		        ;Recalibrate the data
 		if y1 NE y2 then Y_calib(0) = (yn1(0) - yn2(0))/(y1-y2)  ; protect divide by 0
		Y_calib(1) = yn1(0) - Y_calib(0)*y1
		tmp.d = Y_calib(0)*tmp.d + Y_calib(1)
		tmp.dl = tmp.dl + ' Cy2'
		HANDLE_VALUE, Data(0), tmp, /SET
  		PlotBuf, 0
 		txt = 'Y.2: Ynew = Yold*' + STRCOMPRESS(string(Y_calib(0))) + ' + ' + STRCOMPRESS(string(Y_calib(1)))
		axis_log, txt
  	  ENDIF else WIDGET_CONTROL, Uprompt, SET_VALUE='Calib.Y.2: not for images'
  	ENDIF
    END

 'Spectra.Calibrate.numerical' : BEGIN
 ; ********* calibrate Y-axis with # inputs **************
 	HANDLE_VALUE, Data(CurBuf), tmp
 	IF n_tags(tmp) ne 0 THEN BEGIN
 	  If tmp.t EQ '1d' then begin
		WIDGET_CONTROL, Uprompt, SET_VALUE='Define current value of FIRST Y-calib.point'
  		o1 = Get_Num( PROMPT = 'Old Y1 : ', group=axis_ID)     ;Get the old value for that point
		WIDGET_CONTROL, Uprompt, SET_VALUE='Define NEW value of this point'
  		n1 = Get_Num( PROMPT = 'New Y1 : ', group=axis_ID)     ;Get the new value for that point
		o2 = o1  & n2 = n1  ; kluge to let user set slope =1 fast
 		WIDGET_CONTROL, Uprompt, SET_VALUE='Define current value of SECOND Y-calib.point'
 		o2 = Get_Num( PROMPT = 'Old Y2: ', VAL=o2(0), group=axis_ID)
		WIDGET_CONTROL, Uprompt, SET_VALUE='Define NEW value of this point'
  		n2 = Get_Num( PROMPT = 'New Y2: ', VAL=n2(0), group=axis_ID)
		Ycalib(0) = 1.0          ;Recalibrate the data
		if o1(0) NE o2(0) then Ycalib(0) = (n1(0) - n2(0))/(o1(0)-o2(0))
		Y_calib(1) = n1(0) - Y_calib(0)*o1(0)
		tmp.d = Y_calib(0)*tmp.d + Y_calib(1)
		tmp.dl = tmp.dl + ' Cy_#'
		HANDLE_VALUE, Data(0), tmp, /SET
  		PlotBuf, 0
  		 txt = 'Y.#: Ynew = Yold*' + STRCOMPRESS(string(Y_calib(0))) + ' + ' + STRCOMPRESS(string(Y_calib(1)))
		axis_log, txt
  	  ENDIF else axis_log, 'Calib.Y.2: not for images'
  	ENDIF
    END

  'Spectra.Convert to.OD' : BEGIN
;-------- Converts I spectrum to OD, using Io present in another aXis2000 buffer
	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 then return
	IF tmp.t EQ '1d' THEN BEGIN
 		b = Buffer(group = AXIS_ID, PROMPT='Select Buffer with Io')
 		HANDLE_VALUE, Data(b(0)), tmp2
		IF tmp2.t NE '1d' THEN BEGIN
			axis_log,'Io spectrum not supplied, conversion unsuccessful'
			return
		ENDIF ELSE BEGIN
			t = ax_mesh(tmp, tmp2, 1, /first)
			IF t EQ 1 then begin
	 			tmp.d = -1.0*alog(float(tmp.d)/float(tmp2.d))
		 		tmp.dl = tmp.dl + ' OD Io = ' + tmp2.dl
		 		yl = 'Optical density'
		 		xl = 'Photon energy (eV)'
		 		tmp = {t:'1d', d:tmp.d, x: tmp.x, xl:xl, yl: yl, dn:tmp.d, dl: tmp.dl}
		 		HANDLE_VALUE, Data(0), tmp, /SET
		 		Curbuf = 0
			  	PlotBuf, 0
		 	ENDIF ELSE axis_log, 'Buffers do not overlap. OD conversion not performed'
 		ENDELSE
	ENDIF ELSE  axis_log,'OD1 conversion only for spectra'
	END

  'Spectra.Convert to.OD1' : BEGIN
	;Converts an absorption spectrum (OD)  to an OD1 scale (response for 1 nm) by ratio-ing to the elemental signal
	axis_log,'FIRST: Generate predicted response for elemental composition, density and t = 1 nm'
	axis_log,' using utilities~calculate_X-ray_parameters(SF)'
	axis_log,'Convert to OD1 plots the ratio of the spectrum to the elemental response for 1 nm'
	axis_log,'select a scale factor from the ratio plot in the region of the far continuum'
	axis_log,'the ratio in the pre-edge region should have the same value. If it does not, the Io may have been wrong'
	axis_log, 'consider adding or subtracting a constant, then convert to OD1 again'
	HANDLE_VALUE, Data(CurBuf), tmp1
	IF n_tags(tmp1) EQ 0 then return
	IF tmp1.t EQ '1d' THEN BEGIN
 		b = Buffer(group = AXIS_ID, PROMPT='Buffer with elemental spectrum for 1 nm')
		HANDLE_VALUE, Data(b(0)), tmp2
		IF tmp2.t NE '1d' then begin
			axis_log, 'please restart and select a buffer with the elemental response for 1 nm'
			return
		ENDIF
	    t = ax_mesh(tmp1, tmp2, 1, /first)
	    IF t NE 0 then BEGIN
	    	d = float(tmp1.d) / float(tmp2.d)
			dl = tmp1.dl + ' / ' + tmp2.dl
			tmp = {t:'1d', x:tmp1.x, d:d, xl:tmp1.xl, dn:d, dl: dl}
			CurBuf = 0
			HANDLE_VALUE, Data(CurBuf), tmp, /SET
		    PlotBuf, CurBuf
		    thickness = mean(tmp.d(n_elements(tmp.d)-11:n_elements(tmp.d)-1))
			thickness = Get_Num( PROMPT = 'value at high E (thickness in nm) ',val=thickness, group=axis_ID)
			tmp1.d = tmp1.d/thickness
			tmp1.dl =  tmp1.dl + ' OD1'
			yl = 'Linear abdsorbance per nm'
			xl = 'Photon energy (eV)'
			tmp = {t:'1d', d:tmp.d, x: tmp.x, xl: xl, yl: yl, dn:tmp.d, dl: tmp.dl}
	 		HANDLE_VALUE, Data(0), tmp1, /SET
	 		Curbuf = 0
		  	PlotBuf, 0
		ENDIF ELSE axis_log, 'Buffers do not overlap. OD1 conversion not performed'
	ENDIF ELSE  axis_log,'Convert to OD1: only for spectra'
	END

'Spectra.Convert to.IP' : BEGIN
;  ------ convert E-scal to Binding energy (IP)
 	HANDLE_VALUE, Data(CurBuf), tmp
 	IF n_tags(tmp) ne 0 THEN BEGIN
; 		if n_elements(tmp.E) NE 0 then PhotonE = tmp.E
		PhotonE = get_num(Prompt = 'Photon energy', val = PhotonE, group=axis_ID)
		tmp.x = PhotonE - tmp.x
		tmp.x = reverse(tmp.x)
		tmp.d = reverse(tmp.d)
		tmp.dn = reverse(tmp.dn)
		tmp.dl = tmp.dl + ' PES'
		tmp.xl = 'Photon E = ' +string(PhotonE, format='(F7.2)') + '      IP (eV)'
		HANDLE_VALUE, Data(0), tmp, /SET
		PlotBuf, 0
	ENDIF else axis_log,'spectral ocnversion to IP: not for images'

    END

  'Spectra.Curve fit.CGO fit (=SVD)' : BEGIN
  ; ***************	Fit spectrum to set of ref. spectra using CG_Optimize **********
 	HANDLE_VALUE, Data(CurBuf), tmp
 	IF n_tags(tmp) EQ 0 THEN RETURN
 	IF (tmp.t) EQ 1 then BEGIN
		Ax_CurvFit, tmp, /axis
	ENDIF else WIDGET_CONTROL, Uprompt, SET_VALUE='Curve fit not for images'
  END


'Spectra.Curve fit.linear regression (=stack fit)' : BEGIN
  ; ***************	Fit spectrum to set of ref. spectra using REGRESS procedure **********
 	HANDLE_VALUE, Data(CurBuf), tmp
 	IF n_tags(tmp) EQ 0 THEN RETURN
 	IF (tmp.t) EQ 1 then BEGIN
		Ax_regress_spectra, tmp, /axis
	ENDIF else WIDGET_CONTROL, Uprompt, SET_VALUE='Curve fit not for images'
  END

  'Spectra.Curve fit.CGO fit (=SVD)' : BEGIN
  ; ***************	Fit spectrum to set of ref. spectra using CG_Optimize **********
 	HANDLE_VALUE, Data(CurBuf), tmp
 	IF n_tags(tmp) EQ 0 THEN RETURN
 	IF (tmp.t) EQ 1 then BEGIN
		Ax_CurvFit, tmp, /axis
	ENDIF else WIDGET_CONTROL, Uprompt, SET_VALUE='Curve fit not for images'
  END

  'Spectra.Curve fit.polarization fit' : BEGIN
  ; ***************	Fit curve to [const + ampl*cos^2(angle-angle_ref) **********
 	HANDLE_VALUE, Data(CurBuf), tmp
 	IF n_tags(tmp) EQ 0 THEN RETURN
 	IF (tmp.t) EQ 1 then BEGIN
 		curv=fltarr(2,n_elements(tmp.x))
 		curv(0,*) = tmp.x
 		curv(1,*) = tmp.d
 		param=fltarr(3)
 		param(0) = get_num(prompt='constant', val=0.5, group=axis_ID)
 		param(1) = get_num(prompt='amplitude', val=0.5, group=axis_ID)
 		param(2) = get_num(prompt='ref_angle', val=90., group=axis_ID)
 	; ------- set tolerance for fits
		tol = 1e-6
		tol = get_num(prompt='tolerance', val=tol, group=axis_ID)
	; ---------- get max iterations
		max_iter=500
		max_iter = get_num(prompt='maximum # of iterations', val=max_iter, group=axis_ID)
		polfit = Ax_Pol_Fit(curv,param=param, sigma=sigma, max_iter=max_iter, tol=tol)
		tmp.d = polfit
		tmp.dl = tmp.dl + ' Pol Fit'
		HANDLE_VALUE, Data(0), tmp, /SET
		CurBuf = 0
		PlotBuf, CurBuf
	ENDIF else WIDGET_CONTROL, Uprompt, SET_VALUE='Curve fit not for images'
  END

  'Spectra.Delete' : BEGIN
;  **************	Delete all data points between 2 cursors ************
  ax_spec_delete
  end

'Spectra.Differentiate' : BEGIN
; ********************** Differentiate spectra ****************
  HANDLE_VALUE, Data(CurBuf), tmp
	if n_tags(tmp) EQ 0 then return
	if tmp.t NE '1d' then return
	for i = 0, n_elements(tmp.d)-2 do begin
		dax = tmp.x(i+1) - tmp.x(i)
		if dax NE 0 then tmp.d(i) = (tmp.d(i+1) - tmp.d(i))/dax
	endfor
	tmp.d(n_elements(tmp.d)-1) = tmp.d(n_elements(tmp.d)-2)
	tmp.d = shift(tmp.d,1)
	tmp.d(0) = tmp.d(1)
    tmp.dl = tmp.dl + ' Der'
	HANDLE_VALUE, Data(0), tmp, /SET
	PlotBuf, 0
	WIDGET_CONTROL, Uprompt, SET_VALUE=''
  END

'Spectra.Fix rollover' : BEGIN
 ; *********************** Fix rollover (add 65535)  ***************
    HANDLE_VALUE, Data(CurBuf), tmp
    IF n_tags(tmp) EQ 0 THEN RETURN
    IF tmp.t NE '1d' THEN RETURN
	count = 1
    while count NE 0 do begin		; perform multiple times to remove all roll-over points
    neg_ind = where(tmp.d LT 0, count)
	IF count GT 0 then tmp.d(neg_ind) = tmp.d(neg_ind)+ 65535.
;		  	tmp.d(1,1) = tmp.d(1,1) +1e-6*tmp.d(1,1)   ; kluge to force REAL *,nc file !
    ENDWHILE
    CurBuf = 0
   	tmp.dl = tmp.dl + ' fix rollover'
   	Label(CurBuf) = tmp.dl
  	HANDLE_VALUE, Data(CurBuf), tmp, /set
   	PlotBuf,CurBuf
	END

 'Spectra.Gain.multiply' : BEGIN
; ************* Multiply Y-scale by user-selected constant *************
	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) ne 0 THEN BEGIN
	  If tmp.t EQ '1d' then begin
		WIDGET_CONTROL, Uprompt, SET_VALUE='Gain: multiply y-values by factor'
  		gain_m = Get_Num(val=gain_m, Prompt = 'Gain - multiply by', group=axis_ID)
		tmp.d = gain_m * tmp.d
		tmp.dl =  string(format='(A," * ",g10.3)', tmp.dl, gain_m)
		HANDLE_VALUE, Data(0), tmp, /SET
  		PlotBuf, 0
  		WIDGET_CONTROL, Uprompt, SET_VALUE=''
  	   ENDIF else  WIDGET_CONTROL, Uprompt, SET_VALUE='Gain: not for images'
  	ENDIF
    END

'Spectra.Gain.divide' : BEGIN
; ************* Divide Y-scale by user-selected constant *************
	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) ne 0 THEN BEGIN
	  If tmp.t EQ '1d' then begin
		WIDGET_CONTROL, Uprompt, SET_VALUE='Gain: divide y-values by factor'
  		gain_m = Get_Num(val=gain_m, Prompt = 'Gain - Divide by', group=axis_ID)
		tmp.d =  tmp.d / gain_m
		tmp.dl = string(format='(A,"/",g10.3)', tmp.dl , gain_m)
		HANDLE_VALUE, Data(0), tmp, /SET
  		PlotBuf, 0
  		WIDGET_CONTROL, Uprompt, SET_VALUE=''
  	   ENDIF else  WIDGET_CONTROL, Uprompt, SET_VALUE='Gain: not for images'
  	ENDIF
    END

'Spectra.Integrate' : BEGIN
; ********************** Integrate spectra ****************
  HANDLE_VALUE, Data(CurBuf), tmp
	if n_tags(tmp) EQ 0 then return
	if tmp.t NE '1d' then return
	sum = tmp.d(0)*(tmp.x(1)-tmp.x(0))
	for i = 1, n_elements(tmp.d)-1  do begin
		sum = sum +tmp.d(i)*(tmp.x(i)-tmp.x(i-1))
		tmp.d(i) = sum
	endfor
	tmp.d(0)= tmp.d(1)
;	tmp.d = shift(tmp.d,-1)
;	tmp.d(n_elements(tmp.d)-1) = tmp.d(n_elements(tmp.d)-2)
    tmp.dl = tmp.dl + ' Int'
	HANDLE_VALUE, Data(0), tmp, /SET
	PlotBuf, 0
	WIDGET_CONTROL, Uprompt, SET_VALUE=''
  END

  'Spectra.Linear Background' : BEGIN
  ; ***************	Subtract a user-defined Linear Background **********
  	SetGraf, 'MainImg'
  	HANDLE_VALUE, Data(CurBuf), tmp     ;Get the data
  	IF n_tags(tmp) ne 0 THEN BEGIN
  	  If tmp.t EQ '1d' then begin
  		WIDGET_CONTROL, Uprompt, SET_VALUE='Subtract Line: select point 1'
  		CURSOR, x1, y1, /UP, /DATA         ;Get two cursor points from the user
  		WIDGET_CONTROL, Uprompt, SET_VALUE='Subtract Line: select point 2'
		CURSOR, x2, y2, /UP, /DATA
		slope = (y1(0) - y2(0))/(x1(0)-x2(0))
		int = y1(0) - slope*x1(0)
		tmp.d = tmp.d - (slope*tmp.x + int)
		tmp.dl = tmp.dl + ' BS'
		HANDLE_VALUE, Data(0), tmp, /SET
  		PlotBuf, 0
  	  ENDIF else WIDGET_CONTROL, Uprompt, SET_VALUE='Subtract Line: not for images'
  	ENDIF
    END

'Spectra.Modify one point' : BEGIN
 ; ************** delete or add one point ********************
	ax_one_pt
  END

'Spectra.Multiply' : BEGIN
 ; ************** Generate natural log of data ********************
  WIDGET_CONTROL, Uprompt, SET_VALUE='Take product of two spectra'
  HANDLE_VALUE, Data(Curbuf), tmp1
  if n_tags(tmp1) EQ 0 then RETURN
  if tmp1.t EQ '1d' then begin
	    b_prod = Buffer(group = AXIS_ID)
	    IF b_prod EQ -1 then RETURN
	    PlotBuf, b_prod
		HANDLE_VALUE, Data(b_prod), tmp2
		IF n_tags(tmp2) EQ 0 THEN RETURN
		if tmp2.t EQ '1d' then begin
		    t = ax_mesh(tmp1, tmp2, 1)
		    IF t NE 0 then BEGIN
		    	d = float(tmp1.d) * float(tmp2.d)
				dl = tmp1.dl + ' * ' + tmp2.dl
				tmp = {t:'1d', x:tmp1.x, d:d, xl:tmp1.xl, dn:d, dl: dl}
				CurBuf = 0
				HANDLE_VALUE, Data(CurBuf), tmp, /SET
		    	PlotBuf, CurBuf
		    	WIDGET_CONTROL, Uprompt, SET_VALUE=''
    		endif else  WIDGET_CONTROL, Uprompt, SET_VALUE='Buffers do not overlap. MULTIPLY not performed'
	    endif else  WIDGET_CONTROL, Uprompt, SET_VALUE='Spectra Ratio: not valid for images'
  endif else  WIDGET_CONTROL, Uprompt, SET_VALUE='Spectra Ratio: not valid for images'
  END

'Spectra.Peak area' : BEGIN
 ; ************** Determine area between 2 cursors ********************
	HANDLE_VALUE, Data(Curbuf), tmp
	if n_tags(tmp) EQ 0 then return
	if tmp.t NE '1d' then return
	SetGraf,'MainImg'
	WIDGET_CONTROL, Uprompt, SET_VALUE='Select lower limit', /update
	CURSOR, x1, y1, /UP, /DATA
	WIDGET_CONTROL, Uprompt, SET_VALUE='Select upper limit', /update
	CURSOR, x2, y2, /UP, /DATA
	low =  where(tmp.x GE x1(0)) & low = min(low)
	high = where(tmp.x LE x2(0)) & high = max(high)
;	print, 'Integrate from ',fix(low),' to ', fix(high)
	area = INT_TABULATED(tmp.x(low:high), tmp.d(low:high))
	text = string(x1,x2,area,format='(F6.2," - ",F6.2," . Area= ", G13.6)')
	print, text
	WIDGET_CONTROL, Uprompt, SET_VALUE=text, /update
  END

'Spectra.Power.exp(Y)' : BEGIN
 ; *********************** Exp of data ********************
    HANDLE_VALUE, Data(CurBuf), tmp
     IF n_tags(tmp) NE 0 THEN BEGIN
		tmp.d = exp(tmp.d)
        CurBuf = 0
	   	tmp.dl = tmp.dl + ' e^'
	   	Label(CurBuf) = tmp.dl
	  	HANDLE_VALUE, Data(CurBuf), tmp, /set
	   	PlotBuf,CurBuf
     ENDIF
     END

'Spectra.Power.ln(Y)' : BEGIN
 ; ************** Generate natural log of data ********************
  WIDGET_CONTROL, Uprompt, SET_VALUE='Take natural log of data'
  HANDLE_VALUE, Data(Curbuf), tmp
  if n_tags(tmp) NE 0 then begin
	  	tmp.d = alog(tmp.d)
	    tmp.dl = tmp.dl + ' Ln'
    	HANDLE_VALUE, Data(0), tmp, /SET
    	PlotBuf, 0
    	WIDGET_CONTROL, Uprompt, SET_VALUE=''
  endif
  END

'Spectra.Power.10^(Y)' : BEGIN
 ; *********************** Exp of data ********************
    HANDLE_VALUE, Data(CurBuf), tmp
     IF n_tags(tmp) NE 0 THEN BEGIN
		tmp.d = 10.^(tmp.d)
        CurBuf = 0
	   	tmp.dl = tmp.dl + ' 10^'
	   	Label(CurBuf) = tmp.dl
	  	HANDLE_VALUE, Data(CurBuf), tmp, /set
	   	PlotBuf,CurBuf
     ENDIF
     END

'Spectra.Power.log10(Y)' : BEGIN
 ; ************** Generate natural log of data ********************
  WIDGET_CONTROL, Uprompt, SET_VALUE='Take natural log of data'
  HANDLE_VALUE, Data(Curbuf), tmp
  if n_tags(tmp) NE 0 then begin
	  	tmp.d = alog10(tmp.d)
	    tmp.dl = tmp.dl + ' Log'
    	HANDLE_VALUE, Data(0), tmp, /SET
    	PlotBuf, 0
    	WIDGET_CONTROL, Uprompt, SET_VALUE=''
  endif
  END

'Spectra.Ratio_to' : BEGIN
; ***********  RATIO's 2 files:  Interpolates to finest X-scale in common region *****************
  WIDGET_CONTROL, Uprompt, SET_VALUE='RATIO to another buffer'
  HANDLE_VALUE, Data(Curbuf), tmp1
  if n_tags(tmp1) EQ 0 then RETURN
  if tmp1.t EQ '1d' then begin
	    s1 = Get_num(PROMPT = 'this Buf *', val=factor(0), group=axis_ID)
	    factor(0) = s1
	    b_div = Buffer(group = AXIS_ID)
	    IF b_div EQ -1 then RETURN
	    PlotBuf, b_div
		s2 = Get_num(PROMPT = 'other Buf *', val = factor(1), group=axis_ID)
		factor(1) = s2
		HANDLE_VALUE, Data(b_div), tmp2
		IF n_tags(tmp2) EQ 0 THEN RETURN
		if tmp2.t EQ '1d' then begin
		    t = ax_mesh(tmp1, tmp2, 1)
		    IF t NE 0 then BEGIN
		    	d = (float(s1)*float(tmp1.d)) / (float(s2)*float(tmp2.d))
				dl = tmp1.dl + ' / ' + tmp2.dl
				tmp = {t:'1d', x:tmp1.x, d:d, xl:tmp1.xl, dn:d, dl: dl}
				CurBuf = 0
				HANDLE_VALUE, Data(CurBuf), tmp, /SET
		    	PlotBuf, CurBuf
		    	WIDGET_CONTROL, Uprompt, SET_VALUE=''
    		endif else  WIDGET_CONTROL, Uprompt, SET_VALUE='Buffers do not overlap. RATIO not performed'
	    endif else  WIDGET_CONTROL, Uprompt, SET_VALUE='Spectra Ratio: not valid for images'
  endif else  WIDGET_CONTROL, Uprompt, SET_VALUE='Spectra Ratio: not valid for images'
END

'Spectra.E_to_Wavelength' : BEGIN
   ; ********* Convert X-axis scale from E <-> Lambda ***** (symmetric) ****
   WIDGET_CONTROL, Uprompt, SET_VALUE='Convert X-axis by 12398/x'
   HANDLE_VALUE, Data(Curbuf), tmp
   if n_tags(tmp) NE 0 then begin
     if tmp.t EQ '1d' then begin
		  tmp.x = 12398./(tmp.x)
		  tmp.dl = tmp.dl + ' 1/e'
		  t = size(tmp.x)  &  np = t(1)
		  xord = sort(tmp.x)
		  tmp.x = tmp.x(xord)
		  tmp.d = tmp.d(xord)
		  lbl_t = tmp.xl   & xtra = ' '
		  dot_pos = strpos(lbl_t,',')
		  if dot_pos GT 0 AND dot_pos LT strlen(lbl_t) then begin
			  lbl_tmp = strtrim(strmid(tmp.xl,0,dot_pos))
			  xtra = strmid(tmp.xl,dot_pos+1,strlen(lbl_t)-1)
		  endif else lbl_tmp = lbl_t
		  if lbl_tmp EQ 'Photon Energy' THEN begin lbl_tmp = 'Wavelength'
		  endif else begin
		  	if lbl_tmp EQ 'Wavelength' THEN lbl_tmp = 'Photon Energy'
		  endelse
		  lbl_tmp = lbl_tmp + ','
		  tmp.xl = lbl_tmp + xtra
	      HANDLE_VALUE, Data(0), tmp, /SET
	      PlotBuf, 0
	      WIDGET_CONTROL, Uprompt, SET_VALUE=''
	   endif else  WIDGET_CONTROL, Uprompt, SET_VALUE='eV_to_Lambda: not for images'
    endif
    END


'Spectra.Reverse values' : BEGIN
  ;  ************** reverse ordering of X-values; make y-values follow ****
    HANDLE_VALUE, Data(CurBuf), tmp
  	IF n_tags(tmp) NE 0 then begin
  		IF tmp.t EQ '1d' THEN BEGIN
	 		tmp.d = reverse(tmp.d)
	 		tmp.dl = tmp.dl + ' reverse'
	 		HANDLE_VALUE, Data(0), tmp, /SET
	 		Curbuf = 0
		  	PlotBuf, 0
		ENDIF ELSE  axis_log, 'Reverse values: only for spectra'
  	ENDIF
  	END

'Spectra.Split' : BEGIN
  ;  **************	 Split multi-region, non-monotonic into sections ************
    HANDLE_VALUE, Data(CurBuf), tmp
  	IF n_tags(tmp) NE 0 then begin
	  	IF tmp.t EQ '1d' THEN BEGIN
  ; parse the file for non-monotonic, and split into sections if multi-section
			 del = tmp.x(1:*) - tmp.x(0:*)
			 sect = where(del LT 0,nplot)
			 if nplot GT 0 then PlotSect, CurBuf, AUTOSCALE=1, split=1
		ENDIF ELSE axis_log,'Split: only for spectra'
  	EndIF
  	ThumbLbls  ; update thumbnails
  	END

  'Spectra.Truncate' : BEGIN
  ;  **************	 Delete all data points OUTSIDE of 2 cursors ************
  	HANDLE_VALUE, Data(CurBuf), tmp
  	IF n_tags(tmp) NE 0 then begin
  	  	If tmp.t EQ '1d' then begin
	  		SetGraf, 'MainImg'
	  		WIDGET_CONTROL, Uprompt, SET_VALUE='Truncate: select point 1'
			CURSOR, x1, y1, /UP, /DATA        ;Get two cursor points from the user
			WIDGET_CONTROL, Uprompt, SET_VALUE='Truncate: select point 2'
			CURSOR, x2, y2, /UP, /DATA
			xlo = x1(0)          ; order x1 (low), x2 (hi)
			xhi = x2(0)
			xt = xlo
			if xhi LT xlo THEN BEGIN
				xlo = xhi
				xhi = xt
			endif
			if xlo LT min(tmp.x) THEN xlo = min(tmp.x)    ; limit region to within data set
			if xhi GT max(tmp.x) THEN xhi = max(tmp.x)
			text = 'Truncate from' + strcompress(string(xlo)) + ' to' + strcompress(string(xhi))
			axis_log, text
			xord = sort(tmp.x)            ; sort on x-values to ensure truncate works
			tmp.x = tmp.x(xord)
			tmp.d = tmp.d(xord)
			n=where(tmp.x LT xlo, nl)     ; assumes monotonic increasing X-values
			n=where(tmp.x GT xhi, nh)
			n=where(tmp.x,nt)
			if nh GT 0 then begin
				x=tmp.x(nl:(nt-nh))
				y=tmp.d(nl:(nt-nh))
			endif else begin             ; treat case where truncate above upper limit
				x = tmp.x(nl:nt-1)
				y = tmp.d(nl:nt-1)
			endelse
			tmp.dl = tmp.dl + ' TR'
			s={T:'1d', D:y, X:x, XL: tmp.xl, dn: tmp.dn, DL: tmp.dl}
			HANDLE_VALUE, Data(0), s, /SET
	  		PlotBuf, 0
  		ENDIF else  axis_log, 'Truncate: only for spectra'
  	ENDIF
    END


; **********************************************************
; ################## Display Menu items  ###################
; **********************************************************

 'Display.Over Plot.No Rescale' : BEGIN
; ******************** Overplot multiple spectra on same X, same Y scales ********
HANDLE_VALUE, Data(CurBuf), tmp
if n_tags(tmp) NE 0 then begin
  if tmp.t eq '1d' then begin
	bt = Mbuf(val=pBufs,group=axis_ID)        ; get multi-buffer list
	IF bt(0) NE -1 then begin 		; cancel
		nb = n_elements(bt)
		CurBuf = bt(0)
		FOR i = 0, nb-1 DO BEGIN
			already_plotted = 0
			FOR j = 0, pNum-1 DO if pBufs(j) EQ bt(i) THEN already_plotted = 1
			HANDLE_VALUE, Data(bt(i)), tmpo
		    	IF n_tags(tmpo) ne 0 AND already_plotted EQ 0 then begin
		    	  if tmpo.t EQ '1d' then begin					; only add spectral data
					HANDLE_VALUE, pData(pNum), tmpo, /set       ;and update temporary storage
					pBufs = [pBufs, 1]
					pBufs(pNum) = bt(i)
					pNum = pNum + 1
				  endif
			   	ENDIF
	    ENDFOR
		Refresh
	ENDIF
  endif else axis_log, 'Overplot: not for images'
endif
END

'Display.Over Plot.Rescale' : BEGIN
; ******************** Overplot additional spectrum with same X,recaled Y ********
HANDLE_VALUE, Data(CurBuf), tmp
if n_tags(tmp) NE 0 then begin
  if tmp.t eq '1d' then begin
	bt = Mbuf(val=pBufs,group=axis_ID)           ;Get multiple buffer list from the user; send current plot info
	IF bt(0) NE -1 then begin 	   ; cancel
		nb = n_elements(bt)        ; get size of buffer list
	   	s=fltarr(2) & s(0) = min(tmp.d) & s(1) = max(tmp.d)   ; get data limits for orginal plot
	    FOR i = 0, nb-1 DO BEGIN
			already_plotted = 0
			FOR j = 0, pNum-1 DO IF pBufs(j) EQ bt(i) THEN already_plotted = 1
			HANDLE_VALUE, Data(bt(i)), tmpo
			IF n_tags(tmpo) ne 0 AND already_plotted EQ 0 THEN BEGIN   ; only process new buffers
				if tmpo.t EQ '1d' THEN BEGIN                   ; only overplot spectra
					a=(s(1)-s(0))/(max(tmpo.d)-min(tmpo.d))    ; map onto y-range of first plot
		    		tmpo.d = a*(tmpo.d-min(tmpo.d)) + s(0)
		            HANDLE_VALUE, pData(pNum), tmpo, /set      ;update temporary buffers
		            pBufs = [pBufs, 1]
		 			pBufs(pNum) = bt(i)
		 			pNum = pNum + 1
		 	   endif
	  		ENDIF
	    ENDFOR
		Refresh
	ENDIF
  endif else axis_log, 'Overplot: not for images'
endif
END

'Display.Over Plot.Window' : BEGIN
; ************************* Overplot with user defined vertical window ************
HANDLE_VALUE, Data(CurBuf), tmp
if n_tags(tmp) NE 0 then begin
  if tmp.t eq '1d' then begin
    bt = Buffer(group = AXIS_ID)
    IF bt ne -1 THEN BEGIN
	    HANDLE_VALUE, Data(bt), tmpo
		IF n_tags(tmpo) ne 0 THEN BEGIN
		  if tmpo.t EQ '1d' then begin
			    WIDGET_CONTROL, Uprompt, SET_VALUE='Over Plot.Window: Select lower y-limit'
			    CURSOR, xh, yh, /UP, /Data
			    WIDGET_CONTROL, Uprompt, SET_VALUE='Over Plot.Window: Select upper y-limit'
			    CURSOR, xl, yl, /UP, /Data
			    if yl GT yh then begin
			    	tmp = yl  &  yl = yh  &  yh = tmp
			    ENDIF
				a = (yh - yl) / (max(tmpo.d) - min(tmpo.d))  ;Rescale the new data
		    	b=yl-a*min(tmpo.d)
		    	tmpo.d = a * tmpo.d + b
				HANDLE_VALUE, pData(pNum), tmpo, /set    ; update temporary buffers
				pBufs = [pBufs, 1]
				pBufs(pNum) = bt
				pNum = pNum + 1			; increment total number of buffers
				Refresh
		  endif else axis_log,'Over Plot.Window: incompatible data'
	    ENDIF
	ENDIF
  endif else axis_log, 'Overplot: not for images'
endif
END

'Display.Over Plot.Shift' : BEGIN
; ************************* Overplot with user defined vertical shift ************
HANDLE_VALUE, Data(CurBuf), tmp
if n_tags(tmp) NE 0 then begin
  if tmp.t eq '1d' then begin
	bt = Buffer(group = AXIS_ID)
    IF bt ne -1 THEN BEGIN
		HANDLE_VALUE, Data(bt), tmpo
		IF n_tags(tmpo) ne 0 THEN BEGIN
		  if tmpo.t EQ '1d' then begin
			WIDGET_CONTROL, Uprompt, SET_VALUE='Over Plot.Shift: Select lower y-limit'
	    	CURSOR, x, y, /UP, /Data
			tmpo.d = tmpo.d + y - min(tmpo.d)     ;shift the new data
			HANDLE_VALUE, pData(pNum), tmpo, /set
			pBufs = [pBufs, 1]
			pBufs(pNum) = bt
			pNum = pNum + 1			; increment total number of buffers
			Refresh
		  endif else axis_log,'Over Plot.Shift: incompatible data'
	    ENDIF
	ENDIF
  endif else axis_log, 'Overplot: not for images'
endif
END

'Display.3d plot' : BEGIN
;  ****************** generate shade_surface 3d display *******************
    HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 THEN RETURN
	IF tmp.t NE '2d' THEN RETURN
	t = where(tag_names(tmp) EQ 'E', count)
;	if count GE 1 then tmp.xl = 'E(eV)= ' + string(tmp.E,format='(F6.2)')
	splot3d, tmp, zrange=Zrng, min_value = Zrng(0), max_value = Zrng(1), zstyle=1
	END

'Display.Clear.Lines' : BEGIN
; ********* erase lines from lineout **************
   LineClear
   close,/all
END

'Display.Clear.Current' : BEGIN
; ********* erase current buffer only **************
	ax_clear, /current
END

'Display.Clear.Selected' : BEGIN
; ********* erase selected buffers  **************
	ax_clear, /select
END

'Display.Clear.All' : BEGIN
; ********* erase ALL buffers and launch user-selected logo **************
	if AxSpin EQ 1 then ax_clear,/all, /spin $
	else ax_clear, /all
END

'Display.Modify image colors' : BEGIN
;  ****************** Modify and save Color table *******************
	xloadct, silent = 0, group = axis_id,  /modal, $
		bottom = ax_low_color_index, ncolors=(ax_top_color_index-ax_low_color_index); use (aph-corrected) IDL 5.2 version
	TVLCT, UserR, UserG, UserB, /GET    ; store color tables for replacement
	PlotBuf, CurBuf
    END

'Display.Modify rigid colors' : BEGIN
;  ****************** Modify and save Color table *******************
	axis_log, 'Modify rigid colors: Not yet coded (aph 23-feb-06)'
;	zstack_pickcolor
;	PlotBuf, CurBuf
    END

'Display.Pixels only' : BEGIN
;  ****************** set-up image to plot by pixel *******************
	HANDLE_VALUE, Data(CurBuf), tmp
	IF n_tags(tmp) NE 0 THEN BEGIN
  	  IF tmp.t NE '1d' then begin
		main = 360*gr_scale - 60     ; roughly size of image plot window in SPLOT2D
		nxp = n_elements(tmp.x)  &  nyp = n_elements(tmp.y)
		IF nxp LT main AND nyp LT main THEN BEGIN       ; only rebin if smaller
		   nxtnd = (main - nxp + 1)/2   &  nytnd = (main - nyp + 1)/2
		   dpx = tmp.x(1) - tmp.x(0)                    ; set up extended x-scale
		   sx0 = tmp.x(0) - nxtnd*dpx
		   sx = fltarr(main)
		   FOR i = 0, nxtnd - 1 DO sx(i) = sx0 + i*dpx
		   sx(nxtnd:nxtnd+nxp-1) = tmp.x(0:nxp-1)
		   FOR i = nxtnd, main-1 DO sx(i) = sx0 + i*dpx
		   dpy = tmp.y(1) - tmp.y(0)                    ; set up extended y-scale
		   sy0 = tmp.y(0) - nytnd*dpy
		   sy = fltarr(main)
		   FOR i = 0, nytnd - 1 DO sy(i) = sy0 + i*dpy
		   sy(nytnd:nytnd+nyp-1) = tmp.y(0:nyp-1)
		   FOR i = nytnd, main-1 DO sy(i) = sy0 + i*dpy
		   tmp3 = fltarr(main,main)                      ; set up extended image
		   tmp3(0:main-1,0:main-1) = min(tmp.d)
		   tmp3(nxtnd:nxtnd+nxp-1,nytnd:nytnd+nyp-1) = tmp.d(0:nxp-1,0:nyp-1)
		   tmp3_lbl = tmp.dl + ' px'
		   s = {t:tmp.t,d:tmp3,x:sx,y:sy,xl:tmp.xl,yl:tmp.yl,dl:tmp3_lbl}
		   CurBuf = 0
		   HANDLE_VALUE, Data(CurBuf), s, /set
   		   Label(CurBuf) = s.dl
   		   PlotBuf,CurBuf
        ENDIF  else axis_log,'Pixels only: image larger than MainImg size'
      ENDIF  else axis_log,'Pixels only display: only for images'
    ENDIF
    END

'Display.RGB composite' :  BEGIN
; -------  generate RGB (same as in Images memo)
   ax_RGB
 END

'Display.Show color scheme' :  BEGIN
	cindex
   END

'Display.Scale bar position' :  BEGIN
	handle_value,Data(CurBuf),tmp
	if n_tags(tmp) eq 0 then return
	if tmp.t ne '2d' then return
	scale_bar = 1
	axis_log,'Locate start of scale bar'
	CURSOR, x1, y1, /UP, /normal
;	print, x1, y1
	if Axes then begin
		bar_pos(0) = (x1(0)-0.12 )/0.88
		bar_pos(1) = (y1(0)-0.08)/0.87
	endif else begin
		bar_pos(0) = (x1(0)-0.04)/0.94
		bar_pos(1) = (y1(0)-0.02)/0.96
	endelse
;	print, bar_pos(0), bar_pos(1)
   	plotBuf, CurBuf
	axis_log, ' ', /clear
   END

'Display.Thumbnails.4.common scale' : BEGIN
 ;  ******************** place buffers 1-4 on main screen **************
 	bt = Mbuf(val=[1,2,4,5],group=axis_ID)        ;Get multiple buffer list from the user; send current plot info
	IF bt(0) NE -1 then begin 		; cancel
		nb = n_elements(bt)   ; get size of buffer list
		if nb ge 4 then Buf4 = bt(0:3) else begin
		   Buf4 = intarr(4)
		   Buf4(0:nb-1) = bt(0:nb-1)
		   for i = nb,3 do Buf4(i) = 0
		endelse
		axis_log, '4 - all images to same Z-scale'
	    ThumbZoom, Num=4, BufChoice = Buf4, /all_scale
	ENDIF
	ax_color            ; re-establish color scale
  END

'Display.Thumbnails.4.rescale each' : BEGIN
 ;  ******************** place buffers 1-4 on main screen **************
 	bt = Mbuf(val=[1,2,4,5],group=axis_ID)        ;Get multiple buffer list from the user; send current plot info
	IF bt(0) NE -1 then begin 		; cancel
		nb = n_elements(bt)   ; get size of buffer list
		if nb ge 4 then Buf4 = bt(0:3) else begin
		   Buf4 = intarr(4)
		   Buf4(0:nb-1) = bt(0:nb-1)
		   for i = nb,3 do Buf4(i) = 0
		endelse
		axis_log, '4 - each image full Z-scale'
	    ThumbZoom, Num=4, BufChoice = Buf4, color=1
	ENDIF
	ax_color            ; re-establish color scale
 END

'Display.Thumbnails.9.common scale' : BEGIN
 ;  ******************** place buffers 1-9 on main screen **************
	axis_log, '9 - all images to same Z-scale'
	ThumbZoom, /all_scale
	ax_color            ; re-establish color scale
 END

'Display.Thumbnails.9.rescale each' : BEGIN
 ;  ******************** place buffers 1-9 on main screen **************
	axis_log, '9 - each image full Z-scale'
   	ThumbZoom, color=1
   	ax_color            ; re-establish color scale
 END


; ***************************************************************
; #################### Utilities ################################
; ***************************************************************


  'Utilities.Print.Logbook' : BEGIN
 ;  ****************** Print small size  **************************
	handle_value,Data(CurBuf),tmp
	if n_tags(tmp) ne 0 then begin     ; ONLY print if data is non=zero
		PrintSize = get_num(Prompt='Size (inch)',val = PrintSize, group=axis_ID)
		wset, MainImg
		PrintColor = get_num(prompt = 'Color (0) or B/W (1)', val=PrintColor, group = axis_ID)
		if PrintColor EQ 1 then begin
			old_device = !D.name  	; Trap out so one does not have to assume graphics device
			TVLCT, R, G, B, /GET	; store color tables for replacement
			loadct,0				; set to standard B/W color table
			if tmp.t EQ '1d' AND Thumb_plot EQ 0 then refresh
		endif
		win2lpr, sys = GR_dev, pr = PRINT_dev, Size=PrintSize
		if PrintColor EQ 1 then begin
			SET_PLOT, old_device
			TVLCT, R, G, B		; restore color tables
			if tmp.t EQ '1d' AND Thumb_plot EQ 0 then refresh
		endif
    	close,/all
    endif
    END

  'Utilities.Print.Annotated' : BEGIN
; ************* full scale printing ***************
	handle_value,Data(CurBuf),tmp
	if n_tags(tmp) ne 0 then begin
		PrintSize = get_num(Prompt='Size(inch)',val = PrintSize, group=axis_ID)
		wset, MainImg
		PrintColor = get_num(prompt = 'Color (0) or B/W (1)', val=PrintColor, group = axis_ID)
		if PrintColor EQ 1 then begin
			old_device = !D.name  	; Trap out so one does not have to assume graphics device
			TVLCT, R, G, B, /GET	; store color tables for replacement
			loadct,0				; set to standard B/W color table
			if tmp.t EQ '1d' AND Thumb_plot EQ 0 then refresh
		endif

		ANNOTATE				; allow user to add comments, arrows etc
		win2lpr,SYS = GR_dev,PR = PRINT_dev, Size=PrintSize
		if PrintColor EQ 1 then begin
			SET_PLOT, old_device
			TVLCT, R, G, B		; restore color tables
			if tmp.t EQ '1d' AND Thumb_plot EQ 0 then refresh
		endif
	    close,/all
  	endif
  END

'Utilities.9_pad analysis' : BEGIN
; ********* determine average of each pad of a 9-pad damage pattern **************
   ax_9pad
 end

'Utilities.Calculate concentration' : BEGIN
; ********* pop-up concentration calculator **************  ; added 01 Jun 2018
   ax_conc_calc, GROUP_LEADER = axis_ID
 end

'Utilities.Calculate peptide spectra' : BEGIN
; *************** run XSpecSim_run.sav  to compute amino acid spectra *****************
;  AA_run, group_leader=axis_ID, file=codePath + 'AAData' + ax_sep()
 Xspecsim_run
END

'Utilities.Calculate X-ray parameters (SF)' : BEGIN
; *************** run SF.PRO to compute mass abs. coeff. *****************
; NB full SF code has MANY MORE capabilities !
	WIDGET_CONTROL, Uprompt, SET_VALUE='use SF (Billy Loo) to calculate mass absorption coefficents'
	sf_cmpd = get_text(Prompt = 'Formula', val = sf_cmpd, group = axis_ID)
	sf_Emin = get_num(Prompt = 'minimum energy', val = sf_Emin, group = axis_ID)
	sf_Emax = get_num(Prompt = 'maximum energy', val = sf_Emax, group = axis_ID)
	energy = findgen(sf_Emax - sf_Emin) + sf_Emin
	sfdir = CodePath + 'sfdata' + ax_sep()
	print, ' defining location of SF data as ', sfdir
	SF_INIT, sfdir
	sf_mode ='transmission'
	WIDGET_CONTROL, Uprompt, SET_VALUE='Mass absorption (cm-2/g) or Transmission'
	sf_mode = get_text(Prompt = 'Compute (mu,trans)',val=sf_mode, group = axis_ID)
	if strmid(strlowcase(sf_mode),0,1) EQ 't' then sf_mode = 'transmission' $
	    else sf_mode = 'mass absorption'
	if sf_mode EQ 'transmission' then begin
		sf_density = get_num(Prompt = 'density (g/cc)', val = sf_density, group = axis_ID)
;		help, sf_density
		sf_density = double(sf_density)
		sf_thick = get_num(Prompt = 'thickness (um)', val = sf_thick, group = axis_ID)
		Widget_control,/hourglass
		result = SF(sf_cmpd, energy, density = sf_density, thickness = sf_thick, $
		   result_type='trans', sf_dir=sfdir)
		test = dialog_message(/question, 'Convert to OD ? (No = plot transmission) ')
		if Test EQ 'Yes' then result = -1.0*alog(result)
	endif else begin
		Widget_control,/hourglass
		result = SF(sf_cmpd, energy, sf_dir=sfdir)
	endelse
	; ask to confirm the header
	t = string(sf_density, 1000.*sf_thick, format =' ("d(g/cc) = ",f4.2,"    t(nm) = ",f5.1)  ')
	dl = sf_cmpd(0) + '    '  + t + '   SF   OD1'
	dl = get_text(Prompt = 'Header for output file ',val=dl, group = axis_ID)
	tmp = {t:'1d', x: energy, d: result, yl: sf_mode, xl: 'Energy (eV)', dn: result, dl: dl }
	HANDLE_value, Data(CurBuf),tmp,/set
    Plotbuf,CurBuf
END

'Utilities.Change dwell' : BEGIN
; ********* change dwell **************
  HANDLE_VALUE, Data(CurBuf), tmp
  IF n_tags(tmp) NE 0 THEN BEGIN
;	print, tmp.xl
	ts = strpos(strlowcase(tmp.xl),'dwell')
	if ts GT 0 then begin
		tf = ts+7
		te = strpos(strlowcase(tmp.xl),'ms')
		dwell = float(strmid(tmp.xl, tf, te-ts))
	endif else begin
		dwell = 0.
		tf = 0
		endelse
    dwell = get_num(prompt='dwell (ms)',VAL=dwell, group=axis_ID)
    axis_log, 'dwell set to ' + strtrim(string(dwell),2) + ' ms'
    tmp.xl = strmid(tmp.xl, 0,tf) +  string(dwell, format= '(f7.1," ms")')
	HANDLE_VALUE, Data(CurBuf), tmp, /set
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf	     ; replot - this updates ThumbNails and buffer labels
  endif
END

'Utilities.Change energy' : BEGIN
; ********** adjust energy for an image file (to get correct values for SVD) ********
	handle_value,Data(CurBuf),tmp
	if n_tags(tmp) eq 0 then return
	if tmp.t ne '2d' then return
	test = where(tag_names(tmp) EQ 'E',count)
	if count EQ 1 then energy = tmp.e else begin
		energy = 0.
		eq_pos = strpos(tmp.xl,'=')
		if eq_pos EQ -1 then goto, skip_E
		sp_pos = strpos(tmp.xl,'e',eq_pos+2)
		energy = float(strmid(tmp.xl,eq_pos+1,sp_pos-eq_pos-1))
		eq_pos = strpos(tmp.xl,'=', sp_pos)
		sp_pos = strpos(tmp.xl,'m', eq_pos+2)
		dwell = float(strmid(tmp.xl,eq_pos+1,sp_pos-eq_pos-1))
		if dwell NE 0 then sd.dwell_time = dwell
	endelse
	skip_E:
	energy = get_num(Prompt = 'Energy (eV)', val = energy, group = axis_id)
	if energy NE 0 then sd.wavelength = 12398./energy
	tmp.xl = string(FORMAT='("x (um)     E = ",f8.3," eV     dwell = ",f5.2," ms")', $
      12398./sd.wavelength, sd.dwell_time)
	s = {t:'2d', x:tmp.x, y:tmp.y, d:tmp.d, e: energy, xl:tmp.xl, yl:tmp.yl, dl: tmp.dl}
	HANDLE_VALUE, Data(0), s, /SET           ;Put the data in temp buffer
	PlotBuf, 0
 END

'Utilities.Change label' : BEGIN
; ********* change label **************
  HANDLE_VALUE, Data(CurBuf), tmp
  IF n_tags(tmp) NE 0 THEN BEGIN
    tmp.dl = get_text(prompt='Label',VAL=tmp.dl, group=axis_ID)
	HANDLE_VALUE, Data(CurBuf), tmp, /set
	Label(CurBuf) = tmp.dl
	PlotBuf, CurBuf	; replot - this updates ThumbNails and buffer labels
  endif
END

'Utilities.Change mesh' : BEGIN
; ********* change mesh or x(y) scales **************
  HANDLE_VALUE, Data(CurBuf), tmp
  IF n_tags(tmp) NE 0 THEN BEGIN
	tmp1 = ax_interp(tmp)
	CurBuf = 0
	HANDLE_VALUE, Data(CurBuf), tmp1, /set
	Label(CurBuf) = tmp1.dl
	PlotBuf, CurBuf	; replot - this updates ThumbNails and buffer labels
  endif
END


'Utilities.Execute macro' :  BEGIN
; -------  insert user commands here - modify ax_macro and recompile
; (kluge since cannot find way to execute from a file)
  @ax_macro
 END

'Utilities.Modify rigid colors' :  BEGIN
	ax_pickcolor
   END

;'Utilities.PEEMVision (Scholl Jan 2007)' :  BEGIN
;	PEEMVision
;
;      NEEDS parameters to work
;
;  END

'Utilities.Print SysVar' :  BEGIN
	print_sysvar
   END

'Utilities.Other.ECHEM plot' : BEGIN
; -------------- make a sequence of png images with symbol & line tracing out points
	tmp = echem_plot(group=axis_ID)
   END

'Utilities.Other.ISEELS Display' : BEGIN
; ------------- display ISEELS database spectra
	ax_iseels_display
   END

'Utilities.Other.print ISEELS Database' : BEGIN
; ------------- display ISEELS database spectra from a file list and print using Gadwin PrintScreen
; can select to print, or save as a file from the Gadwin PrintScreen settings
	file = pickfile2(title='Select ISEELS database file LIST', filter='*.txt', /read)
	print_is_database, file = file
   END

'Utilities.Set preferences' : BEGIN
; ********** run widget to let user choose AXIS default properties ********
   test = axis_ini(file=ini_file, /set)
END




; ***************************************************************
; ####################### Menu Buttons ##########################
; ***************************************************************


'Exit' : BEGIN
 ; save the default values
 ; save the default values in the CodePath subdirectory  (aph 29-jan-01)
  	t = axis_ini(/out)   ; (24-jul-15 (aph) removed file=ini_file  to force new OS dependent default ini file names
  	if strlen(t) NE 0 then begin
		print, 'saved default values to ', codePath + ini_file
		loadct,0, /silent
		; Kill the handles
		  for i=0,9 do handle_free, Data(i)
		  for i=0,9 do handle_free, pData(i)
		; reset graphing & color parameters
		; 	!p.color=255
		; 	!p.background = 0
		loadct,0,/silent
		!x.range = 0
		!y.range = 0
		!z.range = 0
		; set default directory to the code directory for ease of modifying
		cd, codePath
		;Kill the widget
		WIDGET_CONTROL, Axis_ID, /DESTROY;, event.top
		axis_ID = 0
		print, 'AXIS terminated. Have a nice day!'
		loadct,0,/silent
   endif
  END

'Quit' : BEGIN
  ;Kill the handles
      for i=0,9 do handle_free, Data(i)
      for i=0,9 do handle_free, pData(i)
 ; save the default values
  	loadct,0, /silent
 ; reset graphing & color parameters
; 	!p.color=255
; 	!p.background = 0
 	loadct,0,/silent
 	!x.range = 0
 	!y.range = 0
 	!z.range = 0
; set default directory to the code directory for ease of modifying
 	cd, codePath
 ;Kill the widget
    WIDGET_CONTROL, Axis_ID, /DESTROY;, event.top
 	axis_ID = 0
 	print, 'AXIS terminated. Have a nice day!'
  END

'XimageViewer' :  BEGIN
;	Doc_library, 'AXIS_C'
	WIDGET_CONTROL, Uprompt, SET_VALUE='XimageViewer - Koprinarov viewer'
	CD, DefPath       ; change directory to current default path
	if !version.os_family EQ 'Windows' then begin
		if fix(strmid(!version.release,0,1)) GE 6 then begin  ; /NOWAIT only from ver 6 on
;			 print, 'NoWait'
			 SPAWN, CodePath + '\XimageViewer "' + DefPath + '\"', /NOSHELL  , /NOWAIT
		endif else SPAWN, CodePath + '\XimageViewer ', /NOSHELL
	endif else axis_log,'XimageViewer restricted to Windows OS'
   END

   'Nexus File Viewer' :  BEGIN
    ax_nexus_viewer
   END

'  Help  ' :  BEGIN
   online_help, book = CodePath + 'axis2000.pdf'
   END

'Reset colors' : BEGIN
  TVLCT, UserR, UserB, UserG	; load current user-defined color table
  ax_color						; set standard axis color scheme
  PlotBuf,CurBuf
  END

'Copy Buffer' : BEGIN
; ******************** Copy CurBuf to a different buffer *********
;   	bt = Buffer(group = AXIS_ID)  	;Get buffer from user
; ----- use Thumbs to select buffer
;; completion of copy from processing of mouse events
	select_flag = 1
	copy_flag = 1
	text = string(format="('Copy buffer ',i1,' to ..',/,'select new buffer with Thumbnails or labels')", CurBuf)
   END

'Clear Buffer' : BEGIN
; ********* erase selected buffers  **************
	text = string('Select buffer(s) to clear in dialog window')
	WIDGET_CONTROL, Uprompt, Set_Value = text
	ax_clear, /select
  END

  ELSE: BEGIN
   text = string(Event.value) + ' menu item not connected'
   WIDGET_CONTROL, Uprompt, SET_VALUE= text
   Message,'Unknown button pressed'
   ENDELSE

  ENDCASE
END

; XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


PRO AXIS_EVENT, Event
@axis_com
@stack_process_align_com
@tif_convert_com
@sdf_com
@nexus_com
on_error, 2

WIDGET_CONTROL,Event.Id,GET_UVALUE=Ev

; animated logo processing
IF TAG_NAMES(event, /STRUCTURE_NAME) EQ 'WIDGET_TIMER' THEN begin
	if logo_more EQ 0 then return
	Widget_control, Axis_ID, timer = logo_rate
	logo_now = logo_now + 1
	if logo_now EQ logo_num then logo_now = 0
	wset, ColorbarPlot			; in case someone hits a thumb
	erase, ax_black_color_index		;ax_black_color_index
	wset, MainImg
	TVLCT, logo_R, logo_G, logo_B
	DEVICE, COPY =[0, 0,logo_size, logo_size, 0, 0, logo_win(logo_now)]
	RETURN
ENDIF else begin
	if ev EQ 'AxisMenu' then begin
;		if (!d.n_colors GT 256) then device,decomposed=0
		logo_more = 0
		frontpanel = 0
;		for i = 0, logo_num-1 do WDELETE, logo_win[i]  ; clean up to free 18 Mb memory
	endif
endelse

CASE Ev OF

  'AxisMenu' : AxisMenu_Event, Event
  'AxisButton1' : AxisMenu_Event, Event
  'AxisButton2' : AxisMenu_Event, Event

  'main_image' : BEGIN
; ----- processing for web links
	if frontpanel EQ 1 then begin
		if Event.Type EQ 1 AND Event.Release EQ 1b then axis_web, event.x, event.y
	endif

 ; ********************** Event for MainImg graph ***********************
    HANDLE_VALUE, Data(CurBuf), tmp    ;Get current data
	if n_tags(tmp) NE 0 then BEGIN
		if tmp.t EQ '3d' then goto, end_of_draw4
  		SetGraf, 'MainImg'      ; restore MainImg scaling parameters
  		curval = CONVERT_COORD(Event.X, Event.Y, /DEVICE, /TO_DATA)
  		if thumb_plot EQ 1 then curval = [Event.X, Event.Y]
  		if thumb_plot EQ 1 then dev_val = 1 else dev_val = 0
 		cursformat = '(G12.5)'
 		pixformat = '(I4)'
 		CASE tmp.t OF
		'3d' : BEGIN
		  END
		'2d' : BEGIN
			CurInd = DIndex(curval(0),curval(1),tmp)  ;Get index of data point closest to cursor
	; only process further if there has been a change in the cursor position
		if CurInd(0) NE CurX OR CurInd(1) NE CurY THEN BEGIN
			CurX = CurInd(0) & CurY = CurInd(1)
			Xval = Curval(0) & Yval = Curval(1)
	        Zval = tmp.d(CurX,CurY)
	 		;print cursor data coordinates
	  		WIDGET_CONTROL,CURSORX,SET_VALUE=string(Xval, format = cursformat)
	        WIDGET_CONTROL,CURSORY,SET_VALUE=string(Yval, format = cursformat)
	        WIDGET_CONTROL,CURSORZ,SET_VALUE=string(Zval, format = cursformat)
	  		WIDGET_CONTROL,PIXELX,SET_VALUE=string(CurX, format = pixformat)
	        WIDGET_CONTROL,PIXELY,SET_VALUE=string(CurY, format = pixformat)
		    if click1 EQ 1 then begin           ; drag line
		 		; erase old line on image
		   		device, get_graphics_function = oldgraph, set_graphics_function = 6      ;Set xor
		       	plots, xline, yline, device = dev_val, thick=1, color = ax_white_color_index     ;ax_white_color_index
		       	xline(1) = Xval  &  yline(1) = Yval
		       	plots, xline, yline, device = dev_val, thick=1, color = ax_white_color_index     ;ax_white_color_index
		       	device, set_graphics_function = oldgraph   ; reset graphics mode
		    endif
;       plot line-out graphs
	        wset, XZPlot
			if Axes EQ 1 then begin
				xmarg=[8,0]
				ymarg = [1,0]
			endif else begin
				xmarg=[6,2]
				ymarg = [1,0]
			endelse
	  		PLOT, tmp.x, tmp.d(*,CurY), xstyle=5,ystyle=1,ymargin=ymarg, $
	  		      Yrange=Zrng,Xrange=Xrng,charsize=0.7, xmargin=xmarg, $		; xmargin was 8,0 prior to display change 20-Jul-14
	  		      symsize=0.5, psym=Line_Sym, color=255, background=0
	        PLOTS, [Xval,Xval], Zrng, color=255               ; line
	        SetGraf, 'XZPlot', /set
	        wset, YZPlot
			if Axes EQ 1 then begin
				xmarg=[1.5,0]
				ymarg = [1,0]
			endif else begin
				xmarg=[0,0]
				ymarg = [2,2]
			endelse
	  		PLOT, tmp.d(CurX,*), tmp.y, ystyle=5,xstyle=1,xmargin=xmarg, $  ; ORDER WRONG !  ; previos had no ymargin call
	  		      Xrange=Zrng,Yrange=Yrng,charsize=0.7,ymargin=ymarg, $		; xmargin was [1.5,0] prior to display change 20-Jul-14
	  		      symsize=0.5,psym=Line_Sym, color=255, background=0
	        PLOTS, Zrng, [Yval,Yval], color=255               ; line
	        SetGraf, 'YZPlot', /set
	        wset, MainImg
	      ENDIF
		END
	    '1d' :  BEGIN         ; cursor INFO for 1-d plots
	  		;Get closest two data points
			gindex=where(tmp.x GE curval(0),gcount)
	        lindex=where(tmp.x LE curval(0),lcount)
	        if gcount NE 0 AND lcount NE 0 THEN BEGIN
	        	;Find the closest data point
	        	dind=size(lindex)
	        	l = lindex(dind(1) - 1)
	        	h = gindex(0)
	        	slope= (tmp.d(h)-tmp.d(l))/(tmp.x(h)-tmp.x(l))
	        	int = tmp.d(h) - slope * tmp.x(h)
		      	dataval = int + slope * curval(0)
		;print interpolated data vale at cursor position
				WIDGET_CONTROL,CURSORZ, SET_VALUE=string(dataval, format = cursformat)
			ENDIF
			;print cursor data coordinates
	        WIDGET_CONTROL,CURSORX,SET_VALUE=string(curval(0), format = cursformat)
	        WIDGET_CONTROL,CURSORY,SET_VALUE=string(curval(1), format = cursformat)
	    END
	    ENDCASE
	  endif

	; Calculate del-(x,y,R, z) based on 2 clicks *****************
	  if Event.Type EQ 1 AND Event.Release EQ 1b then BEGIN
	     HANDLE_VALUE, Data(CurBuf), tmp    ;Get current data
		 if n_tags(tmp) NE 0  then BEGIN
			SetGraf,'MainImg'		; make sure scaling is correct !!
			clktmp = STRCOMPRESS(string(click1))
			CASE clktmp OF
			' 0' : BEGIN
	  			curval = CONVERT_COORD(Event.X, Event.Y, /DEVICE, /TO_DATA)
	  			if thumb_plot EQ 1 then curval = [Event.X, Event.Y]
				CASE tmp.t OF
				'3d' : BEGIN   ; treat all 'OTHER'-format images as non-data
			      END
				'2d' : BEGIN
				  CurInd = DIndex(curval(0),curval(1),tmp)  ;Get index of data point closest to cursor
				  CurX = CurInd(0) & CurY = CurInd(1)
				  Xval = Curval(0) & Yval = Curval(1)
	        	  Zval = tmp.d(CurX,CurY)
	 		;display cursor data coordinates
	  			  WIDGET_CONTROL,CURSORX,SET_VALUE=string(Xval, format = cursformat)
	        	  WIDGET_CONTROL,CURSORY,SET_VALUE=string(Yval, format = cursformat)
	        	  WIDGET_CONTROL,CURSORZ,SET_VALUE=string(Zval, format = cursformat)
		  		  WIDGET_CONTROL,PIXELX,SET_VALUE=string(CurX, format = pixformat)
		          WIDGET_CONTROL,PIXELY,SET_VALUE=string(CurY, format = pixformat)

		; trap out for special processing
					if img_rep_line EQ 1 then ax_img_line
					dXval = Xval & dYval = Yval & dZval = Zval     ; store 1st value in d(xyz)val
				; set up for plotting line, with drag display
		    	  	xline(0) = Xval  &  yline(0) = Yval            ; store for lineout
		    	  	xline(1) = Xval  &  yline(1) = Yval
			  		device, get_graphics_function = oldgraph, set_graphics_function = 6      ;Set xor
		       		plots, xline, yline,device = dev_val, thick=1, color = ax_white_color_index     ;ax_white_color_index
		       		device, set_graphics_function = oldgraph   ; reset graphics mode
		       		if profl EQ 1 then WIDGET_CONTROL, Uprompt, SET_VALUE='Profiles: select 2nd point'
				END
	    		'1d' :  BEGIN         ; cursor INFO for 1-d plots
	  		;Get closest two data points
				  gindex=where(tmp.x GE curval(0),gcount)
	        	  lindex=where(tmp.x LE curval(0),lcount)
	        	  dataval = curval(0)		  ; default value for out-of-range
	        	  if gcount NE 0 AND lcount NE 0 THEN BEGIN
	     			dind=size(lindex)        ;Find the closest data point
	        		l = lindex(dind(1) - 1)
	        		h = gindex(0)
	        		slope= (tmp.d(h)-tmp.d(l))/(tmp.x(h)-tmp.x(l))
	        		int = tmp.d(h) - slope * tmp.x(h)
		      		dataval = int + slope * curval(0)
		     ;display interpolated data value at cursor position
					WIDGET_CONTROL,CURSORZ, SET_VALUE=string(dataval, format = cursformat)
				  ENDIF
			;display cursor data coordinates
	        	  WIDGET_CONTROL,CURSORX,SET_VALUE=string(curval(0), format = cursformat)
	        	  WIDGET_CONTROL,CURSORY,SET_VALUE=string(curval(1), format = cursformat)
	 		; draw first line on spectrum
	 			  xline(0) = curval(0)
	   		   	  device, get_graphics_function = oldgraph, set_graphics_function = 6      ;Set xor
	       		  plots, [xline(0),xline(0)], yRng,device = dev_val, $
	       		      thick=1, color = ax_white_color_index     ;ax_white_color_index     ; color = white !! (0 .xor. 0 = 1)
	       		  device, set_graphics_function = oldgraph   ; reset graphics mode
	 			  dXval = curval(0) & dYval = curval(1) & dZval = dataval  ; store 1st value in d(xyz)val
	    		END
	    	  ENDCASE
	    	WIDGET_CONTROL,delX,SET_VALUE=' -'     ; erase old del(xyz)val
	        WIDGET_CONTROL,delY,SET_VALUE=' -'
	        WIDGET_CONTROL,delR,SET_VALUE=' -'
	        WIDGET_CONTROL,delZ,SET_VALUE=' -'
			click1 = 1                ; set flag that 1st point registered
			END
			' 1' : BEGIN                   ; process second click for DIFFERENCE ***********
				curval = CONVERT_COORD(Event.X, Event.Y, /DEVICE, /TO_DATA)
				if thumb_plot EQ 1 then curval = [Event.X, Event.Y]
				CASE tmp.t OF
				'2d' : BEGIN
				  CurInd = DIndex(curval(0),curval(1),tmp)  ;Get index of data point closest to cursor
				  CurX = CurInd(0) & CurY = CurInd(1)
				  Xval = Curval(0) & Yval = Curval(1)
	        	  Zval = tmp.d(CurX,CurY)
	 		; draw line on image
	   		   	device, get_graphics_function = oldgraph, set_graphics_function = 6      ;Set xor
	       		plots, xline, yline,device = dev_val, thick=1, color = ax_white_color_index     ;ax_white_color_index      ; erase old line on image
	       		xline(1) = Xval  & yline(1) = Yval
	       		plots, xline, yline,device = dev_val, thick=2, color = ax_white_color_index     ;ax_white_color_index      ; write final line
	       		device, set_graphics_function = oldgraph   ; reset graphics mode
	 		;display cursor data coordinates
	  			  WIDGET_CONTROL,CURSORX,SET_VALUE=string(Xval, format = cursformat)
	        	  WIDGET_CONTROL,CURSORY,SET_VALUE=string(Yval, format = cursformat)
	        	  WIDGET_CONTROL,CURSORZ,SET_VALUE=string(Zval, format = cursformat)
		  		  WIDGET_CONTROL,PIXELX,SET_VALUE=string(CurX, format = pixformat)
		          WIDGET_CONTROL,PIXELY,SET_VALUE=string(CurY, format = pixformat)
				  dXval = Xval - dXval
				  dYval = Yval - dYval
				  dRval = sqrt(dXval*dXval + dYval*dYval)
				  dZval = Zval - dZval
			;display DELTA-cursor values
	  			  WIDGET_CONTROL,delX,SET_VALUE=string(dXval, format = cursformat)
	        	  WIDGET_CONTROL,delY,SET_VALUE=string(dYval, format = cursformat)
	        	  WIDGET_CONTROL,delR,SET_VALUE=string(dRval, format = cursformat)
	        	  WIDGET_CONTROL,delZ,SET_VALUE=string(dZval, format = cursformat)
; ---------------- trap out for linear and radial profiles
; (to add radial switch and set up linear as separate profile)
	        ; extract profile
	        	if profl EQ 1 THEN BEGIN
	        		HANDLE_VALUE, Data(CurBuf), tmp
	        		dx = float(tmp.x(1) - tmp.x(0))
		  			dy = float(tmp.y(1) - tmp.y(0))
		  			dr = sqrt (dx*dx + dy*dy)
		  			nr = fix((sqrt((xline(1)-xline(0))^2 + (yline(1)-yline(0))^2))/dr)
		  			if nr EQ 0 then nr = 2   ; trap out if have zero length  KLUGE !
		  			dx = ( xline(1) - xline(0) )/nr
		  			dy = ( yline(1) - yline(0) )/nr
		  			line = fltarr(nr) & r = fltarr(nr)
		  			for i = 0, nr-1 DO BEGIN
		  				xt = xline(0) + i*dx
		  				yt = yline(0) + i*dy
		  				ind = DIndex(xt,yt,tmp)  ;Get index of closest data point
	        			r(i) = i*dr
	        			line(i) = tmp.d(ind(0),ind(1))
		  			endfor
	;	  	wset, XZPlot
	;  	  PLOT, r, line, xstyle=1,ystyle=1,charsize=0.7, thick = 2, $
	;			xmargin=[4,2], ymargin=[2,1], $
	;  			symsize=0.5, psym=Line_Sym, color=0, background=255
	; transfer to user-defined buffer
				 bt = Buffer(group = AXIS_ID)  	;Get buffer from user
		 		if bt(0) NE -1 THEN BEGIN
		  			tlbl = get_text(prompt='Label',VAL='', group=axis_ID)
		  			tsp = {t:'1d',x:r, d:line, xl:'R (um)', dn:line, dl:tlbl}
	   	  			HANDLE_VALUE, Data(bt(0)), tsp, /set  ; it to new buffer
	   	  			Label(bt(0)) = tsp.dl
	   	  			CurBuf = bt(0)
	   	  			PlotBuf,CurBuf
	   			  endif
	   			 WIDGET_CONTROL, Uprompt, SET_VALUE=''
	        	endif
	        	profl = 0

				END
	    		'1d' :  BEGIN         ; cursor INFO for 1-d plots
	  		;Get closest two data points
				  gindex=where(tmp.x GE curval(0),gcount)
	        	  lindex=where(tmp.x LE curval(0),lcount)
	        	  dataval=0.
	        	  if gcount NE 0 AND lcount NE 0 THEN BEGIN
	        ;Find the closest data point
	        		dind=size(lindex)
	        		l = lindex(dind(1) - 1)
	        		h = gindex(0)
	        		slope= (tmp.d(h)-tmp.d(l))/(tmp.x(h)-tmp.x(l))
	        		int = tmp.d(h) - slope * tmp.x(h)
		      		dataval = int + slope * curval(0)
		    ;report interpolated data value at cursor position
					WIDGET_CONTROL,CURSORZ, SET_VALUE=string(dataval, format = cursformat)
				  ENDIF
			;report cursor data coordinates
	        	  WIDGET_CONTROL,CURSORX,SET_VALUE=string(curval(0), format = cursformat)
	        	  WIDGET_CONTROL,CURSORY,SET_VALUE=string(curval(1), format = cursformat)
				  dXval = curval(0) - dXval
				  dYval = curval(1) - dYval
				  dZval = dataval   - dZval
			; draw second line on spectrum
				xline(1) = curval(0)
	   		   	device, get_graphics_function = oldgraph, set_graphics_function = 6      ;Set xor
	       		plots, [xline(1),xline(1)], yRng,device = dev_val, $
	       		     thick=1, color = ax_white_color_index     ;ax_white_color_index
	       		device, set_graphics_function = oldgraph   ; reset graphics mode
			;report DELTA-cursor values
	  			  WIDGET_CONTROL,delX,SET_VALUE=string(dXval, format = cursformat)
	        	  WIDGET_CONTROL,delY,SET_VALUE=string(dYval, format = cursformat)
	        	  WIDGET_CONTROL,delR,SET_VALUE='   '
	        	  WIDGET_CONTROL,delZ,SET_VALUE=string(dZval, format = cursformat)
	    		END
	    		ENDCASE
				click1 = 2                ; set flag that 1st,2nd point registered
			END
			' 2' : BEGIN                  ; UNDO all annotation of MainImg
				WIDGET_CONTROL,delX,SET_VALUE=''     ; erase old del(xyz)val
	            WIDGET_CONTROL,delY,SET_VALUE=''
	            WIDGET_CONTROL,delR,SET_VALUE=''
	        	WIDGET_CONTROL,delZ,SET_VALUE=''
			  CASE tmp.t OF
			  '2d' : BEGIN
			   	device, get_graphics_function = oldgraph, set_graphics_function = 6      ;Set xor - erase line
	       		plots, xline, yline,device = dev_val, thick=2, color = ax_white_color_index     ;ax_white_color_index
	       		device, set_graphics_function = oldgraph   ; reset graphics mode
			   	click1 = 0    ; restart sequence
			   END
			  '1d' : BEGIN
			  ; erase reference lines on spectrum
	   		   	device, get_graphics_function = oldgraph, set_graphics_function = 6      ;Set xor
				plots, [xline(0),xline(0)], yRng,device = dev_val, thick=1, color = ax_white_color_index     ;ax_white_color_index
	       		plots, [xline(1),xline(1)], yRng,device = dev_val, thick=1, color = ax_white_color_index     ;ax_white_color_index
	       		device, set_graphics_function = oldgraph   ; reset graphics mode
	       		click1 = 0    ; restart sequence
	       	   END
			 ENDCASE
			END
	       ENDCASE
		 endif
  endif

; *********** CODE FOR 'Freeze Display and allow 1-d Line-OUTS *** (stxmhe) **
;  if Event.Type EQ 1 AND Event.Release EQ 1b then BEGIN
;      HANDLE_VALUE, Data(CurBuf), tmp    ;Get current data
;	   if n_tags(tmp) NE 0  then BEGIN
;			SetGraf,'MainImg'		; make sure scaling is correct !!
;   		if GraphFrozen EQ 1 then begin
;   			GraphFrozen = 0
;       		device, get_graphics_function = old, set_graphics_function = 6  ;Set xor
;   			plots, [CurFroz(0),CurFroz(0)], Yrng, thick=1  ;, color=MaincurCol
;   			plots, Xrng, [CurFroz(1),CurFroz(1)], thick=1  ;, color=MaincurCol
;        		device, set_graphics_function = old   ; reset graphics mode
; 				splot2d, tmp, background=-1,color=0
;   		endif else begin
;   			GraphFrozen = 1
;   			CurFroz=Curval
;        		device, get_graphics_function = old, set_graphics_function = 6  ;Set xor
;   			plots, [Xval,Xval], Yrng, thick=1   ;, color=MainCurCol
;   			plots, Xrng, [Yval,Yval], thick=1   ;, color=MainCurCol
;        		device, set_graphics_function = old   ; reset graphics mode
;   		endelse
;     ENDIF
;   endif
   end_of_draw4:
   END

 ;   *********************** Event for Thumbnail Windows *************
'thumb_1' : BEGIN
 	if Event.Type EQ 1 AND Event.Release EQ 1b then ax_switch,1
 END
'thumb_2' : BEGIN
 	if Event.Type EQ 1 AND Event.Release EQ 1b then ax_switch,2
 END
'thumb_3' : BEGIN
 	if Event.Type EQ 1 AND Event.Release EQ 1b then ax_switch,3
 END
'thumb_4' : BEGIN
 	if Event.Type EQ 1 AND Event.Release EQ 1b then ax_switch,4
 END
'thumb_5' : BEGIN
 	if Event.Type EQ 1 AND Event.Release EQ 1b then ax_switch,5
 END
'thumb_6' : BEGIN
 	if Event.Type EQ 1 AND Event.Release EQ 1b then ax_switch,6
 END
'thumb_7' : BEGIN
 	if Event.Type EQ 1 AND Event.Release EQ 1b then ax_switch,7
 END
'thumb_8' : BEGIN
 	if Event.Type EQ 1 AND Event.Release EQ 1b then ax_switch,8
 END
'thumb_9' : BEGIN
 	if Event.Type EQ 1 AND Event.Release EQ 1b then ax_switch,9
 END

'BufButs' : BEGIN
 CASE Event.Value OF
    0:  BEGIN ax_switch,0 & END
    1:  BEGIN ax_switch,1 & END
    2:  BEGIN ax_switch,2 & END
    3:  BEGIN ax_switch,3 & END
    4:  BEGIN ax_switch,4 & END
    5:  BEGIN ax_switch,5 & END
    6:  BEGIN ax_switch,6 & END
    7:  BEGIN ax_switch,7 & END
    8:  BEGIN ax_switch,8 & END
    9:  BEGIN ax_switch,9 & END
   	ELSE: Message,'Unknown button pressed'
 ENDCASE
 END

  'OptButs' : BEGIN
     CASE Event.Value OF
       0: BEGIN
       WIDGET_CONTROL, OptButs, Get_Value=test
       if test(0) EQ 0 then Axes = 0 else Axes = 1
		END
       1: BEGIN   ; Motion Lineouts (mouse motion) & Pan_zoom (switch together)
        WIDGET_CONTROL, OptButs, Get_Value=test
         if test(1) EQ 1 then begin
         	mouse = 1  &  pan_smooth=1
         	WIDGET_CONTROL, MainWid, DRAW_MOTION_EVENTS = 1
         endif else begin
         	mouse = 0  & pan_smooth=0
         	WIDGET_CONTROL, MainWid, DRAW_MOTION_EVENTS = 0
         endelse
       END
       2: BEGIN         ; Symbols on Lineouts
         WIDGET_CONTROL, OptButs, Get_Value=test
         line_sym = 0  & !p.psym=0
         if test(2) EQ 1 then line_sym = -1
       END
       3: BEGIN         ; Scale_bar on/off
         WIDGET_CONTROL, OptButs, Get_Value=test
         scale_bar = 0
		 if test(3) EQ 1 then scale_bar = 1
	 	 handle_value,Data(CurBuf),tmp
		 if n_tags(tmp) eq 0 then return
		 if tmp.t eq '2d' then PlotBuf, CurBuf
       END
;       3: BEGIN         ; Continuous zoom (pan) - RELIC from 1999
;         WIDGET_CONTROL, OptButs, Get_Value=test
;         pan_smooth=0
;		 if test(2) EQ 1 then pan_smooth=1
;       END
       ELSE: Message,'Unknown button pressed'
      ENDCASE
	END

'Zmin' : BEGIN
    WIDGET_CONTROL,Event.ID, Get_Value=txt
    Zrng(0) = float(txt(0))
	Handle_Value, Data(CurBuf), tmp
	IF n_tags(tmp) ne 0 then begin
		IF tmp.t EQ '2d' then BEGIN
			PlotBuf, Curbuf, Zvalues=Zrng
		ENDIF ELSE begin
			if tmp.t EQ '1d' then BEGIN
	    		!y.range(0) = Zrng(0)    ;Set the zoom
	    		!y.range(1) = Zrng(1)
		    	Yrng = !y.range
				Refresh
			ENDIF ELSE WIDGET_CONTROL, UPrompt, Set_Value = 'Z: controls only for images and spectra'
		ENDELSE
	ENDIF
   END

'Zmax' : BEGIN
    WIDGET_CONTROL, Event.ID, Get_Value=txt
    Zrng(1) = float(txt(0))
	Handle_Value, Data(CurBuf), tmp
	IF n_tags(tmp) eq 0 then return
	IF tmp.t EQ '2d' then BEGIN
		CurBuf = 0
		Handle_Value, Data(CurBuf), tmp, /set
		PlotBuf, Curbuf, Zvalues=Zrng
	ENDIF ELSE begin
		if tmp.t EQ '1d' then BEGIN
    		!y.range(0) = Zrng(0)
    		!y.range(1) = Zrng(1)    ;Set the zoom
	    	Yrng = !y.range
			Refresh
		ENDIF ELSE WIDGET_CONTROL, UPrompt, Set_Value = 'Z: controls only for images and spectra'
	ENDELSE
  END

'GAMMA' : BEGIN
    WIDGET_CONTROL, g_slider, GET_VALUE = gamma
    gamma = 10^((gamma/50.) - 1)
    WIDGET_CONTROL, g_lbl, SET_VALUE = STRING(gamma, format='(f4.2)')
    GAMMA_CT, gamma
    ax_color		; reset lower portion of color table for spectra
	PlotBuf, Curbuf
 END

'G_lbl' : BEGIN
    WIDGET_CONTROL, g_lbl, GET_VALUE = G
    gamma = G(0)
	if gamma LT 0.1 then gamma = 0.1
	if gamma GT 10 then gamma = 10
	WIDGET_CONTROL, g_lbl, SET_VALUE = STRING(gamma, format='(f5.2)')
    GAMMA_CT, gamma
    gamma = fix(50.*(alog10(gamma)+1))
;    print, 'G = ', gamma
    WIDGET_CONTROL, g_slider, SET_VALUE = gamma(0)
    ax_color		; reset lower portion of color table for spectra
	PlotBuf, Curbuf
 END

'XXmin' : BEGIN
    WIDGET_CONTROL,Event.ID, Get_Value=txt
    Xrng(0) = float(txt(0))
	Handle_Value, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 then return
	IF tmp.t EQ '2d' then BEGIN
		ax_zoom_cut, limits=[Xrng,Yrng]
	ENDIF ELSE begin
		if tmp.t EQ '1d' then BEGIN
    		!x.range(0) = Xrng(0)    ;Set the zoom
    		!x.range(1) = Xrng(1)
	    	Xrng = !x.range
			Refresh
		ENDIF ELSE WIDGET_CONTROL, UPrompt, Set_Value = 'X: controls only for images and spectra'
	ENDELSE
   END

'XXmax' : BEGIN
    WIDGET_CONTROL, Event.ID, Get_Value=txt
    Xrng(1) = float(txt(0))
	Handle_Value, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 then return
	IF tmp.t EQ '2d' then BEGIN
		ax_zoom_cut, limits=[Xrng,Yrng]
	ENDIF ELSE begin
		if tmp.t EQ '1d' then BEGIN
    		!x.range(0) = Xrng(0)
    		!x.range(1) = Xrng(1)    ;Set the zoom
	    	Xrng = !x.range
			Refresh
		ENDIF ELSE WIDGET_CONTROL, UPrompt, Set_Value = 'Z: controls only for images and spectra'
	ENDELSE
  END

'YYmin' : BEGIN
    WIDGET_CONTROL,Event.ID, Get_Value=txt
    Yrng(0) = float(txt(0))
	Handle_Value, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 then return
	IF tmp.t EQ '2d' then BEGIN
		ax_zoom_cut, limits=[Xrng,Yrng]
	ENDIF ELSE begin
		if tmp.t EQ '1d' then BEGIN
    		!y.range(0) = Yrng(0)    ;Set the zoom
    		!y.range(1) = Yrng(1)
	    	Yrng = !y.range
			Refresh
		ENDIF ELSE WIDGET_CONTROL, UPrompt, Set_Value = 'Y: controls only for images and spectra'
	ENDELSE
   END

'YYmax' : BEGIN
    WIDGET_CONTROL, Event.ID, Get_Value=txt
    Yrng(1) = float(txt(0))
	Handle_Value, Data(CurBuf), tmp
	IF n_tags(tmp) EQ 0 then return
	IF tmp.t EQ '2d' then BEGIN
		ax_zoom_cut, limits=[Xrng,Yrng]
	ENDIF ELSE begin
		if tmp.t EQ '1d' then BEGIN
	    	!y.range = Yrng
			Refresh
		ENDIF ELSE WIDGET_CONTROL, UPrompt, Set_Value = 'Y: controls only for images and spectra'
	ENDELSE
  END

 ELSE: Print,' Unknown Widget_ID ', eV
 ENDCASE
END

; XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

PRO AXIS_C, start_file = start_file, GROUP=Group, Group_leader=wGroup, spin = spin
@axis_com
@ax_peem_com
@stack_process_com
@tif_convert_com
@sdf_com
@ptycho_com
@nexus_com

on_error,2
;       ----------- added 13-Jul-15 (&Group_leader) to g
t = size(wGroup)
IF t(1) EQ 0 THEN modal_val=0 else modal_val=1

; *********************************************************************************
; ------------ START OF DEFINITION OF VARIABLE DEFAULT VALUES ---------------------
; *********************************************************************************

  init_sd, sd          ; set up array of NSLS X1A scan parameters
  Data = intarr(13)			;Declare array of permanent storage
  BufStat = intarr(10)		; Setup array for button status
  ButIDs = intarr(10)		; Setup Button Id Array
  BufLbls = strarr(10)		; Setup array for button labels
  Thumbnail = intarr(10)
  BufLbls(0) = ' 0  Working Buffer                           '	; Initialize array for button labels
  For i = 1, 9 DO BufLbls(i) = (STRCOMPRESS(STRING(i))) + '  Empty                                                         '

  for i=0, 12 do Data(i) = HANDLE_CREATE(value=0) 	;Create the handles
  ; ---------------------------------------------- 0-9 AXIS buffers
  ; ---------------------------------------------- 10  assembled image from 4 or 9 buffers (ThumbZoom)
  ; --------------------- (aph 01-jan-99) -------- 11 sample ; 12 reference data

  pData = intarr(20)		;Declare array of temporary storage (20 to allow repeat plotting)
  ;
  ; ------------ Create the handles for multi-spectra display ----------------------
  for i=0, 19 do pData(i) = HANDLE_CREATE(value=0)
  ;
  pNum = 0		;Set the number of plots in temporary storage
  pBufs = INTARR(1)	;Set the original buffer numbers of the temporary storage
  CurX=0 & CurY=0	; Set cursor indices to (0,0) in case cursor starts outside main window
  Label = Strarr(10)	; Set the initial values of the buffer labels
  Label(0) = 'working buffer'
  for i = 1, 9 do Label(i)='empty'
  GraphFrozen = 0	; setup graph storage variables
  MainCurCol = 0
  Overwrite_all = 0	; ignore file overwrites if set
  profl = 0			; don't extract profiles
  Xrng=fltarr(2) & Yrng=fltarr(2) & Zrng=fltarr(2)    ; graph scaling factors
  Xold=fltarr(4,2)  & Yold = fltarr(4,2)
  CurBuf = 1		; Set the current buffer to 1
  First_plot  = 1	; flag for first time through graphics (setting color tables)
  Last_Img = 0		; flag to indicate if image was last displayed (color table)
  Last_image_ext = '*.im*'    ; extension of last image read
  Click1 = 0		; flag for delta-cursor display
  Mouse = 1			; start with continuous line-outs
  Line_Sym = 0      ; start with no symbols on lineouts or spectral plots
  Pan_smooth = 1	; start with continuous zooming
  Thumb_plot = 0    ; not a thumbZoom plot
  Factor = fltarr(2)
  Factor(0) = 1.  &  factor(1) = 1.      ; gain factors
  constant = 0.     ; additive constant
  gain_m = 1.0		; multiplicative gain
  gain_d = 1.0		; divisor gain
  xline=fltarr(2)  &  yline = fltarr(2)  ; arrays for line indicator
  frontpanel = 1	; web links active
  img_rep_line=0		; flag to generate line identification if in image~replace_line
  ax_angle = 0.		; angle to rotate in ax_rotate
  ax_centre = [0.,0.]	; centre of rotation
  PrintSize = 3.	; 3 inch print size
  PrintColor = 1    ; default to B/W printing
  img_SumAvg = 'A'	; default for binning images is to average
  spec_SumAvg = 'A'	; default for binning spectra is to average
  Axes = 0 			; default is not to plot axes for 2D images

; ------ flags for using Thumbnails for selection
  select_flag = 0
  copy_flag = 0

; -------- default flag for ring current normalization - user can change in ax_sdf
  norm_flag = 1				; default is to start with I-ring normalization on
  norm_value = 500. 		; set default to ALS top-off ring current (aph  31-Jul-09)

; -------- default flag for ring current normalization
  xy_correct_flag = 0

; ****** parameters for saving last user-selected values
  X_calib = fltarr(2) & X_calib(0) = 1.0  & X_calib(1) = 0.0  ; Xnew= X_c(0)*Xold +X_c(1)
  Y_calib = fltarr(2) & Y_calib(0) = 1.0  & Y_calib(1) = 0.0  ; Ynew= Y_c(0)*Yold +Y_c(1)
  xlock = fltarr(2)  &  ylock = fltarr(2)
  cll = fltarr(2) & cur  = fltarr(2)   ; limits for cutting data in standard way

; Define string types and initial values for spectral processing (default = ALS)
  location = 'ALS'
  Pr_Command = 'print command'
  I_process = 'none' & Io_process = 'none'
  ALS_readin = 'data'
  S_file = '' & Io_file = ''
  I_col = 2 & Io_col = 2
  ScanPar_Update='on'
  if not keyword_set(spin) then begin
  	logo_more = 0
  	logo_num = 0
  endif else logo_more = 1

 ; Set-up arrays to save scaling parameters for each Buffer (3-d)
 	Xscl = fltarr(10,2)
   	Yscl = fltarr(10,2)
   	Zscl = fltarr(10,2)

; initialize SD common used to save various parameters (nsls, als)
init_sd,sd

;  ----- setup variables for AX_PEEM_COM if not yet defined ------------------
 	if keyword_set(peem_first) EQ 0 then peem_first = ''
 	if keyword_set(peem_last) EQ 0 then peem_last = ''
 	if keyword_set(peem_dark) EQ 0 then peem_dark = ''
 	if keyword_set(peem_gain) EQ 0 then peem_gain = ''
 	if keyword_set(peem_aoi) EQ 0 then peem_aoi = ''
 	if keyword_set(source_path) EQ 0 then source_path = ''
 	if keyword_set(dark_path) EQ 0 then dark_path = ''
 	if keyword_set(gain_path) EQ 0 then gain_path = ''
 	if keyword_set(peem_process) EQ 0 then peem_process = 'no correct'
 	if keyword_set(peem_energy) EQ 0 then peem_energy = 300.
 	if keyword_set(peem_scale) EQ 0 then peem_scale = 60.
 	if keyword_set(peem_bin) EQ 0 then peem_bin = 1
 	if keyword_set(peem_bits) EQ 0 then peem_bits = 12
 	if keyword_set(peem_median) EQ 0 then peem_median = 0
    if keyword_set(peem_opt1) EQ 0 then peem_opt1 = 0
    if keyword_set(peem_opt2) EQ 0 then peem_opt2 = 0
; -----------------------

; ---------- DEFAULTS  for SF calculations
	sf_cmpd = ''
	sf_emin = 250.
	sf_emax = 700.
	sf_mode = 'mass absorption'
	sf_density = 1.0
	sf_thick = 0.001

; ---------- DEFAULTS for Scale Bar
	scale_bar = 1
	bar_pos = [0.1,0.063]

; ------ defaults for TOF
	stop1 = 1
	stop2 = 2
	bin_ns = 0.
	tof1_min = 0.
	tof1_max = 0.
	tof2_min = 0.
	tof2_max = 0.
	tofE = 0.

; ------ defaults for log file and Uprompt
	log_last_line = 3

; *********************************************************************************
; ------------- END OF DEFINITION OF VARIABLE DEFAULT VALUES ----------------------
; *********************************************************************************
;
;  ----- get computer OS type, default file path, printer -------
; ***************************************************************** initialization
; get default values from AXIS.INI or user initialization file
;	if !version.os_family EQ 'unix' then begin
;		 ini_file = '/home/bl7data/axisdir/axis.ini'
;	endif else ini_file = 'c:.ini'
;	if keyword_set(start_file) then ini_file = start_file
;   test = axis_ini(file=ini_file)
CASE 1 OF
	keyword_set(start_file) : BEGIN		; start file is given
		ini_file = start_file
	END
	!version.os_family EQ 'unix' : BEGIN
		 ini_file = '/Users/aXis2000/axis_unix.ini'
	END
	ELSE : BEGIN
		ini_file = 'c:\aXis2000\axis_win.ini'
	END
ENDCASE
test = axis_ini(file=ini_file)
; ---------- change directory to the default path just read-in
if n_elements(DefPath) GT 0 then begin
; ---- check if this also has a filename; ifso separate into lpath and lfile ; 21-Jul-14, aph
	t = ax_name(DefPath)
;	DefPath = t(0)
	if t(1) NE '' then begin
		lfile = t(1) + '.' +t(2)
		lpath = t(0)
		sdf_lastpath = t(0)
		if t(2) EQ 'hdr' then sdf_lastfile = lfile	; only set up sdf
	endif
	test=file_info(DefPath)
	if test.exists NE 0 then begin
		print, 'changing active directory to ', lpath
		cd, lpath
	endif else begin
			print, 'changing active directory to codepath ', CodePath
		cd, CodePath
	endelse
endif
if n_elements(lfile) EQ 0 then lfile='c:\aXis2000\'

; --------------- feedback on operating system, initial DefPath, lpath, and lfile names
print, '============================================='
print, 'Type of IDL platform: ', !version.os_family
print, 'Computer operating system: ', !version.os_name
print, 'folder & filename separator: ', ax_sep()
print, 'Last path & filename (DefPath): ', DefPath
print, 'Current path: ', lpath
print, 'Current filename: ', lfile
print, '============================================='


; ****** Set-up font for buffer labels  **************************
; (aph 12-dec-98:  implemented switching from AXIS.ini
;	if gr_dev EQ 'WIN' then  BufLblFont = 'Arial*14'    ; MICROSOFT WINDOWS SPECIFIC ***
;	if gr_dev EQ 'X'   then  BufLblFont = '6x10' 		; Unix X-WINDOWS SPECIFIC ***
;	if gr_dev EQ 'X'   then  BufLblFont = '8x13' 		; Unix X-WINDOWS SPECIFIC ***
;  see Ch 9 of IDL 4 manual for further clues e.g. !p.font =0 & DEVICE, FONT = '8X13' is sug. for Unix

; ******* Set-up default grahics properties **************
;	!p.thick=1
;	!p.background = 255
;	!p.color = 0
;	!p.charsize=0.7
; set font to DEVICE specific value set in AXIS.INI file
;  WIDGET_CONTROL, Default_Font = BufLblFont

;------ additional initialization that must go after axis.ini is read
logo_size = gr_scale*360	; image size needed to derive web link from front panel
print, 'Starting aXis2000 widget'
print, '--------------'
print, 'CodePath is ', codepath
print, 'Active directory is ', lpath

; ------ start aXis2000 GUI
axis_dialog
;----------- Initialize the color table values ------------------------
UserR=intarr(255) & UserG = intarr(255)  &  UserB = intarr(255)
; Construct a custom color scale
loadct, ColTbl, bottom = 16, ncolors = 256, /silent		; load initial color table for imaging
ax_color		; setup color scale without loading current color table (not yet set)

; Diplay version identifier and logo
if keyword_set(spin) then begin
	AxSpin = 1
	ax_clear, /all
endif else begin
	AxSpin = 0
	ax_clear, /all
endelse

;----------- Initialize the color table values ------------------------
UserR=intarr(255) & UserG = intarr(255)  &  UserB = intarr(255)
; Construct a custom color scale
loadct, ColTbl, bottom = 16, ncolors = 256, /silent		; load initial color table for imaging
ax_color		; setup color scale without loading current color table (not yet set)
TVLCT, UserR, UserG, UserB, /get	; set up internal storage for color tables
bcolor=intarr(10) 		;  color indices for SPECTRA
for i = 0,9 do bcolor(i) = i

XMANAGER, 'axis', AXIS_ID

END
