7 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
fcd6a56e4e new feature: preview and import of pshell data files 2016-04-09 13:07:37 +02:00
25 changed files with 3553 additions and 3196 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* *.ipfT*
doc/html/* doc/html/*
doc/latex/* 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.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. - 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 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>. 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 read and respect the respective license agreements.
Please share your extensions of the code with the original author.
Author Author
------ ------
@ -32,3 +34,12 @@ Copyright
Copyright 2009-2016 by [Paul Scherrer Institut](http://www.psi.ch) 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 # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = PROJECT_NUMBER = $(REVISION)
# Using the PROJECT_BRIEF tag one can provide an optional one line description # 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 # 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. # to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES. # 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 # 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 # generated LaTeX document. The footer should contain everything after the last

View File

@ -11,7 +11,7 @@ DOX=doxygen
DOXOPTS= DOXOPTS=
LATEX_DIR=latex 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 export REVISION
all: docs all: docs
@ -19,7 +19,7 @@ all: docs
docs: doxygen pdf docs: doxygen pdf
doxygen: doxygen:
$(DOX) $(DOXOPTS) Doxyfile $(DOX) $(DOXOPTS) config.dox
pdf: doxygen pdf: doxygen
-$(MAKE) -C $(LATEX_DIR) -$(MAKE) -C $(LATEX_DIR)
@ -27,3 +27,4 @@ pdf: doxygen
clean: clean:
-rm latex/* -rm latex/*
-rm html/* -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. Please read and respect the respective license agreements.
\author Matthias Muntwiler, <mailto:matthias.muntwiler@psi.ch> \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 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) \copyright Licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
*/ */

97
mm/mm-physconst.ipf Normal file
View File

@ -0,0 +1,97 @@
#pragma rtGlobals=1 // Use modern global access method.
#pragma version = 1.05
// physical constants
// original version: 03-05-23 by mm
// $Id$
// source: CODATA 2002 [Rev. Mod. Phys. 77, 1 (2005)]
// universal constants
constant kSpeedOfLight = 2.99792458e8 // m/s
constant kMagnField = 1.25663706144e-6 // V s / A / m
constant kElField = 8.854187817620e-12 // A s / V / m
constant kGravitation = 6.6742e-11 // m^3 / kg / s^2
constant kHBar = 6.58211915e-16 // eV s
constant kPlanckBar = 6.58211915e-16 // eV s
constant kPlanck = 4.13566743e-15 // eV s
constant kHBarC = 197.326968 // MeV fm
constant kHC = 1239.84190605 // eV nm
constant kHCicm = 1239.84190605e-7 // eV cm^-1
constant kPlanckBarSI = 1.05457168e-34 // J s
constant kPlanckSI = 6.6260693e-34 // J s
// electromagnetic constants
constant kElCharge = 1.60217653e-19 // A s
constant kMagnFlux = 2.06783372e-15 // Wb
constant kConductance = 7.748091733e-5 // S
constant kBohrMagneton = 5.788381804e-5 // eV T^-1
constant kBohrMagnetonSI = 9.27400949e-24 // J T^-1 = A m^2
constant kNuclearMagneton = 3.152451259e-8 // eV T^-1
constant kNuclearMagnetonSI = 5.05078343e-27 // J T^-1
// atomic and nuclear constants
constant kFineStruct = 7.297352568e-3
constant kInvFineStruct = 137.03599911
constant kRydberg = 10973731.568525 // m^-1
constant kRydbergEnergy = 13.6056923 // eV
constant kBohrRadius = 0.5291772108e-10 // m
constant kHartreeEnergy = 27.2113845 // eV
constant kHartreeEnergySI = 4.35974417 // J
constant kElectronMass = 510.998918e3 // eV c^-2
constant kMuonMass = 105.6583692e6 // eV c^-2
constant kProtonMass = 938.272029e6 // eV c^-2
constant kNeutronMass = 939.565360e6 // eV c^-2
constant kElectronMassSI = 9.1093826e-31 // kg
constant kProtonMassSI = 1.67262171e-27 // kg
constant kComptonWavelength = 2.426310238e-12 // m
constant kElectronRadius = 2.817940325e-15 // m
constant kThomsonCrossSection = 0.665245873e-28 // m^2
constant kElectronGFactor = -2.0023193043718
// physico-chemical constants
constant kAvogadro = 6.0221415e23 // 1 / mol
constant kAtomicMassUnit = 931.494043e6 // eV / c^2
constant kAtomicMassUnitSI = 1.66053886e-27 // kg
constant kMolarGasSI = 8.314472 // J / K / mol
constant kBoltzmann = 8.617343e-5 // eV / K
constant kBoltzmannSI = 1.3806505e-23 // J /K
constant kWien = 2.8977685e-3 // m K
constant kStefanBoltzmann = 5.670400e-8 // W m^-2 K^-4
constant kJoulesPerEV = 1.60217653e-19 // J / eV
constant kEVPerHartree = 27.2113845 // eV / Eh
// custom constants
constant kFreeElectronDispersion = 3.79736 // eV Angstrom^2
// = h_bar^2 * c^2 / (2 * m_e)
// for E = kFreeElectronDispersion * k^2
threadsafe function FreeElectronWavelength(ekin, [v0, meff])
// Wavelength of a quasi-free electron in meters
variable ekin // kinetic energy of the electron in eV
variable v0 // inner potential (where applicable), default = 0
variable meff // effective mass relative to free electron, default = 1
if (ParamIsDefault(v0))
v0 = 0
endif
if (ParamIsDefault(meff))
meff = 1
endif
return khc * 1e-9 / sqrt(2 * kElectronMass * meff * (ekin + v0))
end

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 "pearl-polar-coordinates"
#include <New Polar Graphs> #include <New Polar Graphs>
// $Id$ // copyright (c) 2013-16 Paul Scherrer Institut
//
// copyright (c) 2013-15 Paul Scherrer Institut
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// http:///www.apache.org/licenses/LICENSE-2.0 // http:///www.apache.org/licenses/LICENSE-2.0
//
// Please acknowledge the use of this code.
/// @file /// @file
/// @brief processing and holographic mapping of angle scanned XPD data. /// @brief processing and holographic mapping of angle scanned XPD data.
@ -64,7 +64,7 @@
/// ///
/// @author matthias muntwiler, matthias.muntwiler@psi.ch /// @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 /// 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 not use this file except in compliance with the License. @n
/// You may obtain a copy of the License at /// You may obtain a copy of the License at
@ -79,15 +79,38 @@
/// ///
/// PearlAnglescanProcess is declared in @ref pearl-anglescan-process.ipf. /// PearlAnglescanProcess is declared in @ref pearl-anglescan-process.ipf.
/// @warning experimental
function strip_remove_frames(strip, yscale, ylo, yhi)
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
if (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
variable qlo
variable qhi
wave theta
wave tilt
wave phi
if (qlo > qhi)
return -1 return -1
endif endif
@ -95,8 +118,8 @@ function strip_remove_frames(strip, yscale, ylo, yhi)
variable snx = dimsize(strip, 0) variable snx = dimsize(strip, 0)
variable sny = dimsize(strip, 1) variable sny = dimsize(strip, 1)
variable sq1lo = 0 variable sq1lo = 0
variable sq1hi = max(round((ylo - dimoffset(strip, 1)) / dimdelta(strip, 1)), 0) variable sq1hi = max(qlo-1, 0)
variable sq2lo = min(round((ylo - dimoffset(strip, 1)) / dimdelta(strip, 1)), sny - 1) variable sq2lo = min(qhi+1, sny - 1)
variable sq2hi = dimsize(strip, 1) - 1 variable sq2hi = dimsize(strip, 1) - 1
// dest indices // dest indices
@ -111,10 +134,24 @@ function strip_remove_frames(strip, yscale, ylo, yhi)
duplicate /free strip, strip_copy duplicate /free strip, strip_copy
redimension /n=(dnx,dny) strip redimension /n=(dnx,dny) strip
strip[][dq1lo,dq1hi] = strip_copy[p][q + q1ofs] strip[][dq1lo,dq1hi] = strip_copy[p][q + q1ofs]
strip[][dq2lo,dq2hi] = strip_copy[p][q + q2ofs] 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 return 0
end end
@ -144,6 +181,7 @@ end
/// @return if check waves are enabled, the following waves are created (overwritten if existing): /// @return if check waves are enabled, the following waves are created (overwritten if existing):
/// @arg check_dist average X distribution /// @arg check_dist average X distribution
/// @arg check_smoo smoothed distribution used to normalize the strip /// @arg check_smoo smoothed distribution used to normalize the strip
///
function normalize_strip_x(strip, [smooth_method, smooth_factor, check]) function normalize_strip_x(strip, [smooth_method, smooth_factor, check])
wave strip wave strip
variable smooth_method variable smooth_method
@ -233,6 +271,7 @@ end
/// @return if check waves are enabled, the following waves are created (overwritten if existing): /// @return if check waves are enabled, the following waves are created (overwritten if existing):
/// @arg check_dist average theta distribution /// @arg check_dist average theta distribution
/// @arg check_smoo smoothed distribution used to normalize the strip /// @arg check_smoo smoothed distribution used to normalize the strip
///
function normalize_strip_theta(strip, theta, [theta_offset, smooth_method, smooth_factor, check]) function normalize_strip_theta(strip, theta, [theta_offset, smooth_method, smooth_factor, check])
wave strip wave strip
wave theta wave theta
@ -300,6 +339,70 @@ function normalize_strip_theta(strip, theta, [theta_offset, smooth_method, smoot
endif endif
end 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. /// crop a strip at the sides.
/// ///
/// the strip is cropped in place, data outside the region of interest is lost. /// 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 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 0 linear
/// @arg 1 stereographic (default) /// @arg 1 stereographic (default)
/// @arg 2 azimuthal /// @arg 2 azimuthal
/// ///
/// projections 0-2 have no effect on the azimuthal coordinate
///
/// @param zeroAngle zeroAngleWhere parameter of polar graphs /// @param zeroAngle zeroAngleWhere parameter of polar graphs
/// @arg 0 (default) zero is at the 3 o'clock position /// @arg 0 (default) zero is at the 3 o'clock position
/// @arg 180 zero is at the 9 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. /// 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. /// open a new graph window with a 2D image.
/// ///
/// this is essentially <code>display; appendimage</code>. /// this is essentially <code>display; appendimage</code>.
@ -72,7 +91,7 @@ function /s ad_display(image)
string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "") string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
string graphtitle = dfname + " View" 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 svar graphname = view_graphname
display /k=1/n=$graphname as graphtitle display /k=1/n=$graphname as graphtitle
graphname = s_name graphname = s_name
@ -104,7 +123,7 @@ function /s ad_display_histogram(image)
string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "") string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
string graphtitle = dfname + " Histogram" 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 svar graphname = hist_graphname
display /k=1/n=$graphname as graphtitle display /k=1/n=$graphname as graphtitle
graphname = s_name graphname = s_name
@ -171,16 +190,15 @@ function /s ad_display_profiles(image, [filter])
duplicate /o image, $viewname /wave=view 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 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=(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
string /g view_filter_options string /g view_filter_options
view_filter = filter view_filter = filter
view_filter_options = "" view_filter_options = ""
variable /g view_filter_smoothing_x = 1 variable /g view_filter_smoothing_x = 1
variable /g view_filter_smoothing_y = 1 variable /g view_filter_smoothing_y = 1
string dfname = GetDataFolder(0, imagedf) string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
string graphtitle = dfname + ":" + NameOfWave(image) + " Profiles" string graphtitle = dfname + NameOfWave(image) + " Profiles"
string /g prof_graphname = CleanupName("prof_" + dfname, 0) string /g prof_graphname = graphname_from_dfref(imagedf, "prof_")
svar graphname = prof_graphname svar graphname = prof_graphname
variable /g graph_avg // average value in ROI (ROI is defined by the crosshairs A and B) 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 variable /g graph_min // minimum value in ROI
@ -193,16 +211,13 @@ function /s ad_display_profiles(image, [filter])
graphname = s_name graphname = s_name
AppendToGraph /w=$graphname /L=xprofiles xprofiles[*][0],xprofiles[*][1],xprofiles[*][2] 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 /VERT/B=yprofiles yprofiles[*][0],yprofiles[*][1],yprofiles[*][2]
AppendToGraph /w=$graphname /R=hist/B=yprofiles hist
AppendImage /w=$graphname view AppendImage /w=$graphname view
string imgname = StringFromList(0, ImageNameList(graphname, ";")) string imgname = StringFromList(0, ImageNameList(graphname, ";"))
ModifyImage /w=$graphname $imgname ctab= {*,*,BlueGreenOrange,0} 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)=(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#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(xprofiles#2)=(0,9472,39168),rgb(yprofiles#2)=(0,9472,39168)
ModifyGraph /w=$graphname rgb(hist)=(43520,43520,43520) ModifyGraph /w=$graphname mirror(xprofiles)=2,mirror(bottom)=3,mirror(yprofiles)=2,mirror(left)=3
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 nticks=3 ModifyGraph /w=$graphname nticks=3
ModifyGraph /w=$graphname minor=1 ModifyGraph /w=$graphname minor=1
ModifyGraph /w=$graphname axThick=0.5 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 btLen=4
ModifyGraph /w=$graphname freePos(xprofiles)=0 ModifyGraph /w=$graphname freePos(xprofiles)=0
ModifyGraph /w=$graphname freePos(yprofiles)=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(xprofiles)={0.64,1}
ModifyGraph /w=$graphname axisEnab(hist)={0.64,1}
ModifyGraph /w=$graphname axisEnab(bottom)={0,0.6} ModifyGraph /w=$graphname axisEnab(bottom)={0,0.6}
ModifyGraph /w=$graphname axisEnab(yprofiles)={0.64,1} ModifyGraph /w=$graphname axisEnab(yprofiles)={0.64,1}
ModifyGraph /w=$graphname axisEnab(left)={0,0.6} ModifyGraph /w=$graphname axisEnab(left)={0,0.6}
ModifyGraph /w=$graphname zero(left)=8 ModifyGraph /w=$graphname zero(left)=8
ModifyGraph /w=$graphname margin(left)=40,margin(bottom)=30,margin(top)=20,margin(right)=40 ModifyGraph /w=$graphname margin(left)=40,margin(bottom)=30,margin(top)=20,margin(right)=40
ModifyGraph /w=$graphname gfSize=10 ModifyGraph /w=$graphname gfSize=10
Label /w=$graphname xprofiles "value (\\U)"
Label /w=$graphname bottom "X (\\U)" // axis labels
Label /w=$graphname yprofiles "value (\\U)" string labels = note(image)
Label /w=$graphname left "Y (\\U)" string lab
Label /w=$graphname hist "\\Epixels" lab = StringByKey("AxisLabelX", labels, "=", "\r")
SetAxis /w=$graphname /A /E=1 hist 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 // legend
if (show_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 "\\s(xprofiles#2)\tROI average"
AppendText /w=$graphname "min\t\\{" + s_viewdf + "graph_min}" AppendText /w=$graphname "min\t\\{" + s_viewdf + "graph_min}"
AppendText /w=$graphname "max\t\\{" + s_viewdf + "graph_max}" 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 "sum\t\\{" + s_viewdf + "graph_sum}"
AppendText /w=$graphname "avg\t\\{" + s_viewdf + "graph_avg}"
AppendText /w=$graphname "sdev\t\\{" + s_viewdf + "graph_sdev}" AppendText /w=$graphname "sdev\t\\{" + s_viewdf + "graph_sdev}"
else 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=text0 /F=0 /B=1 /X=1.00 /Y=1.00
TextBox /w=$graphname /C/N=text_avg/F=0/B=1/X=1.00/Y=6.00 "avg \\{" + s_viewdf + "graph_avg}" lab = StringByKey("Dataset", labels, "=", "\r")
TextBox /w=$graphname /C/N=text_sdev/F=0/B=1/X=1.00/Y=11.00 "sdev \\{" + s_viewdf + "graph_sdev}" 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 endif
// interactive elements // interactive elements
@ -991,7 +1023,7 @@ function /s ad_display_brick(data)
setdatafolder viewdf setdatafolder viewdf
string dfname = ReplaceString("root:", s_datadf, "") string dfname = ReplaceString("root:", s_datadf, "")
string graphtitle = dfname + " Gizmo" 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 svar graphname = gizmo_graphname
if ((strlen(graphname) > 0) && (wintype(graphname) == 13)) if ((strlen(graphname) > 0) && (wintype(graphname) == 13))
@ -1116,12 +1148,31 @@ function ad_brick_slicer(data)
variable /g y_autoinc = 0 variable /g y_autoinc = 0
variable /g z_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 // this section copied from slicer panel
NewPanel /k=1 /W=(500,600,890,940) /N=SlicerPanel as "Brick Slicer" NewPanel /k=1 /W=(500,600,890,940) /N=SlicerPanel as "Brick Slicer"
string /g slicer_panelname = S_name string /g slicer_panelname = S_name
string panel = 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,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 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" 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,pos={336,48},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616"
Button b_xslice_stop win=$panel,help={"stop animation"} 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,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 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" 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,pos={336,148},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616"
Button b_yslice_stop win=$panel,help={"stop animation"} 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,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 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" 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,pos={336,248},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616"
Button b_zslice_stop win=$panel,help={"stop animation"} 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,pos={240,316},size={120,16},title="slab thickness"
//SetVariable setvar0 win=$panel,limits={1,inf,1},value=slab_thickness //SetVariable setvar0 win=$panel,limits={1,inf,1},value=slab_thickness

View File

@ -3,23 +3,35 @@
#pragma ModuleName = PearlAreaImport #pragma ModuleName = PearlAreaImport
#pragma version = 1.06 #pragma version = 1.06
#include <HDF5 Browser> #include <HDF5 Browser>
#include "pearl-gui-tools", version >= 1.01 #include "pearl-gui-tools"
// HDF5 file import from EPICS area detectors // copyright (c) 2013-16 Paul Scherrer Institut
// such as CCD cameras, 2D electron analysers //
// 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
// restriction: as of version 6.3, Igor can open datasets of up to rank 4. /// @file
// i.e. the extra dimension Y of the file plugin cannot be used. /// @brief HDF5 file import from EPICS area detectors
// the extra dimensions N and X are supported. /// @ingroup ArpesPackage
///
///
/// HDF5 file import from EPICS area detectors
/// such as CCD cameras, 2D electron analysers
///
/// as of Igor 6.3, Igor can open datasets of up to rank 4.
/// i.e. the extra dimension Y of the file plugin cannot be used.
/// the extra dimensions N and X are supported.
// created: matthias.muntwiler@psi.ch, 2013-05-31 /// @namespace PearlAreaImport
// Copyright (c) 2013 Paul Scherrer Institut /// @brief HDF5 file import from EPICS area detectors
// $Id$ ///
/// PearlAreaImport is declared in @ref pearl-area-import.ipf.
//------------------------------------------------------------------------------ /// callback function for drag&drop of HDF5 files into Igor.
///
static function BeforeFileOpenHook(refNum,fileName,path,type,creator,kind) static function BeforeFileOpenHook(refNum,fileName,path,type,creator,kind)
// allows drag&drop of data files into an open igor window
// this works only with igor 5.02 or later
variable refNum, kind variable refNum, kind
string fileName, path, type, creator string fileName, path, type, creator
@ -57,20 +69,37 @@ static function BeforeFileOpenHook(refNum,fileName,path,type,creator,kind)
return handledOpen // 1 tells Igor not to open the file return handledOpen // 1 tells Igor not to open the file
End End
/// generate the name of a data folder based on a file name.
///
/// if the file name follows the naming convention source-date-index.extension,
/// the function tries to generate the nick name as source_date_index.
/// otherwise it's just a cleaned up version of the file name.
///
/// date must be in yyyymmdd or yymmdd format and is clipped to the short yymmdd format.
/// index should be a running numeric index of up to 6 digits, or the time encoded as hhmmss.
/// however, in the current version index can be any string that can be a valid Igor folder name.
///
/// @param filename file name, including extension. can also include a folder path (which is ignored).
/// the extension is currently ignored, but may be used to select the parent folder in a later version.
/// @param ignoredate if non-zero, the nick name will not include the date part.
/// defaults to zero.
/// @param sourcename nick name of the data source.
/// by default, the function tries to detect the source from the file name.
/// this option can be used to override auto-detection.
/// the automatic source names are:
/// sci (scienta by area detector),
/// psh (pshell),
/// sl (optics slit camera by area detector),
/// es (end station camera by area detector),
/// xy (unidentified).
/// @param unique if non-zero, the resulting name is made a unique data folder name in the current data folder
/// defaults to zero.
///
function /s ad_suggest_foldername(filename, [ignoredate,sourcename,unique]) function /s ad_suggest_foldername(filename, [ignoredate,sourcename,unique])
// suggests the name of a data folder based on a file name string filename
// if the file name follows the naming convention source-date-index.extension, variable ignoredate
// the function tries to generate the nick name as source_date_index. string sourcename
// otherwise it's just a cleaned up version of the file name. variable unique
string filename // file name, including extension. can also include a folder path (which is ignored)
// the extension is currently ignored, but may be used later to select the parent folder
variable ignoredate // if non-zero, the nick name will not include the date part
// defaults to zero
string sourcename // nick name of the data source
// the function tries to detect the source from the file name
// this option can be used to override auto-detection
variable unique // if non-zero, the resulting name is made a unique data folder name in the current data folder
// defaults to zero
if (ParamIsDefault(ignoredate)) if (ParamIsDefault(ignoredate))
ignoredate = 0 ignoredate = 0
@ -86,6 +115,8 @@ function /s ad_suggest_foldername(filename, [ignoredate,sourcename,unique])
string autosource string autosource
if (strsearch(basename, "scienta", 0, 2) >= 0) if (strsearch(basename, "scienta", 0, 2) >= 0)
autosource = "sci" autosource = "sci"
elseif (strsearch(basename, "pshell", 0, 2) >= 0)
autosource = "psh"
elseif (strsearch(basename, "OP-SL", 0, 2) >= 0) elseif (strsearch(basename, "OP-SL", 0, 2) >= 0)
autosource = "sl" autosource = "sl"
elseif (strsearch(basename, "ES-PS", 0, 2) >= 0) elseif (strsearch(basename, "ES-PS", 0, 2) >= 0)
@ -99,8 +130,12 @@ function /s ad_suggest_foldername(filename, [ignoredate,sourcename,unique])
variable nparts = ItemsInList(basename, "-") variable nparts = ItemsInList(basename, "-")
if (nparts >= 3) if (nparts >= 3)
string datepart = StringFromList(nparts - 2, basename, "-") string datepart = StringFromList(1, basename, "-")
string indexpart = StringFromList(nparts - 1, basename, "-") variable l_datepart = strlen(datepart)
if (l_datepart == 8)
datepart = datepart[l_datepart-6, l_datepart-1]
endif
string indexpart = StringFromList(2, basename, "-")
if (ignoredate) if (ignoredate)
sprintf nickname, "%s_%s", sourcename, indexpart sprintf nickname, "%s_%s", sourcename, indexpart
else else
@ -117,10 +152,12 @@ function /s ad_suggest_foldername(filename, [ignoredate,sourcename,unique])
return nickname return nickname
end end
/// load area detector data files selected in a file dialog window
///
/// @param APathName Igor symbolic path name.
/// if empty, Igor will choose a folder on its own
function ad_load_dialog(APathName) function ad_load_dialog(APathName)
// loads data files selected in a file dialog window string APathName
string APathName // igor symbolic path name
// if empty, Igor will choose a folder on its own
variable refNum variable refNum
string message = "Select data files" string message = "Select data files"
@ -148,17 +185,23 @@ function ad_load_dialog(APathName)
setdatafolder saveDF setdatafolder saveDF
end end
//------------------------------------------------------------------------------ /// import everything from a HDF5 file created by the Area Detector software.
///
/// if the data is from the electron analyser driver and some special attributes are included,
/// the function will set the scales of the image dimensions.
///
/// @param ANickName destination folder name (top level under root)
/// @param APathName igor symbolic path name. can be empty if the path is specified in FileName or a dialog box should be displayed
/// @param AFileName if empty a dialog box shows up
/// @param load_data 1 (default): load data; 0: do not load data
/// @param load_attr 1 (default): load attributes; 0: do not load attributes
/// for proper wave scaling, the attributes must be loaded
function /s adh5_load_complete(ANickName, APathName, AFileName, [load_data, load_attr]) function /s adh5_load_complete(ANickName, APathName, AFileName, [load_data, load_attr])
// this function loads everything from a HDF5 file created by the Area Detector software. string ANickName
// if the data is from the electron analyser driver and some special attributes are included, string APathName
// the function will set the scales of the image dimensions. string AFileName
string ANickName // destination folder name (top level under root) variable load_data
string APathName // igor symbolic path name. can be empty if the path is specified in FileName or a dialog box should be displayed variable load_attr
string AFileName // if empty a dialog box shows up
variable load_data // 1 (default): load data; 0: do not load data
variable load_attr // 1 (default): load attributes; 0: do not load attributes
// for proper wave scaling, the attributes must be loaded
if (ParamIsDefault(load_data)) if (ParamIsDefault(load_data))
load_data = 1 load_data = 1
@ -222,30 +265,43 @@ function /s adh5_load_complete(ANickName, APathName, AFileName, [load_data, load
return AFileName return AFileName
end end
/// load and reduce a dataset from a HDF5 file created by the Area Detector software.
///
/// the resulting dataset is reduced in one image dimension by a user-defined reduction function,
/// e.g. by region-of-interest integration, curve fitting, etc.
///
/// the function loads the dataset image by image using the hyperslab option
/// and applies a custom reduction function to each image.
/// the results from the reduction function are composed into one result wave.
/// the raw data are discarded.
///
/// if the data is from the electron analyser driver and some special attributes are included,
/// the function will set the scales of the image dimensions.
///
/// @param ANickName destination folder name (top level under root)
/// @param APathName igor symbolic path name. can be empty if the path is specified in FileName or a dialog box should be displayed
/// @param AFileName if empty a dialog box shows up
///
/// @param reduction_func custom reduction function
/// (any user-defined function which has the same parameters as adh5_default_reduction())
/// @param reduction_param parameter string for the reduction function
///
/// @param load_data 1 (default): load data; 0: do not load data
/// @param load_attr 1 (default): load attributes; 0: do not load attributes
/// for proper wave scaling, the attributes must be loaded
/// @param progress 1 (default): show progress window; 0: do not show progress window
///
function /s adh5_load_reduced(ANickName, APathName, AFileName, reduction_func, reduction_param, [load_data, load_attr, progress]) function /s adh5_load_reduced(ANickName, APathName, AFileName, reduction_func, reduction_param, [load_data, load_attr, progress])
// this function loads a reduced dataset from a HDF5 file created by the Area Detector software. string ANickName
// the resulting dataset is reduced in one image dimension by a user-defined reduction function, string APathName
// e.g. by region-of-interest integration, curve fitting, etc. string AFileName
// the function loads the dataset image by image using the hyperslab option funcref adh5_default_reduction reduction_func
// and applies a custom reduction function to each image. string reduction_param
// the results from the reduction function are composed into one result wave.
// the raw data are discarded.
// if the data is from the electron analyser driver and some special attributes are included, variable load_data
// the function will set the scales of the image dimensions. variable load_attr
string ANickName // destination folder name (top level under root) variable progress
string APathName // igor symbolic path name. can be empty if the path is specified in FileName or a dialog box should be displayed
string AFileName // if empty a dialog box shows up
funcref adh5_default_reduction reduction_func // custom reduction function
// (any user-defined function which has the same parameters as adh5_default_reduction())
string reduction_param // parameter string for the reduction function
variable load_data // 1 (default): load data; 0: do not load data
variable load_attr // 1 (default): load attributes; 0: do not load attributes
// for proper wave scaling, the attributes must be loaded
variable progress // 1 (default): show progress window; 0: do not show progress window
if (ParamIsDefault(load_data)) if (ParamIsDefault(load_data))
load_data = 1 load_data = 1
@ -306,18 +362,26 @@ function /s adh5_load_reduced(ANickName, APathName, AFileName, reduction_func, r
return AFileName return AFileName
end end
/// load a single image from a HDF5 file created by the Area Detector software.
///
/// the data wave is loaded into the current data folder.
/// attributes are loaded into the attr subfolder. existing waves in attr are deleted.
///
/// @warning EXPERIMENTAL
/// this function uses the root:pearl_area:preview data folder. existing data there may be deleted!
///
/// @param ANickName destination wave name. the wave is created in the current data folder.
/// @param APathName igor symbolic path name. can be empty if the path is specified in FileName or a dialog box should be displayed
/// @param AFileName if empty a dialog box shows up
/// @param load_data 1 (default): load data; 0: do not load data
/// @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
function /s adh5_load_preview(ANickName, APathName, AFileName, [load_data, load_attr]) function /s adh5_load_preview(ANickName, APathName, AFileName, [load_data, load_attr])
// this function loads one image from a HDF5 file created by the Area Detector software. string ANickName
// the data wave is loaded into the current data folder. string APathName
// attributes are loaded into the attr subfolder. existing waves in attr are deleted. string AFileName
// EXPERIMENTAL variable load_data
// this function uses the root:pearl_area:preview data folder. existing data there may be deleted! variable load_attr
string ANickName // destination wave name. the wave is created in the current data folder.
string APathName // igor symbolic path name. can be empty if the path is specified in FileName or a dialog box should be displayed
string AFileName // if empty a dialog box shows up
variable load_data // 1 (default): load data; 0: do not load data
variable load_attr // 1 (default): load attributes; 0: do not load attributes
// note: for correct scaling of the image, the attributes need to be loaded
if (ParamIsDefault(load_data)) if (ParamIsDefault(load_data))
load_data = 1 load_data = 1
@ -412,13 +476,19 @@ function /s adh5_load_preview(ANickName, APathName, AFileName, [load_data, load_
return AFileName return AFileName
end end
/// load descriptive info from a HDF5 file created by the Area Detector software.
///
/// the information returned is the array size and active scans
///
/// @attention EXPERIMENTAL
/// this function should be merged with adh5_load_preview
///
/// @param APathName igor symbolic path name. can be empty if the path is specified in FileName or a dialog box should be displayed
/// @param AFileName if empty a dialog box shows up
///
function /s adh5_load_info(APathName, AFileName) function /s adh5_load_info(APathName, AFileName)
// this function loads descriptive info from a HDF5 file created by the Area Detector software. string APathName
// the information returned is the array size and active scans string AFileName
// EXPERIMENTAL
// this function should be merged with adh5_load_preview
string APathName // igor symbolic path name. can be empty if the path is specified in FileName or a dialog box should be displayed
string AFileName // if empty a dialog box shows up
dfref saveDF = GetDataFolderDFR() dfref saveDF = GetDataFolderDFR()
@ -492,12 +562,17 @@ function /s adh5_load_info(APathName, AFileName)
return s_info return s_info
end end
/// load the detector dataset from the open HDF5 file.
///
/// the function loads the whole dataset at once
/// and redimensions it so that the image dimensions are X and Y
///
/// @param fileID ID of open HDF5 file from HDF5OpenFile
/// @param detectorpath path to detector group in the HDF5 file
///
function adh5_load_detector(fileID, detectorpath) function adh5_load_detector(fileID, detectorpath)
// loads the detector dataset from the open HDF5 file variable fileID
// the function loads the whole dataset at once string detectorpath
// and redimensions it so that the image dimensions are X and Y
variable fileID // ID of open HDF5 file from HDF5OpenFile
string detectorpath // path to detector group in the HDF5 file
// avoid compilation error if HDF5 XOP has not been loaded // avoid compilation error if HDF5 XOP has not been loaded
#if Exists("HDF5LoadData") #if Exists("HDF5LoadData")
@ -526,19 +601,22 @@ function adh5_load_detector(fileID, detectorpath)
#endif #endif
end end
/// redimension a multi-dimensional area detector array loaded from HDF5.
///
/// so that the image dimensions are X and Y
/// singleton dimensions are removed (most common cases only)
///
/// in the redimensioned array, the original dimension type is noted in the dimension label:
/// AD_Dim0 = first image dimension
/// AD_Dim1 = second image dimension
/// AD_DimN = frame sequence
/// AD_DimX = extra dimension X
/// AD_DimY = extra dimension Y (cannot be loaded in Igor)
///
/// @param data area detector data loaded from HDF5 to be redimensioned
///
function adh5_redim(data) function adh5_redim(data)
// redimensions a multi-dimensional area detector array loaded from HDF5 wave data
// so that the image dimensions are X and Y
// singleton dimensions are removed (most common cases only)
// in the redimensioned array, the original dimension type is noted in the dimension label:
// AD_Dim0 = first image dimension
// AD_Dim1 = second image dimension
// AD_DimN = frame sequence
// AD_DimX = extra dimension X
// AD_DimY = extra dimension Y (cannot be loaded in Igor)
wave data // area detector data loaded from HDF5 to be redimensioned
duplicate /free data, tempdata duplicate /free data, tempdata
variable nd = wavedims(tempdata) variable nd = wavedims(tempdata)
@ -608,29 +686,36 @@ function adh5_redim(data)
endswitch endswitch
end end
/// find the attributes data folder of an area detector dataset.
///
/// since version 1.04 attributes should be stored in a subfolder named attr.
/// earlier versions had the attributes in the same data folder as the actual dataset.
///
/// @param data wave containing the main dataset.
///
/// @return data folder reference of the attributes folder.
/// the reference may be invalid (and default to root) if the folder cannot be found,
/// cf. built-in DataFolderRefStatus function.
static function /DF GetAttrDataFolderDFR(data) static function /DF GetAttrDataFolderDFR(data)
// returns a data folder reference to the ND attributes
// since version 1.04 attributes should be written in a subfolder named attr
// earlier versions had the attributes in the same data folder as the actual dataset
wave data wave data
dfref saveDF = GetDataFolderDFR()
dfref dataDF = GetWavesDataFolderDFR(data) dfref dataDF = GetWavesDataFolderDFR(data)
setdatafolder dataDF dfref attrDF = dataDF:attr
if (DataFolderExists(":attr")) if (DataFolderRefStatus(attrDF) == 0)
setdatafolder :attr attrDF = dataDF
endif endif
dfref attrDF = GetDataFolderDFR()
setdatafolder saveDF
return attrDF return attrDF
end end
/// set the dimension scales of an area detector dataset.
///
/// the intrinsic dimensions 0 and 1 are scaled according to the data source
/// (currently supported: Prosilica cameras, Scienta electron analyser).
/// the extra dimensions are scaled according to the scan.
/// the latter requires that the positioner names and position values are available.
///
function adh5_scale(data,[source]) function adh5_scale(data,[source])
// tries to set the dimension scales of an area detector dataset.
// the intrinsic dimensions 0 and 1 are scaled according to the data source
// (currently supported: Prosilica cameras, Scienta electron analyser).
// the extra dimensions are scaled according to the scan.
// the latter requires that the positioner names and position values are available.
wave data wave data
string source string source
@ -671,14 +756,23 @@ function adh5_scale(data,[source])
setdatafolder saveDF setdatafolder saveDF
end end
/// load the detector dataset from the open HDF5 file.
///
/// the function loads the dataset image by image using the hyperslab option.
/// this function gives the same result as adh5_load_detector.
/// it is about 5% slower, and it depends on HDF5 Browser code.
/// but it does not choke on large datasets (as long as the final wave fits into memory).
///
/// @param fileID ID of open HDF5 file from HDF5OpenFile.
/// @param detectorpath path to detector group in the HDF5 file.
/// @param progress 1 (default): show progress window; 0: do not show progress window.
///
/// @return 0 if successful, non-zero if an error occurred.
///
function adh5_load_detector_slabs(fileID, detectorpath, [progress]) function adh5_load_detector_slabs(fileID, detectorpath, [progress])
// loads the detector dataset from the open HDF5 file variable fileID
// the function loads the dataset image by image using the hyperslab option string detectorpath
// this function gives the same result as adh5_load_detector variable progress
// it is about 5% slower, and it depends on HDF5 Browser code.
variable fileID // ID of open HDF5 file from HDF5OpenFile
string detectorpath // path to detector group in the HDF5 file
variable progress // 1 (default): show progress window; 0: do not show progress window
if (ParamIsDefault(progress)) if (ParamIsDefault(progress))
progress = 1 progress = 1
@ -821,23 +915,32 @@ function adh5_load_detector_slabs(fileID, detectorpath, [progress])
return result return result
end end
/// load a single image from the detector dataset of the open HDF5 file
///
/// the function can average over a region in the extra dimensions.
///
/// @param fileID ID of open HDF5 file from HDF5OpenFile
/// @param detectorpath path to detector group in the HDF5 file
/// @param dim2start 2nd dimension coordinate of the first image
/// note that the order of dimensions is reversed in the file
/// 2nd dimension = N dimension in area detector = dimension 0 of the three-dimensional HDF dataset
/// set to 0 if dimension may not be present
/// @param dim2count number of subsequent images to average
/// set to 1 if dimension may not be present
/// @param dim3start 3rd dimension coordinate of the first image
/// note that the order of dimensions is reversed in the file
/// 3rd dimension = extra X dimension in area detector = dimension 0 of the four-dimensional HDF dataset
/// set to 0 if dimension may not be present
/// @param dim3count number of subsequent images to average
/// set to 1 if dimension may not be present
///
function adh5_load_detector_image(fileID, detectorpath, dim2start, dim2count, dim3start, dim3count) function adh5_load_detector_image(fileID, detectorpath, dim2start, dim2count, dim3start, dim3count)
// loads a single image from the detector dataset of the open HDF5 file variable fileID
// the function can average over a region in the extra dimensions string detectorpath
variable fileID // ID of open HDF5 file from HDF5OpenFile variable dim2start
string detectorpath // path to detector group in the HDF5 file variable dim2count
variable dim2start // 2nd dimension coordinate of the first image variable dim3start
// note that the order of dimensions is reversed in the file variable dim3count
// 2nd dimension = N dimension in area detector = dimension 0 of the three-dimensional HDF dataset
// set to 0 if dimension may not be present
variable dim2count // number of subsequent images to average
// set to 1 if dimension may not be present
variable dim3start // 3rd dimension coordinate of the first image
// note that the order of dimensions is reversed in the file
// 3rd dimension = extra X dimension in area detector = dimension 0 of the four-dimensional HDF dataset
// set to 0 if dimension may not be present
variable dim3count // number of subsequent images to average
// set to 1 if dimension may not be present
// avoid compilation error if HDF5 XOP has not been loaded // avoid compilation error if HDF5 XOP has not been loaded
#if Exists("HDF5LoadData") #if Exists("HDF5LoadData")
@ -922,10 +1025,12 @@ function adh5_load_detector_image(fileID, detectorpath, dim2start, dim2count, di
#endif #endif
end end
/// get a list of functions which can be used as reduction functions.
///
/// the function evaluates only the function arguments,
/// it may thus include functions which are not suitable as reduction functions.
///
function /s adh5_list_reduction_funcs() function /s adh5_list_reduction_funcs()
// returns a list of functions which can be used as reduction functions
// the function evaluates only the function arguments,
// it may thus include functions which are not suitable as reduction functions.
string all_funcs = FunctionList("*", ";", "KIND:6,NPARAMS:4,VALTYPE:1") string all_funcs = FunctionList("*", ";", "KIND:6,NPARAMS:4,VALTYPE:1")
string result = "" string result = ""
@ -960,26 +1065,35 @@ function /s adh5_list_reduction_funcs()
return result return result
end end
/// function prototype for adh5_load_reduced_detector
///
/// derived functions reduce a two-dimensional dataset to a one-dimensional dataset,
/// e.g. by ROI-integration, curve fitting, etc.
// the resulting wave must have the same size as either dimension of the source image.
///
/// each destination wave is a one-dimensional intensity distribution.
/// the function must redimension each of these waves to one of the image dimensions
/// by calling the adh5_setup_profile() function.
/// this function will also copy the scale information and dimension labels,
/// which is important for the proper scaling of the result.
///
/// the meaning of the data in dest1 and dest2 is up to the particular function,
/// e.g. dest1 could hold the mean value and dest2 the one-sigma error,
/// or dest1 could hold the X-profile, and dest2 the Y-profile.
///
/// @param source source wave
/// two-dimensional intensity distribution (image)
/// @param dest1, dest2 destination waves
/// @param param string with optional parameters, shared between calls.
/// this is a pass-by-reference argument,
/// the function may modify the string
///
/// @return zero if successful, non-zero if an error occurs.
///
threadsafe function adh5_default_reduction(source, dest1, dest2, param) threadsafe function adh5_default_reduction(source, dest1, dest2, param)
// function prototype for adh5_load_reduced_detector wave source
// derived functions reduce a two-dimensional dataset to a one-dimensional dataset, wave dest1, dest2
// e.g. by ROI-integration, curve fitting, etc. string &param
// the resulting wave must have the same size as either dimension of the source image.
wave source // source wave
// two-dimensional intensity distribution (image)
wave dest1, dest2 // destination waves
// each wave is a one-dimensional intensity distribution
// the function must redimension each of these waves to one of the image dimensions
// by calling the adh5_setup_profile() function.
// this function will also copy the scale information and dimension labels,
// which is important for the proper scaling of the result.
// the meaning of the data in dest1 and dest2 is up to the particular function,
// e.g. dest1 could hold the mean value and dest2 the one-sigma error,
// or dest1 could hold the X-profile, and dest2 the Y-profile.
string &param // string with optional parameters, shared between calls
// this is a pass-by-reference argument,
// the function may modify the string
// demo code // demo code
// integrate along the dimensions // integrate along the dimensions
@ -988,13 +1102,15 @@ threadsafe function adh5_default_reduction(source, dest1, dest2, param)
adh5_setup_profile(source, dest2, 1) adh5_setup_profile(source, dest2, 1)
ad_profile_y_w(source, 0, -1, dest2) ad_profile_y_w(source, 0, -1, dest2)
return 0 // return zero if successful, non-zero if an error occurs return 0
end end
/// set up a one-dimensional wave for a line profile based on a 2D original wave.
///
/// redimensions the profile wave to the given dimension.
/// copies the scale and dimension label of the given dimension.
///
threadsafe function adh5_setup_profile(image, profile, dim) threadsafe function adh5_setup_profile(image, profile, dim)
// sets up a one-dimensional wave for a line profile based on a 2D original wave
// redimensions the profile wave to the given dimension
// copies the scale and dimension label of the given dimension
wave image // prototype wave image // prototype
wave profile // destination wave wave profile // destination wave
variable dim // which dimension to keep: 0 = X, 1 = Y variable dim // which dimension to keep: 0 = X, 1 = Y
@ -1005,10 +1121,11 @@ threadsafe function adh5_setup_profile(image, profile, dim)
setdimlabel 0, -1, $getdimlabel(image, dim, -1), profile setdimlabel 0, -1, $getdimlabel(image, dim, -1), profile
end end
/// wrapper function for testing reduction functions from the command line.
///
/// Igor does not allow global variables as pass-by-reference parameter for reduction_param.
///
function /s adh5_test_reduction_func(source, dest1, dest2, reduction_func, reduction_param) function /s adh5_test_reduction_func(source, dest1, dest2, reduction_func, reduction_param)
// wrapper function for testing reduction functions from the command line.
// Igor does not allow global variables as pass-by-reference parameter for reduction_param.
wave source wave source
wave dest1 wave dest1
wave dest2 wave dest2
@ -1020,28 +1137,35 @@ function /s adh5_test_reduction_func(source, dest1, dest2, reduction_func, reduc
return reduction_param return reduction_param
end end
/// load a reduced detector dataset from the open HDF5 file.
///
/// the function loads the dataset image by image using the hyperslab option
/// and applies a custom reduction function to each image.
/// the results from the reduction function are composed into one result wave.
/// the raw data are discarded.
///
/// by default, the reduction function is called in separate threads to reduce the total loading time.
/// (see the global variable adh5_perf_secs which reports the total run time of the function.)
/// the effect varies depending on the balance between file loading (image size)
/// and data processing (complexity of the reduction function).
/// for debugging the reduction function, multi-threading can be disabled.
///
/// @param fileID ID of open HDF5 file from HDF5OpenFile
/// @param detectorpath path to detector group in the HDF5 file
/// @param reduction_func custom reduction function
/// (any user-defined function which has the same parameters as adh5_default_reduction())
/// @param reduction_param parameter string for the reduction function
/// @param progress 1 (default): show progress window; 0: do not show progress window
/// @param nthreads -1 (default): use as many threads as there are processor cores (in addition to main thread)
/// 0: use main thread only (e.g. for debugging the reduction function)
/// >= 1: use a fixed number of (additional) threads
function adh5_load_reduced_detector(fileID, detectorpath, reduction_func, reduction_param, [progress, nthreads]) function adh5_load_reduced_detector(fileID, detectorpath, reduction_func, reduction_param, [progress, nthreads])
// loads a reduced detector dataset from the open HDF5 file variable fileID
// the function loads the dataset image by image using the hyperslab option string detectorpath
// and applies a custom reduction function to each image. funcref adh5_default_reduction reduction_func
// the results from the reduction function are composed into one result wave. string reduction_param
// the raw data are discarded. variable progress
variable nthreads
// by default, the reduction function is called in separate threads to reduce the total loading time.
// (see the global variable adh5_perf_secs which reports the total run time of the function.)
// the effect varies depending on the balance between file loading (image size)
// and data processing (complexity of the reduction function).
// for debugging the reduction function, multi-threading can be disabled.
variable fileID // ID of open HDF5 file from HDF5OpenFile
string detectorpath // path to detector group in the HDF5 file
funcref adh5_default_reduction reduction_func // custom reduction function
// (any user-defined function which has the same parameters as adh5_default_reduction())
string reduction_param // parameter string for the reduction function
variable progress // 1 (default): show progress window; 0: do not show progress window
variable nthreads // -1 (default): use as many threads as there are processor cores (in addition to main thread)
// 0: use main thread only (e.g. for debugging the reduction function)
// >= 1: use a fixed number of (additional) threads
if (ParamIsDefault(progress)) if (ParamIsDefault(progress))
progress = 1 progress = 1
@ -1340,17 +1464,21 @@ threadsafe static function reduce_slab_image(slabdata, image, profile1, profile2
return reduction_func(image, profile1, profile2, reduction_param) return reduction_func(image, profile1, profile2, reduction_param)
end end
/// load an NDAttributes group from an open HDF5 file into the current data folder.
///
/// datasets contained in the group are loaded as waves.
/// if a dataset contains only one data point, it is added to the IN, ID, IV, IU waves,
/// where IN = EPICS channel name, ID = attribute name, IV = value, IU = unit
/// (units are left empty as they are not saved in HDF5).
/// attributes of the NDAttributes group are added to the IN, ID, IV, IU waves,
/// however, IN and IU are left empty as this information is not saved in the HDF5 file.
///
/// @param fileID ID of open HDF5 file from HDF5OpenFile
/// @param attributespath path to NDAttributes group in the HDF5 file
///
function adh5_loadattr_all(fileID, attributespath) function adh5_loadattr_all(fileID, attributespath)
// loads an NDAttributes group from an open HDF5 file into the current data folder. variable fileID
// datasets contained in the group are loaded as waves. string attributespath
// if a dataset contains only one data point, it is added to the IN, ID, IV, IU waves,
// where IN = EPICS channel name, ID = attribute name, IV = value, IU = unit
// (units are left empty as they are not saved in HDF5).
// attributes of the NDAttributes group are added to the IN, ID, IV, IU waves,
// however, IN and IU are left empty as this information is not saved in the HDF5 file.
variable fileID // ID of open HDF5 file from HDF5OpenFile
string attributespath // path to NDAttributes group in the HDF5 file
string datasetname string datasetname
string datawavename string datawavename
@ -1417,11 +1545,20 @@ function adh5_loadattr_all(fileID, attributespath)
end end
/// sub-function of adh5_loadattr_all.
///
/// reads one attribute from a wave which was loaded from an HDF5 file into the info waves IN, ID, IV, IU.
/// the attribute is read only if the input wave contains exactly one item,
/// i.e. either the measurement is a single image, or the attribute has string type.
///
/// @param datawavename name of the attribute wave in the current folder.
/// can be text or numeric.
/// @param source source identifier (EPICS name) of the attribute.
/// @param idest destination index in IN, ID, IV, IU where the results are written.
/// the variable is incremented if data was written, otherwise it is left unchanged.
/// make sure IN, ID, IV, IU have at least idest + 1 elements.
///
static function read_attribute_info(datawavename, source, idest) static function read_attribute_info(datawavename, source, idest)
// sub-function of adh5_loadattr_all.
// reads one attribute from a wave which was loaded from an HDF5 file into the info waves IN, ID, IV, IU.
// the attribute is read only if the input wave contains exactly one item,
// i.e. either the measurement is a single image, or the attribute has string type.
string datawavename // name of the attribute wave in the current folder. string datawavename // name of the attribute wave in the current folder.
// can be text or numeric. // can be text or numeric.
string source string source
@ -1467,12 +1604,14 @@ static function read_attribute_info(datawavename, source, idest)
endif endif
end end
/// set the energy and angle scales of an area detector dataset from the Scienta analyser.
///
/// the dimension labels of the energy and angle scales must be set correctly:
/// AD_Dim0 = energy dimension; AD_Dim1 = angle dimension.
/// these dimensions must be the first two dimensions of a multi-dimensional dataset.
/// normally, AD_Dim0 is the X dimension, and AD_Dim1 the Y dimension.
///
function adh5_scale_scienta(data) function adh5_scale_scienta(data)
// sets the energy and angle scales of an area detector dataset from the Scienta analyser
// the dimension labels of the energy and angle scales must be set correctly:
// AD_Dim0 = energy dimension; AD_Dim1 = angle dimension
// these dimensions must be the first two dimensions of a multi-dimensional dataset.
// normally, AD_Dim0 is the X dimension, and AD_Dim1 the Y dimension.
wave data wave data
dfref saveDF = GetDataFolderDFR() dfref saveDF = GetDataFolderDFR()
@ -1571,11 +1710,13 @@ function adh5_scale_scienta(data)
setdatafolder saveDF setdatafolder saveDF
end end
/// scales the extra dimensions of an area detector dataset according to the EPICS scan
///
/// the scan positioner name and its values must be available
///
/// @todo incomplete
///
function adh5_scale_scan(data) function adh5_scale_scan(data)
// scales the extra dimensions of an area detector dataset according to the EPICS scan
// the scan positioner name and its values must be available
// TODO: incomplete
wave data wave data
dfref saveDF = GetDataFolderDFR() dfref saveDF = GetDataFolderDFR()

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 yminlocs[ix] = v_minloc
endfor endfor
end 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

@ -5,6 +5,7 @@
#include "pearl-area-display" // 2D and 3D data visualization #include "pearl-area-display" // 2D and 3D data visualization
#include "pearl-area-profiles" // data processing for multi-dimensional datasets #include "pearl-area-profiles" // data processing for multi-dimensional datasets
#include "pearl-area-import" // import data files generated by area detector software #include "pearl-area-import" // import data files generated by area detector software
#include "pearl-pshell-import"
#include "pearl-data-explorer" // preview and import panel for PEARL data #include "pearl-data-explorer" // preview and import panel for PEARL data
#include "pearl-anglescan-process" #include "pearl-anglescan-process"
#include "pearl-anglescan-tracker" // live preview of hemispherical angle scan #include "pearl-anglescan-tracker" // live preview of hemispherical angle scan

View File

@ -1,36 +1,51 @@
#pragma rtGlobals=3 // Use modern global access method and strict wave access. #pragma rtGlobals=3 // Use modern global access method and strict wave access.
#pragma IgorVersion = 6.1 #pragma IgorVersion = 6.1
#pragma ModuleName = PearlDataExplorer #pragma ModuleName = PearlDataExplorer
#pragma version = 1.41 #pragma version = 1.43
#include "pearl-area-import", version >= 1.06 #include "pearl-area-import"
#include "pearl-area-profiles", version >= 1.04 #include "pearl-area-profiles"
#include "pearl-area-display", version >= 1.04 #include "pearl-area-display"
#include "pearl-pshell-import"
// preview and import panel for PEARL data:
// scienta analyser, prosilica cameras, s-scans, otf-scans
// $Id$
// author: matthias.muntwiler@psi.ch
// Copyright (c) 2013-14 Paul Scherrer Institut
// copyright (c) 2013-16 Paul Scherrer Institut
//
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0 // http:///www.apache.org/licenses/LICENSE-2.0
/// @file
/// @brief preview and import panel for PEARL data
/// @ingroup ArpesPackage
///
///
/// preview and import panel for PEARL data:
/// scienta analyser, prosilica cameras, s-scans, otf-scans
/// @namespace PearlDataExplorer
/// @brief preview and import panel for PEARL data
///
/// PearlDataExplorer is declared in @ref pearl-data-explorer.ipf.
static strconstant package_name = "pearl_explorer" static strconstant package_name = "pearl_explorer"
static strconstant package_path = "root:packages:pearl_explorer:" static strconstant package_path = "root:packages:pearl_explorer:"
static strconstant ks_filematch_adh5 = "*.h5"
static strconstant ks_filematch_pshell = "psh*.h5"
static strconstant ks_filematch_itx = "*.itx"
function pearl_data_explorer() function pearl_data_explorer()
init_package() init_package()
load_prefs() load_prefs()
execute /q/z "PearlDataExplorer()" execute /q/z "PearlDataExplorer()"
end end
/// initialize the global variables of the data explorer.
///
/// initializes the global variables and data folder for this procedure file
/// must be called once before the panel is created
/// warning: this function overwrites previous values
static function init_package() static function init_package()
// initializes the global variables and data folder for this procedure file
// must be called once before the panel is created
// warning: this function overwrites previous values
dfref savefolder = GetDataFolderDFR() dfref savefolder = GetDataFolderDFR()
SetDataFolder root: SetDataFolder root:
@ -64,6 +79,7 @@ static function init_package()
string /g s_preview_source = "" // data source, e.g. EPICS channel name, of the current preview string /g s_preview_source = "" // data source, e.g. EPICS channel name, of the current preview
string /g s_profiles_graph = "" // window name of the current preview if the data is two-dimensional string /g s_profiles_graph = "" // window name of the current preview if the data is two-dimensional
string /g s_preview_trace_graph = "" // window name of the current preview if the data is one-dimensional string /g s_preview_trace_graph = "" // window name of the current preview if the data is one-dimensional
string /g s_file_info = "" // description of selected file
variable/g v_InitPanelDone = 1 variable/g v_InitPanelDone = 1
@ -201,9 +217,11 @@ static function preview_file(filename)
dfref saveDF = GetDataFolderDFR() dfref saveDF = GetDataFolderDFR()
if (StringMatch(filename, "*.h5")) if (StringMatch(filename, ks_filematch_pshell))
wave /z image = preview_pshell_file(filename)
elseif (StringMatch(filename, ks_filematch_adh5))
wave /z image = preview_hdf_file(filename) wave /z image = preview_hdf_file(filename)
elseif (StringMatch(filename, "*.itx")) elseif (StringMatch(filename, ks_filematch_itx))
wave /z image = preview_itx_file(filename) wave /z image = preview_itx_file(filename)
endif endif
@ -224,6 +242,49 @@ static function preview_file(filename)
setdatafolder saveDF setdatafolder saveDF
end end
/// load the preview of a PShell HDF5 file (not implemented).
///
/// the preview is an arbitrary detector image extracted from the file, see adh5_load_preview().
/// the preview is loaded to the preview_image wave in the pear_explorer data folder.
///
/// the s_file_info string is updated with information about the scan dimensions.
///
/// @param filename name of a file in the directory specified by the pearl_explorer_filepath path object.
///
/// @return wave reference of the preview image
///
static function /wave preview_pshell_file(filename)
string filename
dfref saveDF = GetDataFolderDFR()
setdatafolder $package_path
svar s_preview_file
svar s_preview_source
psh5_load_preview("preview_image", "pearl_explorer_filepath", filename)
s_preview_file = filename
s_preview_source = ""
wave /z preview_image
svar /z s_file_info
if (! svar_exists(s_file_info))
string /g s_file_info
endif
if (strlen(s_preview_file) > 0)
s_file_info = psh5_load_info("pearl_explorer_filepath", filename)
else
s_file_info = ""
endif
if (DataFolderExists("attr"))
setdatafolder attr
preview_attributes(GetDataFolderDFR())
setdatafolder ::
endif
setdatafolder saveDF
return preview_image
end
/// load the preview of a PEARL HDF5 file. /// load the preview of a PEARL HDF5 file.
/// ///
/// the preview is an arbitrary detector image extracted from the file, see adh5_load_preview(). /// the preview is an arbitrary detector image extracted from the file, see adh5_load_preview().
@ -698,18 +759,21 @@ static function /s show_preview_graph(data, [xdata])
svar s_profiles_graph svar s_profiles_graph
svar s_preview_file svar s_preview_file
svar s_preview_source 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 string graphname
if (wavedims(data) == 2) if (wavedims(data) == 2)
if ((strlen(s_profiles_graph) > 0) && (WinType(s_profiles_graph) == 1)) s_profiles_graph = ad_display_profiles(data)
ad_update_profiles(data) ModifyGraph /w=$s_profiles_graph /z wbRGB=(48640,56832,60160)
else
s_profiles_graph = ad_display_profiles(data)
ModifyGraph /w=$s_profiles_graph /z wbRGB=(48640,56832,60160)
endif
graphname = s_profiles_graph graphname = s_profiles_graph
elseif (wavedims(data) == 1) elseif (wavedims(data) == 1)
svar s_preview_trace_graph
duplicate /o data, preview_trace duplicate /o data, preview_trace
if (!ParamIsDefault(xdata)) if (!ParamIsDefault(xdata))
duplicate /o xdata, preview_trace_x duplicate /o xdata, preview_trace_x
@ -718,20 +782,8 @@ static function /s show_preview_graph(data, [xdata])
preview_trace_x = x preview_trace_x = x
setscale d 0, 0, WaveUnits(data, 0), preview_trace_x setscale d 0, 0, WaveUnits(data, 0), preview_trace_x
endif endif
if ((strlen(s_preview_trace_graph) == 0) || (WinType(s_preview_trace_graph) != 1)) s_preview_trace_graph = display_preview_trace(preview_trace_x, preview_trace)
display /n=pearl_explorer_1d /k=1 preview_trace vs preview_trace_x as "Preview" ModifyGraph /w=$s_preview_trace_graph wbRGB=(48640,56832,60160)
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
graphname = s_preview_trace_graph graphname = s_preview_trace_graph
else else
return "" return ""
@ -747,6 +799,39 @@ static function /s show_preview_graph(data, [xdata])
return graphname return graphname
end 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]) static function load_selected_files([options])
string options string options
@ -777,13 +862,19 @@ static function load_file(filename, [options])
dfref saveDF = GetDataFolderDFR() dfref saveDF = GetDataFolderDFR()
if (StringMatch(filename, "*.h5")) if (StringMatch(filename, ks_filematch_pshell))
if (ParamIsDefault(options))
load_pshell_file(filename)
else
load_pshell_file(filename, options=options)
endif
elseif (StringMatch(filename, ks_filematch_adh5))
if (ParamIsDefault(options)) if (ParamIsDefault(options))
load_hdf_file(filename) load_hdf_file(filename)
else else
load_hdf_file(filename, options=options) load_hdf_file(filename, options=options)
endif endif
elseif (StringMatch(filename, "*.itx")) elseif (StringMatch(filename, ks_filematch_itx))
load_itx_file(filename) load_itx_file(filename)
endif endif
@ -796,7 +887,7 @@ static function prompt_hdf_options(options)
string mode = StringByKey("mode", options, ":", ";") string mode = StringByKey("mode", options, ":", ";")
string reduction_func = StringByKey("reduction_func", options, ":", ";") string reduction_func = StringByKey("reduction_func", options, ":", ";")
string modes = "adh5_load_reduced" string modes = "load_reduced"
string reduction_functions = adh5_list_reduction_funcs() string reduction_functions = adh5_list_reduction_funcs()
if (strlen(mode) == 0) if (strlen(mode) == 0)
@ -817,17 +908,19 @@ static function prompt_hdf_options(options)
return v_flag // 0 = OK, 1 = cancel return v_flag // 0 = OK, 1 = cancel
end end
/// prototype for prompting for processing function parameters.
///
/// the function should prompt the user for function parameters,
/// and update the param argument if the user clicked OK.
/// returns 0 if the user clicked OK, 1 if the user cancelled.
///
/// prompt functions must have the same name as the corresponding reduction function
/// with the prefix "prompt_".
/// be aware of the limited length of function names in Igor.
///
/// this function is a prototype. it does nothing but returns OK.
///
function prompt_default_process(param) function prompt_default_process(param)
// prototype for prompting for processing function parameters.
// the function should prompt the user for function parameters,
// and update the param argument if the user clicked OK.
// returns 0 if the user clicked OK, 1 if the user cancelled.
// prompt functions must have the same name as the corresponding reduction function
// with the prefix "prompt_".
// be aware of the limited length of function names in Igor.
// this function is a prototype. it does nothing but returns OK.
string &param string &param
return 0 return 0
@ -847,6 +940,57 @@ function prompt_func_params(func_name, func_param)
endif endif
end end
static function /df load_pshell_file(filename, [options])
string filename
string options
dfref saveDF = GetDataFolderDFR()
string nickname = ad_suggest_foldername(filename)
string loaded_filename = ""
if (ParamIsDefault(options))
loaded_filename = psh5_load_complete(nickname, "pearl_explorer_filepath", filename)
else
if (strlen(options) == 0)
svar pref_options = $(package_path + "s_hdf_options")
options = pref_options
if (prompt_hdf_options(options) == 0)
// OK
pref_options = options
else
// cancel
options = ""
endif
endif
string mode = StringByKey("mode", options, ":", ";")
strswitch(mode)
case "load_reduced":
string reduction_func = StringByKey("reduction_func", options, ":", ";")
svar pref_params = $(package_path + "s_reduction_params")
string reduction_params = pref_params
if (prompt_func_params(reduction_func, reduction_params) == 0)
pref_params = reduction_params
psh5_load_reduced(nickname, "pearl_explorer_filepath", filename, $reduction_func, reduction_params)
svar s_filepath
loaded_filename = s_filepath
endif
break
endswitch
endif
dfref dataDF
if (strlen(loaded_filename) > 0)
setdatafolder $("root:" + nickname)
dataDF = GetDataFolderDFR()
string /g pearl_explorer_import = "load_pshell_file"
endif
setdatafolder saveDF
return dataDF
end
static function /df load_hdf_file(filename, [options]) static function /df load_hdf_file(filename, [options])
string filename string filename
string options string options
@ -873,7 +1017,7 @@ static function /df load_hdf_file(filename, [options])
string mode = StringByKey("mode", options, ":", ";") string mode = StringByKey("mode", options, ":", ";")
strswitch(mode) strswitch(mode)
case "adh5_load_reduced": case "load_reduced":
string reduction_func = StringByKey("reduction_func", options, ":", ";") string reduction_func = StringByKey("reduction_func", options, ":", ";")
svar pref_params = $(package_path + "s_reduction_params") svar pref_params = $(package_path + "s_reduction_params")
string reduction_params = pref_params string reduction_params = pref_params
@ -1306,6 +1450,9 @@ static function bp_dataset_folder(ba) : ButtonControl
string cmd string cmd
sprintf cmd, "setdatafolder root:%s", PossiblyQuoteName(dataset) sprintf cmd, "setdatafolder root:%s", PossiblyQuoteName(dataset)
execute /q /z cmd execute /q /z cmd
cmd = "setdatafolder :scan1"
execute /q /z cmd
sprintf cmd, "setdatafolder %s", GetDataFolder(1)
print cmd print cmd
endif endif
break 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 end
submenu "Services" submenu "Services"
PearlMenuEnableFunc("pearl_elog") + "ELOG Experiments", /Q, pearl_elog("Experiments") PearlMenuEnableFunc("pearl_elog") + "Open ELOG Panel", /Q, pearl_elog("")
help = {"Create entries in ELOG experiments logbook"} help = {"Open an ELOG panel to send entries to an ELOG logbook"}
PearlMenuEnableFunc("pearl_elog") + "ELOG Calculations", /Q, pearl_elog("Calculations")
help = {"Create entries in ELOG calculations logbook"}
end end
submenu "Sample Preparation" 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

File diff suppressed because it is too large Load Diff