#!/bin/sh
# \
  exec oagwish "$0" "$@"
set auto_path [linsert $auto_path 0 /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]

APSStandardSetup

 
set CVSRevisionAuthor "\$Revision: 1.29 $ \$Author: shang $"

set status "Ready"

proc SetStatus {text} {
    global status
    set status "[exec date +%H:%M:%S] $text"
    update
}

foreach id {1 2  3} {
	foreach nm {origin max_ext} {
		set ${id}$nm ""
	}
}

proc GetDataInformation {args} {
    global dataInfo plotNumber directory rootname ParameterNames datasetList zZeroIndex yZeroIndex zZeroPos yZeroPos
    global ${rootname}InfoGot numSpatialDims NX NY NZ LX LY LZ DIM time
	global origin1 origin2 origin3 max_ext1 max_ext2 max_ext3 delta1 delta2 delta3
	
    set exist 0
    foreach dataset $datasetList {
		set fileroot ${directory}/${rootname}_${dataset}_${plotNumber}
		if [file exist $fileroot.h5] {
			set exist 1
			break 
		}
    }
    if !$exist {
		SetStatus "No data found for $rootname with $plotNumber number, can not get its information."
		return
    }
    SetStatus "Get $rootname data information."
    set dataInfo "Get information of $rootname ${plotNumber}th data ..."
    update
 
    if [catch {exec hdf2sdds $fileroot.h5 -query} result] {
		return -code error "$result"
	}
	
	set dataInfo $result
	update
	set index [lsearch $result "dimensions:"]
	set dimension [lindex $result [expr $index +1]]
	set DIM [expr $dimension -1]
	set index [lsearch $result "sizes:"]
	set index [lsearch $result "time"]
	set time [lindex $result [expr $index +2]]
	set index [lsearch $result "origin"]
	set origin_i [expr $index + 2]
	set origin1 [lindex $result $origin_i]
	set index [lsearch $result "delta"]
	set delta_i [expr $index +2]
	set delta1 [lindex $result $delta_i]
	set index [lsearch $result "max_ext"]
	set max_i [expr $index +2]
	set max_ext1 [lindex $result $max_i]
	set index [lsearch $result "numPhysCells"]
	set cell_i [expr $index + 2]
	set NX [lindex $result $cell_i]
	set LX [format %.6e [expr $max_ext1 - $origin1]]
	set yZeroIndex 1
	set yZeroPos 0
	if {$DIM>=2} {
		set origin2 [lindex $result [expr $origin_i +1]]
		set delta2 [lindex $result [expr $delta_i + 1]]
		set max_ext2 [lindex $result [expr $max_i + 1]]
		set NY [lindex $result [expr $cell_i +1]]
		set LY [format %.6e [expr $max_ext2 - $origin2]]
		set yZeroIndex [format %.0f [expr (0.0 - $origin2)/$delta2]]
		set yZeroPos [expr $delta2 * $yZeroIndex + $origin2]
	}
	if {$DIM>=3} {
		set origin3 [lindex $result [expr $origin_i +2]]
		set delta3 [lindex $result [expr $delta_i + 2]]
		set max_ext3 [lindex $result [expr $max_i + 2]]
		set NZ [lindex $result [expr $cell_i +2]]
		set LZ [format %.6e [expr $max_ext3 - $origin3]]
		set zZeroIndex [format %.0f [expr (0.0 - $origin3)/$delta3]]
		set zZeroPos [expr $delta3 * $zZeroIndex + $origin3]
	} else {
		set zZeroIndex 1
		set zZeroPos 0
	}
	set ${rootname}InfoGot 1
	foreach dataset {electrons ions} {
		global ${dataset}_xMin ${dataset}_xMax ${dataset}_yMin ${dataset}_yMax ${dataset}_zMin ${dataset}_zMax
		global ${dataset}_xBins ${dataset}_yBins ${dataset}_zBins
		set ${dataset}_xMin [format %.3e $origin1]
		set ${dataset}_xMax [format %.3e $max_ext1]
		if [string length $origin2] {
			set ${dataset}_yMin [format %.3e $origin2]
			set ${dataset}_yMax [format %.3e $max_ext2]
		}
		if [string length $origin3] {
			set ${dataset}_zMin [format %.3e $origin3]
			set ${dataset}_zMax [format %.3e $max_ext3]
		} 
		if [string length $NX] {
			set ${dataset}_xBins $NX
		}
		if [string length $NY] {
			set ${dataset}_yBins $NY
		}
		if [string length $NZ] {
			set ${dataset}_zBins $NZ
		}
	}
	if [catch {GetDensity} result] {
		return -code error $result
	}
	ComputeNE
}

proc ProcessData {args} {
	set dataset ""
	set fileroot ""
	APSParseArguments {dataset fileroot}
    global directory rootname reduceFactor outputs plotAll plotNumber plotTime dataset0 DIM
	global electrons_reduceFactor electrons_keep ions_reduceFactor ions_keep
    if ![string length $rootname] {
		SetStatus "rootname is not provided."
		return
    }
	if ![string length $fileroot] {
		if ![string length $dataset] {
			set dataset $dataset0
		}
		global ${dataset}_type
		set fileroot  ${rootname}_${dataset}[set ${dataset}_type]_$plotNumber
	}
    cd $directory
	if ![file exist $fileroot.h5] {
		return -code error "$fileroot.h5 does not exist!"
	}
	SetStatus "Process $dataset ${fileroot} ..."
	if {[regexp {electrons} $fileroot] || [regexp {ions} $fileroot]} {
		if [regexp {electrons} $fileroot] {
			set reduceFactor $electrons_reduceFactor
			set keep $electrons_keep
			set dataset electrons
		} else {
			set reduceFactor $ions_reduceFactor
			set keep $ions_keep
			set dataset ions
		} 
		if [catch {exec  hdf2sdds -reduceFactor=$reduceFactor,keep=$keep \
					   ${fileroot}.h5 ${fileroot}.sdds.1} result] {
			return -code error $result
		}
		set parameters [exec sddsquery -par ${fileroot}.sdds.1]
		if [lsearch $parameters "origin3"]>=0 {
			lappend procOpt \"-redefine=par,zPos,delta3 i_page * origin3 +,units=m\"
			lappend procOpt \"-reprint=par,Description,time=%le seconds\\\\, z=%le m,time,zPos\" 
		} else {
			lappend procOpt \"-redefine=par,zPos,0\" 
			lappend procOpt \"-reprint=par,Description,time=%le seconds,time\"
		}
		if [catch {eval exec sddsprocess $fileroot.sdds.1 $fileroot.sdds [join $procOpt] } result] {
			return -code error $result
		}
	} else {
		set option ""
		switch $DIM {
			1 {
				set option -col=x
			} 
			2 {
				set option "-col=x -col=y"
			} 
			3 {
				set option "-col=x -col=y -col=z"
			}
		}
		if [catch {exec hdf2sdds $fileroot.h5 -withIndex $fileroot.sdds} result] {
			return -code error $result
		}
		if {$DIM==1} {
			if [catch {exec sddsprocess $fileroot.sdds $fileroot.sdds.1 "-define=col,x,Index interval1 * origin1 +" } result] {
				return -code error $result
			}
			exec mv $fileroot.sdds.1 $fileroot.sddds
		}
	}
	SetStatus "Done."
}

proc ConvertHDFToSDDS {args} {
    set fileroot ""
	set computeFFT 1
    APSParseArguments {fileroot computeFFT}
    if ![file exist ${fileroot}.h5] {
		return -code error "${fileroot}.h5 does not exist!"
    }
    global electrons_reduceFactor electrons_keep rootname ions_reduceFactor ions_keep
	SetStatus "Converting $fileroot to sdds ..."
    set procOpt ""
    if {[regexp {electrons} $fileroot] || [regexp {ions} $fileroot]} {
		if [regexp {electrons} $fileroot] {
			set reduceFactor $electrons_reduceFactor
			set keep $electrons_keep
			set dataset electrons
		} else {
			set reduceFactor $ions_reduceFactor
			set keep $ions_keep
			set dataset ions
		} 
		if [catch {exec  hdf2sdds -reduceFactor=$reduceFactor,keep=$keep \
					   ${fileroot}.h5 ${fileroot}.sdds.1} result] {
			return -code error $result
		}
    }  else {
		if [catch {exec  hdf2sdds ${fileroot}.h5 ${fileroot}.sdds.1} result] {
			return -code error $result
		}
		set columnNames [exec sddsquery -col ${fileroot}.sdds.1]
		if [regexp {Rho} $columnNames] {
			lappend procOpt \"-redefine=col,%s,%s -1.6e-19 /,select=Rho*\"
		}
		set parNames [exec sddsquery -par ${fileroot}.sdds.1]
		if [lsearch $parNames "origin1"]>=0 {
			lappend procOpt \"-redefine=col,x,delta1 i_row * origin1 +,units=m\"
		} else {
			lappend procOpt \"-redefine=col,x,delta i_row * origin +,units=m\"
		}
	}
    set parameters [exec sddsquery -par ${fileroot}.sdds.1]
    if [lsearch $parameters "origin3"]>=0 {
		lappend procOpt \"-redefine=par,zPos,delta3 i_page * origin3 +,units=m\"
		lappend procOpt \"-reprint=par,Description,time=%le seconds\\\\, z=%le m,time,zPos\" 
    } else {
		lappend procOpt \"-redefine=par,zPos,0\" 
		lappend procOpt \"-reprint=par,Description,time=%le seconds,time\"
    }
    if [catch {eval exec sddsprocess $fileroot.sdds.1 $fileroot.sdds [join $procOpt] } result] {
		return -code error $result
    }
	SetStatus "done."
    file delete -force ${fileroot}.sdds.1
}

proc ComputeFFT {args} {
	set fileroot ""
	APSParseArguments {fileroot}

    global rootname  ParameterNames filter directory dataset0 plotNumber
    global ${rootname}InfoGot  filter
    
    if {![info exist ${rootname}InfoGot] || ![set ${rootname}InfoGot]} {
		GetDataInformation
    }
    SetStatus "Compute field FFT at y=0 and z=0 ..."
	cd $directory
	if ![string length $fileroot] {
		set fileroot ${rootname}_${dataset0}_$plotNumber
	}
	if ![file exist $fileroot.sdds] {
		if [catch {ProcessData -fileroot $fileroot} result] {
			return -code error $result
		}
	}
    set dim [exec sdds2stream -par=NumOfDimension $fileroot.sdds -page=1]
	set filterOption ""
	if {$filter(xstart) || $filter(xend)} {
		set filterOption -filter=col,x,$filter(xstart),$filter(xend)
	}
	if ![file exist $fileroot.sdds.y0z0] {
		if {$dim==4} {
			foreach nm {origin delta numPhysCells max_ext} {
				foreach digit {2 3} {
					set ${nm}$digit [exec sdds2stream -par=${nm}$digit $fileroot.sdds -page=1]
				}
			}
			set zZeroIndex [format %0.f [expr (0-$origin3)/($max_ext3-$origin3)*$numPhysCells3 + 1]]
			set yZeroIndex [format %0.f [expr (0-$origin2)/($max_ext2-$origin2)*$numPhysCells2 +1]]
			set yZeroPos [expr $origin2 + $yZeroIndex * $delta2]
			set zZeroPos [expr $origin3 + $zZeroIndex * $delta3]
			SetStatus "z zero index=$zZeroIndex, y zero index=$yZeroIndex"
			if [catch {exec sddsconvert $fileroot.sdds -frompage=$zZeroIndex -topage=$zZeroIndex \
						   -retain=col,*_${yZeroIndex} -pipe=out \
						   | sddsconvert -pipe -edit=col,*_${yZeroIndex},%/_${yZeroIndex}// \
						   | sddsprocess -pipe=in $fileroot.sdds.y0z0 \
						   -define=par,yZeroPos,$yZeroPos \
						   -define=par,zZeroPos,$zZeroPos \
						   "-define=col,x,i_row delta1 * origin1 +" } result] {
				return -code error $result
			}
		} elseif {$dim==3} {
			foreach nm {origin2 delta2 numPhysCells2 max_ext2} { 
				set ${nm} [exec sdds2stream -par=${nm} $fileroot.sdds -page=1]
			}
			set yZeroIndex [format %0.f [expr (0-$origin2)/($max_ext2-$origin2)*$numPhysCells2 +1]]
			set yZeroPos [expr $origin2 + $yZeroIndex * $delta2]
			SetStatus "y zero index=$yZeroIndex"
			if [catch {exec sddsconvert $fileroot.sdds  \
						   -retain=col,*_${yZeroIndex} -pipe=out \
						   | sddsconvert -pipe -edit=col,*_${yZeroIndex},%/_${yZeroIndex}// \
						   | sddsprocess -pipe=in $fileroot.sdds.y0z0 \
						   -define=par,yZeroPos,$yZeroPos \
						   "-define=col,x,i_row delta1 * origin1 +" } result] {
				return -code error $result
			}
		} else {
			exec cp $fileroot.sdds $fileroot.sdds.y0z0
		}
	}
	set file $fileroot.sdds.y0z0
	if [string length $filterOption] {
		if [catch {exec sddsprocess $fileroot.sdds.y0z0 $fileroot.sdds.y0z0.1 $filterOption} result] {
			return -code error $result
		}
		APSAddToTmpFileList -ID vorpal -fileList $file.1
		set file $fileroot.sdds.y0z0.1
	}
	set columns [exec sddsquery -col $file]
	foreach col $columns {
		if [string compare $col "x"]!=0 {
			lappend fftColumn $col
		}
	}
    
	if [catch {exec sddsfft -col=x,[join $fftColumn ,] -truncate $file $fileroot.sdds.y0z0.fft } result] {
		return -code error $result
	}
    SetStatus "done."
}

proc PlotFFT {args} {
	set fileroot ""
	APSParseArguments {fileroot}
	
	global rootname  ParameterNames filter directory dataset0 plotNumber plotQuantity
    
	cd $directory
	if ![string length $fileroot] {
		set fileroot ${rootname}_${dataset0}_$plotNumber
	}
	if ![file exist $fileroot.sdds.y0z0.fft] {
		if [catch {ComputeFFT -fileroot $fileroot} result] {
			return -code error $result
		}
	}
	exec sddsplot -sep -grap=line,var -col=f,FFT$plotQuantity $fileroot.sdds.y0z0.fft \
		  -col=x,$plotQuantity $fileroot.sdds.y0z0 &
	
}

proc ContourPlot {args} {
	global dataset0 rootname directory plotNumber xyPlot plotQuantity fieldPlot DIM
	
	cd $directory
	set fileroot ${rootname}_${dataset0}_$plotNumber
	
	if ![file exist $fileroot.sdds] {
		if [catch {exec ProcessData} result] {
			return -code error $result
		}
	}
	set scale -scale=$fieldPlot(xstart),$fieldPlot(xend),$fieldPlot(ystart),$fieldPlot(yend)
	if {$DIM==1} {
		exec sddsplot -col=x,$plotQuantity $fileroot.sdds &
	} elseif {$DIM==2} {
		exec sddscontour -shade -col=Index,${plotQuantity}* $scale $fileroot.sdds -yrange=min=@origin2,max=@max_ext2 \
			-xrange=min=@origin1,max=@max_ext1 "-xlabel=x (m)" "-ylabel=y (m)" &
	} elseif {$DIM==3} {
		switch $xyPlot {
			xy {
				set file $fileroot.sdds
			}
			yz -
			xz {
				set file $fileroot.sdds.$xyPlot
				if ![file exist $file] {
					SetStatus "convert 3d data to $xyPlot plane..."
					if [catch {exec sdds3dconvert  $fileroot.sdds } result] {
						SetStatus "Error: $result"
						return
					}
					SetStatus "done."
				}
			}
		}
			
		if {$fieldPlot(pagestart) || $fieldPlot(pageend)} {
			if {$fieldPlot(pageend) && $fieldPlot(pagestart) && $fieldPlot(pageend)<$fieldPlot(pagestart)} {
				return -code error "Error: the end page is bigger than start page!"
			}
			set option ""
			if $fieldPlot(pagestart) {
				append option -frompage=$fieldPlot(pagestart)
			}
			if $fieldPlot(pageend) {
				append option " -topage=$fieldPlot(pageend)"
			} 
			set tmpfile /tmp/[APSTmpString].$xyPlot
			if [catch {eval exec sddsconvert $file $tmpfile $option} result] {
				return -code error $result
			}
			set plotFile $tmpfile
		} else {
			set plotFile $file
		}
		switch $xyPlot {
			xy {
				exec sddscontour -shade -col=Index,${plotQuantity}* $scale $plotFile -yrange=min=@origin2,max=@max_ext2 \
					-xrange=min=@origin1,max=@max_ext1 "-xlabel=x (m)" "-ylabel=y (m)" &
			}
			yz -
			xz {
				exec sddscontour -shade -quantity=${plotQuantity} $scale $plotFile &
			}
		}
	}
}

proc ComputeAverage {args} {
	global dataset0 rootname directory plotNumber xyPlot plotQuantity fieldPlot DIM filter rhoPower
	
	cd $directory
	set fileroot ${rootname}_${dataset0}_$plotNumber
	
	if {$dataset0!="TotalRhoJ"} {
		SetStatus "Average computation is only for TotalRhoJ dataset."
		return
	}
	if ![file exist $fileroot.sdds] {
		if [catch {ProcessData} result] {
			return -code error $result
		}
	}
	SetStatus "Compute average y, z and Jz..."
	
	set filterOpt ""
	if {$filter(xstart) || $filter(xend)} {
		append filterOpt "-xfilter=col,x,$filter(xstart),$filter(xend)"
	}
	if {$filter(ystart) || $filter(yend)} {
		append filterOpt " -yfilter=col,y,$filter(ystart),$filter(yend)"
	}
	if {$filter(zstart) || $filter(zend)} {
		append filterOpt " -zfilter=col,z,$filter(zstart),$filter(zend)"
	}
	if [catch {eval exec sdds3daverage $fileroot.sdds } result] {
		SetStatus "Error: $result"
		return
	}
	if [catch {exec sddsfft $fileroot.sdds.ave $fileroot.sdds.ave.fft -truncate -col=x,*Ave } result] {
		return -code error $result
	}
	SetStatus "Done."
}

proc PlotAverage {args} {
	global dataset0 rootname directory plotNumber xyPlot plotQuantity fieldPlot DIM filter
	
	if {$dataset0!="TotalRhoJ"} {
		SetStatus "Average plot is only for TotalRhoJ dataset."
		return
	}
	cd $directory
	set fileroot ${rootname}_${dataset0}_$plotNumber
	
	if ![file exist $fileroot.sdds.ave] {
		if [catch {ComputeAverage} result] {
			return -code error $result
		}
	}
	exec sddsplot -sep -legend -col=x,*Ave $fileroot.sdds.ave &
	exec sddsplot -sep -legend -col=f,FFT* $fileroot.sdds.ave.fft &
	
}

proc PlotMomentumFFT {args} {
	set dataset ""
	APSParseArguments {dataset}
	global directory rootname plotNumber 
	global ${dataset}_type

	cd $directory
	set fileroot  ${rootname}_${dataset}[set ${dataset}_type]_$plotNumber
	if ![file exist $fileroot.sdds.momentum.fft] {
		if [catch {ComputeAngularMomentumHistogram -dataset $dataset} result] {
			return -code error $result
		}
	}
	exec sddsplot -col=AngularMomentum,frequency $fileroot.sdds.momentum.fft &
}

proc ComputeAngularMomentumHistogram {args} {
	set file "" 
	set dataset electrons
    APSParseArguments {file  dataset}
	
    global directory rootname plotNumber plotAll yZeroPos zZeroPos delta2 delta3 electronsDensity NP NX NY NZ LX LY LZ
	
	cd $directory
	
    if ![string length $file] {
		global  ${dataset}_type
		set fileroot ${rootname}_${dataset}[set ${dataset}_type]_$plotNumber
    } else {
		if [regexp {electrons} $file] {
			set dataset electrons
		} else {
			set dataset ions
		}
		set fileroot [file root $file]
    }
	
    global ${dataset}_xBins ${dataset}_yBins ${dataset}_zBins Me Mp Ee0 Ep0 ${dataset}_EnergyBins 
    global ${dataset}_xFilter ${dataset}_yFilter ${dataset}_zFilter ${dataset}_xFilterStart ${dataset}_xFilterEnd
	global ${dataset}_yFilterStart ${dataset}_yFilterEnd ${dataset}_zFilterStart ${dataset}_zFilterEnd
    global ${dataset}_xMin ${dataset}_xMax ${dataset}_yMin ${dataset}_yMax ${dataset}_zMin ${dataset}_zMax
	global ${dataset}_momentum_bins ${dataset}_momentum_min ${dataset}_momentum_max   
	
	SetStatus "Computing $dataset angular momentum histogram of $fileroot ..." 
	if ![file exist $fileroot.sdds] {
		SetStatus "Process $fileroot ..."
		if [catch {ConvertHDFToSDDS -fileroot $fileroot} result] {
			return -code error $result
		}
	}
	set columns [exec sddsquery -col $fileroot.sdds]
	set yIndex [lsearch -exact $columns y]
	set zIndex [lsearch -exact $columns z]
	set VyIndex [lsearch -exact $columns Vy]
	set VzIndex [lsearch -exact $columns Vz]
	if {$yIndex<0 || $zIndex<0 || $VyIndex<0 || $VzIndex<0} {
		SetStatus "y, z, Vy, or Vz column does not exist, can not compute angular momentum!"
		return
	}
	set filterOpt ""
	foreach coord {x y z} {
		set ${coord}Filter [set ${dataset}_${coord}Filter]
		foreach nm {Start End} {
			set ${coord}Filter$nm [set ${dataset}_${coord}Filter$nm]
		}
	}	
	if {$xFilter} {
		append filterOption " -filter=col,x,$xFilterStart,$xFilterEnd"
	}
	if {$yFilter} {
		append filterOption " -filter=col,y,$yFilterStart,$yFilterEnd"
	}
	if {$zFilter} {
		append filterOption " -filter=col,z,$zFilterStart,$zFilterEnd"
	}
	set min [set ${dataset}_momentum_min]
	set max [set ${dataset}_momentum_max]
	set lowerLimit ""
	set upperLimit ""
	if {$min || $max} {
		set lowerLimit -lowerLimit=$min
		set upperLImit -upperLImit=$max
	}
	if [catch {eval exec sddsprocess $fileroot.sdds -pipe=out \
				   \"-define=col,AngularMomentum,Vy z * Vz y * - mass *\" \
				   | sddsprocess -pipe -process=AngularMomentum,sum,TotalAngularMomentum \
				   | sddshist -pipe=in $fileroot.sdds.momentum.fft -datacolumn=AngularMomentum \
				   -bins=[set ${dataset}_momentum_bins] \
				   $lowerLimit $upperLimit } result] {
		return -code error $result
	}
	set totalM [exec sdds2stream -par=TotalAngularMomentum $fileroot.sdds.momentum.fft]
	exec sddsplot -col=AngularMomentum,frequency $fileroot.sdds.momentum.fft &
	SetStatus "Done."
}

set Me 9.1093897e-31
set Mp 1.6726231e-27
set Ee0 .511 
set Ep0 938.2723

proc ComputeElectronHistogram {args} {
    set file ""
    set type both
	set dataset electrons
    APSParseArguments {file type dataset}
    
    global directory rootname plotNumber plotAll yZeroPos zZeroPos delta2 delta3 electronsDensity NP NX NY NZ LX LY LZ
    global ${dataset}_xBins ${dataset}_yBins ${dataset}_zBins Me Mp Ee0 Ep0 ${dataset}_EnergyBins 
    global ${dataset}_xFilter ${dataset}_yFilter ${dataset}_zFilter ${dataset}_xFilterStart ${dataset}_xFilterEnd
	global ${dataset}_yFilterStart ${dataset}_yFilterEnd ${dataset}_zFilterStart ${dataset}_zFilterEnd
    global ${dataset}_xMin ${dataset}_xMax ${dataset}_yMin ${dataset}_yMax ${dataset}_zMin ${dataset}_zMax
	global ${dataset}_momentum_bins ${dataset}_momentum_min ${dataset}_momentum_max

	global NE ${dataset}_EnergyStart ${dataset}_EnergyEnd ${rootname}InfoGot ${dataset}_type ionsDensity

	if {![info exist ${rootname}InfoGot] || ![set ${rootname}InfoGot]}  {
		GetDataInformation
	}
	  
    cd $directory

    if ![string length $file] {
		if !$plotAll {
			set idList $plotNumber
		} else {
			set files [glob -nocomplain ${rootname}_${dataset}[set ${dataset}_type]_*.h5]
			set idList ""
			foreach file $files {
				lappend idList [scan $file ${rootname}_${dataset}[set ${dataset}_type]_%ld]
			}
			if ![llength $idList] {
				return -code error "No $dataset data found for $rootname."
			}
			set idList [lsort -integer $idList]
		}
    } else {
		if [regexp {electrons} $file] {
			set dataset electrons
		} else {
			set dataset ions
		}
		set idList [scan $file ${rootname}_${dataset}[set ${dataset}_type]_%ld]
    }
	set ne 1
	 
	set density [set ${dataset}Density]
	if {[string length $NX] && [string length $NY] && [string length $NZ] && \
			[string length $LX] && [string length $LY] && [string length $LZ] && \
			[string length $density] && [string length $NP]} {
		set ne [expr ($LX * $LY * $LZ)/($NX * $NY * $NZ) * $density / $NP]
	}
    foreach id $idList {
		set fileroot ${rootname}_${dataset}[set ${dataset}_type]_$id
		SetStatus "Computing $dataset histogram of $fileroot ..." 
		if ![file exist $fileroot.sdds] {
			SetStatus "Process $fileroot ..."
			if [catch {ConvertHDFToSDDS -fileroot $fileroot} result] {
				return -code error $result
			}
		}
		set columns [exec sddsquery -col $fileroot.sdds]
		set yIndex [lsearch -exact $columns y]
		set zIndex [lsearch -exact $columns z]
		set VyIndex [lsearch -exact $columns Vy]
		set VzIndex [lsearch -exact $columns Vz]
		set time [exec sdds2stream -par=time -page=1 $fileroot.sdds]
		if {$type=="both" || $type=="position"} {
			foreach coord {x y z} {
				foreach nm {Min Max Bins} {
					set ${coord}$nm [set ${dataset}_${coord}$nm]
				}
			}
			if {$xMin || $xMax} {
				set xparam -xparam=$xBins,$xMin,$xMax
				set lowerLimit -lowerLimit=$xMin
				set upperLimit -upperLimit=$xMax
			}  else {
				set xparam -xparam=$xBins
				set lowerLimit ""
				set upperLimit ""
			}
			if {$yMin || $yMax} {
				set yparam -yparam=$yBins,$yMin,$yMax
			} else {
				set yparam -yparam=$yBins
			}
			if {$zMin || $zMax} {
				set zparam -zcolumn=z,bins=$zBins,lower=$zMin,upper=$zMax
			} else {
				set zparam -zcolumn=z,bins=$zBins
			} 
			if {$yIndex>=0} {
				set filterOpt "-filter=col,y,[expr $yZeroPos - $delta2],[expr $yZeroPos + $delta2]" 
				if {$zIndex>=0} {
					if [catch {eval exec sddshist2d $fileroot.sdds $fileroot.sdds.hist.pos.1  -columns=x,y \
								   $xparam $yparam $zparam
						exec sddsprocess $fileroot.sdds.hist.pos.1 $fileroot.sdds.hist.pos \
								   "-reprint=par,Description,time=$time seconds\\, z=%le m,zCenter" \
							   } result] {
						return -code error $result
					}
					set cells 4
					lappend filterOpt "-filter=col,z,[expr $zZeroPos - $delta3],[expr $zZeroPos + $delta3]"
					exec rm $fileroot.sdds.hist.pos.1
				}  else {
					if [catch {eval exec sddshist2d $fileroot.sdds $fileroot.sdds.hist.pos.1 -columns=x,y  $xparam $yparam 
						exec sddsprocess $fileroot.sdds.hist.pos.1 $fileroot.sdds.hist.pos \
								   "-reprint=par,Description,time=$time seconds" \
							   } result] {
						return -code error $result
					}
					set cells 2
					exec rm $fileroot.sdds.hist.pos.1
				}
				if [catch {eval exec sddsprocess $fileroot.sdds $filterOpt -pipe=out \
							   | sddshist -pipe  -datacolum=x -bins=$xBins \
							   $lowerLimit $upperLimit \
							   | sddsprocess -pipe=in $fileroot.sdds.hist.pos.1d \
							   \"-define=col,Rho,frequency $cells / $NP / $density * ReduceFactor * $xBins $NX / *\" } result] {
					return -code error $result
				}
			} else {
				if [catch {eval exec sddshist $fileroot.sdds -pipe=out  $lowerLimit $upperLimit \
							   -datacolumn=x -bins=$xBins -pipe=out \
							   | sddsprocess -pipe=in $fileroot.sdds.hist.pos \
							   "-define=col,Rho,frequency $xBins $NX / * $density * ReduceFactor *" \
					} result] {
					return -code error $result
				}
			}
		}
		if {$type=="both" || $type=="energy"} {
			set EnergyBins [set ${dataset}_EnergyBins]
			set EnergyStart [set ${dataset}_EnergyStart]
			set EnergyEnd [set ${dataset}_EnergyEnd]
			foreach coord {x y z} {
				set ${coord}Filter [set ${dataset}_${coord}Filter]
				foreach nm {Start End} {
					set ${coord}Filter$nm [set ${dataset}_${coord}Filter$nm]
				}
			}
			
			set filterOption ""
			if {$xFilter} {
				append filterOption " -filter=col,x,$xFilterStart,$xFilterEnd"
			}
			if {$yFilter && $yIndex>=0} {
				append filterOption " -filter=col,y,$yFilterStart,$yFilterEnd"
			}
			if {$zFilter && $zIndex>=0} {
				append filterOption " -filter=col,z,$zFilterStart,$zFilterEnd"
			}
			if {$dataset=="ions"} {
				set mass [exec sdds2stream -par=mass $fileroot.sdds]
				set E0 [expr $Ee0 * $mass/$Me] 
			} else {
				set E0 $Ee0
			}

			if {$VyIndex>=0} {
				if {$VzIndex>=0} {
					if [catch {eval exec sddsprocess $fileroot.sdds $fileroot.sdds.energy \
								   $filterOption \
								   \"-redefine=col,V,Vx sqr Vy sqr Vz sqr + + sqrt\" \
								   \"-redefine=col,gamma,V 3.0e8 / sqr 1.0 + sqrt\" \
								   \"-redefine=col,Energy,gamma 1 - $E0 *,units=MeV\" } result] {
						return -code error "sddsprocess: $result"
					}
				} else {
					if [catch {eval exec sddsprocess $fileroot.sdds $fileroot.sdds.energy \
								   $filterOption \
								   \"-redefine=col,V, Vx sqr Vy sqr + sqrt\" \
								   \"-redefine=col,gamma,V 3.0e8 / sqr 1.0 + sqrt\" \
								   \"-redefine=col,Energy,gamma 1 - $E0 *,units=MeV\" } result] {
						return -code error $result
					}
				}
			} else {
				if [catch {eval exec sddsprocess $fileroot.sdds $fileroot.sdds.energy \
							   $filterOption \
							   \"-redefine=col,gamma,Vx 3.0e8 / sqr 1.0 + sqrt\" \
							   \"-redefine=col,Energy,gamma 1 - $E0 *,units=MeV\" } result] {
					return -code error $result
				}
			}
			set rows [exec sdds2stream -rows=bar $fileroot.sdds]
			if [catch {exec sddshist $fileroot.sdds.energy -pipe=out -datacolumn=Energy -bins=$EnergyBins  \
						   -lowerLimit=$EnergyStart -upperLimit=$EnergyEnd \
						   | sddsprocess -pipe=in $fileroot.sdds.hist.energy \
						   "-define=col,$dataset,frequency $ne * ReduceFactor *" \
						   "-define=par,TotalMacroParticles,$rows ReduceFactor *" \
						   -process=$dataset,sum,Total$dataset \
					   } result] {
				return -code error $result
			}
			SetStatus "Total number of macro particles of ${dataset}[set ${dataset}_type] of $fileroot is [exec sdds2stream -par=TotalMacroParticles $fileroot.sdds.hist.energy]"
			SetStatus "Total number of ${dataset}[set ${dataset}_type] of $fileroot is [exec sdds2stream -par=Total$dataset $fileroot.sdds.hist.energy]"
		}
    }
    SetStatus "${dataset}[set ${dataset}_type] histogram computation done."
}

proc PlotElectronHistogram {args} {
    set type ""
	set dataset electrons
    APSParseArguments {type dataset}
    global plotAll plotNumber directory rootname movie createPng 
    global ${dataset}_energyXStart ${dataset}_energyXEnd ${dataset}_energyYStart ${dataset}_energyYEnd
    global ${dataset}_pos_XStart ${dataset}_pos_XEnd ${dataset}_pos_YStart ${dataset}_pos_YEnd 
	global ${dataset}_pos_page_start ${dataset}_pos_page_end ${dataset}_type
	
    cd $directory
    set dimension ""
    set idList ""
    if $plotAll {
		set files [glob -nocomplain ${rootname}_${dataset}[set ${dataset}_type]_*.h5]
		foreach file $files {
			set id [scan $fileroot ${rootname}_${dataset}[set ${dataset}_type]_%ld]
			set fileroot ${rootname}_${dataset}[set ${dataset}_type]_$id
			if ![file exist ${fileroot}.sdds.energy] {
				SetStatus "Computing $dataset histogram for $fileroot..."
				if [catch {ComputeElectronHistogram -file ${fileroot}.sdds } result] {
					SetStatus "$result"
					continue
				}
			}
			lappend idList $id
			if ![string length $dimension] {
				set dimension [exec sdds2stream -par=numSpatialDims -page=1 ${fileroot}.sdds]
			}
		}
    } else {
		set root ${rootname}_${dataset}[set ${dataset}_type]_$plotNumber
		switch $type {
			position {
				set file ${root}.sdds.hist.pos
			}
			1d-position {
				set file ${root}.sdds.hist.pos.1d
			}
			energy {
				set file ${root}.sdds.hist.energy
			}
		}
		
		if ![file exist $file] {
			SetStatus "Computing ${dataset}[set ${dataset}_type] histogram for $root..."
			if [catch {ComputeElectronHistogram -file ${root}.sdds -dataset $dataset} result] {
				return -code error $result
			}
		}
		set energyList ${root}.sdds.hist.energy
		if [string compare $type "energy"]==0 {
			SetStatus "Total number of ${dataset}[set ${dataset}_type] of $root is  [exec sdds2stream -par=Total${dataset} ${root}.sdds.hist.energy]"
		}
		set layoutOpt -layout=1,1
		set positionList ${root}.sdds.hist.pos
		set 1dPositionList ${root}.sdds.hist.pos.1d
		if ![string length $dimension] {
			set dimension [exec sdds2stream -par=numSpatialDims -page=1 ${root}.sdds]
		}
    }
    if [llength $idList] {
		set idList [lsort -integer $idList]
		foreach id $idList {
			lappend energyList ${rootname}_${dataset}[set ${dataset}_type]_${id}.sdds.hist.energy
			if [string compare $type "energy"]==0 {
				SetStatus "Total number of $dataset of ${rootname}_${dataset}[set ${dataset}_type]_${id} =[exec sdds2stream -par=Total$dataset ${rootname}_${dataset}[set ${dataset}_type]_${id}.sdds.hist.energy]"
			}
			lappend positionList ${rootname}_${dataset}[set ${dataset}_type]_${id}.sdds.hist.pos
			lappend 1dPositionList ${rootname}_${dataset}[set ${dataset}_type]_${id}.sdds.hist.pos.1d
		}
    }
    set movieFile ""
    switch $type {
		energy { 
			foreach coord {X Y} {
				foreach nm {Start End} {
					set energy${coord}$nm [set ${dataset}_energy${coord}$nm]
				}
			}
			lappend plotCmd -sep -topline=@Description \"-title=${dataset}[set ${dataset}_type] Density vs. Energy (MeV) Distribution\" \
				-grap=bar \"-ylabel=Number of ${dataset}[set ${dataset}_type]\"  -scale=$energyXStart,$energyXEnd,$energyYStart,$energyYEnd
			foreach file $energyList { 
				lappend plotCmd "-col=Energy,$dataset $file"
			}
			eval exec sddsplot [join $plotCmd] & 
			if {$movie && [llength $energyList]>1} {
				eval exec sddsplot [join $plotCmd] -output=${rootname}_${dataset}[set ${dataset}_type]_energy_hist.movie
			}
			if {$createPng && [llength $energyList]==1} {
				eval exec sddsplot [join $plotCmd] -output=${energyList}.png -device=png
			}
		}
		1d-position {
			set positionXStart [set ${dataset}_pos_XStart]
			set positionXEnd [set ${dataset}_pos_XEnd]
			set positionYStart [set ${dataset}_pos_YStart]
			set positionYEnd [set ${dataset}_pos_YEnd]
			set plotCmd "-topline=@Description -scale=$positionXStart,$positionXEnd,$positionYStart,$positionYEnd"
			lappend plotCmd \"-title=${dataset}[set ${dataset}_type] Density vs. Position Distribution\" 
			lappend plotCmd "-sep"
			foreach file $1dPositionList {
				lappend plotCmd "-col=x,Rho $file"
			}
			if [llength $positionList]>1 {
				set movieFile ${rootname}_${dataet}_hist_pos.1d.movie
			}
			eval exec sddsplot [join $plotCmd] &
			if {[string length $movieFile]} {
				eval exec sddsplot [join $plotCmd] -output=$movieFile
			}
			if {$createPng && [llength $positionList]==1} {
				eval exec sddsplot [join $plotCmd] -output=${positionList}.1d.png -device=png
			}
		}
		position {
			set startPage [set ${dataset}_pos_page_start]
			set endPage [set ${dataset}_pos_page_end]
			set positionXStart [set ${dataset}_pos_XStart]
			set positionXEnd [set ${dataset}_pos_XEnd]
			set positionYStart [set ${dataset}_pos_YStart]
			set positionYEnd [set ${dataset}_pos_YEnd]
			set plotCmd "-topline=@Description  -scale=$positionXStart,$positionXEnd,$positionYStart,$positionYEnd"
			lappend plotCmd \"-title=${dataset}[set ${dataset}_type] Density vs. Position Distribution\" 
			#lappend plotCmd \"-ylabel=N\"
			
			switch $dimension {
				1 {
					lappend plotCmd "-sep -grap=bar"
					foreach file $positionList {
						lappend plotCmd "-col=x,frequency $file"
					}
					if [llength $positionList]>1 {
						set movieFile ${rootname}_${dataet}_hist_pos.movie
					}
					eval exec sddsplot [join $plotCmd] &
					if {[string length $movieFile]} {
						eval exec sddsplot [join $plotCmd] -output=$movieFile
					}
					if {$createPng && [llength $positionList]==1} {
						eval exec sddsplot [join $plotCmd] -output=${positionList}.png -device=png
					}
				}
				2 {
					if [llength $positionList]>1 {
						if ![file exist ${rootname}_electtrons.hist2d.pos]  {
							if [catch {eval exec sddscombine $positionList ${rootname}_${dataset}[set ${dataset}_type].hist2d.pos -over} result] {
								return -code error $result
							}
						}
						set file ${rootname}_${dataset}[set ${dataset}_type].hist2d.pos
					} else {
						set file $positionList
					}
					lappend plotCmd "-quantity=frequency $file"
					if [llength $positionList]>1 {
						set movieFile ${rootname}_${dataset}[set ${dataset}_type]_hist_pos.movie
					}
					eval exec sddscontour -shade [join $plotCmd] &
					if {[string length $movieFile]} {
						eval exec sddscontour -shade [join $plotCmd] -output=$movieFile
					}
					if {$createPng && [llength $positionList]==1} {
						eval exec sddscontour -shade [join $plotCmd] -output=$file.png -device=png
					}
				}
				3 {
					set tmpRoot /tmp/[APSTmpString]
					set index 1
					foreach file $positionList {
						if {$startPage && $endPage} {
							if [catch {exec sddsconvert $file $tmpRoot.$index -frompage=$startPage \
										   -topage=$endPage } result] {
								return -code error $result
							}
							set plotFile $tmpRoot.$index
							incr index
						} else {
							set plotFile $file
						}
						eval exec sddscontour -shade [join $plotCmd] -quantity=frequency $plotFile &
						if {$movie} {
							eval exec sddscontour -shade [join $plotCmd] -quantitye=frequency $plotFile -output=${file}.movie
						}
						if {$createPng} {
							eval exec sddscontour -shade [join $plotCmd] -quantitye=frequency $plotFile -output=${file}.png -device=png
						}
					}
				}
				default {
					return -code error "Invalid dimensions - $dimension for ${dataset}[set ${dataset}_type] data."
				}
			}
		}
    }
}

proc PlayMovie {args} {
    set dataset ""
    APSParseArguments {dataset}
    global interval rootname directory
    
    set movieFiles [glob -nocomplain $directory/${rootname}_${dataset}*.movie]
    if ![llength $movieFiles] {
		SetStatus "No movie files found for $dataset."
		return
    }
    foreach file $movieFiles {
		exec /share/shang/bin/playMovie $file $interval
    }
}
proc PlotCurrentData {args} {
    global DATASET currentPlotCmd
    if {$DATASET!="electrons"} {
		PlotData -dataset $DATASET
    } else {
		$currentPlotCmd -datasest $DATASET
    }
}

proc PlotData {args} {
    set dataset ""
    set oneDplot 0
    APSParseArguments {dataset oneDplot}
    global directory rootname plotAll plotNumber movie createPng electronsX electronsY
    global ${dataset}XStart ${dataset}XEnd ${dataset}YStart ${dataset}YEnd ${dataset}PageStart ${dataset}PageEnd ${dataset}_type
	
    cd $directory
    set plotFiles ""
    set idList ""
    if !$plotAll {
		set fileroot  ${rootname}_${dataset}[set ${dataset}_type]_$plotNumber
		if ![file exist $fileroot.h5] {
			return -code error "$fileroot.h5 does not exist, can not plot data!"
		}
		if ![file exist $fileroot.sdds] {
			SetStatus "Process $fileroot ..."
			if [catch {ConvertHDFToSDDS -fileroot $fileroot} result] {
				return -code error $result
			}
		}
		set plotFiles ${rootname}_${dataset}[set ${dataset}_type]_${plotNumber}.sdds
    } else {
		set files [glob -nocomplain ${rootname}_${dataset}[set ${dataset}_type]_*.h5]
		foreach file $files {
			set fileroot [os editstring %/.h5// $file] 
			if ![file exist $fileroot.sdds] {
				SetStatus "Process $fileroot ..."
				if [catch {ConvertHDFToSDDS -fileroot $fileroot} result] {
					SetStatus "$result"
					continue
				}
			}
			set id [scan $fileroot ${rootname}_${dataset}_%ld]
			lappend idList $id
		}
    }
    if [llength $idList] {
		set idList [lsort -integer $idList]
		foreach id $idList {
			lappend plotFiles ${rootname}_${dataset}_${id}.sdds
		}
    }
    global ${dataset}X ${dataset}Y ${dataset}Quantity
	
    if {$dataset=="electrons" || $dataset=="ions"} {
		set xList [set ${dataset}X]
		set yList [set ${dataset}Y]
		foreach coord {X Y} {
			foreach nm {Start End} {
				set ${coord}$nm [set ${dataset}${coord}$nm]
			}
		}
		foreach x $xList {
			foreach y $yList {
				set plotCmd "-sep -grap=sym,scale=0.2 -topline=@Description -legend=file,edit=%/_${dataset}//%/.sdds// -scale=$XStart,$XEnd,$YStart,$YEnd"
				foreach file $plotFiles {
					lappend plotCmd "-col=$x,$y $file"
				}
				eval exec sddsplot [join $plotCmd] &
				
				set movieFile ${rootname}_${dataset}.${x}${y}.movie
				if {$movie && [llength $plotFiles]>1} {
					eval exec sddsplot [join $plotCmd] -output=$movieFile
				}
				if {$createPng} {
					foreach plotFile $plotFiles {
						eval exec sddsplot [join $plotCmd] -output=${plotFile}.png -device=png
						eval exec sddsplot [join $plotCmd] -output=${plotFile}.eps -device=ceps
					}
				}
			}
		}
    } else {
		foreach nm {XStart XEnd YStart YEnd PageStart PageEnd} {
			set plot$nm [set ${dataset}$nm]
		}
		set tmpRoot /tmp/[APSTmpString]
		if ${oneDplot} {
			foreach file $plotFiles {
				set dim [lindex [exec sdds2stream -par=NumOfDimension $file] 0]
				if {$dim>2} {
					if ![file exist $file.y0z0] {
						if [catch {ComputeFFT -file $file} result] {
							return -code error $result
						}
					}
					lappend files1 ${file}.y0z0
				} else {
					lappend files1 $file
				}
			}
			foreach file $files1 {
				foreach y [set ${dataset}Quantity] {
					exec sddsplot -sep -topline=@Description \
						-col=x,$y  $file \
						-yLabel=$y \
						-scale=$plotXStart,$plotXEnd,$plotYStart,$plotYEnd \
						-col=f,FFT* $file.fft.$y "-title=FFT of $y" &
				}
			}
		} else {
			set index 1
			foreach file $plotFiles {
				if {$plotPageStart || $plotPageEnd} {
					if {$plotPageStart && $plotPageEnd} {
						if [catch {exec sddsconvert $file -from=$plotPageStart -to=$plotPageEnd $tmpRoot.$index} result] {
							return -code error $result
						}
					} elseif {$plotPageStart} {
						if [catch {exec sddsconvert $file -from=$plotPageStart  $tmpRoot.$index} result] {
							return -code error $result
						}
					} elseif {$plotPageEnd} {
						if [catch {exec sddsconvert $file -to=$plotPageEnd $tmpRoot.$index} result] {
							return -code error $result
						}
					}
					set plotFile $tmpRoot.$index
				} else {
					set plotFile $file
				}
				foreach y [set ${dataset}Quantity] {
					exec sddscontour -shade -columnMatch=Index,${y}* -topline=@Description -xlabel=x \
						-scale=$plotXStart,$plotXEnd,$plotYStart,$plotYEnd \
						-ylabel=y "-title=$y vs x and y" \
						-yrange=minim=@origin2,max=@max_ext2 -xrange=min=@origin1,max=@max_ext1 $plotFile & 
					
					if $movie {
						exec sddscontour -shade -columnMatch=Index,${y}* -topline=@Description -xlabel=x \
							-scale=$plotXStart,$plotXEnd,$plotYStart,$plotYEnd \
							-ylabel=y "-title=$y vs x and y" \
							-yrange=minim=@origin2,max=@max_ext2 -xrange=min=@origin1,max=@max_ext1 $plotFile \
							-output=${file}.${y}.movie
					}
					if $createPng {
						exec sddscontour -shade -columnMatch=Index,${y}* -topline=@Description -xlabel=x \
							-scale=$plotXStart,$plotXEnd,$plotYStart,$plotYEnd \
							-ylabel=y "-title=$y vs x and y" \
							-yrange=minim=@origin2,max=@max_ext2 -xrange=min=@origin1,max=@max_ext1 $plotFile \
							-output=${file}.${y}.png -device=png
					}
				}
				incr index
			}
		}
    }
}


set CustThickness 2
set CustLabelSize 1.5
set CustXLabel x
set CustYLabel y
set CustXStart 0
set CustXEnd 0
set CustYStart 0
set CustYEnd 0
set CustString "Total charge density = "
set CustStringXPos 0.3
set CustStringYPos 0.8
set CustStringThickness 2
set CustStringLinetype 1
set CustStringSize 1.5
set CustomPlot 1
set CustPngFile ""
set CustSymbolSize 0.2
set CustXTickSpacing 0
set CustYTickSpacing 0.5
set CustYReduceFactor 1.0e8
set CustomPlotList {CustThickness CustLabelSize CustXLabel CustYLabel CustXStart CustXEnd \
                        CustYStart CustYEnd CustPngFile CustSymbolSize \
						CustString CustStringXPos CustStringYPos CustStringThickness \
                        CustStringLinetype CustStringSize CustomPlot CustXTickSpacing CustYTickSpacing CustYReduceFactor}
proc CustomPlot {args} {
	set type ""
	set dataset electrons
	APSParseArguments {type dataset}
	global CustomPlotList directory rootname plotNumber 
	eval global $CustomPlotList
	
	global ${dataset}_type

	if {$type=="spatial"} {
		set CustPngFile $directory/${rootname}_${dataset}[set ${dataset}_type]_${type}_${plotNumber}.png
	} else {
		set CustPngFile $directory/${rootname}${type}_${plotNumber}.png
	}
	set CustomPlot 1
	APSDialogBox .cust -name "Custom plots" \
		-okCommand "set CustomPlot 1 " \
		-cancelCommand "set CustomPlot 0"
	APSLabeledEntryFrame .thick -parent .cust.userFrame  -label "Enter the thickness of tick label and size of x/y label:" \
		-variableList {CustThickness CustLabelSize} -width 15 -orientation horizontal 
    APSLabeledEntryFrame .thickspa -parent .cust.userFrame  -label "Enter the spacing of x/y tick:" \
		-variableList {CustXTickSpacing CustYTickSpacing} -width 15 -orientation horizontal 
	APSLabeledEntryFrame .label -parent .cust.userFrame -label "Enter the label of x/y axis:"  -width 15 \
		-variableList {CustXLabel CustYLabel} -orientation horizontal
	APSLabeledEntryFrame .x -parent .cust.userFrame -label "Enter plot start/end of x axis: "  -width 15 \
		-variableList {CustXStart CustXEnd} -orientation horizontal
	APSLabeledEntryFrame .y -parent .cust.userFrame -label "Enter plot start/end of y axis:" -width 15 \
		-variableList {CustYStart CustYEnd} -orientation horizontal
	APSLabeledEntry .string -parent .cust.userFrame -label "Enter the string text:" -width 50 -textVariable CustString
	APSLabeledEntryFrame .pos -parent .cust.userFrame -label "Enter x/y position of string text:" -width 15 \
		-variableList {CustStringXPos CustStringYPos} -orientation horizontal
	APSLabeledEntryFrame .str -parent .cust.userFrame -label "Enter line type, size and thickness of string text:" -width 8 \
		-variableList {CustStringLinetype CustStringSize CustStringThickness} -orientation horizontal
	APSLabeledEntry .sym -parent .cust.userFrame -label "Size of plot symbol:" -width 20 -textVariable CustSymbolSize
	APSLabeledEntry .fac -parent .cust.userFrame -label "Reduce factor of y axis:" -width 20 -textVariable CustYReduceFactor 
	APSLabeledOutput .png -parent .cust.userFrame -label "Output png file name:" -width 50 -textVariable CustPngFile
	tkwait window .cust
	if !$CustomPlot {
		SetStatus "Custom plot for $type was cancelled."
		return
	}
	switch $type {
		Energy {
			set root $directory/${rootname}_${dataset}[set ${dataset}_type]_${plotNumber} 
			if ![file exist $root.sdds] {
				SetStatus "Convert $root ..."
				if [catch {ConvertHDFToSDDS -fileroot $root -dataset $dataset} result] {
					return -code error $result
				}
			}
			if ![file exist $root.sdds.hist.energy] {
				SetStatus "Computing $dataset histogram for $root..."
				if [catch {ComputeElectronHistogram -file ${root}.sdds} result] {
					SetStatus "$result"
					return
				}
			}
            set file $root.sdds.hist.energy.custom
            
			if [catch {exec sddsprocess $root.sdds.hist.energy $file \
						   "-redefine=col,$dataset,$dataset $CustYReduceFactor / sddshistBinSize /" } result] {
				SetStatus $result
				return
			}
            set power [format %.0f [expr log10($CustYReduceFactor)]]
		exec sddsplot -grap=line,thick=2  -col=Energy,$dataset "-ylabel=dN/dE (10\\\$a${power}\\\$nMeV\\\$a-1\\\$n),scale=$CustLabelSize,thickness=$CustThickness" \
				"-xlabel=scale=$CustLabelSize,thickness=$CustThickness" \
				-scale=$CustXStart,$CustXEnd,$CustYStart,$CustYEnd -grap=line,thick=2 \
				-tick=xLabelThickness=$CustThickness,yLabelThickness=$CustThickness,yspacing=$CustYTickSpacing \
				"-string=[APSMakeSafeQualifierString [APSMakeSafeQualifierString $CustString]],p=$CustStringXPos,q=$CustStringYPos,scale=$CustStringSize,thickness=$CustStringThickness,linetype=$CustStringLinetype" \
				$file &
		exec sddsplot -col=Energy,$dataset "-ylabel=dN/dE (10\\\$a${power}\\\$nMeV\\\$a-1\\\$n),scale=$CustLabelSize,thickness=$CustThickness" \
				"-xlabel=scale=$CustLabelSize,thickness=$CustThickness" -grap=line,thick=2 \
				-scale=$CustXStart,$CustXEnd,$CustYStart,$CustYEnd \
				-tick=xLabelThickness=$CustThickness,yLabelThickness=$CustThickness,yspacing=$CustYTickSpacing \
				"-string=[APSMakeSafeQualifierString [APSMakeSafeQualifierString $CustString]],p=$CustStringXPos,q=$CustStringYPos,scale=$CustStringSize,thickness=$CustStringThickness,linetype=$CustStringLinetype" \
				$file -output=$CustPngFile -device=png
		}
		Rho {
			set root $directory/${rootname}_TotalRhoJ_${plotNumber}
			if ![file exist $root.sdds.custom] {
				if ![file exist $root.sdds] {
					if [catch {ProcessData -fileroot $root} result] {
						return -code error $result
					}
				}
				#process the units, x user um (1e-6 m), Rho
				set npages [exec sdds2stream -npages=bar $root.sdds]
				set retain [expr $npages/2]
				if [catch {exec sddsconvert $root.sdds.xy -pipe=out -from=$retain -to=$retain \
							   | sddsprocess -pipe=in $root.sdds.custom \
							   "-redefine=par,%s,%s 1.0e6 *,units=\\\$gm\\\$rm,select=origin*" \
							   "-redefine=par,%s,%s 1.0e6 *,units=\\\$gm\\\$rm,select=max_ext*" \
							   "-redefine=par,%s,%s 1.0e6 *,units=\\\$gm\\\$rm,select=delta*" } result] {
					SetStatus "$result"
					return
				}
			}
			set file $root.sdds.custom 
			exec sddscontour -quantity=Index,Rho* -xrange=min=@origin1,max=@max_ext1 -yrange=min=@origin2,max=@max_ext2   \
				-thickness=$CustThickness $file -topline= -title= -shade \
				"-xlabel=$CustXLabel (\\\$gm\\\$rm),scale=$CustLabelSize" "-ylabel=$CustYLabel (\\\$gm\\\$rm),scale=$CustLabelSize" \
				-scale=$CustXStart,$CustXEnd,$CustYStart,$CustYEnd -nocolorbar &
			exec sddscontour -quantity=Index,Rho* -xrange=min=@origin1,max=@max_ext1 -yrange=min=@origin2,max=@max_ext2   \
				-thickness=$CustThickness $file -topline= -title= -shade \
				"-xlabel=$CustXLabel (\$gm\$rm),scale=$CustLabelSize" "-ylabel=$CustYLabel (\\\$gm\\\$rm),scale=$CustLabelSize" -device=png \
				-output=$CustPngFile -scale=$CustXStart,$CustXEnd,$CustYStart,$CustYEnd -nocolorbar
			
		}
		Emittance {
			set root $directory/${rootname}_${dataset}[set ${dataset}_type]_${plotNumber}
			set file $root.sdds.hist.emit.custom
			if ![file exist $root.sdds.emit] {
				SetStatus "Computing emittance for $root..."
				if [catch {ComputeEmittance -root ${root}} result] {
					SetStatus "$result"
					return
				}
			}
			if ![file exist $file] {
				if [catch {exec sddsprocess $root.sdds.emit $file \
							   "-redefine=col,y,y 1.0e6 *,units=\\\$gm\\\$rm" \
							   "-redefine=col,z,z 1.0e6 *,units=\\\$gm\\\$rm" } result] {
					SetStatus "$result"
					return
				}
			}
			 
			set yemit [format %.3e [exec sdds2stream -par=eny -page=1 $root.sdds.emit]]
		 
			eval exec sddsplot $file   \
				-scale=$CustXStart,$CustXEnd,$CustYStart,$CustYEnd \
				-col=y,yp \
				\"-xlabel=scale=$CustLabelSize,thickness=$CustThickness\" \
				\"-ylabel=P\\\$by\\\$n/P\\\$bx\\\$n,scale=$CustLabelSize,thickness=$CustThickness\" \
				-tick=xLabelThickness=$CustThickness,yLabelThickness=$CustThickness \
				\"-string=\\\$ge\\\$r\\\$by\\\$n=$yemit m*rad,p=$CustStringXPos,q=$CustStringYPos,scale=$CustStringSize,thick=$CustStringThickness,line=$CustStringLinetype\" \
				-grap=sym,scale=$CustSymbolSize  -title=  &
			eval exec sddsplot $file   \
				-scale=$CustXStart,$CustXEnd,$CustYStart,$CustYEnd \
				-col=y,yp \
				"-xlabel=scale=$CustLabelSize,thickness=$CustThickness" \
				\"-ylabel=P\\\$by\\\$n/P\\\$bx\\\$n,scale=$CustLabelSize,thickness=$CustThickness\" \
				-tick=xLabelThickness=$CustThickness,yLabelThickness=$CustThickness \
				\"-string=\\\$ge\\\$r\\\$by\\\$n=$yemit m*rad,p=$CustStringXPos,q=$CustStringYPos,scale=$CustStringSize,thick=$CustStringThickness,line=$CustStringLinetype\" \
				-grap=sym,scale=$CustSymbolSize  -output=$CustPngFile -device=png -title=
		}
		V {
            set root $directory/${rootname}_${dataset}[set ${dataset}_type]_${plotNumber}
			if ![file exist $root.sdds] {
				SetStatus "Process $root ..."
				if [catch {ConvertHDFToSDDS -fileroot $root} result] {
					SetStatus "$result"
					return
				}
			}
			set file $root.sdds.custom
			if ![file exist $file] {
				if [catch {exec sddsconvert $root.sdds -retain=col,x,Vx -pipe=out \
							   | sddsprocess -pipe=in $file \
							   "-redefine=col,x,x 1.0e6 *,units=\\\$gm\\\$rm" \
							   "-redefine=col,Vx,Vx 3.0e8 /,units=m/s" } result] {
					SetStatus "$result"
					return
				}
			}
			exec sddsplot $file -grap=sym,scale=$CustSymbolSize -scale=$CustXStart,$CustXEnd,$CustYStart,$CustYEnd \
				"-xlabel=scale=$CustLabelSize,thickness=$CustThickness" \
				"-ylabel=P\\\$bx\\\$n/mc,scale=$CustLabelSize,thickness=$CustThickness" \
				-tick=xLabelThickness=$CustThickness,yLabelThickness=$CustThickness \
				-col,x,Vx -title= &
			exec sddsplot $file -grap=sym,scale=$CustSymbolSize -scale=$CustXStart,$CustXEnd,$CustYStart,$CustYEnd \
				"-xlabel=scale=$CustLabelSize,thickness=$CustThickness" \
				"-ylabel=P\\\$bx\\\$n/mc,scale=$CustLabelSize,thickness=$CustThickness" \
				-tick=xLabelThickness=$CustThickness,yLabelThickness=$CustThickness \
				-col,x,Vx -output=$CustPngFile -device=png -title=
		}
		spatial {
			set root $directory/${rootname}_${dataset}[set ${dataset}_type]_${plotNumber}
			set file $root.sdds.hist.pos.custom
			if ![file exist $file] {
				if ![file exist $root.sdds.hist.pos] {
					if [catch {ComputeElectronHistogram -file $root.sdds -type position -dataset $dataset} result] {
						return -code error $result
					}
				}
				set pages [exec sdds2stream -npages=bar $root.sdds.hist.pos]
				set zero_page [expr $pages/2]
				if !$zero_page {
					set zero_page 1
				}
				if [catch {eval exec sddsconvert $root.sdds.hist.pos -pipe=out -frompage=$zero_page -topage=$zero_page \
							   | sddsprocess -pipe=in $file \
							   \"-redefine=par,%s,%s 1.0e6 *,units=\\\$gm\\\$rm\,select=*Minimum\" \
							   \"-redefine=par,%s,%s 1.0e6 *,units=\\\$gm\\\$rm\,select=*Interval\" } result] {
					return -code error $result
				}
			}
			eval exec sddscontour -shade -quantity=frequency -nocolorbar $file -title= -topline= \
				-scale=$CustXStart,$CustXEnd,$CustYStart,$CustYEnd  \
				\"-xlabel=x (\\\$gm\\\$rm),scale=$CustLabelSize\" \
				\"-ylabel=y (\\\$gm\\\$rm),scale=$CustLabelSize\" \
				-thickness=$CustThickness &
			eval exec sddscontour -shade -quantity=frequency -nocolorbar $file -title= -topline= \
				-scale=$CustXStart,$CustXEnd,$CustYStart,$CustYEnd \
				\"-xlabel=x (\\\$gm\\\$rm),scale=$CustLabelSize\" \
				\"-ylabel=y (\\\$gm\\\$rm),scale=$CustLabelSize\" -thickness=$CustThickness \
				-device=png -output=$CustPngFile 
		}
	}

}

proc UpdateInfo {args} {
    set dataset ""
    APSParseArguments {dataset}
    if ![string length $dataset] {
		return
    }
    global ${dataset}InfoWidget ${dataset}Info
    
    set window [set ${dataset}InfoWidget]
    $window.frame.fg.top.text delete end
    $window.frame.fg.top.text insert end [set ${dataset}Info]
}

proc UpdatePlotNumber {args} {
    global directory rootname tabList IDList plotNumber inputFile
    global ${rootname}IDList
    
    if [info exist ${rootname}IDList] {
		set plotNumber [lindex [set ${rootname}IDList] 0]
		if [winfo exist .userFrame.f1.frame.grid.x2.num] {
			destroy .userFrame.f1.frame.grid.x2.num
			APSComboboxFrame .num -parent .userFrame.f1.frame.grid.x2 -label "      Plot/Process which data:" -width 25  \
				-textVariable plotNumber -itemList [set ${rootname}IDList] -editable 1 
		}
    }
    set inputFile ""
    GetDataInformation
}

proc UpdatePlotList {args} {
	global dataset0 plotList plotListParent plotQuantity
	switch $dataset0 {
		YeeElecField {
			set plotList {Ex Ey Ez}
			set plotQuantity Ex
		}
		YeeMagField {
			set plotList {Bx By Bz}
			set plotQuantity Bx
		}
		TotalRhoJ {
			set plotList {Rho Jx Jy Jz}
			set plotQuantity Rho
		}
		myComboField {
			set plotList {Ex Ey Ex Bx By Bz}
			set plotQuantity Ex
		}
	}
	if [winfo exist $plotListParent.plot] {
		destroy $plotListParent.plot
	}
	APSComboboxFrame .plot -parent $plotListParent -width 25 -label "Contour plot quantity:" -textVariable plotQuantity -itemList $plotList \
		-packOption "-side left"
}
set inputFile ""
set electronsDensity ""
proc GetDensity {args} {
    global directory rootname electronsDensity inputFile NP NE
    
	if [string length $electronsDensity] {
		if [APSYesNoPopUp "Current electrons density is $electronsDensity, is it correct?\nIf not correct, the density will be obtained from $rootname input file."] {
			return
		}
	}
	set NE 1
    if [string length $inputFile] {
		if ![APSYesNoPopUp "Get input parameters from $inputFile?"] {
			set inputFile ""
		}
    }
    if [file exist $rootname.in]  {
		set inputFile $rootname.in
    }
    if ![string length $inputFile] {
		cd $directory
		if ![file exist ${rootname}.sh] {
			SetStatus "$rootname.sh does not exist, can not get the input information."
			return
		}
		set fd [open $rootname.sh "r"]
		set inputFile ""
		while {![eof $fd]} {
			gets $fd line
			if [string match "\#*" $line] {
				continue
			}
			if [string match "*${rootname}*" $line] { 
				set tmpList [split $line " "] 
				set index [lsearch -regexp $tmpList -i]
				if {$index>=0} {
					set inputFile [lindex $tmpList [expr $index +1]]
				} 
				set index [lsearch -regexp $tmpList -dim]
				if {$index>=0} {
					set DIM [lindex $tmpList [expr $index +1]]
				}
				break
			}
		}
		close $fd
    }
    if ![string length $inputFile] {
		SetStatus "Can not find the input file of $rootname.sh, probably did not named as *.in"
		return
    }
    if ![file exist $inputFile] {
		SetStatus "$inputFile does not exist!"
		return
    }
    set fid [open $inputFile "r"]
	set density ""
	set NP ""
    while {![eof $fid]} {
		gets $fid line
		if [string match "\\#*" $line] {
			continue
		}
		if [string match "nominalDensity*" $line] { 
			set tmpList [split $line " "]
			set index [lsearch $tmpList "="]
			set density [lindex $tmpList [expr $index +1]] 
		}
		if [string match "nomPtclsPerCell*" $line] { 
			set tmpList [split $line " "]
			set index  [lsearch $tmpList "="]
			set NP [lindex $tmpList [expr $index +1]]
		}
		if {[string length $NP] && [string length $density]} {
			break
		}
    }
	set electronsDensity $density
    close $fid
}

proc ComputeNE {} {
    global NX NY NZ LZ LY LX electronsDensity NP NE
    if {[string length $NX] && [string length $NY] && [string length $NZ] && \
			[string length $LX] && [string length $LY] && [string length $LZ] && \
			[string length $electronsDensity] && [string length $NP]} {
		set NE [expr ($LX * $LY * $LZ)/($NX * $NY * $NZ) * $electronsDensity / $NP] 
    }
}

proc GetRootnameList {args} {
    global directory rootnameList rootname tabList plotNumber datasetList
    set oldDir [pwd]
    cd $directory
    set files0 ""
    set index 1
    set files ""
    set dataList [concat $datasetList ions electrons]
    foreach dataset $dataList {
        if [catch {set files [glob *_${dataset}_*.h5]} result] {
            continue
        } else {
            set dataset0 $dataset
            break
        }
    }
    if ![llength $files] {
        set rootList ""
    } else {
        foreach file $files {
            set id [os editstring 10Z_%/.h5//  $file]
            set root [os editstring %/_${dataset0}_${id}.h5// $file]
            lappend rootList $root
            lappend ${root}IdList $id
        }
        set rootList [lsort -unique $rootList] 
        foreach root $rootList {
            global ${root}IDList
            set ${root}IDList [lsort -integer [set ${root}IdList]]
        }
    }
    if ![llength $rootList] {
        SetStatus "No datasets found in $directory."
        cd $oldDir
        return
    }
    if [string compare $rootnameList $rootList]!=0 {
		set rootnameList $rootList
		set rootname [lindex $rootnameList 0]
		if [winfo exist .userFrame.f1.grame.grid.x1.root] {
			destroy .userFrame.f1.frame.grid.x1.root
			APSComboboxFrame .root -parent .userFrame.f1.frame.grid.x1 -label "Data rootname:" -width 25  \
				-textVariable rootname -itemList $rootnameList -editable 1 \
				-callback UpdatePlotNumber
		}
		set plotNumber [lindex [set ${rootname}IDList] 0]
		
		if [winfo exist .userFrame.f1.frame.grid.x2.num] {
			destroy .userFrame.f1.freame.grid.x2.num
			APSComboboxFrame .num -parent .userFrame.f1.frame.grid.x2 -label "      Plot/Process which data:" -width 25 \
				-textVariable plotNumber -itemList [set ${rootname}IDList] -editable 1
	    
		}
    }
}

proc CreateFieldDataWidgets {args} {
    set parent ""
    APSParseArguments {parent}
    
	APSFrame .info -parent $parent  -label "Data infomation"
    set w $parent.info.frame
	set width 25
	APSLabeledOutputFrame .info1 -parent $w -label "time(s)/spatial dimensions:" \
		-variableList {time DIM} -width $width -orientation horizontal
    APSLabeledOutputFrame .xrange -parent $w -label "x(m) min/max" \
		-variableList {origin1 max_ext1} -width $width -orientation horizontal
    APSLabeledOutputFrame .yrange -parent $w -label "y(m) min/max" \
		-variableList {origin2 max_ext2} -width $width -orientation horizontal
    APSLabeledOutputFrame .zrange -parent $w -label "z(m) min/max" \
		-variableList {origin3 max_ext3} -width $width -orientation horizontal
	
	APSFrameGrid .grid -parent $parent -xList {x2 x3}
	#set w1 $parent.grid.x1
	set w2 $parent.grid.x2
	set w3 $parent.grid.x3
	set width 15 

	APSFrame .filter -parent $w2  -label "FFT/average filter Parameters"
	global filter fieldPlot
	foreach nm {xstart xend ystart yend zstart zend} {
		set filter($nm) 0
		set fieldPlot($nm) 0
	}
	global rhoPower
	set rhoPower 1
	set wf $w2.filter.frame
	APSLabeledEntryFrame .xfilter -parent $wf  -label "x start/end" -width $width \
		-variableList {filter(xstart) filter(xend)} -orientation horizontal
	APSLabeledEntryFrame .yfilter -parent $wf  -label "y start/end" -width $width \
		-variableList {filter(ystart) filter(yend)} -orientation horizontal
	APSLabeledEntryFrame .zfilter -parent $wf  -label "z start/end" -width $width \
		-variableList {filter(zstart) filter(zend)} -orientation horizontal
	APSLabeledEntry .power -parent $wf -label "Rho Power for average: " -width 25 \
		-textVariable rhoPower
	APSFrame .plot -parent $w3 -label "Plot range parameters"
	set wp $w3.plot.frame
	set fieldPlot(pagestart) 0
	set fieldPlot(pageend) 0
	APSLabeledEntryFrame .x -parent $wp  -label "x axis start/end      " -width $width \
		-variableList {fieldPlot(xstart) fieldPlot(xend)} -orientation horizontal
	APSLabeledEntryFrame .y -parent $wp  -label "y axis start/end      " -width $width \
		-variableList {fieldPlot(ystart) fieldPlot(yend)} -orientation horizontal
	APSLabeledEntryFrame .z -parent $wp  -label "contour axis start/end" -width $width \
		-variableList {fieldPlot(zstart) fieldPlot(zend)} -orientation horizontal
	APSLabeledEntryFrame .p -parent $wp -label "Page start/end        " -width $width \
		-variableList {fieldPlot(pagestart) fieldPlot(pageend)} -orientation horizontal
	APSFrame .proc -parent $parent -label "Process and Plot"
	global dataset0 datasetList plotList plotQuantity plotListParent xyPlot
	foreach dataset $datasetList {
		global ${dataset}_type
		set ${dataset}_type ""
	}
	set dataset0 YeeElecField  
	set plotList "Ex Ey Ez"
	set plotQuantity Ex
	set xyPlot xy
	APSFrame .sel -parent $parent.proc.frame -relief flat -label ""
	set w $parent.proc.frame.sel.frame
	APSComboboxFrame .dataset -parent $w -width 25 -label "Dataset:" -textVariable dataset0 -itemList $datasetList \
		-callback UpdatePlotList -packOption "-side left"
	APSComboboxFrame .plot -parent $w -width 25 -label "Contour plot quantity:" -textVariable plotQuantity -itemList $plotList \
		  -packOption "-side left"
	set plotListParent $w
	set procFrame $parent.proc.frame 
	APSRadioButtonFrame .xy -parent $procFrame -label "2D plot x and y axis:" -buttonList {xy xz yz} \
		-valueList {xy xz yz} -variable xyPlot -orientation horizontal 
	 
	APSButton .proc -parent $procFrame -text "Process" -command "ProcessData"
	APSButton .fft -parent $procFrame -text "Compute FFT" -command "ComputeFFT"
	APSButton .plot -parent $procFrame -text "Raw Data Plot" -command "ContourPlot" 
	APSButton .fft1 -parent $procFrame -text "FFT Plot" -command "PlotFFT"
	APSButton .yzAve -parent $procFrame -text "Compute Average" \
		-command "ComputeAverage" -contextHelp "It computes the averaged y, z, Jz over Rho for each x value."
	APSButton .yzAve1 -parent $procFrame -text "Plot Average" -command "PlotAverage" 
	APSButton .cust -parent $procFrame -text "Custom Plot(Rho)" \
		-command "CustomPlot -type Rho"
	APSFrame .tt -parent $parent -label "" -relief flat 
}   

set ions_type ""
set electrons_type ""
set ionsDensity ""
set electronsDensity ""
proc CreateElectronsIonsDataWidget {args} {
    set parent ""
	set dataset electrons
    APSParseArguments {parent dataset} 

	if {$dataset=="electrons"} {
		global electronsDensity
		APSLabeledEntry .iondensity -parent $parent -label "Electrons density" -textVariable electronsDensity -width 20 \
			-contextHelp "provided the electrons density"
	}
    APSFrame .data -parent $parent -label "Raw Data"
    APSFrameGrid .grid -parent $parent.data.frame -xList {x1 x2} 
    set w1 $parent.data.frame.grid.x1
    set w2 $parent.data.frame.grid.x2
    if {$dataset=="ions"} {
		APSLabeledEntry .iontype -parent $w1 -label "Ions type" -textVariable ions_type -width 20 \
			-contextHelp "provided the ions type, the data for given ions would be <rootname>_ions<ions_type>_<plotNumber>.h5"
		global ionsDensity
		APSLabeledEntry .iondensity -parent $w2 -label "Ions density" -textVariable ionsDensity -width 20 \
			-contextHelp "provided the ions density for the type of ion given in the left"
	}
    APSLabeledEntryFrame .factor -parent $w1 -label "Reduce factor/Keep Point: " -width 10 \
		-variableList [list ${dataset}_reduceFactor ${dataset}_keep] -orientation horizontal \
		-contextHelp "if >1, then only the <keep>th value of every <reduceFactor> values is writtend to sdds output data during converting hdf file to sdds."
    bind $w1.factor.frame.entry1 <Return> "ProcessData -dataset $dataset;PlotData -dataset $dataset"
    bind $w1.factor.frame.entry2 <Return> "ProcessData -dataset $dataset;PlotData -dataset $dataset"
    APSFrame .buttons -parent $w2
    APSButton .proc -parent $w2.buttons.frame -text "Process" -command "ProcessData -dataset $dataset"  
    APSButton .plot -parent $w2.buttons.frame -text "Plot Raw data" -command "PlotData -dataset $dataset"  
	APSButton .cust -parent $w2.buttons.frame -text "Custom Vx - x Plot" -command "CustomPlot -type V -dataset $dataset"
	
    APSRadioButtonFrame .x -parent $w1 -label "plot x axis: " -variable ${dataset}X -buttonList {x y z all} \
		-valueList {x y z "x y z"} -orientation horizontal 
    APSRadioButtonFrame .y -parent $w1 -label "plot y axis: " -variable ${dataset}Y -buttonList {rVx rVy rVz all} \
		-valueList {Vx Vy Vz "Vx Vy Vz"} -orientation horizontal 
 
    APSLabeledEntryFrame .xrange -parent $w2 -label "Plot x axis start/end" -width 8 \
		-variableList [list ${dataset}XStart ${dataset}XEnd] -orientation horizontal
    APSButton .default -parent $w2.xrange -packOption "-side left" -text "default" -size small \
		-command "set ${dataset}XStart 0;set ${dataset}XEnd 0" 
    APSLabeledEntryFrame .yrange -parent $w2 -label "Plot y axis start/end" -width 8 \
		-variableList [list ${dataset}YStart ${dataset}YEnd] -orientation horizontal
    APSButton .default -parent $w2.yrange -packOption "-side left" -text "default" -size small \
		-command "set ${dataset}YStart 0;set ${dataset}YEnd 0"
    
	
    APSFrame .energy -parent $parent -label "Energy Histogram/Emittance Calculation"
    APSFrameGrid .grid -parent $parent.energy.frame -xList {x1 x2}
    set w1a $parent.energy.frame.grid.x1
    set w2a $parent.energy.frame.grid.x2
    APSCheckButtonFrame .filter -parent $w1a -label "Use x/y/z filter" -buttonList {x y z} \
		-variableList [list ${dataset}_xFilter ${dataset}_yFilter ${dataset}_zFilter] -orientation horizontal -allNone 1
	
    APSLabeledEntryFrame .xfilter -parent $w1a -label "X filter: start/end" -width 8 \
		-variableList [list ${dataset}_xFilterStart ${dataset}_xFilterEnd] -orientation horizontal
    APSLabeledEntryFrame .yfilter -parent $w1a -label "Y filter: start/end" -width 8 \
		-variableList [list ${dataset}_yFilterStart ${dataset}_yFilterEnd] -orientation horizontal
    APSLabeledEntryFrame .zfilter -parent $w1a -label "Z filter: start/end" -width 8 \
		-variableList [list ${dataset}_zFilterStart ${dataset}_zFilterEnd] -orientation horizontal
	

    APSLabeledEntryFrame .range -parent $w2a -label "Energy bins/min/max:" -variableList \
		[list ${dataset}_EnergyBins ${dataset}_EnergyStart ${dataset}_EnergyEnd] -width 8 -orientation horizontal \
		-contextHelp "number, minimum and maximum value of energy bins for electron energy histogram analysis."
    bind $w2a.range.frame.entry1 <Return> "ComputeElectronHistogram -type energy -dataset $dataset"
    bind $w2a.range.frame.entry2  <Return> "ComputeElectronHistogram -type energy -dataset $dataset"
	bind $w2a.range.frame.entry3  <Return> "ComputeElectronHistogram -type energy -dataset $dataset"
	global ${dataset}_momentum_bins ${dataset}_momentum_min ${dataset}_momentum_max
	set ${dataset}_momentum_bins 100
	set ${dataset}_momentum_min 0
	set ${dataset}_momentum_max 0

	APSLabeledEntryFrame .angle -parent $w2a -label "Ang. Mom. bins/min/max:" \
		-variableList [list ${dataset}_momentum_bins ${dataset}_momentum_min ${dataset}_momentum_max] -width 8 \
		-orientation horizontal 
	bind $w2a.angle.frame.entry1 <Return> "ComputeElectronHistogram -type momentum -dataset $dataset"
    bind $w2a.angle.frame.entry2  <Return> "ComputeElectronHistogram -type momentum -dataset $dataset"
	bind $w2a.angle.frame.entry3  <Return> "ComputeElectronHistogram -type momentum -dataset $dataset"

    APSLabeledEntryFrame .emit -parent $w2a -label "w(=Pz/P) range (emit. cal.):    " -variableList [list ${dataset}_wStart ${dataset}_wEnd] \
		-width 10 -contextHelp "provide the w range for calculating emittance." -orientation horizontal
    bind $w2a.emit.frame.entry1 <Return> "ComputeEmittance -dataset $dataset"
    bind $w2a.emit.frame.entry2 <Return> "ComputeEmittance -dataset $dataset"
    

	
    APSLabeledEntryFrame .xrange -parent $w2a -label "Plot x start/end" -width 8 \
		-variableList [list ${dataset}_energyXStart ${dataset}_energyXEnd] -orientation horizontal
    APSButton .default -parent $w2a.xrange -packOption "-side left" -text "default" -size small \
		-command "set ${dataset}_energyXStart 0;set ${dataset}_energyXEnd 0" 
    APSLabeledEntryFrame .yrange -parent $w2a -label "Plot y start/end" -width 8 \
		-variableList [list ${dataset}_energyYStart ${dataset}_energyYEnd] \
		-orientation horizontal
    APSButton .default -parent $w2a.yrange -packOption "-side left" -text "default" -size small \
		-command "set ${dataset}_energyYStart 0;set ${dataset}_energyYEnd 0"
	
    APSFrameGrid .grid -parent $w1a -yList {y1 y2 y3}
    set w1 $w1a.grid.y1
    set w2 $w1a.grid.y2
	set w3 $w1a.grid.y3
    APSButton .compute -parent $w1  -text "Compute Energy Histogram" -size medium \
		-command "ComputeElectronHistogram -type energy -dataset $dataset" -contextHelp "compute energy histogram."
	APSButton .compute -parent $w2  -text "Compute Angular Momentum Histogram" -size medium \
		-command "ComputeAngularMomentumHistogram -dataset $dataset" -contextHelp "compute angular momentum histogram."
    APSButton .compute1 -parent $w3  -text "Calculate Normalized Emittance" -size medium \
		-command "ComputeEmittance -dataset $dataset" -contextHelp "compute normalized emittance"
	APSFrameGrid .grid -parent $w2a -yList {y1 y2}
	set w1 $w2a.grid.y1
	set w2 $w2a.grid.y2
    APSButton .plot -parent $w1 -text "Plot Energy Histogram" -command "PlotElectronHistogram -type energy -dataset $dataset"
    APSButton .view -parent $w1 -text "Plot Emittance" -command "DisplayBeamEmittance -dataset $dataset"
	APSButton .plot2 -parent $w1 -text "Plot Momentum Hist." -command "PlotMomentumFFT -dataset $dataset"
	APSButton .plot1 -parent $w2 -text "Custom Energy Hist Plot" -command "CustomPlot -type Energy -dataset $dataset"
	APSButton .plot2 -parent $w2 -text "Custom Emittance Plot" -command "CustomPlot -type Emittance -dataset $dataset"
	
    APSFrame .pos -parent $parent -label "Electron spatial histogram"
    APSFrameGrid .grid -parent $parent.pos.frame -xList {x1 x2}
    set w1 $parent.pos.frame.grid.x1
    set w2 $parent.pos.frame.grid.x2
    
	
    APSLabeledEntryFrame .cells -parent $w1 \
		-label "x/y/z bins:" -variableList [list ${dataset}_xBins ${dataset}_yBins ${dataset}_zBins] \
		-orientation horizontal \
		-contextHelp "number of x, y, z bins for $dataset spatial histogram analysis." -width 15

	APSLabeledEntryFrame .xrange -parent $w1 -label "hist. xrange: min/max" -width 18 \
		-variableList [list ${dataset}_xMin ${dataset}_xMax] -orientation horizontal
	APSLabeledEntryFrame .yrange -parent $w1 -label "hist. yrange: min/max" -width 18 \
		-variableList [list ${dataset}_yMin ${dataset}_yMax] -orientation horizontal
	APSLabeledEntryFrame .zrange -parent $w1 -label "hist. zrange: min/max" -width 18 \
		-variableList [list ${dataset}_zMin ${dataset}_zMax] -orientation horizontal
	
    APSLabeledEntryFrame .xrange -parent $w2 -label "Plot x start/end" -width 8 \
		-variableList [list ${dataset}_pos_XStart ${dataset}_pos_XEnd] -orientation horizontal 
    APSButton .default -parent $w2.xrange -packOption "-side left" -text "default" -size small \
		-command "set ${dataset}_pos_XStart 0;set ${dataset}_pos_XEnd 0" 
    APSLabeledEntryFrame .yrange -parent $w2 -label "Plot y start/end" -width 8 \
		-variableList [list ${dataset}_pos_YStart ${dataset}_pos_YEnd] -orientation horizontal  
    APSButton .default -parent $w2.yrange -packOption "-side left" -text "default" -size small \
		-command "set ${dataset}_pos_YStart 0;set ${dataset}_pos_YEnd 0"
	
    APSLabeledEntryFrame .zrange -parent $w2 -label "Plot page start/end " -width 6 \
		-variableList [list ${dataset}_pos_page_start ${dataset}_pos_page_end] -orientation horizontal  
    APSButton .default -parent $w2.zrange -packOption "-side left" -text "default" -size small \
		-command "set ${dataset}_pos_page_start 0;set ${dataset}_pos_page_end 0"

    APSButton .compute -parent $w1 -text "Compute Spatial Histogram"   \
		-command "ComputeElectronHistogram -type position -dataset $dataset" -contextHelp "compute spatial $dataset histogram."
	APSButton .plot1  -parent $w1 -text "Plot 1D Spatial Histogram"   \
		-command "PlotElectronHistogram -type 1d-position -dataset $dataset" -contextHelp "compute spatial $dataset histogram."
    APSButton .plot -parent $w2 -text "Plot Spatial Histogram" -command "PlotElectronHistogram -type position -dataset $dataset"
	APSButton .cust -parent $w2 -text "Custom Plot" -command "CustomPlot -type spatial -dataset $dataset"
}

proc CreateDataInfoWidget {args} {
    set parent ""
    APSParseArguments {parent}
    global dataInfo NX NY NZ LX LY LZ electronsDensity NP NE inputFile
    set dataInfo ""
    
    APSScrolledStatus .datainfo -parent $parent -textVariable dataInfo \
		-withButtons 0 -height 10 -width 80
	APSFrame .info -parent $parent -label "Electrons data infomation"
    set w $parent.info.frame
    
    APSLabeledOutputFrame .info1 -parent $w -label "time (s) / spatial dimensions:                " \
		-variableList {time DIM} -width 25 -orientation horizontal
    APSLabeledOutputFrame .xrange -parent $w -label "Range of X (m), minimum / maximum:            " \
		-variableList {origin1 max_ext1} -width 25 -orientation horizontal
    APSLabeledOutputFrame .yrange -parent $w -label "Range of Y (m), minimum / maximum:            " \
		-variableList {origin2 max_ext2} -width 25 -orientation horizontal
    APSLabeledOutputFrame .zrange -parent $w -label "Range of Z (m), minimum / maximum:            " \
		-variableList {origin3 max_ext3} -width 25 -orientation horizontal
    
    APSFrame .input -parent $parent -label "Input Parameters"
    set w $parent.input.frame
    APSLabeledEntryFrame .file -parent $w -label "Input file / Dimension:"  \
		-width 30 -variableList {inputFile DIM} -orientation horizontal
	APSLabeledEntryFrame .cells -parent $w -label "Number of physical cells Nx/Ny/Nz:              "\
		-variableList {NX NY NZ} -width 15 -orientation horizontal
	APSLabeledEntryFrame .len -parent $w -label "Length (meters) of physical cell Lx/Ly/Lz:        "\
		-variableList {LX LY LZ} -width 15 -orientation horizontal
	APSLabeledEntryFrame .den -parent $w -label "Density / Number of macro-particles per cell:  " \
		-variableList {electronsDensity} -width 15 -orientation horizontal 
	bind $w.den.frame.entry1 <Return> "ComputeNE"
	APSLabeledEntry .ne -parent $w -label "Number of electrons per macro-particle:" -width 50 \
		-textVariable NE
    APSButton .get -parent $parent -text "Get Info" -command "GetDataInformation"
	#  APSButton .get1 -parent $parent -text "Get Input Parameters" -command "GetInputParameters"
	APSButton .comp -parent $parent -text "Compute Electron Density" -command "ComputeNE"
}


proc SetDefaultValues {args} {
    set dataset ""
    set type X
    APSParseArguments {dataset type}

    foreach nm [list ${type}Start ${type}End] {
		set name ${dataset}$nm
		global $name
		set $name 0
    }
}

proc ComputeEmittance {args} {
    set root ""
	set dataset electrons
    APSParseArguments {root dataset}
    global directory rootname plotNumber plotAll electrons_wStart electrons_wEnd frameIndex ions_wStart ions_wEnd
    
    if ![string length $root] {
		if ![string length $rootname] {
			SetStatus "rootname is not provided."
			return
		}
		cd $directory
		if !$plotAll {
			set rootList ${rootname}_${dataset}_$plotNumber
			if {![file exist $rootList.h5] && ![file exist $rootList.sdds]} {
				SetStatus "Both $rootList.h5  and $rootList.sdds does not exit, can not compute its emittance!"
				return
			}
		} else {
			set files [glob -nocomplain ${rootname}_${dataset}_*.h5]
			if ![llength $files] {
				SetStatus "No $dataset found for $rootname."
				return
			}
			foreach file $files {
				set fileroot [os editstring %/.h5// $file]
				lappend rootList $fileroot
			}
		}
    } else {
		set rootList $root
		if [regexp {electrons} $root] {
			set dataset electrons
		} else {
			set dataset ions
		}
    }
	set wStart [set ${dataset}_wStart]
	set wEnd [set ${dataset}_wEnd]
	
    global Me ${dataset}_xFilter ${dataset}_yFilter ${dataset}_zFilter 
	global ${dataset}_xFilterStart ${dataset}_xFilterEnd ${dataset}_yFilterStart ${dataset}_yFilterEnd 
	global ${dataset}_zFilterStart ${dataset}_zFilterEnd
    set filterOption ""
    set wFilter ""
    if {$wStart && $wEnd} {
		set wFilter -filter=col,w,$wStart,$wEnd
    }
	foreach coord {x y z} {
		set ${coord}Filter [set ${dataset}_${coord}Filter]
		foreach nm {Start End} {
			set ${coord}Filter$nm [set ${dataset}_${coord}Filter$nm]
		}
	}
    if {$xFilter} {
		append filterOption " -filter=col,x,$xFilterStart,$xFilterEnd"
    }
    if {$yFilter} {
		append filterOption " -filter=col,y,$yFilterStart,$yFilterEnd"
    }
    if {$zFilter} {
		append filterOption " -filter=col,z,$zFilterStart,$zFilterEnd"
    }
    foreach root $rootList {
		if ![file exist $root.sdds] {
			if [catch {ConvertHDFToSDDS -fileroot $root} result] {
				SetStatus "$result"
				continue
			}
		}
		set columns [exec sddsquery -col $root.sdds]
		if {[lsearch $columns z]<0 || [lsearch $columns Vz]<0} {
			return -code error "Emittance calculation has to be 3-dimensional."
		}
		#note here, Vx is rVx, Vy is rVy, Vz is rVz and V is rV
		#note that in Vorpal applications, electrons move in x direction, not in z direction
		#so here x->z, Xp=Vz/Vx, y=y, yp=Vy/Vx, z->x
		if [catch {eval exec sddsprocess $root.sdds -pipe=out \
					   $filterOption \
					   -filter=col,Vx,0,0,! \
					   \"-redefine=col,x1,z 1.0 *,units=m\" \
					   \"-redefine=col,y,y 1.0 *,units=m\" \
					   \"-redefine=col,V,Vx sqr Vy sqr Vz sqr + + sqrt\" \
					   \"-redefine=col,gamma,V 3.0e8 / sqr 1.0 + sqrt\" \
					   \"-redefine=col,p,V 3.0e8 /,units=m\\\$be\\\$nc\" \
					   \"-redefine=col,xp,Vz Vx /\"  \
					   \"-redefine=col,yp,Vy Vx /\" \
					   \"-process=x,max,xMax\" \
					   \"-redefine=col,t,xMax x - gamma * Vx /,units=s\"  \
					   | sddsprocess -pipe -filter=col,V,0,0,! \
					   | sddsprocess -pipe \
					   \"-define=col,w,Vx V / abs\" \
					   $wFilter \
					   | sddsconvert -pipe -retain=col,x1,y,xp,yp,t,p -del=par,* \
					   | sddsconvert -pipe -rename=col,x1=x \
					   | tee $root.sdds.emit.tmp \
					   | sddsanalyzebeam -pipe \
					   | sddsprocess -pipe \"-redefine=col,enl,el pAverage *,units=m\" \
					   | sddsconvert -pipe -edit=col,*x,%/x/z/ \
					   | sddsexpand -pipe=in $root.sdds.emit.anal} result] {
			return -code error $result
		}
		set zemittance [exec sdds2stream -par=enz $root.sdds.emit.anal]
		set yemittance [exec sdds2stream -par=eny $root.sdds.emit.anal]
		set lemittance [exec sdds2stream -par=el $root.sdds.emit.anal] 
		SetStatus "The z emittance of $root is $zemittance m-rad."
		SetStatus "The y emittance of $root is $yemittance m-rad."
		SetStatus "The longitudial emittance of $root is $lemittance m-rad."
		# invariant J  = x^2 gamma + 2 alpha x x' + x'^2 gamma
		if [catch {exec sddsconvert $root.sdds.emit.tmp -pipe=out -rename=col,x=z,xp=zp \
					   | sddsprocess -pipe "-redefine=par,enl,$lemittance,units=m" \
					   | sddsxref -pipe=in ${root}.sdds.emit.anal   \
					   -transfer=para,*   $root.sdds.emit } result] {
			return -code error $result
		}
		exec rm $root.sdds.emit.tmp
		exec rm $root.sdds.emit.anal
    }
    SetStatus "Done."
}

set currentPlot PlotData
proc DisplayBeamEmittance {args} {
    global directory rootname plotNumber plotAll createPng movie  
    global currentPlot frameIndex
	
	set dataset electrons
	APSParseArguments {dataset}
	
	global ${dataset}_energyXStart ${dataset}_energyXEnd ${dataset}_energyYStart ${dataset}_energyYEnd
    if ![string length $rootname] {
		SetStatus "rootname is not provided."
		return
    }
 
    set currentPlot DisplayBeamEmittance
    cd $directory
 
	if !$plotAll { 
		set rootList ${rootname}_${dataset}_${plotNumber}
	} else {
		set files [glob -nocomplain ${rootname}_${dataset}_*.h5]
		if ![llength $files] {
			SetStatus "No $dataset found for $rootname."
			return
		}
		foreach file $files {
			set fileroot [os editstring %/.h5// $file]
			lappend rootList $fileroot
		}
	}
    foreach root $rootList {
		if ![file exist $root.h5] {
			SetStatus "$root.h5 does not exist!"
			return
		}
		if ![file exist $root.sdds.emit] {
			if [catch {ComputeEmittance -root $root} result] {
				return -code error $result
			}
		}
		set zemit [format %.3e [exec sdds2stream -par=enz -page=1 $root.sdds.emit]]
		set yemit [format %.3e [exec sdds2stream -par=eny -page=1 $root.sdds.emit]]
		set lemit [format %.3e [exec sdds2stream -par=el -page=1 $root.sdds.emit]]
		lappend plotFiles $root.sdds.emit
		SetStatus "The longtidual emittance of $root is $lemit m-rad."
		foreach coord {X Y} {
			foreach nm {Start End} {
				set energy${coord}$nm [set ${dataset}_energy${coord}$nm]
			}
		}
		
		if $createPng {
			eval exec sddsplot \
				\"-title=longitudial emittance is $lemit m-rad.\" \
				-scale=$energyXStart,$energyXEnd,$energyYStart,$energyYEnd \
				\"-xlabel=z (m)\" \
				\"-ylabel=zp (rad)\" \
				\"-string=\\$ge\\$r\\\$bxz\\$n=$zemit m-rad,p=0.15,q=0.85,scale=1.5,thick=2\" \
				-grap=sym,vary=sub   \
				-col=z,zp $root.sdds.emit \
				-dev=ceps -out=$root.sdds.emitz.eps   
			eval  exec sddsplot \
				\"-title=longitudial emittance is $lemit m-rad.\" \
				-scale=$energyXStart,$energyXEnd,$energyYStart,$energyYEnd \
				\"-xlabel=z (m)\" \
				\"-ylabel=zp (rad)\" \
				\"-string=\\\$ge\\\$r\\\$bz\\\$n=$zemit m-rad,p=0.15,q=0.85,scale=1.5,thick=2\" \
				-grap=sym,vary=sub   \
				-col=z,zp $root.sdds.emit \
				-dev=png -out=$root.sdds.emitz.png  
			eval  exec sddsplot \
				\"-title=longitudial emittance is $lemit m-rad.\" \
				-scale=$energyXStart,$energyXEnd,$energyYStart,$energyYEnd \
				\"-xlabel=y (m)\" \
				\"-ylabel=yp (rad)\" \
				\"-string=\\\$ge\\\$r\\\$by\\\$n=$yemit m-rad,p=0.15,q=0.85,scale=1.5,thick=2\" \
				-grap=sym,vary=sub   \
				-col=y,yp $root.sdds.emit \
				-dev=ceps -out=$root.sdds.emity.eps   
			eval exec sddsplot \
				\"-title=longitudial emittance is $lemit m-rad.\" \
				-scale=$energyXStart,$energyXEnd,$energyYStart,$energyYEnd \
				\"-xlabel=y (m)\" \
				\"-ylabel=yp (rad)\" \
				\"-string=\\\$ge\\\$r\\\$by\\\$n=$yemit m-rad,p=0.15,q=0.85,sca=1.5,thick=2\" \
				-grap=sym,vary=sub   \
				-col=y,yp $root.sdds.emit \
				-dev=png -out=$root.sdds.emity.png  
		}
    }
    eval exec sddsplot $plotFiles -sep -legend=file,edit=%/${rootname}_//%/.sdds.emit//  \
		-scale=$energyXStart,$energyXEnd,$energyYStart,$energyYEnd \
		-col=z,zp \
		\"-xlabel=z (m)\" \
		\"-ylabel=zp (rad)\" \
		\"-string=\\\$ge\\\$r\\\$bz\\\$n=$zemit m-rad,p=0.15,q=0.85,scale=1.5,thick=2,line=1\" \
		-grap=sym,vary=sub   &
    eval exec sddsplot $plotFiles -sep -legend=file,edit=%/${rootname}_//%/.sdds.emit//  \
		-scale=$energyXStart,$energyXEnd,$energyYStart,$energyYEnd \
		-col=y,yp \
		\"-xlabel=y (m)\" \
		\"-ylabel=yp (rad)\" \
		\"-string=\\\$ge\\\$r\\\$by\\\$n=$yemit m-rad,p=0.15,q=0.85,scale=1.5,thick=2,line=1\" \
		-grap=sym,vary=sub    &
    
    if {$movie} {
		eval exec sddsplot $plotFiles -sep -legend=file -output=${rootname}_electrons.emitx.movie \
			-scale=$energyXStart,$energyXEnd,$energyYStart,$energyYEnd \
			-col=z,zp \
			\"-xlabel=z (m)\" \
			\"-ylabel=zp (rad)\" \
			\"-string=\\\$ge\\\$r\\\$bz\\\$n=$zemit m-rad,p=0.15,q=0.85,scale=1.5,thick=2\" \
			-grap=sym,vary=sub   
		eval exec sddsplot $plotFiles -sep -legend=file -output=${rootname}_electrons.emity.movie \
			-col=y,yp \
			\"-xlabel=y (m)\" \
			\"-ylabel=yp (rad)\" \
			\"-string=$yemit m-rad,p=0.15,q=0.85,scale=1.5,thick=2\" \
			-grap=sym,vary=sub    
    }
}

proc SetGlobalDefaultValues {} {
	#common globals
	global datasetList outputs directory rootnameList rootname plotNumber movie createPng plotAll DIM NE
	set datasetList {YeeElecField YeeMagField TotalRhoJ myComboField}
	set outputs 1
	set directory .
	set rootnameList "" 
	set plotNumber 1
	set plotAll 0
	set movie 0  
	set createPng 0 
	set DIM 3
	set NE 1
	
	#electrons/ions data 
	foreach dataset {electrons ions} {
		foreach nm {reduceFactor keep} {
			global ${dataset}_$nm
			set ${dataset}_$nm 1
		}
		
		global ${dataset}X ${dataset}Y ${dataset}_EnergyBins ${dataset}_EnergyStart ${dataset}_EnergyEnd
		set ${dataset}X x
		set ${dataset}Y Vx
		
		#energy histogram
		set ${dataset}_EnergyBins 100
		set ${dataset}_EnergyStart 0
		set ${dataset}_EnergyEnd 100
		foreach coord {X Y} {
			foreach nm {Start End} {
				global ${dataset}${coord}$nm 
				set ${dataset}${coord}$nm 0
			}
		}
		foreach coord {x y z} {
			global ${dataset}_${coord}Filter
			set ${dataset}_${coord}Filter 0
			foreach nm {Start End} {
				global ${dataset}_${coord}Filter$nm
				set ${dataset}_${coord}Filter$nm 0
			}
		}
		foreach coord {X Y} {
			foreach nm {Start End} {
				global ${dataset}_energy${coord}$nm
				set ${dataset}_energy${coord}$nm 0
			}
		}
		
		#spatial histogram
		global  ${dataset}_xBins ${dataset}_yBins ${dataset}_zBins
		set ${dataset}_xBins 100
		set ${dataset}_yBins 20
		set ${dataset}_zBins 10
		foreach coord {x y z} {
			foreach nm {Min Max} {
				global  ${dataset}_${coord}$nm
				set ${dataset}_${coord}$nm 0
			}
		}
		foreach coord {X Y} {
			foreach nm {Start End} {
				global  ${dataset}_pos_${coord}$nm
				set ${dataset}_pos_${coord}$nm 0
			}
		}
		global  ${dataset}_pos_page_start ${dataset}_pos_page_end
		set ${dataset}_pos_page_start 0
		set ${dataset}_pos_page_end 0
		
		global ${dataset}_wStart ${dataset}_wEnd
		set ${dataset}_wStart 0.01
		set ${dataset}_wEnd 1.01
	}
	global NX NY NY LX LY LZ
	set NX ""
	set NY ""
	set NZ ""
	set LX ""
	set LY ""
	set LZ ""
}

set xyFFTstart 0
set xyFFTend 0
set xzFFTstart 0
set xzFFTend 0
proc ComputeRhoZYToX {args} {
	set fileroot ""
	set column Rho
	set compute 1
	APSParseArguments {fileroot column compute}
	set tmpRoot /tmp/[APSTmpString]
	if ![file exist $fileroot.sdds] {
		SetStatus "Converting $fileroot.h5 to sdds..."
		if ![file exist $fileroot.h5] {
			return -code error "$fileroot.h5 does not exist!"
		}
		if [catch {ConvertHDFToSDDS -fileroot $fileroot -computeFFT 0}  result] {
			return -code error $result
		}
	}
	if {![file exist $fileroot.zAve.sdds] || ![file exist $fileroot.yAve.sdds]} {
		if [catch {exec sddsconvert $fileroot.sdds -pipe=out -retain=col,${column}_* \
					   | sddsprocess -pipe "-redefine=col,%s,%s abs,select=${column}*" \
					   | sddsrowstats -pipe -sum=Sum,${column}* \
					   | sddsconvert -pipe -retain=col,Sum \
					   | sddstranspose -pipe \
					   | sddsconvert -pipe -del=col,Old* \
					   | sddscombine -pipe -merge \
					   | sddsprocess -pipe -process=Column*,sum,%sSum \
					   | sddscollapse -pipe \
					   | sddscollect -pipe=in $tmpRoot.1 -collect=suffix=Sum } result] {
			return -code error $result
		}
		if [catch {exec sddsconvert $fileroot.sdds -pipe=out -retain=col,${column}_* \
					   | sddstranspose -pipe \
					   | sddsprocess -pipe -scan=col,yIndex,OldColumnNames,${column}_%ld \
					   | sddsconvert -pipe -del=col,OldColumnNames \
					   | sddsprocess -pipe "-define=col,y,yIndex 1.0 - delta2 * origin2 +" \
					   | sddsprocess -pipe "-redefine=col,%s,%s abs y *,select=Column*" \
					   | sddscombine -pipe -merge \
					   | sddsprocess -pipe -process=Column*,sum,%sYAve \
					   | sddscollapse -pipe \
					   | sddscollect -pipe -collect=suffix=YAve \
					   | sddsprocess -pipe=in $tmpRoot.2  \
					   "-define=col,x,i_row delta1 * origin1 +" } result] {
			return -code error $result
		}
		
		if [catch {exec sddsconvert $fileroot.sdds -pipe=out -retain=col,${column}_* \
					   | sddstranspose -pipe \
					   | sddsconvert -pipe -del=col,OldColumnNames \
					   | sddsprocess -pipe "-redefine=col,%s,%s abs zPos *,select=Column*" \
					   | sddscombine -pipe -merge \
					   | sddsprocess -pipe -process=Column*,sum,%sZAve \
					   | sddscollapse -pipe \
					   | sddscollect -pipe -collect=suffix=ZAve \
					   | sddsprocess -pipe=in $tmpRoot.3  \
					   "-define=col,x,i_row delta1 * origin1 +" } result] {
			return -code error $result
		}
		if [catch {exec sddsxref $tmpRoot.2 $tmpRoot.1 -pipe=out -take=Sum \
					   | sddsprocess -pipe "-redefine=col,YAve,YAve Sum 1.0e-20 + /" \
					   | sddsconvert -pipe=in $fileroot.yAve.sdds -retain=col,x,YAve } result] {
			return -code error $result
		}
		if [catch {exec sddsxref $tmpRoot.3 $tmpRoot.1 -pipe=out -take=Sum \
					   | sddsprocess -pipe "-redefine=col,ZAve,ZAve Sum 1.0e-20 + /" \
					   | sddsconvert -pipe=in $fileroot.zAve.sdds -retain=col,x,ZAve } result] {
			return -code error $result
		}
		APSAddToTmpFileList -ID vorpal -fileList "$tmpRoot.1 $tmpRoot.2 $tmpRoot.3"
	}
	exec sddsplot -col=x,YAve $fileroot.yAve.sdds &
	exec sddsplot -col=x,ZAve $fileroot.zAve.sdds &
	if {![file exist $fileroot.y.sdds] || ![file exist $fileroot.z.sdds] || $compute} {
		global xyFFTstart xyFFTend xzFFTstart xzFFTend process
		APSDialogBox .cust2 -name "X  FFT filter" \
			-okCommand "set process 1 " \
			-cancelCommand "set process 0"
		APSLabeledEntryFrame .xfft -parent .cust2.userFrame  -label "Enter start and end value of x position (x filter) for yAve:" \
			-variableList {xyFFTstart xyFFTend} -width 15 -orientation horizontal 
		APSLabeledEntryFrame .xfft1 -parent .cust2.userFrame  -label "Enter start and end value of x position (x filter) for zAve:" \
			-variableList {xzFFTstart xzFFTend} -width 15 -orientation horizontal 
		tkwait window .cust2
		if !$process {
			return
		}
	}
	if {![file exist $fileroot.y.sdds] || $compute} {
		set filterOpt ""
		if {$xyFFTstart || $xyFFTend} {
			append filterOpt "-filter=col,x,$xyFFTstart,$xyFFTend"
		}
		if [string length $filterOpt] {
			if [catch {eval exec sddsprocess $fileroot.yAve.sdds $fileroot.y.sdds  $filterOpt } result] {
				return -code error $result
			}
		} else {
			exec cp $fileroot.yAve.sdds $fileroot.y.sdds
		}
	}
	if {![file exist $fileroot.z.sdds] || $compute} {
		set filterOpt ""
		if {$xzFFTstart || $xzFFTend} {
			append filterOpt "-filter=col,x,$xzFFTstart,$xzFFTend"
		}
		if [string length $filterOpt] {
			if [catch {eval exec sddsprocess $fileroot.zAve.sdds $fileroot.z.sdds  $filterOpt } result] {
				return -code error $result
			}
		} else {
			exec cp $fileroot.zAve.sdds $fileroot.z.sdds
		}
		if [catch {exec sddsfft -truncate -col=x,YAve $fileroot.y.sdds $fileroot.y.sdds.fft
			exec sddsfft -truncate -col=x,ZAve $fileroot.z.sdds $fileroot.z.sdds.fft
		} result] {
			return -code error $result
		}
	}
	exec sddsplot -sep -grap=line,vary -col=x,YAve $fileroot.y.sdds -col=f,FFT* $fileroot.y.sdds.fft &
	exec sddsplot -sep -grap=line,vary -col=x,ZAve $fileroot.z.sdds -col=f,FFT* $fileroot.z.sdds.fft &
}


set xFFTstart 0
set xFFTend 0
set zFFTstart 0
set zFFTend 0
set yFFTstart 0
set yFFTend 0
proc ComputeCustomerizedFFT {args} {
	set fileroot ""
	set column Rho
	set yIndex 1
	set compute 1
	set yPosition 0
	APSParseArguments {fileroot column yIndex compute yPosition}
	
	set tmpRoot /tmp/[APSTmpString]
	if ![file exist $fileroot.sdds] {
		SetStatus "Converting $fileroot.h5 to sdds..."
		if ![file exist $fileroot.h5] {
			return -code error "$fileroot.h5 does not exist!"
		}
		if [catch {ConvertHDFToSDDS -fileroot $fileroot -computeFFT 0}  result] {
			return -code error $result
		}
	}
	if [catch {exec sddsquery -col $fileroot.sdds | grep $column} columns] {
		return -code error "$fileroot.sdds does not contain ${column}* columns!"
	}
	if [lsearch $columns ${column}_$yIndex]<0 {
		return -code error "$fileroot.sdds does not contain ${column}_$yIndex column!"
	}
	if ![file exist $fileroot.y${yIndex}.sdds] {
		if [catch {exec sddsconvert $fileroot.sdds -pipe=out -retain=col,x,${column}_$yIndex \
					   | sddsconvert -pipe -rename=col,${column}_${yIndex}=${column} \
					   | sddsprocess -pipe=in $fileroot.y${yIndex}.sdds \
					   "-print=par,Variable1Name,Z" "-print=par,Variable2Name,X" \
					   "-define=par,XMinimum,origin1" "-define=par,XMaximum,max_ext1" "-define=par,XInterval,delta1" \
					   "-define=par,XDimension,numPhysCells1,type=long" "-define=par,ZDimension,numPhysCells3,type=long" \
					   "-define=par,ZMinimum,origin3" "-define=par,ZMaximum,max_ext3" "-define=par,ZInterval,delta3" } result] {
			return -code error "Error1: $result"
		}
	}
	if ![file exist  $fileroot.y${yIndex}.sdds.merge] {
		if [catch {exec sddscombine $fileroot.y${yIndex}.sdds  $fileroot.y${yIndex}.sdds.merge -merge -over} result] {
			return -code error $result
		}
	}
	exec sddscontour $fileroot.y${yIndex}.sdds.merge -quantity=${column} -shade=256 -swapxy  &
	if {![file exist $fileroot.y${yIndex}.zAve.sdds] || $compute} {
		SetStatus "Compute Z average ..."
		global xFFTstart xFFTend zFFTstart zFFTend process
		APSDialogBox .cust1 -name "X and Z FFT filter" \
			-okCommand "set process 1 " \
			-cancelCommand "set process 0"
		APSLabeledEntryFrame .xfft -parent .cust1.userFrame  -label "Enter start and end value of x position (x filter):" \
			-variableList {xFFTstart xFFTend} -width 15 -orientation horizontal 
		APSLabeledEntryFrame .zfft -parent .cust1.userFrame  -label "Enter start and end value of z position (z filter):" \
			-variableList {zFFTstart zFFTend} -width 15 -orientation horizontal 
		tkwait window .cust1
		if !$process {
			return
		}
		set filterOpt ""
		if {$xFFTstart || $xFFTend} {
			append filterOpt "-filter=col,x,$xFFTstart,$xFFTend"
		}
		if {$zFFTstart || $zFFTend} {
			append filterOpt " -filter=par,zPos,$zFFTstart,$zFFTend"
		}
		if [string length $filterOpt] {
			if [catch {eval exec sddsprocess $fileroot.y${yIndex}.sdds $tmpRoot.1  $filterOpt } result] {
				return -code error $result
			}
			APSAddToTmpFileList -ID vorpal -fileList $tmpRoot.1
			set procFile $tmpRoot.1
		} else {
			set procFile $fileroot.y${yIndex}.sdds
		}
		if [catch {exec sddsconvert $procFile -retain=col,${column}* -pipe=out \
					   | sddstranspose -pipe \
					   | sddscombine -pipe=in -merge $tmpRoot.2 } result] {
			return -code error $result
		}
		APSAddToTmpFileList -ID vorpal -fileList "$tmpRoot.2 $tmpRoot.3"
		if [catch {exec sddscollapse $procFile $tmpRoot.3
			exec sddsxref $tmpRoot.2 $tmpRoot.3 -take=zPos -pipe=out \
					   | sddsprocess -pipe "-redefine=col,%s,%s abs,select=Column*" \
					   | sddsprocess -pipe "-define=col,ZRho%s,%s zPos *,select=Column*" \
					   | sddsconvert -pipe -del=col,OldColumnNames \
					   | sddsprocess -pipe "-process=*Column*,sum,%sSum" \
					   | sddsprocess -pipe "-define=par,%sZAve,ZRho%s %s 1.0e-20 + /,select=Column*" \
					   | sddsconvert -pipe -retain=par,Z*Sum,*ZAve -del=col,* \
					   | sddscollapse -pipe \
					   | sddscollect -pipe -collect=suffix=ZAve -collect=prefix=ZRho \
					   | sddsprocess -pipe -define=par,yPosition,$yPosition,units=m \
					   | sddsxref -pipe=in $procFile -take=x $fileroot.y${yIndex}.ZAve.sdds } result] {
			return -code error $result
		}
	}
	exec sddsplot -sep -col=x,ZAve -col=x,ZRho $fileroot.y${yIndex}.ZAve.sdds &
	#display 
	if {![file exist $fileroot.y${yIndex}.ZAve.sdds.fft] || $compute} {
		SetStatus "Do FFT for ZAve ~ x of $fileroot.y${yIndex}.ZAve.sdds.fft"
		if [catch {exec sddsfft -truncate -col=x,ZAve,ZRho $fileroot.y${yIndex}.ZAve.sdds \
					   $fileroot.y${yIndex}.ZAve.sdds.fft } result] {
			return -code error $result
		}
	}
	exec sddsplot -sep -col=f,FFT*  $fileroot.y${yIndex}.ZAve.sdds.fft &
}

proc ComputeJzAverage {args} {
	set fileroot ""
	set yIndex 1
	set compute 1
	set yPosition 0
	APSParseArguments {fileroot yIndex compute yPosition}
	
	set tmpRoot /tmp/[APSTmpString]
	if ![file exist $fileroot.sdds] {
		SetStatus "Converting $fileroot.h5 to sdds..."
		if ![file exist $fileroot.h5] {
			return -code error "$fileroot.h5 does not exist!"
		}
		if [catch {ConvertHDFToSDDS -fileroot $fileroot -computeFFT 0}  result] {
			return -code error $result
		}
	}
	if [catch {exec sddsquery -col $fileroot.sdds | grep Rho} columns] {
		return -code error "$fileroot.sdds does not contain Rho* columns!"
	}
	if [catch {exec sddsquery -col $fileroot.sdds | grep Jz} columns1] {
		return -code error "$fileroot.sdds does not contain Jz* columns!"
	}
	if [lsearch $columns Rho_$yIndex]<0 {
		return -code error "$fileroot.sdds does not contain Rho_$yIndex column!"
	}
	if [lsearch $columns1 Jz_$yIndex]<0 {
		return -code error "$fileroot.sdds does not contain Jz_$yIndex column!"
	}
	
	if {![file exist $fileroot.Jz.y${yIndex}.sdds] || $compute} {
		global xFFTstart xFFTend zFFTstart zFFTend  process
		APSDialogBox .cust1 -name "X and Z FFT filter" \
			-okCommand "set process 1 " \
			-cancelCommand "set process 0"
		APSLabeledEntryFrame .xfft -parent .cust1.userFrame  -label "Enter start and end value of x position (x filter):" \
			-variableList {xFFTstart xFFTend} -width 15 -orientation horizontal 
		APSLabeledEntryFrame .zfft -parent .cust1.userFrame  -label "Enter start and end value of z position (z filter):" \
			-variableList {zFFTstart zFFTend} -width 15 -orientation horizontal 
		tkwait window .cust1
		if !$process {
			return
		}
		set filterOpt ""
		if {$xFFTstart || $xFFTend} {
			append filterOpt "-filter=col,x,$xFFTstart,$xFFTend"
		}
		if {$zFFTstart || $zFFTend} {
			append filterOpt " -filter=par,zPos,$zFFTstart,$zFFTend"
		}
		if [catch {eval exec sddsprocess $fileroot.sdds $filterOpt -pipe=out \
					   | sddsconvert  -pipe  -retain=col,x,Rho_$yIndex,Jz_$yIndex \
					   | sddsconvert -pipe -rename=col,Rho_${yIndex}=Rho,Jz_$yIndex=Jz \
						| sddsprocess -pipe \"-define=col,JzRho,Rho Jz *\" \
					   | sddsprocess -pipe \
					   \"-redefine=col,Rho,Rho sqr\" \
					   | sddscombine -pipe -merge \
					   | sddssort -pipe -col=x \
					   | sddsbreak -pipe -changeof=x \
					   | sddsprocess -pipe -process=x,first,X \
					   -process=JzRho,sum,Jz -process=Rho,sum,RhoSum \
					   | sddscollapse -pipe \
					   | sddsconvert -pipe -retain=col,X,Jz,RhoSum \
					   | sddsprocess -pipe=in $fileroot.Jz.y${yIndex}.sdds \
					   \"-define=col,JzAve,Jz RhoSum 1.0e-20 + /\" } result] {
			return -code error "Error1: $result"
		}
		if [catch {exec sddsfft $fileroot.Jz.y${yIndex}.sdds -truncate -col=X,Jz,JzAve \
					   $fileroot.Jz.y${yIndex}.sdds.fft } result] {
			return -code error $result
		}
	}
	exec sddsplot -sep -legend -col=X,Jz* $fileroot.Jz.y${yIndex}.sdds &
	exec sddsplot -sep -legend -col=f,FFT*  $fileroot.Jz.y${yIndex}.sdds.fft &
}

proc CustomerizeRhoFFT {args} {
	global directory rootname plotNumber Recompute
	set dataset TotalRhoJ 
	set sumYZ 0
	set JzAve 0
	APSParseArguments {sumYZ JzAve}
	
	cd $directory
	
	set fileroot ${rootname}_${dataset}_$plotNumber
	if ![file exist ${fileroot}.sdds] {
		SetStatus "Converting $fileroot.h5 to sdds..."
		if ![file exist $fileroot.h5] {
			return -code error "$fileroot.h5 does not exist!"
		}
		if [catch {ConvertHDFToSDDS -fileroot $fileroot -computeFFT 0}  result] {
			return -code error $result
		}
	}
	if $sumYZ {
		SetStatus "Compute/Display zyRho FFT..."
		if [catch {ComputeRhoZYToX -column Rho -fileroot $fileroot -compute $Recompute} result] {
			return -code error $result
		}
		SetStatus "Done."
		return
	}
	SetStatus "Compute/Display zRho FFT ..."
	if [catch {exec sddsquery -col $fileroot.sdds | grep Rho} columns] {
		return -code error "$fileroot.sdds does not contain Rho* columns!"
	}
	set indexList [regsub -all {Rho_} $columns ""]
	set y0 [exec sdds2stream -par=origin2 $fileroot.sdds -page=1]
	set yInterval [exec sdds2stream -par=delta2 $fileroot.sdds -page=1]
	foreach i $indexList {
		set pos [format %.5e [expr $y0 + $yInterval * ($i-1)]]
		lappend itemList "$i   $pos"
	}
	global yIndexSelection
	set yIndexSelection ""
	APSScrolledListWindow .custrho -name "Y posistion list" \
		-label "Select a Y position"  -acceptButton 0 \
		-itemList $itemList -selectionVar yIndexSelection
	tkwait window .custrho
	if ![string length $yIndexSelection] {
		SetStatus "Y position is not selected."
		return
	}
	set yIndex [lindex [lindex $yIndexSelection 0] 0]
	set yPos [lindex [lindex $yIndexSelection 0] 1]
	if $JzAve {
		SetStatus "compute Jz average ..."
		if [catch {ComputeJzAverage -yIndex $yIndex -compute $Recompute -fileroot $fileroot} result] {
			SetStatus "$result"
			return
		}
	} else {
		if [catch {ComputeCustomerizedFFT -fileroot $fileroot -column Rho -yIndex $yIndex -yPosition $yPos -compute $Recompute} result] {
			SetStatus "$result"
			return
		}
	}
	SetStatus "Rho FFT compute done."
}



####### MAIN #######

SetGlobalDefaultValues

APSApplication . -name "Vorpal Visualtion Tool" -version $CVSRevisionAuthor  

APSScrolledStatus .status -parent .userFrame -packOption "-side top" -textVariable status -width 80 -height 2

APSLabeledEntry .dir -parent .userFrame -label "Data Directory: "  -width 60 \
    -textVariable directory -fileSelectDirectory 1 -buttonsOnLeft 1 -fileSelectButton 1
bind .userFrame.dir.entry <Leave> "GetRootnameList"
GetRootnameList
set rootname [lindex $rootnameList 0]
#GetDataInformation
APSFrame .f1 -parent .userFrame -width 95
APSFrameGrid .grid -parent .userFrame.f1.frame -xList {x1 x2}
set w1a .userFrame.f1.frame.grid.x1
set w2a .userFrame.f1.frame.grid.x2
if [llength $rootnameList] {
    APSComboboxFrame .root -parent $w1a -label "Data rootname:" -width 25  \
	-textVariable rootname -itemList $rootnameList -editable 1 \
	-callback UpdatePlotNumber
    set plotNumber [lindex [set ${rootname}IDList] 0]
   
    APSComboboxFrame .num -parent $w2a -label "      Plot/process which data:" -width 25  \
	-textVariable plotNumber -itemList [set ${rootname}IDList] -editable 1 
} else {
    APSLabeledEntry .root -parent $w1a -label "Data rootname:" -width 25 \
	-textVariable rootname 
    APSLabeledEntry .num  -parent $w2a -label "      Plot/process which data:" -width 25 \
	-textVariable plotNumber
}

if {0} {
APSFrameGrid .grid -parent .userFrame -xList {x1 x2}
set w1 .userFrame.grid.x1
set w2 .userFrame.grid.x2

APSRadioButtonFrame .plotall -parent $w1 -label "Plot/Process All data?" -buttonList {Yes No} \
    -valueList {1 0} -variable plotAll -orientation horizontal
APSRadioButtonFrame .movie -parent $w2 -label "Create movie file?" -buttonList {Yes No} \
    -valueList {1 0} -variable movie -orientation horizontal -packOption "-side left"
APSRadioButtonFrame .png -parent $w2 -label "  Create png file?" -buttonList {Yes No} \
    -valueList {1 0} -variable createPng -orientation horizontal -packOption "-side left"
    }
set frameIndex -1
set widgetList [APSTabFrame .tab -parent .userFrame -label "" -frameIndexVariable frameIndex \
					-labelList "FieldsData ElectronsData IonsData DataInformation" -width 950 -height 610 ]

CreateFieldDataWidgets -parent [lindex $widgetList 0]
CreateElectronsIonsDataWidget -parent [lindex $widgetList 1] -dataset electrons
CreateElectronsIonsDataWidget -parent [lindex $widgetList 2] -dataset ions
CreateDataInfoWidget -parent [lindex $widgetList 3]
#APSScrolledStatus .status -parent [lindex $widgetList 4] -packOption "-side top" -textVariable status -width 80 -height 20

#GetDataInformation
