6 Commits

Author SHA1 Message Date
0dc6ca820b bugfix release: pshell import and preview
changes:
- catch runtime errors due to empty datasets
- improve window titles and graph names
- fix scaling of scienta image from XPSSpectrum script
- remove unnecessary spaces and underscores from folder names
2016-09-22 14:15:09 +02:00
a87975d1e6 update data explorer: axis scale and labels in preview 2016-08-17 12:12:52 +02:00
86cf328961 README.md: fix heading levels 2016-06-06 16:07:19 +02:00
2479582c08 README.md: add release notes 2016-06-06 16:04:56 +02:00
02709fd4df maintenance release: pshell import, elog, documentation
* bugfixes in pshell import
* updates to elog interface: templates, login, separate persistent and volatile data
* new header and revision information in documentation
2016-06-03 12:06:04 +02:00
724c73ef19 remove unnecessary files and dependencies
* remove unit tests (require third-party testing framework)
* remove sample preparation (require EPICS.XOP)
* remove scans and live view (require EPICS.XOP)

these files are useful for hard-core developers or on-site only.
for all off-site use, broken dependencies cause unnecessary problems.
contact the PEARL staff if you need to use one of the omitted files.
2016-04-22 13:53:26 +02:00
22 changed files with 1261 additions and 3039 deletions

20
.gitattributes vendored Normal file
View File

@ -0,0 +1,20 @@
.git* export-ignore
#*.ipf diff=igorpro
# git diff --check should output something useful
*.ipf whitespace=indent-with-non-tab,tabwidth=4
# mark files as binary
# you can also add -delta if you regularly
# commit large files of these types
*.ibw binary
*.xop binary
*.pxp binary
*.pxt binary
*.uxp binary
*.uxt binary
*.ihf binary
*.ifn binary
*.ift binary
# automatic end of line normalization
*.ipf eol=lf

1
.gitignore vendored
View File

@ -4,3 +4,4 @@
*.ipfT*
doc/html/*
doc/latex/*

View File

@ -14,13 +14,15 @@ PEARL Procedures should be installed according to the regular Igor Pro guideline
- Find the `HDF5.XOP` extension in the `Igor Pro Folder` under `More Extensions/File Loaders`, create a shortcut, and move the shortcut to the `Igor Extensions` folder next to your `User Procedures` folder.
- Find the `HDF5 Help.ihf` next to `HDF5.XOP`, create a shortcut, and move the shortcut to the `Igor Help Files` folder next to your `User Procedures` folder.
PEARL Procedures has been tested under Igor Pro version 6.37 (32-bit). Older versions (particularly prior to 6.34) may not be compatible. Please update to the latest Igor Pro version before reporting any problems.
License
=======
The source code of PEARL Procedures is available under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) at <https://git.psi.ch/pearl-public/igor-procs>.
Users of PEARL Procedures are requested to coordinate and share the development of the code with the original author.
Please read and respect the respective license agreements.
Please share your extensions of the code with the original author.
Author
------
@ -32,3 +34,12 @@ Copyright
Copyright 2009-2016 by [Paul Scherrer Institut](http://www.psi.ch)
Release Notes
=============
## rev-distro-1.1.1
- If you have upgraded PEARL Procedures from pre-1.1.1 and Igor breaks in pearl-elog.ipf while opening an experiment, please delete the ELOG preferences file `pearl-elog/preferences.pxp`. (Check the Igor Help to find the package preferences folder on your system.)

View File

@ -38,7 +38,7 @@ PROJECT_NAME = "PEARL Procedures"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER =
PROJECT_NUMBER = $(REVISION)
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@ -1647,7 +1647,7 @@ EXTRA_PACKAGES =
# to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
LATEX_HEADER = src/header.tex
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last

View File

@ -11,7 +11,7 @@ DOX=doxygen
DOXOPTS=
LATEX_DIR=latex
REVISION=$(shell git describe --always --tags --dirty --long)
REVISION=$(shell git describe --always --tags --dirty --long || echo "unknown, "`date +"%F %T %z"`)
export REVISION
all: docs
@ -19,7 +19,7 @@ all: docs
docs: doxygen pdf
doxygen:
$(DOX) $(DOXOPTS) Doxyfile
$(DOX) $(DOXOPTS) config.dox
pdf: doxygen
-$(MAKE) -C $(LATEX_DIR)
@ -27,3 +27,4 @@ pdf: doxygen
clean:
-rm latex/*
-rm html/*

149
doc/src/header.tex Normal file
View File

@ -0,0 +1,149 @@
% Latex header for doxygen 1.8.9.1
%
% To generate this file, call:
% doxygen -w latex header.tex footer.tex doxygen.sty
% and substitute the placeholders:
% $title, $datetime, $date, $doxygenversion, $projectname, $projectnumber, $projectbrief, $projectlogo
% (or diff and merge with previous version)
%
\documentclass[twoside]{book}
% Packages required by doxygen
\usepackage{fixltx2e}
\usepackage{calc}
\usepackage{doxygen}
\usepackage[export]{adjustbox} % also loads graphicx
\usepackage{graphicx}
\usepackage[utf8]{inputenc}
\usepackage{makeidx}
\usepackage{multicol}
\usepackage{multirow}
\PassOptionsToPackage{warn}{textcomp}
\usepackage{textcomp}
\usepackage[nointegrals]{wasysym}
\usepackage[table]{xcolor}
% Font selection
\usepackage[T1]{fontenc}
\usepackage[scaled=.90]{helvet}
\usepackage{courier}
\usepackage{amssymb}
\usepackage{sectsty}
\renewcommand{\familydefault}{\sfdefault}
\allsectionsfont{%
\fontseries{bc}\selectfont%
\color{darkgray}%
}
\renewcommand{\DoxyLabelFont}{%
\fontseries{bc}\selectfont%
\color{darkgray}%
}
\newcommand{\+}{\discretionary{\mbox{\scriptsize$\hookleftarrow$}}{}{}}
% Page & text layout
\usepackage{geometry}
\geometry{%
a4paper,%
top=2.5cm,%
bottom=2.5cm,%
left=2.5cm,%
right=2.5cm%
}
\tolerance=750
\hfuzz=15pt
\hbadness=750
\setlength{\emergencystretch}{15pt}
\setlength{\parindent}{0cm}
\setlength{\parskip}{0.2cm}
\makeatletter
\renewcommand{\paragraph}{%
\@startsection{paragraph}{4}{0ex}{-1.0ex}{1.0ex}{%
\normalfont\normalsize\bfseries\SS@parafont%
}%
}
\renewcommand{\subparagraph}{%
\@startsection{subparagraph}{5}{0ex}{-1.0ex}{1.0ex}{%
\normalfont\normalsize\bfseries\SS@subparafont%
}%
}
\makeatother
% Headers & footers
\usepackage{fancyhdr}
\pagestyle{fancyplain}
\fancyhead[LE]{\fancyplain{}{\bfseries\thepage}}
\fancyhead[CE]{\fancyplain{}{}}
\fancyhead[RE]{\fancyplain{}{\bfseries\leftmark}}
\fancyhead[LO]{\fancyplain{}{\bfseries\rightmark}}
\fancyhead[CO]{\fancyplain{}{}}
\fancyhead[RO]{\fancyplain{}{\bfseries\thepage}}
\fancyfoot[LE]{\fancyplain{}{}}
\fancyfoot[CE]{\fancyplain{}{}}
\fancyfoot[RE]{\fancyplain{}{\bfseries\scriptsize $projectnumber}}
\fancyfoot[LO]{\fancyplain{}{\bfseries\scriptsize $projectnumber}}
\fancyfoot[CO]{\fancyplain{}{}}
\fancyfoot[RO]{\fancyplain{}{}}
\renewcommand{\footrulewidth}{0.4pt}
\renewcommand{\chaptermark}[1]{%
\markboth{#1}{}%
}
\renewcommand{\sectionmark}[1]{%
\markright{\thesection\ #1}%
}
% Indices & bibliography
\usepackage{natbib}
\usepackage[titles]{tocloft}
\setcounter{tocdepth}{3}
\setcounter{secnumdepth}{5}
\makeindex
% Hyperlinks (required, but should be loaded last)
\usepackage{ifpdf}
\ifpdf
\usepackage[pdftex,pagebackref=true]{hyperref}
\else
\usepackage[ps2pdf,pagebackref=true]{hyperref}
\fi
\hypersetup{%
colorlinks=true,%
linkcolor=blue,%
citecolor=blue,%
unicode%
}
% Custom commands
\newcommand{\clearemptydoublepage}{%
\newpage{\pagestyle{empty}\cleardoublepage}%
}
%===== C O N T E N T S =====
\begin{document}
% Titlepage & ToC
\hypersetup{pageanchor=false,
bookmarks=true,
bookmarksnumbered=true,
pdfencoding=unicode
}
\pagenumbering{roman}
\begin{titlepage}
\vspace*{7cm}
\begin{center}%
{\Large $projectname}\\
\vspace*{1cm}
{\large $projectbrief }\\
\vspace*{0.5cm}
{\small Version $projectnumber}\\
\vspace*{0.5cm}
{\small $datetime}\\
\end{center}
\end{titlepage}
\clearemptydoublepage
\tableofcontents
\clearemptydoublepage
\pagenumbering{arabic}
\hypersetup{pageanchor=true}
%--- Begin generated contents ---

View File

@ -21,7 +21,7 @@ Users of PEARL Procedures are requested to coordinate and share the development
Please read and respect the respective license agreements.
\author Matthias Muntwiler, <mailto:matthias.muntwiler@psi.ch>
\version This documentation is compiled from revision $(REVISION).
\version This documentation is compiled from version $(REVISION).
\copyright 2009-2016 by [Paul Scherrer Institut](http://www.psi.ch)
\copyright Licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
*/

View File

@ -1,80 +0,0 @@
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
#pragma IgorVersion = 6.1
#pragma ModuleName = PearlAnglescanProcessTest
#pragma version = 1.0
#include "pearl-anglescan-process"
#include "unit-testing"
// test suite for pearl-anglescan-process.ipf
// unit testing framework: http://www.igorexchange.com/project/unitTesting
// run all test cases with RunTest("pearl-anglescan-process.ipf")
// if wave equalities fail, EnableDebugOutput() and read Igor help on equalWaves().
// created: matthias.muntwiler@psi.ch, 2013-11-18
// Copyright (c) 2013 Paul Scherrer Institut
// $Id$
static function test_convert_angles_ttpa()
// function parameters
variable ntests = 3
make /n=(ntests)/d/free i_theta, i_tilt, i_phi
make /n=3/d/free i_ana
make /n=1/d/free o_polar, o_azi
i_theta = {0, 90, 90}
i_tilt = {0, 0, 0}
i_phi = {0, 0, 10}
i_ana = {-30, 0, +30}
make /n=(3,ntests)/d/free e_polar, e_azi
e_polar[][0] = {30, 0, 30}
e_azi[][0] = {-90, 0, 90} // 180, 90, 0
e_polar[][1] = {90, 90, 90}
e_azi[][1] = {-30, 0, +30}
e_polar[][2] = {90, 90, 90}
e_azi[][2] = {-20, 10, +40}
variable phi0 = 0
e_azi += phi0
convert_angles_ttpa2polar(i_theta, i_tilt, i_phi, i_ana, o_polar, o_azi)
CHECK_EQUAL_WAVES(o_polar, e_polar, tol=0.001)
CHECK_EQUAL_WAVES(o_azi, e_azi, tol=0.001)
nvar /z errors = root:packages:unittesting:error_count
if ((nvar_exists(errors)) && (errors > 0))
print o_azi
print e_azi
endif
end
static function test_hist_hemi_aziscan()
CHECK_EMPTY_FOLDER()
make /n=360/d/free value, azi
azi = p
value = 1
variable polar = 45 // dphi = 2
make_hemi_grid(91, "")
wave w_index = index
wave w_nphis = nphis
wave w_dphi = dphi
wave w_values = values
wave w_azim = azim
wave w_polar = polar
duplicate /free w_values, e_values
variable p1 = w_index[44]
variable p2 = w_index[45]
e_values = (p >= p1) && (p < p2) ? 1 : 0
hemi_add_aziscan("", value, polar, azi)
CHECK_EQUAL_WAVES(w_values, e_values, tol=0.001)
end

View File

@ -6,14 +6,14 @@
#include "pearl-polar-coordinates"
#include <New Polar Graphs>
// $Id$
//
// copyright (c) 2013-15 Paul Scherrer Institut
// copyright (c) 2013-16 Paul Scherrer Institut
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http:///www.apache.org/licenses/LICENSE-2.0
//
// Please acknowledge the use of this code.
/// @file
/// @brief processing and holographic mapping of angle scanned XPD data.
@ -64,7 +64,7 @@
///
/// @author matthias muntwiler, matthias.muntwiler@psi.ch
///
/// @copyright 2013-15 Paul Scherrer Institut @n
/// @copyright 2013-16 Paul Scherrer Institut @n
/// Licensed under the Apache License, Version 2.0 (the "License"); @n
/// you may not use this file except in compliance with the License. @n
/// You may obtain a copy of the License at
@ -79,15 +79,38 @@
///
/// PearlAnglescanProcess is declared in @ref pearl-anglescan-process.ipf.
/// @warning experimental
function strip_remove_frames(strip, yscale, ylo, yhi)
/// delete a contiguous range of frames from a strip.
///
/// this can be used to remove a region of bad frames due to, e.g., measurement problems.
/// the function operates on 2D intensity data and manipulator coordinates at the same time.
///
/// @param[in,out] strip 2D data, X-axis = analyser angle, Y-axis = arbitrary manipulator scan.
/// the result is written to the original wave.
///
/// @param[in,out] theta 1D data, manipulator scan.
/// the result is written to the original wave.
///
/// @param[in,out] tilt 1D data, manipulator scan.
/// the result is written to the original wave.
///
/// @param[in,out] phi 1D data, manipulator scan.
/// the result is written to the original wave.
///
/// @param[in] qlo point index of first frame to delete.
///
/// @param[in] qhi point index of last frame to delete.
/// qhi must be greater or equal than qlo.
///
function strip_delete_frames(strip, qlo, qhi, theta, tilt, phi)
wave strip // 2D data, X-axis = analyser angle, Y-axis = arbitrary manipulator scan
wave /z yscale // Y scaling, e.g. ManipulatorPhi
// if unassigned, point scaling is assumed
variable ylo
variable yhi
variable qlo
variable qhi
wave theta
wave tilt
wave phi
if (ylo > yhi)
if (qlo > qhi)
return -1
endif
@ -95,8 +118,8 @@ function strip_remove_frames(strip, yscale, ylo, yhi)
variable snx = dimsize(strip, 0)
variable sny = dimsize(strip, 1)
variable sq1lo = 0
variable sq1hi = max(round((ylo - dimoffset(strip, 1)) / dimdelta(strip, 1)), 0)
variable sq2lo = min(round((ylo - dimoffset(strip, 1)) / dimdelta(strip, 1)), sny - 1)
variable sq1hi = max(qlo-1, 0)
variable sq2lo = min(qhi+1, sny - 1)
variable sq2hi = dimsize(strip, 1) - 1
// dest indices
@ -111,10 +134,24 @@ function strip_remove_frames(strip, yscale, ylo, yhi)
duplicate /free strip, strip_copy
redimension /n=(dnx,dny) strip
strip[][dq1lo,dq1hi] = strip_copy[p][q + q1ofs]
strip[][dq2lo,dq2hi] = strip_copy[p][q + q2ofs]
duplicate /free theta, theta_copy
redimension /n=(dny) theta
theta[dq1lo,dq1hi] = theta_copy[p + q1ofs]
theta[dq2lo,dq2hi] = theta_copy[p + q2ofs]
duplicate /free tilt, tilt_copy
redimension /n=(dny) tilt
tilt[dq1lo,dq1hi] = tilt_copy[p + q1ofs]
tilt[dq2lo,dq2hi] = tilt_copy[p + q2ofs]
duplicate /free phi, phi_copy
redimension /n=(dny) phi
phi[dq1lo,dq1hi] = phi_copy[p + q1ofs]
phi[dq2lo,dq2hi] = phi_copy[p + q2ofs]
return 0
end
@ -144,6 +181,7 @@ end
/// @return if check waves are enabled, the following waves are created (overwritten if existing):
/// @arg check_dist average X distribution
/// @arg check_smoo smoothed distribution used to normalize the strip
///
function normalize_strip_x(strip, [smooth_method, smooth_factor, check])
wave strip
variable smooth_method
@ -233,6 +271,7 @@ end
/// @return if check waves are enabled, the following waves are created (overwritten if existing):
/// @arg check_dist average theta distribution
/// @arg check_smoo smoothed distribution used to normalize the strip
///
function normalize_strip_theta(strip, theta, [theta_offset, smooth_method, smooth_factor, check])
wave strip
wave theta
@ -300,6 +339,70 @@ function normalize_strip_theta(strip, theta, [theta_offset, smooth_method, smoot
endif
end
/// divide the strip by a two-dimensional normalization function.
///
/// @warning experimental. this function is under development.
///
/// @param check enable output of intermediate results
/// @arg 0 (default) don't create additional waves
/// @arg 1 create check waves in the current folder
/// @arg 2 calculate check waves only, do not modify strip
///
/// @return if check waves are enabled, the following waves are created (overwritten if existing):
/// @arg check_dist average theta distribution
/// @arg check_smoo smoothed distribution used to normalize the strip
///
function normalize_strip_2d(strip, theta, [theta_offset, smooth_method, smooth_factor, check])
wave strip
wave theta
variable theta_offset
variable smooth_method
variable smooth_factor
variable check
if (ParamIsDefault(check))
check = 0
endif
if (ParamIsDefault(theta_offset))
theta_offset = 0
endif
if (ParamIsDefault(smooth_method))
smooth_method = 4
endif
if (ParamIsDefault(smooth_factor))
smooth_factor = 0.5
endif
variable nx = dimsize(strip, 0)
variable ny = dimsize(strip, 1)
duplicate /free strip, dist, alpha_int, theta_int
theta_int = theta[q] - theta_offset
alpha_int = dimoffset(strip, 0) + p * dimdelta(strip, 0)
redimension /n=(nx * ny) dist, alpha_int, theta_int
switch(smooth_method)
case 4:
loess /dest=dist_smoo /smth=(smooth_factor) srcWave=dist, factors={alpha_int, theta_int}
redimension /n=(nx, ny) dist_smoo
break
default:
Abort "undefined smooth method"
break
endswitch
// divide
if (check != 2)
strip /= dist_smoo
endif
// check
if (check)
//duplicate /o dist, check_dist
duplicate /o dist_smoo, check_smoo
endif
end
/// crop a strip at the sides.
///
/// the strip is cropped in place, data outside the region of interest is lost.
@ -1893,13 +1996,12 @@ end
///
/// @param x, y projected Cartesian coordinate
///
/// @param projection mapping function from polar to cartesian coordinates
/// @param projection mapping function from polar to cartesian coordinates.
/// projections 0-2 have no effect on the azimuthal coordinate.
/// @arg 0 linear
/// @arg 1 stereographic (default)
/// @arg 2 azimuthal
///
/// projections 0-2 have no effect on the azimuthal coordinate
///
/// @param zeroAngle zeroAngleWhere parameter of polar graphs
/// @arg 0 (default) zero is at the 3 o'clock position
/// @arg 180 zero is at the 9 o'clock position

File diff suppressed because it is too large Load Diff

View File

@ -52,6 +52,25 @@
/// PearlAreaDisplay is declared in @ref pearl-area-display.ipf.
///
/// compose a valid and unique graph name from a data folder reference
static function /s graphname_from_dfref(df, prefix)
dfref df
string prefix
string name
name = GetDataFolder(1, df)
name = ReplaceString("root:", name, "")
name = name[0, strlen(name) - 2]
name = ReplaceString(" ", name, "")
name = CleanupName(prefix + name, 0)
if (CheckName(name, 6))
name = UniqueName(name, 6, 0)
endif
return name
end
/// open a new graph window with a 2D image.
///
/// this is essentially <code>display; appendimage</code>.
@ -72,7 +91,7 @@ function /s ad_display(image)
string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
string graphtitle = dfname + " View"
string /g view_graphname = CleanupName("view_" + dfname, 0)
string /g view_graphname = graphname_from_dfref(imagedf, "view_")
svar graphname = view_graphname
display /k=1/n=$graphname as graphtitle
graphname = s_name
@ -104,7 +123,7 @@ function /s ad_display_histogram(image)
string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
string graphtitle = dfname + " Histogram"
string /g hist_graphname = CleanupName("hist_" + dfname, 0)
string /g hist_graphname = graphname_from_dfref(imagedf, "hist_")
svar graphname = hist_graphname
display /k=1/n=$graphname as graphtitle
graphname = s_name
@ -171,16 +190,15 @@ function /s ad_display_profiles(image, [filter])
duplicate /o image, $viewname /wave=view
make /n=(3,3)/o xprofiles // NX x 3 wave with 3 one-dimensional profiles along Y dimension
make /n=(3,3)/o yprofiles // NY x 3 wave with 3 one-dimensional profiles along X dimension
make /n=(1)/o hist // histogram
string /g view_filter
string /g view_filter_options
view_filter = filter
view_filter_options = ""
variable /g view_filter_smoothing_x = 1
variable /g view_filter_smoothing_y = 1
string dfname = GetDataFolder(0, imagedf)
string graphtitle = dfname + ":" + NameOfWave(image) + " Profiles"
string /g prof_graphname = CleanupName("prof_" + dfname, 0)
string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
string graphtitle = dfname + NameOfWave(image) + " Profiles"
string /g prof_graphname = graphname_from_dfref(imagedf, "prof_")
svar graphname = prof_graphname
variable /g graph_avg // average value in ROI (ROI is defined by the crosshairs A and B)
variable /g graph_min // minimum value in ROI
@ -193,16 +211,13 @@ function /s ad_display_profiles(image, [filter])
graphname = s_name
AppendToGraph /w=$graphname /L=xprofiles xprofiles[*][0],xprofiles[*][1],xprofiles[*][2]
AppendToGraph /w=$graphname /VERT/B=yprofiles yprofiles[*][0],yprofiles[*][1],yprofiles[*][2]
AppendToGraph /w=$graphname /R=hist/B=yprofiles hist
AppendImage /w=$graphname view
string imgname = StringFromList(0, ImageNameList(graphname, ";"))
ModifyImage /w=$graphname $imgname ctab= {*,*,BlueGreenOrange,0}
ModifyGraph /w=$graphname rgb(xprofiles)=(39168,0,0),rgb(yprofiles)=(39168,0,0)
ModifyGraph /w=$graphname rgb(xprofiles#1)=(0,26112,0),rgb(yprofiles#1)=(0,26112,0)
ModifyGraph /w=$graphname rgb(xprofiles#2)=(0,9472,39168),rgb(yprofiles#2)=(0,9472,39168)
ModifyGraph /w=$graphname rgb(hist)=(43520,43520,43520)
ModifyGraph /w=$graphname mode(hist)=5,hbFill(hist)=2
ModifyGraph /w=$graphname mirror(xprofiles)=0,mirror(bottom)=3,mirror(yprofiles)=3,mirror(left)=3
ModifyGraph /w=$graphname mirror(xprofiles)=2,mirror(bottom)=3,mirror(yprofiles)=2,mirror(left)=3
ModifyGraph /w=$graphname nticks=3
ModifyGraph /w=$graphname minor=1
ModifyGraph /w=$graphname axThick=0.5
@ -210,21 +225,33 @@ function /s ad_display_profiles(image, [filter])
ModifyGraph /w=$graphname btLen=4
ModifyGraph /w=$graphname freePos(xprofiles)=0
ModifyGraph /w=$graphname freePos(yprofiles)=0
ModifyGraph /w=$graphname freePos(hist)=0
ModifyGraph /w=$graphname axisEnab(xprofiles)={0.64,1}
ModifyGraph /w=$graphname axisEnab(hist)={0.64,1}
ModifyGraph /w=$graphname axisEnab(bottom)={0,0.6}
ModifyGraph /w=$graphname axisEnab(yprofiles)={0.64,1}
ModifyGraph /w=$graphname axisEnab(left)={0,0.6}
ModifyGraph /w=$graphname zero(left)=8
ModifyGraph /w=$graphname margin(left)=40,margin(bottom)=30,margin(top)=20,margin(right)=40
ModifyGraph /w=$graphname gfSize=10
Label /w=$graphname xprofiles "value (\\U)"
Label /w=$graphname bottom "X (\\U)"
Label /w=$graphname yprofiles "value (\\U)"
Label /w=$graphname left "Y (\\U)"
Label /w=$graphname hist "\\Epixels"
SetAxis /w=$graphname /A /E=1 hist
// axis labels
string labels = note(image)
string lab
lab = StringByKey("AxisLabelX", labels, "=", "\r")
if (!strlen(lab))
lab = "X"
endif
Label /w=$graphname bottom lab + " (\\U)"
lab = StringByKey("AxisLabelY", labels, "=", "\r")
if (!strlen(lab))
lab = "Y"
endif
Label /w=$graphname left lab + " (\\U)"
lab = StringByKey("AxisLabelD", labels, "=", "\r")
if (!strlen(lab))
lab = "value"
endif
Label /w=$graphname xprofiles lab + " (\\U)"
Label /w=$graphname yprofiles lab + " (\\U)"
// legend
if (show_legend)
@ -233,13 +260,18 @@ function /s ad_display_profiles(image, [filter])
AppendText /w=$graphname "\\s(xprofiles#2)\tROI average"
AppendText /w=$graphname "min\t\\{" + s_viewdf + "graph_min}"
AppendText /w=$graphname "max\t\\{" + s_viewdf + "graph_max}"
AppendText /w=$graphname "avg\t\\{" + s_viewdf + "graph_avg}"
AppendText /w=$graphname "sum\t\\{" + s_viewdf + "graph_sum}"
AppendText /w=$graphname "avg\t\\{" + s_viewdf + "graph_avg}"
AppendText /w=$graphname "sdev\t\\{" + s_viewdf + "graph_sdev}"
else
TextBox /w=$graphname /C/N=text_sum/F=0/B=1/X=1.00/Y=1.00 "sum \\{" + s_viewdf + "graph_sum}"
TextBox /w=$graphname /C/N=text_avg/F=0/B=1/X=1.00/Y=6.00 "avg \\{" + s_viewdf + "graph_avg}"
TextBox /w=$graphname /C/N=text_sdev/F=0/B=1/X=1.00/Y=11.00 "sdev \\{" + s_viewdf + "graph_sdev}"
TextBox /w=$graphname /C/N=text0 /F=0 /B=1 /X=1.00 /Y=1.00
lab = StringByKey("Dataset", labels, "=", "\r")
if (strlen(lab))
AppendText /w=$graphname lab
endif
AppendText /w=$graphname "sum\t\\{" + s_viewdf + "graph_sum}"
AppendText /w=$graphname "avg\t\\{" + s_viewdf + "graph_avg}"
AppendText /w=$graphname "sdev\t\\{" + s_viewdf + "graph_sdev}"
endif
// interactive elements
@ -991,7 +1023,7 @@ function /s ad_display_brick(data)
setdatafolder viewdf
string dfname = ReplaceString("root:", s_datadf, "")
string graphtitle = dfname + " Gizmo"
string /g gizmo_graphname = CleanupName("giz_" + dfname, 0)
string /g gizmo_graphname = graphname_from_dfref(datadf, "giz_")
svar graphname = gizmo_graphname
if ((strlen(graphname) > 0) && (wintype(graphname) == 13))
@ -1115,13 +1147,32 @@ function ad_brick_slicer(data)
variable /g x_autoinc = 0
variable /g y_autoinc = 0
variable /g z_autoinc = 0
// axis labels
string labels = note(data)
string xlabel = StringByKey("AxisLabelX", labels, "=", "\r")
if (!strlen(xlabel))
xlabel = "X"
endif
string ylabel = StringByKey("AxisLabelY", labels, "=", "\r")
if (!strlen(ylabel))
ylabel = "Y"
endif
string zlabel = StringByKey("AxisLabelZ", labels, "=", "\r")
if (!strlen(zlabel))
zlabel = "Z"
endif
string dlabel = StringByKey("Dataset", labels, "=", "\r")
if (!strlen(dlabel))
dlabel = NameOfWave(data)
endif
// this section copied from slicer panel
NewPanel /k=1 /W=(500,600,890,940) /N=SlicerPanel as "Brick Slicer"
string /g slicer_panelname = S_name
string panel = s_name
GroupBox g_xslice win=$panel,pos={8,8},size={376,96},title="X Slice"
GroupBox g_xslice win=$panel,pos={8,8},size={376,96},title=xlabel
Slider sl_xslice_position win=$panel,pos={16,32},size={240,56},proc=PearlAreaDisplay#slp_slice_position
Slider sl_xslice_position win=$panel,limits={0,100,1},variable=x_slice_pos,vert= 0
SetVariable sv_xslice_position win=$panel,pos={20,80},size={92,16},proc=PearlAreaDisplay#svp_slice_position,title="X"
@ -1141,7 +1192,7 @@ function ad_brick_slicer(data)
Button b_xslice_stop win=$panel,pos={336,48},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616"
Button b_xslice_stop win=$panel,help={"stop animation"}
GroupBox g_yslice win=$panel,pos={8,108},size={376,96},title="Y Slice"
GroupBox g_yslice win=$panel,pos={8,108},size={376,96},title=ylabel
Slider sl_yslice_position win=$panel,pos={16,132},size={240,56},proc=PearlAreaDisplay#slp_slice_position
Slider sl_yslice_position win=$panel,limits={0,100,1},variable=y_slice_pos,vert= 0
SetVariable sv_yslice_position win=$panel,pos={20,180},size={92,16},proc=PearlAreaDisplay#svp_slice_position,title="Y"
@ -1161,7 +1212,7 @@ function ad_brick_slicer(data)
Button b_yslice_stop win=$panel,pos={336,148},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616"
Button b_yslice_stop win=$panel,help={"stop animation"}
GroupBox g_zslice win=$panel,pos={8,208},size={376,96},title="Z Slice"
GroupBox g_zslice win=$panel,pos={8,208},size={376,96},title=zlabel
Slider sl_zslice_position win=$panel,pos={16,232},size={240,56},proc=PearlAreaDisplay#slp_slice_position
Slider sl_zslice_position win=$panel,limits={0,100,1},variable=z_slice_pos,vert= 0
SetVariable sv_zslice_position win=$panel,pos={20,280},size={92,16},proc=PearlAreaDisplay#svp_slice_position,title="Z"
@ -1181,7 +1232,7 @@ function ad_brick_slicer(data)
Button b_zslice_stop win=$panel,pos={336,248},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616"
Button b_zslice_stop win=$panel,help={"stop animation"}
TitleBox t_slicerpath win=$panel,pos={8,316},size={128,20},disable=2,title=GetDataFolder(1,viewdf)
TitleBox t_slicerpath win=$panel,pos={8,316},size={128,20},disable=2,title=dlabel
//SetVariable setvar0 win=$panel,pos={240,316},size={120,16},title="slab thickness"
//SetVariable setvar0 win=$panel,limits={1,inf,1},value=slab_thickness

View File

@ -1,368 +0,0 @@
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
#pragma IgorVersion = 6.1
#pragma ModuleName = PearlAreaLive
#pragma version = 1.03
#include "pearl-epics", version >= 1.02
// preview panel for EPICS area detectors
// such as CCD cameras, 2D electron analysers
// the image is read from the NDPluginStdArrays plugin of the area detector
// make sure that plugin is enabled
// created: matthias.muntwiler@psi.ch, 2013-05-29
// $Id$
static strconstant package_name = "pearl_epics"
static strconstant package_path = "root:pearl_epics:"
// semicolon-separated list of persistent variable, string, and wave names
static strconstant prefs_objects = ""
function ad_connect(epicsname, nickname)
// connects to the necessary EPICS channels of the detector
// to disconnect, call epics_disconnect()
// (caution: this will disconnect all EPICS channels of all PEARL EPICS procedures!)
string epicsname // base name of the detector, e.g. X03DA-SCIENTA:
// image1: and cam1: are appended by the function
string nickname // nick name under which this detector is referred to in Igor
// must be a valid data folder name
// the data folder is created under root:pearl_epics
dfref savedf = GetDataFolderDFR()
setdatafolder root:
// data folder for common EPICS metadata
newdatafolder /o/s $package_name
dfref epicsdf = GetDataFolderDFR()
string /g ad_chids
string /g ad_nicknames
// data folder this detector
string foldername = nickname
newdatafolder /s/o $foldername
dfref detectordf = GetDataFolderDFR()
// create variables and waves
make /n=(1)/o arraydata, xscale, yscale
make /n=(1,1)/o image
variable /g ndimensions
variable /g arraysize0, arraysize1
variable /g datatype
variable /g colormode
string /g controls, monitors
string /g xunits, yunits
print "connecting EPICS channels..."
// channel lists
controls = ""
monitors = ""
string imagename = epicsname + "image1:"
string camname = epicsname + "cam1:"
// we will set our own monitor on ArrayData, so add this to the controls list
controls = ReplaceStringByKey("ArrayData", controls, imagename + "ArrayData", "=")
// check whether it has been set already
variable chidArrayData = epics_chid(imagename + "ArrayData")
variable array_connected = chidArrayData > 0
monitors = ReplaceStringByKey("NDimensions", monitors, imagename + "NDimensions_RBV", "=")
monitors = ReplaceStringByKey("ArraySize0", monitors, imagename + "ArraySize0_RBV", "=")
monitors = ReplaceStringByKey("ArraySize1", monitors, imagename + "ArraySize1_RBV", "=")
monitors = ReplaceStringByKey("DataType", monitors, imagename + "DataType_RBV", "=")
monitors = ReplaceStringByKey("ColorMode", monitors, imagename + "ColorMode_RBV", "=")
monitors = ReplaceStringByKey("XScale", monitors, camname + "CHANNEL_SCALE_RBV", "=")
monitors = ReplaceStringByKey("YScale", monitors, camname + "SLICE_SCALE_RBV", "=")
variable nroi = 4
variable iroi
string roikey, roiname
for (iroi = 0; iroi < nroi; iroi += 1)
roikey = "ROI" + num2str(iroi + 1)
roiname = epicsname + "ROI" + num2str(iroi + 1) + ":"
controls = ReplaceStringByKey(roikey + "Enable", controls, roiname + "EnableCallbacks", "=")
controls = ReplaceStringByKey(roikey + "EnableX", controls, roiname + "EnableX", "=")
controls = ReplaceStringByKey(roikey + "MinX", controls, roiname + "MinX", "=")
controls = ReplaceStringByKey(roikey + "SizeX", controls, roiname + "SizeX", "=")
controls = ReplaceStringByKey(roikey + "EnableY", controls, roiname + "EnableY", "=")
controls = ReplaceStringByKey(roikey + "MinY", controls, roiname + "MinY", "=")
controls = ReplaceStringByKey(roikey + "SizeY", controls, roiname + "SizeY", "=")
monitors = ReplaceStringByKey(roikey + "Enable", monitors, roiname + "EnableCallbacks_RBV", "=")
monitors = ReplaceStringByKey(roikey + "EnableX", monitors, roiname + "EnableX_RBV", "=")
monitors = ReplaceStringByKey(roikey + "MinX", monitors, roiname + "MinX_RBV", "=")
monitors = ReplaceStringByKey(roikey + "SizeX", monitors, roiname + "SizeX_RBV", "=")
monitors = ReplaceStringByKey(roikey + "EnableY", monitors, roiname + "EnableY_RBV", "=")
monitors = ReplaceStringByKey(roikey + "MinY", monitors, roiname + "MinY_RBV", "=")
monitors = ReplaceStringByKey(roikey + "SizeY", monitors, roiname + "SizeY_RBV", "=")
endfor
// connect EPICS channels
epics_connect(controls, monitors)
// keep track of detector IDs
ad_nicknames = AddListItem(nickname, ad_nicknames)
variable iad = WhichListItem(nickname, ad_nicknames, ";", 0, 0)
ad_chids = AddListItem(num2istr(epics_chid(imagename + "ArrayData")), ad_chids, ";", iad)
// set callback function
if (!array_connected)
pvMonitor /F=ad_live_callback epics_chid(imagename + "ArrayData")
endif
print "...done"
setdatafolder savedf
end
function ad_live_callback(chan)
variable chan
dfref savedf = GetDataFolderDFR()
setdatafolder $package_path
// find the data folder of the detector
svar ad_chids
svar ad_nicknames
variable iad = WhichListItem(num2istr(chan), ad_chids, ";", 0, 0)
if (iad >= 0)
string nickname = StringFromList(iad, ad_nicknames)
else
return -1
endif
setdatafolder $nickname
// retrieve data
svar controls
svar monitors
variable chidArrayData = epics_chid(StringByKey("ArrayData", controls, "="))
variable chidNDimensions = epics_chid(StringByKey("NDimensions", monitors, "="))
variable chidArraySize0 = epics_chid(StringByKey("ArraySize0", monitors, "="))
variable chidArraySize1 = epics_chid(StringByKey("ArraySize1", monitors, "="))
variable chidDataType = epics_chid(StringByKey("DataType", monitors, "="))
variable chidColorMode = epics_chid(StringByKey("ColorMode", monitors, "="))
variable chidXScale = epics_chid(StringByKey("XScale", monitors, "="))
variable chidYScale = epics_chid(StringByKey("YScale", monitors, "="))
wave arraydata
wave image
nvar ndimensions
nvar arraysize0
nvar arraysize1
nvar datatype
nvar colormode
wave xscale
wave yscale
pvGet chidNDimensions, ndimensions
pvGet chidArraySize0, arraysize0
pvGet chidArraySize1, arraysize1
pvGet chidDataType, datatype
pvGet chidColorMode, colormode
// sanity checks
if (ndimensions != 2)
return -2
endif
if (colormode != 0)
return -3
endif
redimension /n=(arraysize0 * arraysize1) arraydata
redimension /n=(arraysize0, arraysize1) image
redimension /n=(arraysize0) xscale
redimension /n=(arraysize1) yscale
switch(datatype)
case 0: // int8
redimension /b arraydata, image
break
case 1: // uint8
redimension /b/u arraydata, image
break
case 2: // int16
redimension /w arraydata, image
break
case 3: // uint16
redimension /w/u arraydata, image
break
case 4: // int32
redimension /i arraydata, image
break
case 5: // uint32
redimension /i/u arraydata, image
break
case 6: // float32
redimension /s arraydata, image
break
case 7: // float64
redimension /d arraydata, image
break
endswitch
pvGetWave chidArrayData, arraydata
pvGetWave chidXScale, xscale
pvGetWave chidYScale, yscale
image = arraydata[p + q * arraysize0]
setscale /i x xscale[0], xscale[numpnts(xscale)-1], image
setscale /i y yscale[0], yscale[numpnts(yscale)-1], image
ad_update_profiles(image)
// update ROI rectangles
svar /z graphname = :view_image:prof_graphname
if (svar_exists(graphname))
variable nroi = 4
variable iroi
for (iroi = 0; iroi < nroi; iroi += 1)
ad_update_ROI(graphname, iroi)
endfor
endif
setdatafolder savedf
return 0
end
static function ad_update_ROI(graphname, iroi)
string graphname
variable iroi
string roikey
variable enable
svar monitors
wave xscale
wave yscale
variable enableX = 0
variable minX = 0
variable sizeX = numpnts(xscale)
variable enableY = 0
variable minY = 0
variable sizeY = numpnts(yscale)
roikey = "ROI" + num2str(iroi + 1)
enable = epics_get_num(StringByKey(roikey + "Enable", monitors, "="))
if (enable)
enableX = epics_get_num(StringByKey(roikey + "EnableX", monitors, "="))
if (enableX)
minX = epics_get_num(StringByKey(roikey + "MinX", monitors, "="))
sizeX = epics_get_num(StringByKey(roikey + "SizeX", monitors, "="))
endif
enableY = epics_get_num(StringByKey(roikey + "EnableY", monitors, "="))
if (enableY)
minY = epics_get_num(StringByKey(roikey + "MinY", monitors, "="))
sizeY = epics_get_num(StringByKey(roikey + "SizeY", monitors, "="))
endif
variable x1 = xscale[minX]
variable x2 = xscale[minX + sizeX - 1]
variable y1 = yscale[minY]
variable y2 = yscale[minY + sizeY - 1]
endif
ad_update_ROI_rect(graphname, iroi, x1, y1, x2, y2, enable)
end
static function ad_update_ROI_rect(graphname, iroi, x1, y1, x2, y2, enable)
string graphname
variable iroi // 0...3
variable x1,y1,x2,y2
variable enable // enable = 1; disable = 0
string roiname = "roi" + num2str(iroi + 1)
variable color = 65536 * (1 - iroi/8) - 1
if (enable)
DrawAction /w=$graphname getgroup=$roiname, delete, begininsert
SetDrawEnv /w=$graphname gstart,gname=$roiname
SetDrawEnv /w=$graphname xcoord= bottom,ycoord= left
SetDrawEnv /w=$graphname linefgc= (65535,color,color)
SetDrawEnv /w=$graphname fillpat= 0
SetDrawEnv /w=$graphname linethick= 0.50
DrawRect /w=$graphname x1,y1,x2,y2
SetDrawEnv /w=$graphname gstop
DrawAction /w=$graphname endinsert
else
DrawAction /w=$graphname getgroup=$roiname, delete
endif
end
function ad_set_ROI(nickname, iroi, p1, q1, p2, q2, enable)
// set a ROI rectangle to the given coordinates
string nickname
variable iroi // 0...3
variable p1,q1,p2,q2 // rectangular coordinates of the new ROI (point scaling)
variable enable // enable = 1; disable = 0
string roiname = "roi" + num2str(iroi + 1)
string roikey
dfref savedf = GetDataFolderDFR()
setdatafolder $package_path
setdatafolder $nickname
svar controls
wave xscale
wave yscale
variable minX = min(p1, p2)
variable sizeX = max(p1, p2) - min(p1, p2) + 1
variable enableX = sizeX > 0
variable minY = min(q1, q2)
variable sizeY = max(q1, q2) - min(q1, q2) + 1
variable enableY = sizeY > 0
roikey = "ROI" + num2str(iroi + 1)
epics_set_num(StringByKey(roikey + "Enable", controls, "="), enable)
if (enable)
epics_set_num(StringByKey(roikey + "EnableX", controls, "="), enableX)
if (enableX)
epics_set_num(StringByKey(roikey + "MinX", controls, "="), minX)
epics_set_num(StringByKey(roikey + "SizeX", controls, "="), sizeX)
endif
epics_set_num(StringByKey(roikey + "EnableY", controls, "="), enableY)
if (enableY)
epics_set_num(StringByKey(roikey + "MinY", controls, "="), minY)
epics_set_num(StringByKey(roikey + "SizeY", controls, "="), sizeY)
endif
endif
svar graphname = :view_image:prof_graphname
ad_update_ROI(graphname, iroi)
setdatafolder savedf
end
function add_roi_controls()
PopupMenu pm_set_roi mode=0,value="ROI 1;ROI 2;ROI 3;ROI 4",title="Set ROI"
PopupMenu pm_set_roi pos={400,0},bodyWidth=60,proc=PearlAreaLive#pmp_set_roi
PopupMenu pm_set_roi help={"Set a detector ROI to the current cursor selection"}
end
static function pmp_set_roi(pa) : PopupMenuControl
STRUCT WMPopupAction &pa
switch( pa.eventCode )
case 2: // mouse up
variable popNum = pa.popNum
string imgname = StringFromList(0, ImageNameList(pa.win, ";"))
wave /z image = ImageNameToWaveRef(pa.win, imgname)
if (waveexists(image))
wave /z source = PearlAreaDisplay#get_source_image(image)
if (waveexists(source))
dfref sourcedf = GetWavesDataFolderDFR(source)
string nickname = GetDataFolder(0, sourcedf)
ad_set_ROI(nickname, popNum - 1, pcsr(A, pa.win), qcsr(A, pa.win), pcsr(B, pa.win), qcsr(B, pa.win), 1)
endif
endif
break
case -1: // control being killed
break
endswitch
return 0
End

View File

@ -1,454 +0,0 @@
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
#pragma IgorVersion = 6.1
#pragma ModuleName = PearlAreaProfilesTest
#pragma version = 1.02
#include "pearl-area-profiles"
#include "unit-testing"
/// @file
/// @brief test suite for pearl-area-profiles.ipf
///
/// unit testing framework: http://www.igorexchange.com/project/unitTesting.
/// run all test cases with <code>RunTest("pearl-area-profiles-test.ipf")</code>.
/// if wave equalities fail, EnableDebugOutput() and read Igor help on equalWaves().
///
/// @author matthias muntwiler, matthias.muntwiler@psi.ch
///
/// @copyright 2013-15 Paul Scherrer Institut @n
/// Licensed under the Apache License, Version 2.0 (the "License"); @n
/// you may not use this file except in compliance with the License. @n
/// You may obtain a copy of the License at
/// http://www.apache.org/licenses/LICENSE-2.0
/// @namespace PearlAreaProfilesTest
/// @brief profile extraction for multi-dimensional datasets acquired from area detectors.
///
/// PearlAreaProfilesTest is declared in @ref pearl-area-profiles-test.ipf.
///
/// test the ad_profile_x() function
static function test_ad_profile_x_w()
make /n=(11,21) /d /free source
setscale /p x 10, 1, "X", source
setscale /p y 100, 100, "Y", source
setscale d 0, 0, "D", source
source = x + y
make /n=11 /d /free expected
setscale /p x 10, 1, "X", expected
setscale d 0, 0, "D", expected
expected = 30 + 3 * p + 500 + 600 + 700
make /n=1 /d /free result1, result0
variable p1, p2
p1 = 4
p2 = 6
ad_profile_x_w(source, p1, p2, result1, noavg=1)
CHECK_EQUAL_WAVES(result1, expected, tol=1e-6)
expected /= 3
ad_profile_x_w(source, p1, p2, result0, noavg=0)
CHECK_EQUAL_WAVES(result0, expected, tol=1e-6)
end
/// test the ad_profile_y() function
static function test_ad_profile_y_w()
make /n=(11,21) /d /free source
setscale /p x 10, 1, "X", source
setscale /p y 100, 100, "Y", source
setscale d 0, 0, "D", source
source = x + y
make /n=21 /d /free expected
setscale /p x 100, 100, "Y", expected
setscale d 0, 0, "D", expected
expected = 3 * x + 14 + 15 + 16
make /n=1 /d /free result1, result0
variable p1, p2
p1 = 4
p2 = 6
ad_profile_y_w(source, p1, p2, result1, noavg=1)
CHECK_EQUAL_WAVES(result1, expected)
expected /= 3
ad_profile_y_w(source, p1, p2, result0, noavg=0)
CHECK_EQUAL_WAVES(result0, expected)
end
/// test the ad_extract_slab_x() function
static function test_ad_extract_slab_x()
variable nx = 11
variable ny = 16
variable nz = 21
make /n=(nx,ny,nz) /d /free source
setscale /i x -1, 1, "X", source
setscale /i y -2, 2, "Y", source
setscale /i z -3, 3, "Z", source
setscale d 0, 0, "D", source
source = x + y + z
source[4][][] = 1
source[5][][] = 1
make /n=(ny,nz) /d /free expected
setscale /i x -2, 2, "Y", expected
setscale /i y -3, 3, "Z", expected
setscale d 0, 0, "D", expected
expected = 2
variable p1, p2
p1 = 4
p2 = 5
wave result = ad_extract_slab_x(source, p1, p2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
expected = 1
wave result = ad_extract_slab_x(source, p1, p2, "", noavg=0)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
p1 = -inf
p2 = 5
source = y + z
expected = (x + y) * 6
wave result = ad_extract_slab_x(source, p1, p2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
p1 = 4
p2 = +inf
expected = (x + y) * (nx - 4)
wave result = ad_extract_slab_x(source, p1, p2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
end
/// test the ad_extract_slab_y() function
static function test_ad_extract_slab_y()
variable nx = 11
variable ny = 16
variable nz = 21
make /n=(nx,ny,nz) /d /free source
setscale /i x -1, 1, "X", source
setscale /i y -2, 2, "Y", source
setscale /i z -3, 3, "Z", source
setscale d 0, 0, "D", source
source = x + y + z
source[][4][] = 1
source[][5][] = 1
make /n=(nx,nz) /d /free expected
setscale /i x -1, 1, "X", expected
setscale /i y -3, 3, "Z", expected
setscale d 0, 0, "D", expected
expected = 2
variable p1, p2
p1 = 4
p2 = 5
wave result = ad_extract_slab_y(source, p1, p2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
expected = 1
wave result = ad_extract_slab_y(source, p1, p2, "", noavg=0)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
p1 = -inf
p2 = 5
source = x + z
expected = (x + y) * 6
wave result = ad_extract_slab_y(source, p1, p2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
p1 = 4
p2 = +inf
expected = (x + y) * (ny - 4)
wave result = ad_extract_slab_y(source, p1, p2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
end
/// test the ad_extract_slab_z() function
static function test_ad_extract_slab_z()
variable nx = 11
variable ny = 16
variable nz = 21
make /n=(nx,ny,nz) /d /free source
setscale /i x -1, 1, "X", source
setscale /i y -2, 2, "Y", source
setscale /i z -3, 3, "Z", source
setscale d 0, 0, "D", source
source = x + y + z
source[][][4] = 1
source[][][5] = 1
make /n=(nx,ny) /d /free expected
setscale /i x -1, 1, "X", expected
setscale /i y -2, 2, "Y", expected
setscale d 0, 0, "D", expected
expected = 2
variable p1, p2
p1 = 4
p2 = 5
wave result = ad_extract_slab_z(source, p1, p2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
expected = 1
wave result = ad_extract_slab_z(source, p1, p2, "", noavg=0)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
p1 = -inf
p2 = 5
source = x + y
expected = (x + y) * 6
wave result = ad_extract_slab_z(source, p1, p2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
p1 = 4
p2 = +inf
expected = (x + y) * (nz - 4)
wave result = ad_extract_slab_z(source, p1, p2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
end
/// test the ad_extract_slab() function
static function test_ad_extract_slab()
variable nx = 11
variable ny = 16
variable nz = 21
make /n=(nx,ny,nz) /d /free source
setscale /i x -1, 1, "X", source
setscale /i y -2, 2, "Y", source
setscale /i z -3, 3, "Z", source
setscale d 0, 0, "D", source
source = x + y + z
variable x1, x2
variable y1, y2
variable z1, z2
make /n=(ny,nz) /d /free expected
setscale /i x -2, 2, "Y", expected
setscale /i y -3, 3, "Z", expected
setscale d 0, 0, "D", expected
x1 = 0
x2 = 0
y1 = nan
y2 = nan
z1 = nan
z2 = nan
expected = source[(nx-1)/2][p][q]
wave result = ad_extract_slab(source, x1, x2, y1, y2, z1, z2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
x1 = -inf
x2 = inf
expected = (x + y) * nx
wave result = ad_extract_slab(source, x1, x2, y1, y2, z1, z2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
make /n=(nx,nz) /d /free expected
setscale /i x -1, 1, "X", expected
setscale /i y -3, 3, "Z", expected
setscale d 0, 0, "D", expected
x1 = nan
x2 = nan
y1 = 0
y2 = 0
z1 = nan
z2 = nan
expected = source[p][(ny-1)/2][q]
wave result = ad_extract_slab(source, x1, x2, y1, y2, z1, z2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
y1 = -inf
y2 = +inf
expected = (x + y) * ny
wave result = ad_extract_slab(source, x1, x2, y1, y2, z1, z2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
make /n=(nx,ny) /d /free expected
setscale /i x -1, 1, "X", expected
setscale /i y -2, 2, "Y", expected
setscale d 0, 0, "D", expected
x1 = nan
x2 = nan
y1 = nan
y2 = nan
z1 = 0
z2 = 0
expected = source[p][q][(nz-1)/2]
wave result = ad_extract_slab(source, x1, x2, y1, y2, z1, z2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
z1 = -inf
z2 = inf
expected = (x + y) * nz
wave result = ad_extract_slab(source, x1, x2, y1, y2, z1, z2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
end
/// test the ad_extract_rod_x() function
static function test_ad_extract_rod_x()
variable nx = 11
variable ny = 16
variable nz = 21
make /n=(nx,ny,nz) /d /free source
setscale /i x -1, 1, "X", source
setscale /i y -2, 2, "Y", source
setscale /i z -3, 3, "Z", source
setscale d 0, 0, "D", source
source = x + y + z
source[][4][4] = 1
source[][4][5] = 1
source[][5][4] = 1
source[][5][5] = 1
make /n=(nx) /d /free expected
setscale /i x -1, 1, "X", expected
setscale d 0, 0, "D", expected
expected = 4
variable q1, q2
variable r1, r2
q1 = 4
q2 = 5
r1 = 4
r2 = 5
wave result = ad_extract_rod_x(source, q1, q2, r1, r2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
expected = 1
wave result = ad_extract_rod_x(source, q1, q2, r1, r2, "", noavg=0)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
end
/// test the ad_extract_rod() function, X coordinate
static function test_ad_extract_rod__x()
variable nx = 11
variable ny = 16
variable nz = 21
make /n=(nx,ny,nz) /d /free source
setscale /i x -1, 1, "X", source
setscale /i y -2, 2, "Y", source
setscale /i z -3, 3, "Z", source
setscale d 0, 0, "D", source
source = x + y + z
variable x1, x2
variable y1, y2
variable z1, z2
make /n=(nx) /d /free expected
setscale /i x -1, 1, "X", expected
setscale d 0, 0, "D", expected
x1 = nan
x2 = nan
y1 = 0
y2 = 0
z1 = 0
z2 = 0
expected = source[p][(ny-1)/2][(nz-1)/2]
wave result = ad_extract_rod(source, x1, x2, y1, y2, z1, z2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
y1 = -inf
y2 = +inf
z1 = -inf
z2 = +inf
expected = x * ny * nz
wave result = ad_extract_rod(source, x1, x2, y1, y2, z1, z2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
end
/// test the ad_extract_rod() function, Y coordinate
static function test_ad_extract_rod__y()
variable nx = 11
variable ny = 16
variable nz = 21
make /n=(nx,ny,nz) /d /free source
setscale /i x -1, 1, "X", source
setscale /i y -2, 2, "Y", source
setscale /i z -3, 3, "Z", source
setscale d 0, 0, "D", source
source = x + y + z
variable x1, x2
variable y1, y2
variable z1, z2
make /n=(ny) /d /free expected
setscale /i x -2, 2, "Y", expected
setscale d 0, 0, "D", expected
x1 = 0
x2 = 0
y1 = nan
y2 = nan
z1 = 0
z2 = 0
expected = source[(nx-1)/2][p][(nz-1)/2]
wave result = ad_extract_rod(source, x1, x2, y1, y2, z1, z2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
x1 = -inf
x2 = +inf
z1 = -inf
z2 = +inf
expected = x * nx * nz
wave result = ad_extract_rod(source, x1, x2, y1, y2, z1, z2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
end
/// test the ad_extract_rod() function, Z coordinate
static function test_ad_extract_rod__z()
variable nx = 11
variable ny = 16
variable nz = 21
make /n=(nx,ny,nz) /d /free source
setscale /i x -1, 1, "X", source
setscale /i y -2, 2, "Y", source
setscale /i z -3, 3, "Z", source
setscale d 0, 0, "D", source
source = x + y + z
variable x1, x2
variable y1, y2
variable z1, z2
make /n=(nz) /d /free expected
setscale /i x -3, 3, "Z", expected
setscale d 0, 0, "D", expected
x1 = 0
x2 = 0
y1 = 0
y2 = 0
z1 = nan
z2 = nan
expected = source[(nx-1)/2][(ny-1)/2][p]
wave result = ad_extract_rod(source, x1, x2, y1, y2, z1, z2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
x1 = -inf
x2 = +inf
y1 = -inf
y2 = +inf
expected = x * nx * ny
wave result = ad_extract_rod(source, x1, x2, y1, y2, z1, z2, "", noavg=1)
CHECK_EQUAL_WAVES(result, expected, tol=0.001)
end

View File

@ -613,3 +613,36 @@ threadsafe function calc_y_profile_mins(image)
yminlocs[ix] = v_minloc
endfor
end
/// collect profiles from a multi-scan.
///
/// @warning experimental: name and interface of this function may change.
///
function ad_collect_multiscan_y(dataset, positions, destwave, [noavg])
wave dataset
wave positions
wave destwave
variable noavg
variable tol = (wavemax(positions) - wavemin(positions)) / numpnts(positions) / 100
duplicate /free positions, positions_sorted
sort positions_sorted, positions_sorted
duplicate /free positions_sorted, positions_diff
differentiate /p /meth=2 positions_sorted /d=positions_diff
positions_diff[0] = 1
extract /free positions_sorted, positions_unique, positions_diff > tol
variable n_unique = numpnts(positions_unique)
redimension /n=(dimsize(dataset, 0), n_unique) destwave
variable i
variable nx, ny
for (i = 0; i < n_unique; i += 1)
extract /free dataset, data_extract, abs(positions[q] - positions_unique[i]) < tol
nx = dimsize(dataset, 0)
ny = dimsize(data_extract, 0) / nx
redimension /n=(nx, ny) data_extract
wave profile = ad_profile_x(data_extract, -inf, inf, "", noavg=noavg)
destwave[][i] = profile[p]
endfor
end

View File

@ -1,152 +0,0 @@
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
#pragma IgorVersion = 6.1
#pragma ModuleName = PearlArpesScans
#pragma version = 1.01
#include "mm-physconst"
#include "pearl-optics-theory"
#include "pearl-epics", version >= 1.01
// EPICS scans of Scienta
// matthias muntwiler, 2013-03-15
// $Id: pearl-optics-scans.ipf 129 2013-06-26 15:53:13Z muntwiler_m $
static strconstant basename = "X03DA-SCIENTA:"
static strconstant camname = "cam1:"
static strconstant hdfname = "HDF1:"
static strconstant imgname = "image1:"
static strconstant statsname = "Stats1:"
function scienta_connect()
dfref savedf = GetDataFolderDFR()
print "connecting EPICS channels..."
// channel lists
string controls = ""
controls += basename + camname + "PASS_ENERGY;"
controls += basename + camname + "LOW_ENERGY;"
controls += basename + camname + "CENTRE_ENERGY;"
controls += basename + camname + "HIGH_ENERGY;"
controls += basename + camname + "LENS_MODE;"
controls += basename + camname + "ACQ_MODE;"
controls += basename + camname + "ENERGY_MODE;"
controls += basename + camname + "DETECTOR_MODE;"
controls += basename + camname + "ELEMENT_SET;"
controls += basename + camname + "STEP_SIZE;"
controls += basename + camname + "SLICES;"
controls += basename + camname + "NumExposures;"
controls += basename + camname + "FRAMES;"
controls += basename + camname + "STEP_TIME;"
string monitors = ""
monitors += basename + camname + "PASS_ENERGY_RBV;"
monitors += basename + camname + "LOW_ENERGY_RBV;"
monitors += basename + camname + "CENTRE_ENERGY_RBV;"
monitors += basename + camname + "HIGH_ENERGY_RBV;"
monitors += basename + camname + "ENERGY_WIDTH_RBV;"
monitors += basename + camname + "LENS_MODE_RBV;"
monitors += basename + camname + "ACQ_MODE_RBV;"
monitors += basename + camname + "ENERGY_MODE_RBV;"
monitors += basename + camname + "DETECTOR_MODE_RBV;"
monitors += basename + camname + "ELEMENT_SET_RBV;"
monitors += basename + camname + "STEP_SIZE_RBV;"
monitors += basename + camname + "SLICES_RBV;"
monitors += basename + camname + "NumExposures_RBV;"
monitors += basename + camname + "CURRENT_CHANNEL_RBV;"
monitors += basename + camname + "TOTAL_POINTS_RBV;"
monitors += basename + camname + "PROGRESS_RBV;"
//monitors += basename + camname + "INT_SPECTRUM;"
monitors += basename + camname + "BinX_RBV;"
monitors += basename + camname + "BinY_RBV;"
monitors += basename + camname + "MinX_RBV;"
monitors += basename + camname + "MinY_RBV;"
monitors += basename + camname + "SizeX_RBV;"
monitors += basename + camname + "SizeY_RBV;"
monitors += basename + camname + "ReverseX_RBV;"
monitors += basename + camname + "ReverseY_RBV;"
// variable name list corresponding to channel lists
string variables = ""
variables = AddListItem("ArrayData", variables, ";", ItemsInList(variables))
// connect EPICS channels
epics_connect(controls, monitors)
print "...done"
setdatafolder savedf
end
function pearl_set_attr_ch(attr_wave_name, attr_channel_name)
string attr_wave_name
string attr_channel_name
variable result
variable chid
pvOpen chid, attr_channel_name
switch(wavetype($attr_wave_name, 1))
case 1: // numeric
wave w_attr = $attr_wave_name
pvPutNumber /Q chid, w_attr[0]
result = 0
break
case 2: // text
wave /t wt_attr = $attr_wave_name
pvPutString /Q chid, wt_attr[0]
result = 0
break
default: // error
result = -1
endswitch
pvClose chid
return result
end
function pearl_set_sscan(scan_rec_num)
variable scan_rec_num
string chan_base = "X03DA-PC:scan" + num2str(scan_rec_num) + ":"
string wave_base = "Scan" + num2str(scan_rec_num)
variable nfields
variable ifield
string wave_name
string chan_name
wave /z w_active = $(wave_base + "Active")
if (WaveExists(w_active))
if (w_active[0] != 0)
nfields = 4
for (ifield = 1; ifield <= nfields; ifield += 1)
sscanf wave_name, "%sPositioner%u", ifield
sscanf chan_name, "%sP%uPV", chan_base, ifield
pearl_set_attr_ch(wave_name, chan_name)
sscanf wave_name, "%sReadback%u", ifield
sscanf chan_name, "%sR%uPV", chan_base, ifield
pearl_set_attr_ch(wave_name, chan_name)
sscanf wave_name, "%sTrigger%u", ifield
sscanf chan_name, "%sT%uPV", chan_base, ifield
pearl_set_attr_ch(wave_name, chan_name)
endfor
nfields = 20
for (ifield = 1; ifield <= nfields; ifield += 1)
sscanf wave_name, "%sDetector%u", ifield
sscanf chan_name, "%sD%uPV", chan_base, ifield
pearl_set_attr_ch(wave_name, chan_name)
endfor
endif
endif
end
function pearl_repeat_scan()
// set up a scan according to the attributes of the given dataset
dfref savedf = GetDataFolderDFR()
setdatafolder :attr
setdatafolder savedf
end

View File

@ -759,18 +759,21 @@ static function /s show_preview_graph(data, [xdata])
svar s_profiles_graph
svar s_preview_file
svar s_preview_source
svar s_preview_trace_graph
if ((strlen(s_profiles_graph) > 0) && (WinType(s_profiles_graph) == 1))
KillWindow $s_profiles_graph
endif
if ((strlen(s_preview_trace_graph) > 0) && (WinType(s_preview_trace_graph) == 1))
KillWindow $s_preview_trace_graph
endif
string graphname
if (wavedims(data) == 2)
if ((strlen(s_profiles_graph) > 0) && (WinType(s_profiles_graph) == 1))
ad_update_profiles(data)
else
s_profiles_graph = ad_display_profiles(data)
ModifyGraph /w=$s_profiles_graph /z wbRGB=(48640,56832,60160)
endif
s_profiles_graph = ad_display_profiles(data)
ModifyGraph /w=$s_profiles_graph /z wbRGB=(48640,56832,60160)
graphname = s_profiles_graph
elseif (wavedims(data) == 1)
svar s_preview_trace_graph
duplicate /o data, preview_trace
if (!ParamIsDefault(xdata))
duplicate /o xdata, preview_trace_x
@ -779,20 +782,8 @@ static function /s show_preview_graph(data, [xdata])
preview_trace_x = x
setscale d 0, 0, WaveUnits(data, 0), preview_trace_x
endif
if ((strlen(s_preview_trace_graph) == 0) || (WinType(s_preview_trace_graph) != 1))
display /n=pearl_explorer_1d /k=1 preview_trace vs preview_trace_x as "Preview"
s_preview_trace_graph = s_name
ModifyGraph /w=$s_preview_trace_graph wbRGB=(48640,56832,60160)
ModifyGraph /w=$s_preview_trace_graph rgb[0]=(0,0,0)
ModifyGraph /w=$s_preview_trace_graph grid=2
ModifyGraph /w=$s_preview_trace_graph mirror=1
ModifyGraph /w=$s_preview_trace_graph minor=1
ModifyGraph /w=$s_preview_trace_graph axThick=0.5
ModifyGraph /w=$s_preview_trace_graph gridRGB=(52224,52224,52224)
ModifyGraph /w=$s_preview_trace_graph gridHair=0
ModifyGraph /w=$s_preview_trace_graph tick=0
ModifyGraph /w=$s_preview_trace_graph btLen=4
endif
s_preview_trace_graph = display_preview_trace(preview_trace_x, preview_trace)
ModifyGraph /w=$s_preview_trace_graph wbRGB=(48640,56832,60160)
graphname = s_preview_trace_graph
else
return ""
@ -808,6 +799,39 @@ static function /s show_preview_graph(data, [xdata])
return graphname
end
static function /s display_preview_trace(xtrace, ytrace)
wave xtrace
wave ytrace
display /n=pearl_explorer_1d /k=1 ytrace vs xtrace as "Preview"
string graphname = s_name
ModifyGraph /w=$graphname rgb[0]=(0,0,0)
ModifyGraph /w=$graphname grid=2
ModifyGraph /w=$graphname mirror=1
ModifyGraph /w=$graphname minor=1
ModifyGraph /w=$graphname axThick=0.5
ModifyGraph /w=$graphname gridRGB=(52224,52224,52224)
ModifyGraph /w=$graphname gridHair=0
ModifyGraph /w=$graphname tick=0
ModifyGraph /w=$graphname btLen=4
// axis labels
string labels = note(ytrace)
string lab
lab = StringByKey("AxisLabelX", labels, "=", "\r")
if (!strlen(lab))
lab = "X"
endif
Label /w=$graphname bottom lab + " (\\U)"
lab = StringByKey("AxisLabelD", labels, "=", "\r")
if (!strlen(lab))
lab = "value"
endif
Label /w=$graphname left lab + " (\\U)"
return s_name
end
static function load_selected_files([options])
string options
@ -1426,6 +1450,9 @@ static function bp_dataset_folder(ba) : ButtonControl
string cmd
sprintf cmd, "setdatafolder root:%s", PossiblyQuoteName(dataset)
execute /q /z cmd
cmd = "setdatafolder :scan1"
execute /q /z cmd
sprintf cmd, "setdatafolder %s", GetDataFolder(1)
print cmd
endif
break

View File

@ -1,28 +0,0 @@
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
function export_otf()
// export OTF folders to text files
string objname
variable index= 0
setdatafolder root:
dfref parentfolder = getdatafolderdfr()
string filename
do
objname = GetindexedObjNameDFR(parentfolder, 4, index)
if (strlen(objname) > 0)
if (cmpstr(StringFromList(0, objname, "_"), "otf") == 0)
setdatafolder parentfolder
setdatafolder $objname
wave ringcurrent,photonenergy,current_ch1,current_ch2
filename = objname + ".txt"
Save/G/M="\r\n"/W/P=pearl_explorer_filepath photonenergy,current_ch1,current_ch2,ringcurrent as filename
endif
index += 1
else
break
endif
while(1)
end

File diff suppressed because it is too large Load Diff

View File

@ -55,10 +55,8 @@ menu "PEARL"
end
submenu "Services"
PearlMenuEnableFunc("pearl_elog") + "ELOG Experiments", /Q, pearl_elog("Experiments")
help = {"Create entries in ELOG experiments logbook"}
PearlMenuEnableFunc("pearl_elog") + "ELOG Calculations", /Q, pearl_elog("Calculations")
help = {"Create entries in ELOG calculations logbook"}
PearlMenuEnableFunc("pearl_elog") + "Open ELOG Panel", /Q, pearl_elog("")
help = {"Open an ELOG panel to send entries to an ELOG logbook"}
end
submenu "Sample Preparation"

View File

@ -1,73 +0,0 @@
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
#pragma IgorVersion = 6.1
#pragma ModuleName = PearlPreparation
#pragma version = 1.04
#include "pearl-area-display" // 2D and 3D data visualization
#include "pearl-area-profiles" // data processing for multi-dimensional datasets
#include "pearl-elog"
#if exists("pvOpen")
#include "pearl-epics" // EPICS access under Igor
#include "pearl-anneal" // automated sample annealing
#endif
// author: matthias.muntwiler@psi.ch
// Copyright (c) 2015 Paul Scherrer Institut
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
/// @file
/// @brief PEARL sample preparation package
///
/// this procedure defines the PEARL sample preparation package
/// the main purpose of this file is to load the necessary dependent procedures
/// (see the include statements at the top)
///
/// @pre
/// * on-line process control functionality requires the EPICS XOP to be loaded
///
/// @author matthias muntwiler, matthias.muntwiler@psi.ch
///
/// @copyright 2015 Paul Scherrer Institut @n
/// Licensed under the Apache License, Version 2.0 (the "License"); @n
/// you may not use this file except in compliance with the License. @n
/// You may obtain a copy of the License at
/// http://www.apache.org/licenses/LICENSE-2.0
/// @namespace PearlPreparation
/// @brief PEARL sample preparation package
///
/// PearlPreparation is declared in @ref pearl-preparation.ipf.
///
/// @defgroup PreparationPackage Sample preparation package
/// @brief PEARL sample preparation package
///
/// The purpose of a package is to load a bunch of dependent procedure files.
/// The sample preparation package loads the following files.
///
/// * pearl-area-import.ipf
/// * pearl-area-display.ipf
/// * pearl-area-profiles.ipf
/// * pearl-elog.ipf
/// * pearl-anneal.ipf
///
/// The following files are loaded if the EPICS.XOP is present:
///
/// * pearl-epics.ipf
///
/// initializes package data once when the procedure is first loaded
static function AfterCompiledHook()
dfref savefolder = GetDataFolderDFR()
return 0
end
function UnloadPearlPreparationPackage()
execute /p/q/z "DELETEINCLUDE \"pearl-preparation\""
execute /p/q/z "COMPILEPROCEDURES "
end

View File

@ -1,5 +1,5 @@
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
#pragma IgorVersion = 6.2
#pragma IgorVersion = 6.36
#pragma ModuleName = PearlPShellImport
#pragma version = 1.02
#include <HDF5 Browser>
@ -183,7 +183,9 @@ function /s psh5_load_complete(ANickName, APathName, AFileName, [load_data, load
for (ig = 0; ig < ng; ig += 1)
sg = StringFromList(ig, s_scanpaths, ";")
folder = CleanupName(ReplaceString("/", sg, ""), 0)
folder = ReplaceString("/", sg, "")
folder = ReplaceString(" ", folder, "")
folder = CleanupName(folder, 0)
setdatafolder fileDF
newdatafolder /s /o $folder
psh5_load_scan_complete(fileID, sg, load_data=load_data, load_attr=load_attr)
@ -219,14 +221,26 @@ end
/// @param load_attr 1 (default): load attributes; 0: do not load attributes
/// note: for correct scaling of the image, the attributes need to be loaded
///
/// @param pref_scans semicolon-separated list of preferred scans.
/// the items of the list are match strings for the Igor StringMatch function.
/// the first matching scan (i.e. top-level HDF5 group with a matching name) is loaded from the file.
/// if no match is found, the first scan is loaded.
///
/// @param pref_datasets semicolon-separated list of preferred datasets.
/// the items of the list are match strings for the Igor StringMatch function.
/// the first matching dataset is loaded from the file.
/// if no match is found, the first dataset listed in the file is loaded.
///
/// @return name of loaded preview wave.
///
function /s psh5_load_preview(ANickName, APathName, AFileName, [load_data, load_attr])
function /s psh5_load_preview(ANickName, APathName, AFileName, [load_data, load_attr, pref_scans, pref_datasets])
string ANickName
string APathName
string AFileName
variable load_data
variable load_attr
string pref_scans
string pref_datasets
if (ParamIsDefault(load_data))
load_data = 1
@ -234,7 +248,13 @@ function /s psh5_load_preview(ANickName, APathName, AFileName, [load_data, load_
if (ParamIsDefault(load_attr))
load_attr = 1
endif
if (ParamIsDefault(pref_scans))
pref_scans = "*scan1*;"
endif
if (ParamIsDefault(pref_datasets))
pref_datasets = ""
endif
dfref saveDF = GetDataFolderDFR()
setdatafolder root:
newdatafolder /o/s pearl_area
@ -253,12 +273,35 @@ function /s psh5_load_preview(ANickName, APathName, AFileName, [load_data, load_
if (v_flag == 0)
AFileName = s_path + s_filename
dfref fileDF = GetDataFolderDFR()
scanpaths = psh5_list_scans(fileID)
variable ng = ItemsInList(scanpaths)
variable ig
string sg
ig = 0
sg = StringFromList(ig, scanpaths, ";")
dataname = psh5_load_scan_preview(fileID, sg, set_scale=load_attr)
variable np = ItemsInList(pref_scans)
variable ip
string sp
variable found = 0
if (ng > 0)
for (ip = 0; ip < np; ip += 1)
for (ig = 0; ig < ng; ig += 1)
sg = StringFromList(ig, scanpaths)
sp = StringFromList(ip, pref_scans)
if (StringMatch(sg, sp))
found = 1
break
endif
endfor
if (found)
break
endif
endfor
if (!found)
ig = 0
endif
sg = StringFromList(ig, scanpaths)
dataname = psh5_load_scan_preview(fileID, sg, set_scale=load_attr, pref_datasets=pref_datasets)
endif
wave /z data = $dataname
string destpath = GetDataFolder(1, saveDF) + ANickName
@ -396,6 +439,9 @@ end
///
/// data is loaded into the current data folder.
///
/// this function does not scale the datasets.
/// call ps_scale_datasets() separately.
///
/// @param fileID ID of open HDF5 file from psh5_open_file().
///
/// @param scanpath path to the scan group in the HDF5 file, e.g. "/scan 1".
@ -517,27 +563,29 @@ function /s psh5_load_scan_meta(fileID, scanpath)
HDF5LoadData /O /Q /Z /A="Dimensions" /N=ScanDimensions /TYPE=1 fileID, scanpath
if (!v_flag)
wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
HDF5LoadData /O /Q /Z /A="Writables" /N=ScanWritables /TYPE=1 fileID, scanpath
if (!v_flag)
wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
endif
HDF5LoadData /O /Q /Z /A="Readables" /N=ScanReadables /TYPE=1 fileID, scanpath
if (!v_flag)
wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
endif
HDF5LoadData /O /Q /Z /A="Steps" /N=ScanSteps /TYPE=1 fileID, scanpath
if (!v_flag)
wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
endif
else
make /n=1 /o ScanDimensions
ScanDimensions = 0
wavenames = AddListItem("ScanDimensions", wavenames, ";", inf)
endif
HDF5LoadData /O /Q /Z /A="Readables" /N=ScanReadables /TYPE=1 fileID, scanpath
if (!v_flag)
wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
else
make /n=1 /o /t ScanReadables
ScanReadables[0] = "ScientaSpectrum"
wavenames = AddListItem("ScanReadables", wavenames, ";", inf)
endif
HDF5LoadData /O /Q /Z /A="Writables" /N=ScanWritables /TYPE=1 fileID, scanpath
if (!v_flag)
wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
endif
HDF5LoadData /O /Q /Z /A="Steps" /N=ScanSteps /TYPE=1 fileID, scanpath
if (!v_flag)
wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
endif
wavenames = ReplaceString(";;", wavenames, ";")
return wavenames
end
@ -572,6 +620,10 @@ function /s psh5_load_dataset(fileID, scanpath, datasetname, [set_scale])
string datasetname
variable set_scale
if (ParamIsDefault(set_scale))
set_scale = 1
endif
string datasetpath
datasetpath = scanpath + "/" + datasetname
datasetpath = ReplaceString("//", datasetpath, "/")
@ -585,7 +637,7 @@ function /s psh5_load_dataset(fileID, scanpath, datasetname, [set_scale])
endif
string dataname
if (di.ndims < 3)
if (di.ndims < 2)
HDF5LoadData /O /Q /Z fileID, datasetpath
dataname = StringFromList(0, S_waveNames)
else
@ -625,36 +677,70 @@ end
/// @arg 1 (default) set the wave scaling.
/// @arg 0 do not set the wave scaling.
///
/// @param pref_datasets semicolon-separated list of preferred datasets.
/// the items of the list are match strings for the Igor StringMatch function.
/// the first matching dataset is loaded from the file.
/// if no match is found, the first dataset listed in the file is loaded.
/// if empty, a hard-coded default preference list is used.
///
/// @return name of loaded wave if successful. empty string otherwise.
///
function /s psh5_load_scan_preview(fileID, scanpath, [set_scale])
function /s psh5_load_scan_preview(fileID, scanpath, [set_scale, pref_datasets])
variable fileID
string scanpath
variable set_scale
string pref_datasets
if (ParamIsDefault(set_scale))
set_scale = 1
endif
if (ParamIsDefault(pref_datasets) || (strlen(pref_datasets) == 0))
pref_datasets = "ScientaImage;ScientaSpectrum;ImageAngleDistribution;ImageEnergyDistribution;Counts;SampleCurrent"
endif
dfref saveDF = GetDataFolderDFR()
dfref dataDF = saveDF
string datasets = psh5_list_scan_datasets(fileID, scanpath)
string datasetname = ""
// todo: this should be generalized
if (strsearch(datasets, "ScientaImage", 0) >= 0)
datasetname = "ScientaImage"
elseif (strsearch(datasets, "ScientaSpectrum", 0) >= 0)
datasetname = "ScientaSpectrum"
elseif (strsearch(datasets, "ScientaEnergyDistribution", 0) >= 0)
datasetname = "ScientaEnergyDistribution"
elseif (strsearch(datasets, "Counts", 0) >= 0)
datasetname = "Counts"
elseif (strsearch(datasets, "SampleCurrent", 0) >= 0)
datasetname = "SampleCurrent"
variable index
variable nds = ItemsInList(datasets)
variable ids
string sds
variable np = ItemsInList(pref_datasets)
variable ip
string sp
variable found = 0
if (nds > 0)
for (ip = 0; ip < np; ip += 1)
for (ids = 0; ids < nds; ids += 1)
sds = StringFromList(ids, datasets)
index = ItemsInList(sds, "/") - 1
sds = StringFromList(index, sds, "/")
sp = StringFromList(ip, pref_datasets)
if (StringMatch(sds, sp))
found = 1
break
endif
endfor
if (found)
break
endif
endfor
if (!found)
ids = 0
sds = StringFromList(ids, datasets)
index = ItemsInList(sds, "/") - 1
sds = StringFromList(index, sds, "/")
endif
else
datasetname = StringFromList(0, datasets)
return ""
endif
string datasetpath
string datasetname = sds
datasetpath = scanpath + "/" + datasetname
datasetpath = ReplaceString("//", datasetpath, "/")
STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
InitHDF5DataInfo(di)
variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
@ -664,9 +750,13 @@ function /s psh5_load_scan_preview(fileID, scanpath, [set_scale])
endif
string dataname
if (di.ndims < 3)
if (di.ndims < 2)
HDF5LoadData /O /Q /Z fileID, datasetpath
dataname = StringFromList(0, S_waveNames)
wave /z data = $dataname
if (waveexists(data))
ps_set_dimlabels(data)
endif
else
variable dim2start = 0
variable dim2count = 1
@ -687,6 +777,21 @@ function /s psh5_load_scan_preview(fileID, scanpath, [set_scale])
wave /z data = $dataname
if (waveexists(data))
if (set_scale)
setdatafolder dataDF
string positioners
string positioner
string positionerpath
positioners = psh5_load_scan_meta(fileID, scanpath)
wave /t /z ScanWritables
if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
positioner = ScanWritables[0]
if (strlen(positioner) > 0)
positionerpath = scanpath + "/" + positioner
positionerpath = ReplaceString("//", positionerpath, "/")
HDF5LoadData /O /Q /Z fileID, positionerpath
endif
endif
setdatafolder dataDF
newdatafolder /o/s attr
killwaves /a/z
@ -775,6 +880,9 @@ end
///
/// @return name of loaded wave if successful. empty string otherwise.
///
/// @todo images are transposed in the first two dimensions.
/// this is useful for Scienta images but may not be appropriate for other sources.
///
function /s psh5_load_dataset_slabs(fileID, datapath, datasetname, [progress])
variable fileID
string datapath
@ -899,6 +1007,9 @@ end
///
/// @return name of loaded wave if successful. empty string otherwise.
///
/// @todo images are transposed in the first two dimensions.
/// this is useful for Scienta images but may not be appropriate for other data sources.
///
function /s psh5_load_dataset_slab(fileID, datapath, datasetname, dim2start, dim2count, dim3start, dim3count)
variable fileID
string datapath
@ -982,34 +1093,63 @@ end
///
/// dimension labels are required by scaling functions.
///
/// @param data data wave as loaded from PShell file
///
/// @return @arg 0 all labels set successfully.
/// @arg 1 unidentified data source.
/// @arg 2 wave does not contain data.
///
function ps_set_dimlabels(data)
wave data
string name = NameOfWave(data)
// intrinsic dimensions
strswitch(name)
case "ScientaImage":
setdimlabel 0, -1, $kEnergyDimLabel, data
setdimlabel 1, -1, $kAngleDimLabel, data
if (WaveDims(data) >= 3)
setdimlabel 2, -1, $kScanDimLabel, data
endif
break
case "ScientaSpectrum":
setdimlabel 0, -1, $kEnergyDimLabel, data
break
case "ImageAngleDistribution":
setdimlabel 0, -1, $kScanDimLabel, data
setdimlabel 1, -1, $kAngleDimLabel, data
break
case "ImageEnergyDistribution":
setdimlabel 0, -1, $kScanDimLabel, data
setdimlabel 1, -1, $kEnergyDimLabel, data
break
default:
setdimlabel 0, -1, $kScanDimLabel, data
endswitch
variable dummy
try
// intrinsic dimensions
strswitch(name)
case "ScientaImage":
setdimlabel 0, -1, $kEnergyDimLabel, data
setdimlabel 1, -1, $kAngleDimLabel, data
if (WaveDims(data) >= 3)
setdimlabel 2, -1, $kScanDimLabel, data
endif
AbortOnRTE
break
case "ImageAngleDistribution":
case "ScientaAngleDistribution":
if (WaveDims(data) >= 2)
setdimlabel 0, -1, $kScanDimLabel, data
setdimlabel 1, -1, $kAngleDimLabel, data
else
setdimlabel 0, -1, $kAngleDimLabel, data
endif
AbortOnRTE
break
case "ScientaSpectrum":
case "ImageEnergyDistribution":
case "ScientaEnergyDistribution":
if (WaveDims(data) >= 2)
setdimlabel 0, -1, $kScanDimLabel, data
setdimlabel 1, -1, $kEnergyDimLabel, data
else
setdimlabel 0, -1, $kEnergyDimLabel, data
endif
AbortOnRTE
break
default:
if (WaveDims(data) == 1)
setdimlabel 0, -1, $kScanDimLabel, data
AbortOnRTE
else
return 1
endif
endswitch
catch
dummy = GetRTError(1)
return 2
endtry
return 0
end
/// set the dimension scales of loaded PShell Scienta datasets according to attributes.
@ -1026,8 +1166,8 @@ function ps_scale_datasets()
dfref attrDF = :attr
make /n=3 /free lo, hi
make /n=3 /t /free un
ps_detect_scale(lo, hi, un)
make /n=3 /t /free ax, un
ps_detect_scale(ax, lo, hi, un)
wave /t /z /SDFR=dataDF ScanReadables
if (WaveExists(ScanReadables))
@ -1037,7 +1177,7 @@ function ps_scale_datasets()
for (isr = 0; isr < nsr; isr += 1)
wave /z /SDFR=dataDF wsr = $ScanReadables[isr]
if (WaveExists(wsr))
ps_scale_dataset_2(wsr, lo, hi, un)
ps_scale_dataset_2(wsr, ax, lo, hi, un)
endif
endfor
endif
@ -1064,9 +1204,9 @@ function ps_scale_dataset(data)
setdatafolder dataDF
make /n=3 /free lo, hi
make /n=3 /t /free un
ps_detect_scale(lo, hi, un)
ps_scale_dataset_2(data, lo, hi, un)
make /n=3 /t /free ax, un
ps_detect_scale(ax, lo, hi, un)
ps_scale_dataset_2(data, ax, lo, hi, un)
setdatafolder saveDF
end
@ -1082,7 +1222,7 @@ end
/// @arg `lo[%%energy]` analyser energy dimension.
/// @arg `lo[%%angle]` analyser angle dimension.
/// @arg `lo[%%scan]` scan dimension.
/// @arg `lo[%%data]` data dimension (units).
/// @arg `lo[%%data]` data dimension.
///
/// the function tries to read the following waves,
/// and may fall back to more or less reasonable default values if they are not found.
@ -1094,15 +1234,18 @@ end
/// @arg `ScanWritables`
/// @arg wave referenced by `ScanWritables[0]`
///
/// @param ax text wave to receive the axis labels.
///
/// @param lo wave to receive the lower limits.
///
/// @param hi wave to receive the upper limits.
///
/// @param un text wave to receive the unit labels.
///
/// @return the function results are written to the lo, hi, un waves.
/// @return the function results are written to the lo, hi, un, and ax waves.
///
function ps_detect_scale(lo, hi, un)
function ps_detect_scale(ax, lo, hi, un)
wave /t ax
wave lo
wave hi
wave /t un
@ -1110,28 +1253,32 @@ function ps_detect_scale(lo, hi, un)
dfref dataDF = GetDataFolderDFR()
dfref attrDF = :attr
redimension /n=4 lo, hi, un
setdimlabel 0, 0, $kEnergyDimLabel, lo, hi, un
setdimlabel 0, 1, $kAngleDimLabel, lo, hi, un
setdimlabel 0, 2, $kScanDimLabel, lo, hi, un
setdimlabel 0, 3, $kDataDimLabel, lo, hi, un
redimension /n=4 lo, hi, un, ax
setdimlabel 0, 0, $kEnergyDimLabel, lo, hi, un, ax
setdimlabel 0, 1, $kAngleDimLabel, lo, hi, un, ax
setdimlabel 0, 2, $kScanDimLabel, lo, hi, un, ax
setdimlabel 0, 3, $kDataDimLabel, lo, hi, un, ax
// default values
lo[%$kEnergyDimLabel] = 0
hi[%$kEnergyDimLabel] = 1
un[%$kEnergyDimLabel] = "eV"
ax[%$kEnergyDimLabel] = "Ekin"
lo[%$kAngleDimLabel] = -1
hi[%$kAngleDimLabel] = 1
un[%$kAngleDimLabel] = ""
un[%$kAngleDimLabel] = "arb."
un[%$kAngleDimLabel] = "slice"
lo[%$kScanDimLabel] = 0
hi[%$kScanDimLabel] = 1
un[%$kScanDimLabel] = ""
un[%$kScanDimLabel] = "arb."
ax[%$kScanDimLabel] = "scan"
lo[%$kDataDimLabel] = 0
hi[%$kDataDimLabel] = 0
un[%$kDataDimLabel] = "arb."
ax[%$kDataDimLabel] = "value"
wave /SDFR=attrDF /T /Z LensMode
wave /SDFR=attrDF /Z ChannelBegin = ScientaChannelBegin
@ -1146,14 +1293,17 @@ function ps_detect_scale(lo, hi, un)
lo[%$kAngleDimLabel] = -45/2
hi[%$kAngleDimLabel] = +45/2
un[%$kAngleDimLabel] = "deg"
ax[%$kAngleDimLabel] = "angle"
break
case "Angular60":
lo[%$kAngleDimLabel] = -60/2
hi[%$kAngleDimLabel] = +60/2
un[%$kAngleDimLabel] = "deg"
ax[%$kAngleDimLabel] = "angle"
break
case "Transmission":
un[%$kAngleDimLabel] = "arb."
ax[%$kAngleDimLabel] = "offset"
break
endswitch
endif
@ -1173,9 +1323,10 @@ function ps_detect_scale(lo, hi, un)
if (!WaveExists(scanner))
wave /z /SDFR=attrDF scanner = $ScanWritables[0]
endif
if (WaveExists(scanner))
if (WaveExists(scanner) && (numpnts(scanner) >= 1))
lo[%$kScanDimLabel] = scanner[0]
hi[%$kScanDimLabel] = scanner[numpnts(scanner)-1]
ax[%$kScanDimLabel] = NameOfWave(scanner)
endif
endif
end
@ -1197,14 +1348,23 @@ end
/// @param data data wave to be scaled.
/// dimension labels (index -1) must be set to match the limit waves.
///
/// @param ax axis labels.
/// the axis labels are written to the wave note in the format `AxisLabel%%s=%%s`
/// where `X`, `Y`, `Z`, `D` is substituted for the first place holder
/// and the label for the second one.
///
/// @param lo lower limits.
/// the lower limits are applied using the SetScale operation.
///
/// @param hi upper limits.
/// the upper limits are applied using the SetScale operation.
///
/// @param un unit labels.
/// the unit labels are applied using the SetScale operation.
///
function ps_scale_dataset_2(data, lo, hi, un)
function ps_scale_dataset_2(data, ax, lo, hi, un)
wave data
wave /t ax
wave lo
wave hi
wave /t un
@ -1213,19 +1373,24 @@ function ps_scale_dataset_2(data, lo, hi, un)
sdim = GetDimLabel(data, 0, -1)
if (strlen(sdim))
setscale /i x lo[%$sdim], hi[%$sdim], un[%$sdim], data
Note data, "AxisLabelX=" + ax[%$sdim]
endif
sdim = GetDimLabel(data, 1, -1)
if (strlen(sdim))
setscale /i y lo[%$sdim], hi[%$sdim], un[%$sdim], data
Note data, "AxisLabelY=" + ax[%$sdim]
endif
sdim = GetDimLabel(data, 2, -1)
if (strlen(sdim))
setscale /i z lo[%$sdim], hi[%$sdim], un[%$sdim], data
Note data, "AxisLabelZ=" + ax[%$sdim]
endif
setscale d 0, 0, un[%$kDataDimLabel], data
Note data, "AxisLabelD=" + ax[%$kDataDimLabel]
Note data, "Dataset=" + NameOfWave(data)
end
/// load and reduce the ScientaImage dataset of the first scan of a PShell data file.
@ -1301,7 +1466,9 @@ function /s psh5_load_reduced(ANickName, APathName, AFileName, reduction_func, r
string folder
sg = StringFromList(ig, s_scanpaths)
folder = CleanupName(ReplaceString("/", sg, ""), 0)
folder = ReplaceString("/", sg, "")
folder = ReplaceString(" ", folder, "")
folder = CleanupName(folder, 0)
setdatafolder fileDF
newdatafolder /s /o $folder
dfref dataDF = GetDataFolderDFR()