Compare commits
11 Commits
rev-distro
...
rev-distro
Author | SHA1 | Date | |
---|---|---|---|
80a01f2bdb | |||
9a65d26984 | |||
c8a69460bc | |||
600061f684 | |||
0dc6ca820b | |||
a87975d1e6 | |||
86cf328961 | |||
2479582c08 | |||
02709fd4df | |||
724c73ef19 | |||
fcd6a56e4e |
20
.gitattributes
vendored
Normal file
20
.gitattributes
vendored
Normal 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
1
.gitignore
vendored
@ -4,3 +4,4 @@
|
||||
*.ipfT*
|
||||
doc/html/*
|
||||
doc/latex/*
|
||||
|
||||
|
17
README.md
17
README.md
@ -11,16 +11,20 @@ PEARL Procedures should be installed according to the regular Igor Pro guideline
|
||||
|
||||
- Make a `pearl-procs` directory in your private or shared `User Procedures` folder, and copy the PEARL Procedures distribution there.
|
||||
- Create shortcuts of the `pearl-arpes.ipf` and `pearl-menu.ipf` files, and move them to the `Igor Procedures` 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.XOP` (`HDF5-64.xop` for Igor 7 64-bit) extension in the `Igor Pro Folder` under `More Extensions/File Loaders` (`More Extensions (64-bit)/File Loaders`), create a shortcut, and move the shortcut to the `Igor Extensions` folder next to your `User Procedures` folder.
|
||||
- Find the `HDF5 Help.ihf` next to `HDF5.XOP`, create a shortcut, and move the shortcut to the `Igor Help Files` folder next to your `User Procedures` folder.
|
||||
|
||||
PEARL Procedures has been tested under Igor Pro version 6.37 (32-bit). Older versions prior to 6.36 are not be compatible. Please update to the latest Igor Pro 6 version before reporting any problems.
|
||||
|
||||
PEARL Procedures compiles under Igor 7.00. Some features, in particular 3D graphics, may not work properly.
|
||||
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
The source code of PEARL Procedures is available under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) at <https://git.psi.ch/pearl-public/igor-procs>.
|
||||
Users of PEARL Procedures are requested to coordinate and share the development of the code with the original author.
|
||||
Please read and respect the respective license agreements.
|
||||
Please share your extensions of the code with the original author.
|
||||
|
||||
Author
|
||||
------
|
||||
@ -32,3 +36,12 @@ Copyright
|
||||
|
||||
Copyright 2009-2016 by [Paul Scherrer Institut](http://www.psi.ch)
|
||||
|
||||
|
||||
Release Notes
|
||||
=============
|
||||
|
||||
## rev-distro-1.1.1
|
||||
|
||||
- If you have upgraded PEARL Procedures from pre-1.1.1 and Igor breaks in pearl-elog.ipf while opening an experiment, please delete the ELOG preferences file `pearl-elog/preferences.pxp`. (Check the Igor Help to find the package preferences folder on your system.)
|
||||
|
||||
|
||||
|
@ -38,7 +38,7 @@ PROJECT_NAME = "PEARL Procedures"
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER =
|
||||
PROJECT_NUMBER = $(REVISION)
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
@ -1647,7 +1647,7 @@ EXTRA_PACKAGES =
|
||||
# to HTML_HEADER.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_HEADER =
|
||||
LATEX_HEADER = src/header.tex
|
||||
|
||||
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
|
||||
# generated LaTeX document. The footer should contain everything after the last
|
@ -11,7 +11,7 @@ DOX=doxygen
|
||||
DOXOPTS=
|
||||
LATEX_DIR=latex
|
||||
|
||||
REVISION=$(shell git describe --always --tags --dirty --long)
|
||||
REVISION=$(shell git describe --always --tags --dirty --long || echo "unknown, "`date +"%F %T %z"`)
|
||||
export REVISION
|
||||
|
||||
all: docs
|
||||
@ -19,7 +19,7 @@ all: docs
|
||||
docs: doxygen pdf
|
||||
|
||||
doxygen:
|
||||
$(DOX) $(DOXOPTS) Doxyfile
|
||||
$(DOX) $(DOXOPTS) config.dox
|
||||
|
||||
pdf: doxygen
|
||||
-$(MAKE) -C $(LATEX_DIR)
|
||||
@ -27,3 +27,4 @@ pdf: doxygen
|
||||
clean:
|
||||
-rm latex/*
|
||||
-rm html/*
|
||||
|
||||
|
149
doc/src/header.tex
Normal file
149
doc/src/header.tex
Normal 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 ---
|
@ -21,7 +21,7 @@ Users of PEARL Procedures are requested to coordinate and share the development
|
||||
Please read and respect the respective license agreements.
|
||||
|
||||
\author Matthias Muntwiler, <mailto:matthias.muntwiler@psi.ch>
|
||||
\version This documentation is compiled from revision $(REVISION).
|
||||
\version This documentation is compiled from version $(REVISION).
|
||||
\copyright 2009-2016 by [Paul Scherrer Institut](http://www.psi.ch)
|
||||
\copyright Licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
*/
|
||||
|
97
mm/mm-physconst.ipf
Normal file
97
mm/mm-physconst.ipf
Normal 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
|
@ -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
|
@ -6,14 +6,14 @@
|
||||
#include "pearl-polar-coordinates"
|
||||
#include <New Polar Graphs>
|
||||
|
||||
// $Id$
|
||||
//
|
||||
// copyright (c) 2013-15 Paul Scherrer Institut
|
||||
// copyright (c) 2013-16 Paul Scherrer Institut
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http:///www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Please acknowledge the use of this code.
|
||||
|
||||
/// @file
|
||||
/// @brief processing and holographic mapping of angle scanned XPD data.
|
||||
@ -64,7 +64,7 @@
|
||||
///
|
||||
/// @author matthias muntwiler, matthias.muntwiler@psi.ch
|
||||
///
|
||||
/// @copyright 2013-15 Paul Scherrer Institut @n
|
||||
/// @copyright 2013-16 Paul Scherrer Institut @n
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License"); @n
|
||||
/// you may not use this file except in compliance with the License. @n
|
||||
/// You may obtain a copy of the License at
|
||||
@ -79,15 +79,38 @@
|
||||
///
|
||||
/// PearlAnglescanProcess is declared in @ref pearl-anglescan-process.ipf.
|
||||
|
||||
/// @warning experimental
|
||||
function strip_remove_frames(strip, yscale, ylo, yhi)
|
||||
|
||||
/// delete a contiguous range of frames from a strip.
|
||||
///
|
||||
/// this can be used to remove a region of bad frames due to, e.g., measurement problems.
|
||||
/// the function operates on 2D intensity data and manipulator coordinates at the same time.
|
||||
///
|
||||
/// @param[in,out] strip 2D data, X-axis = analyser angle, Y-axis = arbitrary manipulator scan.
|
||||
/// the result is written to the original wave.
|
||||
///
|
||||
/// @param[in,out] theta 1D data, manipulator scan.
|
||||
/// the result is written to the original wave.
|
||||
///
|
||||
/// @param[in,out] tilt 1D data, manipulator scan.
|
||||
/// the result is written to the original wave.
|
||||
///
|
||||
/// @param[in,out] phi 1D data, manipulator scan.
|
||||
/// the result is written to the original wave.
|
||||
///
|
||||
/// @param[in] qlo point index of first frame to delete.
|
||||
///
|
||||
/// @param[in] qhi point index of last frame to delete.
|
||||
/// qhi must be greater or equal than qlo.
|
||||
///
|
||||
function strip_delete_frames(strip, qlo, qhi, theta, tilt, phi)
|
||||
wave strip // 2D data, X-axis = analyser angle, Y-axis = arbitrary manipulator scan
|
||||
wave /z yscale // Y scaling, e.g. ManipulatorPhi
|
||||
// if unassigned, point scaling is assumed
|
||||
variable ylo
|
||||
variable yhi
|
||||
variable qlo
|
||||
variable qhi
|
||||
wave theta
|
||||
wave tilt
|
||||
wave phi
|
||||
|
||||
if (ylo > yhi)
|
||||
if (qlo > qhi)
|
||||
return -1
|
||||
endif
|
||||
|
||||
@ -95,8 +118,8 @@ function strip_remove_frames(strip, yscale, ylo, yhi)
|
||||
variable snx = dimsize(strip, 0)
|
||||
variable sny = dimsize(strip, 1)
|
||||
variable sq1lo = 0
|
||||
variable sq1hi = max(round((ylo - dimoffset(strip, 1)) / dimdelta(strip, 1)), 0)
|
||||
variable sq2lo = min(round((ylo - dimoffset(strip, 1)) / dimdelta(strip, 1)), sny - 1)
|
||||
variable sq1hi = max(qlo-1, 0)
|
||||
variable sq2lo = min(qhi+1, sny - 1)
|
||||
variable sq2hi = dimsize(strip, 1) - 1
|
||||
|
||||
// dest indices
|
||||
@ -111,10 +134,24 @@ function strip_remove_frames(strip, yscale, ylo, yhi)
|
||||
|
||||
duplicate /free strip, strip_copy
|
||||
redimension /n=(dnx,dny) strip
|
||||
|
||||
strip[][dq1lo,dq1hi] = strip_copy[p][q + q1ofs]
|
||||
strip[][dq2lo,dq2hi] = strip_copy[p][q + q2ofs]
|
||||
|
||||
duplicate /free theta, theta_copy
|
||||
redimension /n=(dny) theta
|
||||
theta[dq1lo,dq1hi] = theta_copy[p + q1ofs]
|
||||
theta[dq2lo,dq2hi] = theta_copy[p + q2ofs]
|
||||
|
||||
duplicate /free tilt, tilt_copy
|
||||
redimension /n=(dny) tilt
|
||||
tilt[dq1lo,dq1hi] = tilt_copy[p + q1ofs]
|
||||
tilt[dq2lo,dq2hi] = tilt_copy[p + q2ofs]
|
||||
|
||||
duplicate /free phi, phi_copy
|
||||
redimension /n=(dny) phi
|
||||
phi[dq1lo,dq1hi] = phi_copy[p + q1ofs]
|
||||
phi[dq2lo,dq2hi] = phi_copy[p + q2ofs]
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
@ -144,6 +181,7 @@ end
|
||||
/// @return if check waves are enabled, the following waves are created (overwritten if existing):
|
||||
/// @arg check_dist average X distribution
|
||||
/// @arg check_smoo smoothed distribution used to normalize the strip
|
||||
///
|
||||
function normalize_strip_x(strip, [smooth_method, smooth_factor, check])
|
||||
wave strip
|
||||
variable smooth_method
|
||||
@ -233,6 +271,7 @@ end
|
||||
/// @return if check waves are enabled, the following waves are created (overwritten if existing):
|
||||
/// @arg check_dist average theta distribution
|
||||
/// @arg check_smoo smoothed distribution used to normalize the strip
|
||||
///
|
||||
function normalize_strip_theta(strip, theta, [theta_offset, smooth_method, smooth_factor, check])
|
||||
wave strip
|
||||
wave theta
|
||||
@ -261,6 +300,7 @@ function normalize_strip_theta(strip, theta, [theta_offset, smooth_method, smoot
|
||||
duplicate /free dist, dist_smoo
|
||||
duplicate /free theta, theta_int
|
||||
theta_int = theta - theta_offset
|
||||
setscale /p x theta_int[0], theta_int[1] - theta_int[0], waveunits(theta,-1), dist, dist_smoo
|
||||
variable nx = dimsize(strip, 0)
|
||||
variable ix
|
||||
|
||||
@ -297,6 +337,71 @@ function normalize_strip_theta(strip, theta, [theta_offset, smooth_method, smoot
|
||||
if (check)
|
||||
duplicate /o dist, check_dist
|
||||
duplicate /o dist_smoo, check_smoo
|
||||
setscale /p x dimoffset(dist,0), dimdelta(dist,0), waveunits(dist,0), check_dist, check_smoo
|
||||
endif
|
||||
end
|
||||
|
||||
/// divide the strip by a two-dimensional normalization function.
|
||||
///
|
||||
/// @warning experimental. this function is under development.
|
||||
///
|
||||
/// @param check enable output of intermediate results
|
||||
/// @arg 0 (default) don't create additional waves
|
||||
/// @arg 1 create check waves in the current folder
|
||||
/// @arg 2 calculate check waves only, do not modify strip
|
||||
///
|
||||
/// @return if check waves are enabled, the following waves are created (overwritten if existing):
|
||||
/// @arg check_dist average theta distribution
|
||||
/// @arg check_smoo smoothed distribution used to normalize the strip
|
||||
///
|
||||
function normalize_strip_2d(strip, theta, [theta_offset, smooth_method, smooth_factor, check])
|
||||
wave strip
|
||||
wave theta
|
||||
variable theta_offset
|
||||
variable smooth_method
|
||||
variable smooth_factor
|
||||
variable check
|
||||
|
||||
if (ParamIsDefault(check))
|
||||
check = 0
|
||||
endif
|
||||
if (ParamIsDefault(theta_offset))
|
||||
theta_offset = 0
|
||||
endif
|
||||
if (ParamIsDefault(smooth_method))
|
||||
smooth_method = 4
|
||||
endif
|
||||
if (ParamIsDefault(smooth_factor))
|
||||
smooth_factor = 0.5
|
||||
endif
|
||||
|
||||
variable nx = dimsize(strip, 0)
|
||||
variable ny = dimsize(strip, 1)
|
||||
|
||||
duplicate /free strip, dist, alpha_int, theta_int
|
||||
theta_int = theta[q] - theta_offset
|
||||
alpha_int = dimoffset(strip, 0) + p * dimdelta(strip, 0)
|
||||
redimension /n=(nx * ny) dist, alpha_int, theta_int
|
||||
|
||||
switch(smooth_method)
|
||||
case 4:
|
||||
loess /dest=dist_smoo /smth=(smooth_factor) srcWave=dist, factors={alpha_int, theta_int}
|
||||
redimension /n=(nx, ny) dist_smoo
|
||||
break
|
||||
default:
|
||||
Abort "undefined smooth method"
|
||||
break
|
||||
endswitch
|
||||
|
||||
// divide
|
||||
if (check != 2)
|
||||
strip /= dist_smoo
|
||||
endif
|
||||
|
||||
// check
|
||||
if (check)
|
||||
//duplicate /o dist, check_dist
|
||||
duplicate /o dist_smoo, check_smoo
|
||||
endif
|
||||
end
|
||||
|
||||
@ -705,9 +810,9 @@ function convert_angles_ttpa2polar(theta, tilt, phi, analyser, polar, azi)
|
||||
// this is simply a polar-cartesian mapping, independent of the manipulator
|
||||
// phi=0 is in the polar rotation plane
|
||||
make /n=(3,na) /d /free w_orig_polar, w_orig_cart, w_rot_cart, w_rot_polar
|
||||
w_orig_polar[0] = radius
|
||||
w_orig_polar[1] = analyser[q]
|
||||
w_orig_polar[2] = 0
|
||||
w_orig_polar[0][] = radius
|
||||
w_orig_polar[1][] = analyser[q]
|
||||
w_orig_polar[2][] = 0
|
||||
polar2cart_wave(w_orig_polar, w_orig_cart)
|
||||
// if the angle-dispersive axis was horizontal, we'd need to rotate the detector
|
||||
//rotate_z_wave(w_orig_cart, 90)
|
||||
@ -1758,7 +1863,7 @@ function /s display_scanlines(nickname, alpha_lo, alpha_hi, m_theta, m_tilt, m_p
|
||||
make /n=1 /d /free d_polar, d_azi
|
||||
variable n_alpha = round(alpha_hi - alpha_lo) + 1
|
||||
make /n=(n_alpha) /d /free analyser
|
||||
setscale /i x alpha_lo, alpha_hi, "deg", analyser
|
||||
setscale /i x alpha_lo, alpha_hi, "<EFBFBD>", analyser
|
||||
analyser = x
|
||||
|
||||
convert_angles_ttpa2polar(m_theta, loc_m_tilt, m_phi, analyser, d_polar, d_azi)
|
||||
@ -1802,21 +1907,46 @@ function /s display_scanlines(nickname, alpha_lo, alpha_hi, m_theta, m_tilt, m_p
|
||||
return graphname
|
||||
end
|
||||
|
||||
static constant kProjScaleLinear = 2
|
||||
/// @page PageProjections Projections
|
||||
///
|
||||
/// the functions of the anglescan package support the following map projections.
|
||||
/// for a description of the different projections, see, for example,
|
||||
/// https://en.wikipedia.org/wiki/Map_projection
|
||||
///
|
||||
/// | Selector | Projection | Function | Properties |
|
||||
/// | :----: | :----: | :----: | :---- |
|
||||
/// | kProjDist = 0 | azimuthal equidistant | r = c * theta | radius is proportional to polar angle. |
|
||||
/// | kProjStereo = 1 | stereographic | r = c * tan theta/2 | circles on sphere map to circles. |
|
||||
/// | kProjArea = 2 | azimuthal equal-area | r = c * sin theta/2 | preserves area measure. |
|
||||
/// | kProjGnom = 3 | gnomonic | r = c * tan theta | great circles map to straight lines. |
|
||||
/// | kProjOrtho = 4 | orthographic | r = c * sin theta | k-space mapping in ARPES and LEED. |
|
||||
///
|
||||
/// the projections in this package are defined for 0 <= theta < 90.
|
||||
///
|
||||
constant kProjDist = 0
|
||||
constant kProjStereo = 1
|
||||
constant kProjArea = 2
|
||||
constant kProjGnom = 3
|
||||
constant kProjOrtho = 4
|
||||
|
||||
static constant kProjScaleDist = 2
|
||||
static constant kProjScaleStereo = 2
|
||||
static constant kProjScaleAzim = 2
|
||||
static constant kProjScaleArea = 2
|
||||
// scaled so that radius(gnom) = radius(stereo) for polar = 88
|
||||
static constant kProjScaleGnomonic = 0.06744519021
|
||||
static constant kProjScaleGnom = 0.06744519021
|
||||
static constant kProjScaleOrtho = 2
|
||||
|
||||
/// calculate the projected polar angle
|
||||
///
|
||||
/// @param polar polar angle in degrees
|
||||
///
|
||||
/// @param projection mapping function from polar to cartesian coordinates
|
||||
/// @arg 0 linear
|
||||
/// @arg 1 stereographic (default)
|
||||
/// @arg 2 azimuthal
|
||||
/// @arg 3 gnomonic (0 <= polar < 90)
|
||||
/// @param projection mapping function from polar to cartesian coordinates.
|
||||
/// see @ref PageProjections for details.
|
||||
/// @arg kProjDist = 0 azimuthal equidistant
|
||||
/// @arg kProjStereo = 1 stereographic (default)
|
||||
/// @arg kProjArea = 2 azimuthal equal-area
|
||||
/// @arg kProjGnom = 3 gnomonic (0 <= polar < 90)
|
||||
/// @arg kProjOrtho = 4 orthographic
|
||||
///
|
||||
/// @return projected radius.
|
||||
/// the radius is scaled such that grazing emission maps to 2.
|
||||
@ -1830,17 +1960,20 @@ threadsafe function calc_graph_radius(polar, [projection])
|
||||
|
||||
variable radius
|
||||
switch(projection)
|
||||
case 1: // stereographic
|
||||
case kProjStereo: // stereographic
|
||||
radius = kProjScaleStereo * tan(polar / 2 * pi / 180)
|
||||
break
|
||||
case 2: // azimuthal
|
||||
radius = kProjScaleAzim * cos((180 - polar) / 2 * pi / 180)
|
||||
case kProjArea: // equal area
|
||||
radius = kProjScaleArea * sin(polar / 2 * pi / 180)
|
||||
break
|
||||
case 3: // gnomonic
|
||||
radius = polar < 90 ? kProjScaleGnomonic * tan(polar * pi / 180) : inf
|
||||
case kProjGnom: // gnomonic
|
||||
radius = polar < 90 ? kProjScaleGnom * tan(polar * pi / 180) : inf
|
||||
break
|
||||
default: // linear
|
||||
radius = kProjScaleLinear * polar / 90
|
||||
case kProjOrtho: // orthographic
|
||||
radius = kProjScaleOrtho * sin(polar * pi / 180)
|
||||
break
|
||||
default: // equidistant
|
||||
radius = kProjScaleDist * polar / 90
|
||||
endswitch
|
||||
|
||||
return radius
|
||||
@ -1852,10 +1985,13 @@ end
|
||||
///
|
||||
/// @param x, y projected Cartesian coordinate
|
||||
///
|
||||
/// @param projection mapping function from polar to cartesian coordinates
|
||||
/// @arg 0 linear
|
||||
/// @arg 1 stereographic (default)
|
||||
/// @arg 2 azimuthal
|
||||
/// @param projection mapping function from polar to cartesian coordinates.
|
||||
/// see @ref PageProjections for details.
|
||||
/// @arg kProjDist = 0 azimuthal equidistant
|
||||
/// @arg kProjStereo = 1 stereographic (default)
|
||||
/// @arg kProjArea = 2 azimuthal equal-area
|
||||
/// @arg kProjGnom = 3 gnomonic (0 <= polar < 90)
|
||||
/// @arg kProjOrtho = 4 orthographic
|
||||
///
|
||||
/// @returns polar angle in degrees
|
||||
///
|
||||
@ -1873,17 +2009,20 @@ threadsafe function calc_graph_polar(x, y, [projection])
|
||||
|
||||
radius = sqrt(x^2 + y^2)
|
||||
switch(projection)
|
||||
case 1: // stereographic
|
||||
case kProjStereo: // stereographic
|
||||
polar = 2 * atan(radius / kProjScaleStereo) * 180 / pi
|
||||
break
|
||||
case 2: // azimuthal
|
||||
polar = 180 - 2 * acos(radius / kProjScaleAzim) * 180 / pi
|
||||
case kProjArea: // equal area
|
||||
polar = 2 * asin(radius / kProjScaleArea) * 180 / pi
|
||||
break
|
||||
case 3: // gnomonic
|
||||
polar = atan(radius / kProjScaleGnomonic) * 180 / pi
|
||||
case kProjGnom: // gnomonic
|
||||
polar = atan(radius / kProjScaleGnom) * 180 / pi
|
||||
break
|
||||
default: // linear
|
||||
polar = 90 * radius / kProjScaleLinear
|
||||
case kProjOrtho: // orthographic
|
||||
polar = asin(radius / kProjScaleOrtho) * 180 / pi
|
||||
break
|
||||
default: // equidistant
|
||||
polar = 90 * radius / kProjScaleDist
|
||||
endswitch
|
||||
|
||||
return polar
|
||||
@ -1893,12 +2032,14 @@ end
|
||||
///
|
||||
/// @param x, y projected Cartesian coordinate
|
||||
///
|
||||
/// @param projection mapping function from polar to cartesian coordinates
|
||||
/// @arg 0 linear
|
||||
/// @arg 1 stereographic (default)
|
||||
/// @arg 2 azimuthal
|
||||
///
|
||||
/// projections 0-2 have no effect on the azimuthal coordinate
|
||||
/// @param projection mapping function from polar to cartesian coordinates.
|
||||
/// all supported projections are azimuthal, they have no effect on the azimuthal coordinate.
|
||||
/// see @ref PageProjections for details.
|
||||
/// @arg kProjDist = 0 azimuthal equidistant
|
||||
/// @arg kProjStereo = 1 stereographic (default)
|
||||
/// @arg kProjArea = 2 azimuthal equal-area
|
||||
/// @arg kProjGnom = 3 gnomonic (0 <= polar < 90)
|
||||
/// @arg kProjOrtho = 4 orthographic
|
||||
///
|
||||
/// @param zeroAngle zeroAngleWhere parameter of polar graphs
|
||||
/// @arg 0 (default) zero is at the 3 o'clock position
|
||||
@ -2447,8 +2588,35 @@ end
|
||||
|
||||
/// import a hemispherical scan from theta-phi-intensity waves and display it
|
||||
///
|
||||
/// @warning EXPERIMENTAL
|
||||
/// the interface and behaviour of this function may change
|
||||
/// in the tpi format, the hemi scan data is represented
|
||||
/// by a triple of flat one-dimensional waves
|
||||
/// corresponding to the polar angle (theta), azimuthal angle (phi) and intensity.
|
||||
/// no specific sort order is required.
|
||||
///
|
||||
/// @param nickname nick name for output data
|
||||
/// @arg in default mode, this will become the name of a child folder containing the output.
|
||||
/// @arg in XPDplot mode, this will become a prefix of the generated data in the root folder.
|
||||
///
|
||||
/// @param theta theta angles, 0 = normal emission.
|
||||
///
|
||||
/// @param phi phi angles, 0 = azimuthal origin. size = dimsize(data, 1)
|
||||
///
|
||||
/// @param intensity intensity wave, see requirements above.
|
||||
///
|
||||
/// @param npolar number of polar angles, determines polar and azimuthal step size.
|
||||
/// default = 91 (1 degree steps)
|
||||
///
|
||||
/// @param folding rotational averaging.
|
||||
/// example: 3 = average to 3-fold symmetry.
|
||||
/// default = 1.
|
||||
///
|
||||
/// @param nograph display a new graph window?
|
||||
/// @arg 0 (default) display a new polar graph
|
||||
/// @arg 1 don't display a new graph
|
||||
///
|
||||
/// @param xpdplot XPDplot compatibility
|
||||
/// @arg 0 (default) create waves in child folder $nickname
|
||||
/// @arg 1 create waves in root folder (compatible with XPDplot)
|
||||
///
|
||||
function import_tpi_scan(nickname, theta, phi, intensity, [folding, npolar, nograph, xpdplot])
|
||||
string nickname
|
||||
@ -2483,5 +2651,195 @@ function import_tpi_scan(nickname, theta, phi, intensity, [folding, npolar, nogr
|
||||
fold_phi = fold_phi >= 180 ? fold_phi + 360 / folding - fold_phi : fold_phi + 360 / folding
|
||||
endfor
|
||||
|
||||
display_hemi_scan(nickname)
|
||||
end
|
||||
if (nograph==0)
|
||||
display_hemi_scan(nickname)
|
||||
endif
|
||||
end
|
||||
|
||||
/// trim a hemispherical scan at grazing angle
|
||||
///
|
||||
/// the function recalaculates the values wave from totals and weights
|
||||
/// but sets elements above a given polar angle to nan.
|
||||
///
|
||||
/// @param nickname name of the scan dataset.
|
||||
/// can be empty if no prefix is used.
|
||||
/// the dataset must be in the current datafolder.
|
||||
///
|
||||
/// @param theta_max highest polar angle to keep (0...90 degrees).
|
||||
///
|
||||
function trim_hemi_scan(nickname, theta_max)
|
||||
string nickname
|
||||
variable theta_max
|
||||
|
||||
if (strlen(nickname))
|
||||
string s_prefix = nickname + "_"
|
||||
string s_int = s_prefix + "i"
|
||||
else
|
||||
s_prefix = ""
|
||||
s_int = "values"
|
||||
endif
|
||||
string s_totals = s_prefix + "tot"
|
||||
string s_weights = s_prefix + "wt"
|
||||
string s_polar = s_prefix + "pol"
|
||||
|
||||
wave w_polar = $s_polar
|
||||
wave w_values = $s_int
|
||||
wave w_totals = $s_totals
|
||||
wave w_weights = $s_weights
|
||||
|
||||
w_values = w_polar <= theta_max ? w_totals / w_weights : nan
|
||||
end
|
||||
|
||||
/// extract a polar cut from a hemispherical scan.
|
||||
///
|
||||
/// for each polar angle, the function first extracts all azimuthal angles.
|
||||
/// the intensity is then interpolated between the nearest neighbours of the given azimuth.
|
||||
///
|
||||
/// the hemi grid must have been created in the current data folder by the make_hemi_grid function.
|
||||
/// correct ordering is required.
|
||||
///
|
||||
/// @param nickname name of the scan dataset.
|
||||
/// can be empty if no prefix is used.
|
||||
/// the dataset must be in the current datafolder.
|
||||
///
|
||||
/// @param azim azimuthal angle in degrees
|
||||
///
|
||||
/// @return reference of the created wave.
|
||||
/// the wave has the same name as the intensity wave of the dataset
|
||||
/// with the suffix "_azi" and the azimuthal angle rounded to integer.
|
||||
/// it is created in the same datafolder as the original data.
|
||||
///
|
||||
function /wave hemi_polar_cut(nickname, azim)
|
||||
string nickname
|
||||
variable azim
|
||||
|
||||
if (strlen(nickname))
|
||||
string s_prefix = nickname + "_"
|
||||
string s_int = s_prefix + "i"
|
||||
else
|
||||
s_prefix = ""
|
||||
s_int = "values"
|
||||
endif
|
||||
string s_totals = s_prefix + "tot"
|
||||
string s_weights = s_prefix + "wt"
|
||||
string s_polar = s_prefix + "pol"
|
||||
string s_azim = s_prefix + "az"
|
||||
string s_index = s_prefix + "index"
|
||||
string s_theta = s_prefix + "th"
|
||||
string s_dphi = s_prefix + "dphi"
|
||||
string s_nphis = s_prefix + "nphis"
|
||||
string s_cut
|
||||
sprintf s_cut, "%s_azi%03u", s_int, round(azim)
|
||||
|
||||
wave w_polar = $s_polar
|
||||
wave w_azim = $s_azim
|
||||
wave w_values = $s_int
|
||||
wave w_totals = $s_totals
|
||||
wave w_weights = $s_weights
|
||||
wave w_index = $s_index
|
||||
wave w_theta = $s_theta
|
||||
wave w_dphi = $s_dphi
|
||||
wave w_nphis = $s_nphis
|
||||
|
||||
variable npol = numpnts(w_theta)
|
||||
variable ipol
|
||||
variable pol_st = abs(w_theta[1] - w_theta[0])
|
||||
variable pol
|
||||
variable pol1, pol2
|
||||
variable nsel
|
||||
make /n=(npol) /o $s_cut
|
||||
wave w_cut = $s_cut
|
||||
setscale /i x w_theta[0], w_theta[numpnts(w_theta)-1], "deg", w_cut
|
||||
make /n=1 /free azi_slice
|
||||
make /n=1 /free values_slice
|
||||
|
||||
for (ipol = 0; ipol < npol; ipol += 1)
|
||||
pol = w_theta[ipol]
|
||||
pol1 = pol - pol_st / 2
|
||||
pol2 = pol + pol_st / 2
|
||||
extract /free /indx w_polar, sel, (pol1 < w_polar) && (w_polar <= pol2)
|
||||
nsel = numpnts(sel)
|
||||
if (nsel > 0)
|
||||
redimension /n=(nsel+2) azi_slice, values_slice
|
||||
azi_slice[1, nsel] = w_azim[sel[p-1]]
|
||||
azi_slice[0] = azi_slice[nsel] - 360
|
||||
azi_slice[nsel+1] = azi_slice[1] + 360
|
||||
values_slice[1, nsel] = w_values[sel[p-1]]
|
||||
values_slice[0] = values_slice[nsel]
|
||||
values_slice[nsel+1] = values_slice[1]
|
||||
w_cut[ipol] = interp(azim, azi_slice, values_slice)
|
||||
else
|
||||
w_cut[ipol] = nan
|
||||
endif
|
||||
endfor
|
||||
return w_cut
|
||||
end
|
||||
|
||||
/// extract an azimuthal cut from a hemispherical scan
|
||||
///
|
||||
/// the function extracts all azimuthal angles that are present for the given polar angle.
|
||||
///
|
||||
/// the hemi grid must have been created in the current data folder by the make_hemi_grid function.
|
||||
/// correct ordering is required.
|
||||
///
|
||||
/// @param nickname name of the scan dataset.
|
||||
/// can be empty if no prefix is used.
|
||||
/// the dataset must be in the current datafolder.
|
||||
///
|
||||
/// @param pol polar angle in degrees
|
||||
///
|
||||
/// @return reference of the created wave.
|
||||
/// the wave has the same name as the intensity wave of the dataset
|
||||
/// with the suffix "_azi" and the azimuthal angle rounded to integer.
|
||||
/// it is created in the same datafolder as the original data.
|
||||
///
|
||||
function /wave hemi_azi_cut(nickname, pol)
|
||||
string nickname
|
||||
variable pol
|
||||
|
||||
if (strlen(nickname))
|
||||
string s_prefix = nickname + "_"
|
||||
string s_int = s_prefix + "i"
|
||||
else
|
||||
s_prefix = ""
|
||||
s_int = "values"
|
||||
endif
|
||||
string s_totals = s_prefix + "tot"
|
||||
string s_weights = s_prefix + "wt"
|
||||
string s_polar = s_prefix + "pol"
|
||||
string s_azim = s_prefix + "az"
|
||||
string s_index = s_prefix + "index"
|
||||
string s_theta = s_prefix + "th"
|
||||
string s_dphi = s_prefix + "dphi"
|
||||
string s_nphis = s_prefix + "nphis"
|
||||
string s_cut
|
||||
sprintf s_cut, "%s_pol%03u", s_int, round(pol)
|
||||
|
||||
wave w_polar = $s_polar
|
||||
wave w_azim = $s_azim
|
||||
wave w_values = $s_int
|
||||
wave w_totals = $s_totals
|
||||
wave w_weights = $s_weights
|
||||
wave w_index = $s_index
|
||||
wave w_theta = $s_theta
|
||||
wave w_dphi = $s_dphi
|
||||
wave w_nphis = $s_nphis
|
||||
|
||||
variable pol_st = abs(w_theta[1] - w_theta[0])
|
||||
variable pol1, pol2
|
||||
variable nsel
|
||||
|
||||
pol1 = pol - pol_st / 2
|
||||
pol2 = pol + pol_st / 2
|
||||
extract /free /indx w_polar, sel, (pol1 < w_polar) && (w_polar <= pol2)
|
||||
nsel = numpnts(sel)
|
||||
if (nsel > 0)
|
||||
make /n=(nsel) /o $s_cut
|
||||
wave w_cut = $s_cut
|
||||
w_cut = w_values[sel]
|
||||
setscale /i x w_azim[sel[0]], w_azim[sel[nsel-1]], "<22>", w_cut
|
||||
return w_cut
|
||||
else
|
||||
return $""
|
||||
endif
|
||||
end
|
||||
|
@ -436,7 +436,7 @@ static function setup_detector()
|
||||
setdatafolder $(package_path)
|
||||
|
||||
make /n=31 /o detector_angle, detector_pol, detector_az, detector_rad
|
||||
setscale /i x -30, 30, "deg", detector_angle, detector_pol, detector_az, detector_rad
|
||||
setscale /i x -30, 30, "°", detector_angle, detector_pol, detector_az, detector_rad
|
||||
detector_angle = x
|
||||
|
||||
setdatafolder saveDF
|
||||
@ -573,7 +573,7 @@ static function update_detector(theta, tilt, phi, range)
|
||||
//m_phi *= -1 // checked 140702
|
||||
|
||||
wave detector_angle, detector_pol, detector_az, detector_rad
|
||||
setscale /i x -range/2, +range/2, "deg", detector_angle
|
||||
setscale /i x -range/2, +range/2, "°", detector_angle
|
||||
detector_angle = x
|
||||
|
||||
convert_angles_ttpa2polar(m_theta, m_tilt, m_phi, detector_angle, detector_pol, detector_az)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -52,6 +52,25 @@
|
||||
/// PearlAreaDisplay is declared in @ref pearl-area-display.ipf.
|
||||
///
|
||||
|
||||
/// compose a valid and unique graph name from a data folder reference
|
||||
static function /s graphname_from_dfref(df, prefix)
|
||||
dfref df
|
||||
string prefix
|
||||
|
||||
string name
|
||||
|
||||
name = GetDataFolder(1, df)
|
||||
name = ReplaceString("root:", name, "")
|
||||
name = name[0, strlen(name) - 2]
|
||||
name = ReplaceString(" ", name, "")
|
||||
name = CleanupName(prefix + name, 0)
|
||||
if (CheckName(name, 6))
|
||||
name = UniqueName(name, 6, 0)
|
||||
endif
|
||||
|
||||
return name
|
||||
end
|
||||
|
||||
/// open a new graph window with a 2D image.
|
||||
///
|
||||
/// this is essentially <code>display; appendimage</code>.
|
||||
@ -72,7 +91,7 @@ function /s ad_display(image)
|
||||
|
||||
string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
|
||||
string graphtitle = dfname + " View"
|
||||
string /g view_graphname = CleanupName("view_" + dfname, 0)
|
||||
string /g view_graphname = graphname_from_dfref(imagedf, "view_")
|
||||
svar graphname = view_graphname
|
||||
display /k=1/n=$graphname as graphtitle
|
||||
graphname = s_name
|
||||
@ -104,7 +123,7 @@ function /s ad_display_histogram(image)
|
||||
|
||||
string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
|
||||
string graphtitle = dfname + " Histogram"
|
||||
string /g hist_graphname = CleanupName("hist_" + dfname, 0)
|
||||
string /g hist_graphname = graphname_from_dfref(imagedf, "hist_")
|
||||
svar graphname = hist_graphname
|
||||
display /k=1/n=$graphname as graphtitle
|
||||
graphname = s_name
|
||||
@ -171,16 +190,16 @@ function /s ad_display_profiles(image, [filter])
|
||||
duplicate /o image, $viewname /wave=view
|
||||
make /n=(3,3)/o xprofiles // NX x 3 wave with 3 one-dimensional profiles along Y dimension
|
||||
make /n=(3,3)/o yprofiles // NY x 3 wave with 3 one-dimensional profiles along X dimension
|
||||
make /n=(1)/o hist // histogram
|
||||
string /g view_filter
|
||||
string /g view_filter_options
|
||||
view_filter = filter
|
||||
view_filter_options = ""
|
||||
variable /g view_filter_smoothing_x = 1
|
||||
variable /g view_filter_smoothing_y = 1
|
||||
string dfname = GetDataFolder(0, imagedf)
|
||||
string graphtitle = dfname + ":" + NameOfWave(image) + " Profiles"
|
||||
string /g prof_graphname = CleanupName("prof_" + dfname, 0)
|
||||
variable /g view_cursor_mode = 0
|
||||
string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
|
||||
string graphtitle = dfname + NameOfWave(image) + " Profiles"
|
||||
string /g prof_graphname = graphname_from_dfref(imagedf, "prof_")
|
||||
svar graphname = prof_graphname
|
||||
variable /g graph_avg // average value in ROI (ROI is defined by the crosshairs A and B)
|
||||
variable /g graph_min // minimum value in ROI
|
||||
@ -193,16 +212,13 @@ function /s ad_display_profiles(image, [filter])
|
||||
graphname = s_name
|
||||
AppendToGraph /w=$graphname /L=xprofiles xprofiles[*][0],xprofiles[*][1],xprofiles[*][2]
|
||||
AppendToGraph /w=$graphname /VERT/B=yprofiles yprofiles[*][0],yprofiles[*][1],yprofiles[*][2]
|
||||
AppendToGraph /w=$graphname /R=hist/B=yprofiles hist
|
||||
AppendImage /w=$graphname view
|
||||
string imgname = StringFromList(0, ImageNameList(graphname, ";"))
|
||||
ModifyImage /w=$graphname $imgname ctab= {*,*,BlueGreenOrange,0}
|
||||
ModifyGraph /w=$graphname rgb(xprofiles)=(39168,0,0),rgb(yprofiles)=(39168,0,0)
|
||||
ModifyGraph /w=$graphname rgb(xprofiles#1)=(0,26112,0),rgb(yprofiles#1)=(0,26112,0)
|
||||
ModifyGraph /w=$graphname rgb(xprofiles#2)=(0,9472,39168),rgb(yprofiles#2)=(0,9472,39168)
|
||||
ModifyGraph /w=$graphname rgb(hist)=(43520,43520,43520)
|
||||
ModifyGraph /w=$graphname mode(hist)=5,hbFill(hist)=2
|
||||
ModifyGraph /w=$graphname mirror(xprofiles)=0,mirror(bottom)=3,mirror(yprofiles)=3,mirror(left)=3
|
||||
ModifyGraph /w=$graphname mirror(xprofiles)=2,mirror(bottom)=3,mirror(yprofiles)=2,mirror(left)=3
|
||||
ModifyGraph /w=$graphname nticks=3
|
||||
ModifyGraph /w=$graphname minor=1
|
||||
ModifyGraph /w=$graphname axThick=0.5
|
||||
@ -210,21 +226,33 @@ function /s ad_display_profiles(image, [filter])
|
||||
ModifyGraph /w=$graphname btLen=4
|
||||
ModifyGraph /w=$graphname freePos(xprofiles)=0
|
||||
ModifyGraph /w=$graphname freePos(yprofiles)=0
|
||||
ModifyGraph /w=$graphname freePos(hist)=0
|
||||
ModifyGraph /w=$graphname axisEnab(xprofiles)={0.64,1}
|
||||
ModifyGraph /w=$graphname axisEnab(hist)={0.64,1}
|
||||
ModifyGraph /w=$graphname axisEnab(bottom)={0,0.6}
|
||||
ModifyGraph /w=$graphname axisEnab(yprofiles)={0.64,1}
|
||||
ModifyGraph /w=$graphname axisEnab(left)={0,0.6}
|
||||
ModifyGraph /w=$graphname zero(left)=8
|
||||
ModifyGraph /w=$graphname margin(left)=40,margin(bottom)=30,margin(top)=20,margin(right)=40
|
||||
ModifyGraph /w=$graphname gfSize=10
|
||||
Label /w=$graphname xprofiles "value (\\U)"
|
||||
Label /w=$graphname bottom "X (\\U)"
|
||||
Label /w=$graphname yprofiles "value (\\U)"
|
||||
Label /w=$graphname left "Y (\\U)"
|
||||
Label /w=$graphname hist "\\Epixels"
|
||||
SetAxis /w=$graphname /A /E=1 hist
|
||||
|
||||
// axis labels
|
||||
string labels = note(image)
|
||||
string lab
|
||||
lab = StringByKey("AxisLabelX", labels, "=", "\r")
|
||||
if (!strlen(lab))
|
||||
lab = "X"
|
||||
endif
|
||||
Label /w=$graphname bottom lab + " (\\U)"
|
||||
lab = StringByKey("AxisLabelY", labels, "=", "\r")
|
||||
if (!strlen(lab))
|
||||
lab = "Y"
|
||||
endif
|
||||
Label /w=$graphname left lab + " (\\U)"
|
||||
lab = StringByKey("AxisLabelD", labels, "=", "\r")
|
||||
if (!strlen(lab))
|
||||
lab = "value"
|
||||
endif
|
||||
Label /w=$graphname xprofiles lab + " (\\U)"
|
||||
Label /w=$graphname yprofiles lab + " (\\U)"
|
||||
|
||||
// legend
|
||||
if (show_legend)
|
||||
@ -233,13 +261,18 @@ function /s ad_display_profiles(image, [filter])
|
||||
AppendText /w=$graphname "\\s(xprofiles#2)\tROI average"
|
||||
AppendText /w=$graphname "min\t\\{" + s_viewdf + "graph_min}"
|
||||
AppendText /w=$graphname "max\t\\{" + s_viewdf + "graph_max}"
|
||||
AppendText /w=$graphname "avg\t\\{" + s_viewdf + "graph_avg}"
|
||||
AppendText /w=$graphname "sum\t\\{" + s_viewdf + "graph_sum}"
|
||||
AppendText /w=$graphname "avg\t\\{" + s_viewdf + "graph_avg}"
|
||||
AppendText /w=$graphname "sdev\t\\{" + s_viewdf + "graph_sdev}"
|
||||
else
|
||||
TextBox /w=$graphname /C/N=text_sum/F=0/B=1/X=1.00/Y=1.00 "sum \\{" + s_viewdf + "graph_sum}"
|
||||
TextBox /w=$graphname /C/N=text_avg/F=0/B=1/X=1.00/Y=6.00 "avg \\{" + s_viewdf + "graph_avg}"
|
||||
TextBox /w=$graphname /C/N=text_sdev/F=0/B=1/X=1.00/Y=11.00 "sdev \\{" + s_viewdf + "graph_sdev}"
|
||||
TextBox /w=$graphname /C/N=text0 /F=0 /B=1 /X=1.00 /Y=1.00
|
||||
lab = StringByKey("Dataset", labels, "=", "\r")
|
||||
if (strlen(lab))
|
||||
AppendText /w=$graphname lab
|
||||
endif
|
||||
AppendText /w=$graphname "sum\t\\{" + s_viewdf + "graph_sum}"
|
||||
AppendText /w=$graphname "avg\t\\{" + s_viewdf + "graph_avg}"
|
||||
AppendText /w=$graphname "sdev\t\\{" + s_viewdf + "graph_sdev}"
|
||||
endif
|
||||
|
||||
// interactive elements
|
||||
@ -316,15 +349,88 @@ function ad_update_profiles(image)
|
||||
return 0
|
||||
end
|
||||
|
||||
/// switch cursors on a profiles graph
|
||||
///
|
||||
/// the standard cursors allow to select the profiles to display in the profiles panes.
|
||||
/// additional cursors are shown in the profiles panes.
|
||||
///
|
||||
/// in the background selection mode, additional cursors allow the user to select
|
||||
/// the limits of the background and peak integration regions.
|
||||
/// the meaning of the cursors depends on the particular processing function.
|
||||
///
|
||||
/// @param mode cursor mode.
|
||||
/// @arg 0 (default) standard profile selection. cursors C-F on profile panes.
|
||||
/// @arg 1 background selection. cursors A-F on image.
|
||||
///
|
||||
/// @param image image displayed in the graph.
|
||||
/// this is the original image, not the one in the view data folder.
|
||||
///
|
||||
function ad_profiles_cursor_mode(image, mode)
|
||||
wave image
|
||||
variable mode
|
||||
|
||||
dfref savedf = GetDataFolderDFR()
|
||||
wave view_image = get_view_image(image)
|
||||
dfref viewdf = GetWavesDataFolderDFR(view_image)
|
||||
svar /sdfr=viewdf graphname = prof_graphname
|
||||
nvar /sdfr=viewdf cursor_mode = view_cursor_mode
|
||||
wave /sdfr=viewdf xprofiles, yprofiles
|
||||
|
||||
variable dx = DimSize(view_image, 0)
|
||||
variable dy = DimSize(view_image, 1)
|
||||
switch(mode)
|
||||
case 1: // background selection
|
||||
Cursor /w=$graphname /A=0 /P /I /S=2 /H=1 /L=1 A view_image 0, 0
|
||||
Cursor /w=$graphname /A=0 /P /I /S=2 /H=1 /L=1 B view_image dx-1, dy-1
|
||||
Cursor /w=$graphname /A=0 /P /I /S=2 /H=2 /L=1 C view_image round(0.2 * dx) -1, 0
|
||||
Cursor /w=$graphname /A=0 /P /I /S=2 /H=2 /L=1 D view_image round(0.8 * dx) -1, 0
|
||||
Cursor /w=$graphname /A=0 /P /I /S=2 /H=2 /L=1 E view_image round(0.4 * dx) -1, 0
|
||||
Cursor /w=$graphname /A=0 /P /I /S=2 /H=2 /L=1 F view_image round(0.6 * dx) -1, 0
|
||||
|
||||
ShowInfo /w=$graphname /CP=0
|
||||
cursor_mode = mode
|
||||
break
|
||||
default:
|
||||
Cursor /w=$graphname /A=1 /P /I /S=2 /H=1 /L=1 A view_image 0,0
|
||||
Cursor /w=$graphname /A=1 /P /I /S=2 /H=1 /L=1 B view_image dx-1, dy-1
|
||||
variable pcurs
|
||||
pcurs = floor(DimSize(xprofiles, 0) / 3)
|
||||
Cursor /w=$graphname /A=0 /P /S=1 /H=0 C xprofiles#2 pcurs
|
||||
pcurs = floor(DimSize(xprofiles, 0) * 2 / 3)
|
||||
Cursor /w=$graphname /A=0 /P /S=1 /H=0 D xprofiles#2 pcurs
|
||||
pcurs = floor(DimSize(yprofiles, 0) / 3)
|
||||
Cursor /w=$graphname /A=0 /P /S=1 /H=0 E yprofiles#2 pcurs
|
||||
pcurs = floor(DimSize(yprofiles, 0) * 2 / 3)
|
||||
Cursor /w=$graphname /A=0 /P /S=1 /H=0 F yprofiles#2 pcurs
|
||||
ShowInfo /w=$graphname /CP=0
|
||||
cursor_mode = 0
|
||||
endswitch
|
||||
|
||||
setdatafolder savedf
|
||||
return 0
|
||||
end
|
||||
|
||||
/// move a cursor to the specified position in a profiles graph.
|
||||
///
|
||||
/// this function can only set cursors in the image part of the profiles graph.
|
||||
///
|
||||
/// @param image image displayed in the graph.
|
||||
/// this is the original image, not the one in the view data folder.
|
||||
/// @param cursorname name of the cursor, e.g. "A" or "B".
|
||||
/// other cursors are allowed but need to be activated separately.
|
||||
/// @param xa x-coordinate to move the cursor to.
|
||||
/// the position is coerced to the image scale. +/-inf is allowed.
|
||||
/// @param ya y-coordinate to move the cursor to.
|
||||
/// the position is coerced to the image scale. +/-inf is allowed.
|
||||
/// @param pscale scaling of the position argument
|
||||
/// @arg 0 (default) wave scaling
|
||||
/// @arg 1 point scaling
|
||||
///
|
||||
function ad_profiles_set_cursor(image, cursorname, xa, ya, [pscale])
|
||||
wave image // image displayed in the graph. this is the original image, not the one in the view data folder.
|
||||
string cursorname // name of the cursor. must be "A" or "B".
|
||||
variable xa, ya // position to move the cursor to.
|
||||
// the position is coerced to the image scale. +/-inf is allowed.
|
||||
variable pscale // scaling of the position argument
|
||||
// 0 (default) = wave scaling
|
||||
// 1 = point scaling
|
||||
wave image
|
||||
string cursorname
|
||||
variable xa, ya
|
||||
variable pscale
|
||||
|
||||
if (ParamIsDefault(pscale))
|
||||
pscale = 0
|
||||
@ -991,7 +1097,7 @@ function /s ad_display_brick(data)
|
||||
setdatafolder viewdf
|
||||
string dfname = ReplaceString("root:", s_datadf, "")
|
||||
string graphtitle = dfname + " Gizmo"
|
||||
string /g gizmo_graphname = CleanupName("giz_" + dfname, 0)
|
||||
string /g gizmo_graphname = graphname_from_dfref(datadf, "giz_")
|
||||
svar graphname = gizmo_graphname
|
||||
|
||||
if ((strlen(graphname) > 0) && (wintype(graphname) == 13))
|
||||
@ -1115,13 +1221,32 @@ function ad_brick_slicer(data)
|
||||
variable /g x_autoinc = 0
|
||||
variable /g y_autoinc = 0
|
||||
variable /g z_autoinc = 0
|
||||
|
||||
// axis labels
|
||||
string labels = note(data)
|
||||
string xlabel = StringByKey("AxisLabelX", labels, "=", "\r")
|
||||
if (!strlen(xlabel))
|
||||
xlabel = "X"
|
||||
endif
|
||||
string ylabel = StringByKey("AxisLabelY", labels, "=", "\r")
|
||||
if (!strlen(ylabel))
|
||||
ylabel = "Y"
|
||||
endif
|
||||
string zlabel = StringByKey("AxisLabelZ", labels, "=", "\r")
|
||||
if (!strlen(zlabel))
|
||||
zlabel = "Z"
|
||||
endif
|
||||
string dlabel = StringByKey("Dataset", labels, "=", "\r")
|
||||
if (!strlen(dlabel))
|
||||
dlabel = NameOfWave(data)
|
||||
endif
|
||||
|
||||
// this section copied from slicer panel
|
||||
NewPanel /k=1 /W=(500,600,890,940) /N=SlicerPanel as "Brick Slicer"
|
||||
string /g slicer_panelname = S_name
|
||||
string panel = s_name
|
||||
|
||||
GroupBox g_xslice win=$panel,pos={8,8},size={376,96},title="X Slice"
|
||||
|
||||
GroupBox g_xslice win=$panel,pos={8,8},size={376,96},title=xlabel
|
||||
Slider sl_xslice_position win=$panel,pos={16,32},size={240,56},proc=PearlAreaDisplay#slp_slice_position
|
||||
Slider sl_xslice_position win=$panel,limits={0,100,1},variable=x_slice_pos,vert= 0
|
||||
SetVariable sv_xslice_position win=$panel,pos={20,80},size={92,16},proc=PearlAreaDisplay#svp_slice_position,title="X"
|
||||
@ -1141,7 +1266,7 @@ function ad_brick_slicer(data)
|
||||
Button b_xslice_stop win=$panel,pos={336,48},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616"
|
||||
Button b_xslice_stop win=$panel,help={"stop animation"}
|
||||
|
||||
GroupBox g_yslice win=$panel,pos={8,108},size={376,96},title="Y Slice"
|
||||
GroupBox g_yslice win=$panel,pos={8,108},size={376,96},title=ylabel
|
||||
Slider sl_yslice_position win=$panel,pos={16,132},size={240,56},proc=PearlAreaDisplay#slp_slice_position
|
||||
Slider sl_yslice_position win=$panel,limits={0,100,1},variable=y_slice_pos,vert= 0
|
||||
SetVariable sv_yslice_position win=$panel,pos={20,180},size={92,16},proc=PearlAreaDisplay#svp_slice_position,title="Y"
|
||||
@ -1161,7 +1286,7 @@ function ad_brick_slicer(data)
|
||||
Button b_yslice_stop win=$panel,pos={336,148},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616"
|
||||
Button b_yslice_stop win=$panel,help={"stop animation"}
|
||||
|
||||
GroupBox g_zslice win=$panel,pos={8,208},size={376,96},title="Z Slice"
|
||||
GroupBox g_zslice win=$panel,pos={8,208},size={376,96},title=zlabel
|
||||
Slider sl_zslice_position win=$panel,pos={16,232},size={240,56},proc=PearlAreaDisplay#slp_slice_position
|
||||
Slider sl_zslice_position win=$panel,limits={0,100,1},variable=z_slice_pos,vert= 0
|
||||
SetVariable sv_zslice_position win=$panel,pos={20,280},size={92,16},proc=PearlAreaDisplay#svp_slice_position,title="Z"
|
||||
@ -1181,7 +1306,7 @@ function ad_brick_slicer(data)
|
||||
Button b_zslice_stop win=$panel,pos={336,248},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616"
|
||||
Button b_zslice_stop win=$panel,help={"stop animation"}
|
||||
|
||||
TitleBox t_slicerpath win=$panel,pos={8,316},size={128,20},disable=2,title=GetDataFolder(1,viewdf)
|
||||
TitleBox t_slicerpath win=$panel,pos={8,316},size={128,20},disable=2,title=dlabel
|
||||
//SetVariable setvar0 win=$panel,pos={240,316},size={120,16},title="slab thickness"
|
||||
//SetVariable setvar0 win=$panel,limits={1,inf,1},value=slab_thickness
|
||||
|
||||
|
@ -3,23 +3,35 @@
|
||||
#pragma ModuleName = PearlAreaImport
|
||||
#pragma version = 1.06
|
||||
#include <HDF5 Browser>
|
||||
#include "pearl-gui-tools", version >= 1.01
|
||||
#include "pearl-gui-tools"
|
||||
|
||||
// HDF5 file import from EPICS area detectors
|
||||
// such as CCD cameras, 2D electron analysers
|
||||
// copyright (c) 2013-16 Paul Scherrer Institut
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http:///www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// restriction: as of version 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.
|
||||
/// @file
|
||||
/// @brief HDF5 file import from EPICS area detectors
|
||||
/// @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
|
||||
// Copyright (c) 2013 Paul Scherrer Institut
|
||||
// $Id$
|
||||
/// @namespace PearlAreaImport
|
||||
/// @brief HDF5 file import from EPICS area detectors
|
||||
///
|
||||
/// 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)
|
||||
// allows drag&drop of data files into an open igor window
|
||||
// this works only with igor 5.02 or later
|
||||
variable refNum, kind
|
||||
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
|
||||
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])
|
||||
// suggests 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.
|
||||
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
|
||||
string filename
|
||||
variable ignoredate
|
||||
string sourcename
|
||||
variable unique
|
||||
|
||||
if (ParamIsDefault(ignoredate))
|
||||
ignoredate = 0
|
||||
@ -86,6 +115,8 @@ function /s ad_suggest_foldername(filename, [ignoredate,sourcename,unique])
|
||||
string autosource
|
||||
if (strsearch(basename, "scienta", 0, 2) >= 0)
|
||||
autosource = "sci"
|
||||
elseif (strsearch(basename, "pshell", 0, 2) >= 0)
|
||||
autosource = "psh"
|
||||
elseif (strsearch(basename, "OP-SL", 0, 2) >= 0)
|
||||
autosource = "sl"
|
||||
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, "-")
|
||||
if (nparts >= 3)
|
||||
string datepart = StringFromList(nparts - 2, basename, "-")
|
||||
string indexpart = StringFromList(nparts - 1, basename, "-")
|
||||
string datepart = StringFromList(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)
|
||||
sprintf nickname, "%s_%s", sourcename, indexpart
|
||||
else
|
||||
@ -117,10 +152,12 @@ function /s ad_suggest_foldername(filename, [ignoredate,sourcename,unique])
|
||||
return nickname
|
||||
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)
|
||||
// loads data files selected in a file dialog window
|
||||
string APathName // igor symbolic path name
|
||||
// if empty, Igor will choose a folder on its own
|
||||
string APathName
|
||||
|
||||
variable refNum
|
||||
string message = "Select data files"
|
||||
@ -148,17 +185,23 @@ function ad_load_dialog(APathName)
|
||||
setdatafolder saveDF
|
||||
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])
|
||||
// this function loads 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.
|
||||
string ANickName // destination folder name (top level under root)
|
||||
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
|
||||
// for proper wave scaling, the attributes must be loaded
|
||||
string ANickName
|
||||
string APathName
|
||||
string AFileName
|
||||
variable load_data
|
||||
variable load_attr
|
||||
|
||||
if (ParamIsDefault(load_data))
|
||||
load_data = 1
|
||||
@ -222,30 +265,43 @@ function /s adh5_load_complete(ANickName, APathName, AFileName, [load_data, load
|
||||
return AFileName
|
||||
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])
|
||||
// this function loads a reduced 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.
|
||||
string ANickName
|
||||
string APathName
|
||||
string AFileName
|
||||
|
||||
// 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.
|
||||
funcref adh5_default_reduction reduction_func
|
||||
string reduction_param
|
||||
|
||||
// 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.
|
||||
string ANickName // destination folder name (top level under root)
|
||||
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
|
||||
variable load_data
|
||||
variable load_attr
|
||||
variable progress
|
||||
|
||||
if (ParamIsDefault(load_data))
|
||||
load_data = 1
|
||||
@ -306,18 +362,26 @@ function /s adh5_load_reduced(ANickName, APathName, AFileName, reduction_func, r
|
||||
return AFileName
|
||||
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])
|
||||
// this function loads one 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.
|
||||
// EXPERIMENTAL
|
||||
// this function uses the root:pearl_area:preview data folder. existing data there may be deleted!
|
||||
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
|
||||
string ANickName
|
||||
string APathName
|
||||
string AFileName
|
||||
variable load_data
|
||||
variable load_attr
|
||||
|
||||
if (ParamIsDefault(load_data))
|
||||
load_data = 1
|
||||
@ -412,13 +476,19 @@ function /s adh5_load_preview(ANickName, APathName, AFileName, [load_data, load_
|
||||
return AFileName
|
||||
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)
|
||||
// this function loads descriptive info from a HDF5 file created by the Area Detector software.
|
||||
// the information returned is the array size and active scans
|
||||
// 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
|
||||
string APathName
|
||||
string AFileName
|
||||
|
||||
dfref saveDF = GetDataFolderDFR()
|
||||
|
||||
@ -492,12 +562,17 @@ function /s adh5_load_info(APathName, AFileName)
|
||||
return s_info
|
||||
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)
|
||||
// loads 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
|
||||
variable fileID // ID of open HDF5 file from HDF5OpenFile
|
||||
string detectorpath // path to detector group in the HDF5 file
|
||||
variable fileID
|
||||
string detectorpath
|
||||
|
||||
// avoid compilation error if HDF5 XOP has not been loaded
|
||||
#if Exists("HDF5LoadData")
|
||||
@ -526,19 +601,22 @@ function adh5_load_detector(fileID, detectorpath)
|
||||
#endif
|
||||
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)
|
||||
// redimensions 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)
|
||||
|
||||
wave data // area detector data loaded from HDF5 to be redimensioned
|
||||
wave data
|
||||
|
||||
duplicate /free data, tempdata
|
||||
variable nd = wavedims(tempdata)
|
||||
@ -608,29 +686,36 @@ function adh5_redim(data)
|
||||
endswitch
|
||||
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)
|
||||
// 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
|
||||
|
||||
dfref saveDF = GetDataFolderDFR()
|
||||
dfref dataDF = GetWavesDataFolderDFR(data)
|
||||
setdatafolder dataDF
|
||||
if (DataFolderExists(":attr"))
|
||||
setdatafolder :attr
|
||||
dfref attrDF = dataDF:attr
|
||||
if (DataFolderRefStatus(attrDF) == 0)
|
||||
attrDF = dataDF
|
||||
endif
|
||||
dfref attrDF = GetDataFolderDFR()
|
||||
setdatafolder saveDF
|
||||
|
||||
return attrDF
|
||||
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])
|
||||
// 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
|
||||
string source
|
||||
|
||||
@ -671,14 +756,23 @@ function adh5_scale(data,[source])
|
||||
setdatafolder saveDF
|
||||
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])
|
||||
// loads 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.
|
||||
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
|
||||
variable fileID
|
||||
string detectorpath
|
||||
variable progress
|
||||
|
||||
if (ParamIsDefault(progress))
|
||||
progress = 1
|
||||
@ -821,23 +915,32 @@ function adh5_load_detector_slabs(fileID, detectorpath, [progress])
|
||||
return result
|
||||
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)
|
||||
// loads a single image from the detector dataset of the open HDF5 file
|
||||
// the function can average over a region in the extra dimensions
|
||||
variable fileID // ID of open HDF5 file from HDF5OpenFile
|
||||
string detectorpath // path to detector group in the HDF5 file
|
||||
variable 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
|
||||
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
|
||||
variable fileID
|
||||
string detectorpath
|
||||
variable dim2start
|
||||
variable dim2count
|
||||
variable dim3start
|
||||
variable dim3count
|
||||
|
||||
// avoid compilation error if HDF5 XOP has not been loaded
|
||||
#if Exists("HDF5LoadData")
|
||||
@ -922,10 +1025,12 @@ function adh5_load_detector_image(fileID, detectorpath, dim2start, dim2count, di
|
||||
#endif
|
||||
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()
|
||||
// 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 result = ""
|
||||
|
||||
@ -960,26 +1065,35 @@ function /s adh5_list_reduction_funcs()
|
||||
return result
|
||||
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)
|
||||
// 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.
|
||||
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 ¶m // string with optional parameters, shared between calls
|
||||
// this is a pass-by-reference argument,
|
||||
// the function may modify the string
|
||||
wave source
|
||||
wave dest1, dest2
|
||||
string ¶m
|
||||
|
||||
// demo code
|
||||
// integrate along the dimensions
|
||||
@ -988,13 +1102,15 @@ threadsafe function adh5_default_reduction(source, dest1, dest2, param)
|
||||
adh5_setup_profile(source, dest2, 1)
|
||||
ad_profile_y_w(source, 0, -1, dest2)
|
||||
|
||||
return 0 // return zero if successful, non-zero if an error occurs
|
||||
return 0
|
||||
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)
|
||||
// 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 profile // destination wave
|
||||
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
|
||||
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)
|
||||
// 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 dest1
|
||||
wave dest2
|
||||
@ -1020,28 +1137,35 @@ function /s adh5_test_reduction_func(source, dest1, dest2, reduction_func, reduc
|
||||
return reduction_param
|
||||
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])
|
||||
// loads 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.
|
||||
|
||||
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
|
||||
variable fileID
|
||||
string detectorpath
|
||||
funcref adh5_default_reduction reduction_func
|
||||
string reduction_param
|
||||
variable progress
|
||||
variable nthreads
|
||||
|
||||
if (ParamIsDefault(progress))
|
||||
progress = 1
|
||||
@ -1340,17 +1464,21 @@ threadsafe static function reduce_slab_image(slabdata, image, profile1, profile2
|
||||
return reduction_func(image, profile1, profile2, reduction_param)
|
||||
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)
|
||||
// loads 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.
|
||||
|
||||
variable fileID // ID of open HDF5 file from HDF5OpenFile
|
||||
string attributespath // path to NDAttributes group in the HDF5 file
|
||||
variable fileID
|
||||
string attributespath
|
||||
|
||||
string datasetname
|
||||
string datawavename
|
||||
@ -1417,11 +1545,20 @@ function adh5_loadattr_all(fileID, attributespath)
|
||||
|
||||
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)
|
||||
// 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.
|
||||
// can be text or numeric.
|
||||
string source
|
||||
@ -1467,12 +1604,14 @@ static function read_attribute_info(datawavename, source, idest)
|
||||
endif
|
||||
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)
|
||||
// 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
|
||||
|
||||
dfref saveDF = GetDataFolderDFR()
|
||||
@ -1528,12 +1667,12 @@ function adh5_scale_scienta(data)
|
||||
case 1: // Angular45
|
||||
ALow = -45/2
|
||||
AHigh = +45/2
|
||||
AUnit = "deg"
|
||||
AUnit = "°"
|
||||
break
|
||||
case 2: // Angular60
|
||||
ALow = -60/2
|
||||
AHigh = +60/2
|
||||
AUnit = "deg"
|
||||
AUnit = "°"
|
||||
break
|
||||
endswitch
|
||||
endif
|
||||
@ -1571,11 +1710,13 @@ function adh5_scale_scienta(data)
|
||||
setdatafolder saveDF
|
||||
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)
|
||||
// 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
|
||||
|
||||
dfref saveDF = GetDataFolderDFR()
|
||||
|
@ -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
|
@ -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
|
@ -613,3 +613,36 @@ threadsafe function calc_y_profile_mins(image)
|
||||
yminlocs[ix] = v_minloc
|
||||
endfor
|
||||
end
|
||||
|
||||
/// collect profiles from a multi-scan.
|
||||
///
|
||||
/// @warning experimental: name and interface of this function may change.
|
||||
///
|
||||
function ad_collect_multiscan_y(dataset, positions, destwave, [noavg])
|
||||
wave dataset
|
||||
wave positions
|
||||
wave destwave
|
||||
variable noavg
|
||||
|
||||
variable tol = (wavemax(positions) - wavemin(positions)) / numpnts(positions) / 100
|
||||
|
||||
duplicate /free positions, positions_sorted
|
||||
sort positions_sorted, positions_sorted
|
||||
duplicate /free positions_sorted, positions_diff
|
||||
differentiate /p /meth=2 positions_sorted /d=positions_diff
|
||||
positions_diff[0] = 1
|
||||
extract /free positions_sorted, positions_unique, positions_diff > tol
|
||||
variable n_unique = numpnts(positions_unique)
|
||||
redimension /n=(dimsize(dataset, 0), n_unique) destwave
|
||||
|
||||
variable i
|
||||
variable nx, ny
|
||||
for (i = 0; i < n_unique; i += 1)
|
||||
extract /free dataset, data_extract, abs(positions[q] - positions_unique[i]) < tol
|
||||
nx = dimsize(dataset, 0)
|
||||
ny = dimsize(data_extract, 0) / nx
|
||||
redimension /n=(nx, ny) data_extract
|
||||
wave profile = ad_profile_x(data_extract, -inf, inf, "", noavg=noavg)
|
||||
destwave[][i] = profile[p]
|
||||
endfor
|
||||
end
|
||||
|
@ -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
|
@ -5,6 +5,7 @@
|
||||
#include "pearl-area-display" // 2D and 3D data visualization
|
||||
#include "pearl-area-profiles" // data processing for multi-dimensional datasets
|
||||
#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-anglescan-process"
|
||||
#include "pearl-anglescan-tracker" // live preview of hemispherical angle scan
|
||||
|
@ -1,36 +1,58 @@
|
||||
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
|
||||
#pragma IgorVersion = 6.1
|
||||
#pragma ModuleName = PearlDataExplorer
|
||||
#pragma version = 1.41
|
||||
#include "pearl-area-import", version >= 1.06
|
||||
#include "pearl-area-profiles", version >= 1.04
|
||||
#include "pearl-area-display", version >= 1.04
|
||||
|
||||
// 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
|
||||
#pragma version = 1.50
|
||||
#include "pearl-area-import"
|
||||
#include "pearl-area-profiles"
|
||||
#include "pearl-area-display"
|
||||
#include "pearl-pshell-import"
|
||||
#if exists("MFR_OpenResultFile")
|
||||
#include "pearl-matrix-import"
|
||||
#endif
|
||||
|
||||
// copyright (c) 2013-16 Paul Scherrer Institut
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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:
|
||||
/// @arg area detector (HDF5) files from scienta analyser and prosilica cameras (if HDF5.xop is installed).
|
||||
/// @arg igor text files from s-scans and otf-scans.
|
||||
/// @arg pshell (HDF5) data files (if HDF5.xop is installed).
|
||||
/// @arg matrix STM files (if MatrixFileReader.xop is installed).
|
||||
|
||||
/// @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_path = "root:packages:pearl_explorer:"
|
||||
|
||||
static strconstant ks_filematch_adh5 = "*.h5"
|
||||
static strconstant ks_filematch_pshell = "psh*.h5"
|
||||
static strconstant ks_filematch_itx = "*.itx"
|
||||
static strconstant ks_filematch_mtrx = "*_mtrx"
|
||||
|
||||
function pearl_data_explorer()
|
||||
init_package()
|
||||
load_prefs()
|
||||
execute /q/z "PearlDataExplorer()"
|
||||
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()
|
||||
// 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()
|
||||
SetDataFolder root:
|
||||
@ -64,7 +86,8 @@ static function init_package()
|
||||
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_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
|
||||
|
||||
SetDataFolder savefolder
|
||||
@ -124,31 +147,64 @@ static function load_prefs()
|
||||
return result
|
||||
end
|
||||
|
||||
/// check whether a file can be imported by this module.
|
||||
///
|
||||
/// the file type is determined by the extension of the file name.
|
||||
///
|
||||
/// @return file type
|
||||
/// @arg 0 not a recognized file type
|
||||
/// @arg 1 PShell file (HDF5, name starts with psh_)
|
||||
/// @arg 2 area detector HDF5 file
|
||||
/// @arg 3 Igor text (itx) file
|
||||
/// @arg 4 Matrix STM file (*_mtrx)
|
||||
///
|
||||
static function pearl_file_type(filename)
|
||||
string filename
|
||||
|
||||
if (StringMatch(filename, ks_filematch_pshell))
|
||||
return 1
|
||||
elseif (StringMatch(filename, ks_filematch_adh5))
|
||||
return 2
|
||||
elseif (StringMatch(filename, ks_filematch_itx))
|
||||
return 3
|
||||
#if exists("MFR_OpenResultFile")
|
||||
elseif (StringMatch(filename, ks_filematch_mtrx))
|
||||
return 4
|
||||
#endif
|
||||
else
|
||||
return 0
|
||||
endif
|
||||
end
|
||||
|
||||
/// read a list of PEARL files from the file system
|
||||
///
|
||||
/// wtFiles and wSelectedFiles in the package data folder are updated.
|
||||
/// only files for which pearl_file_type() returns non-zero are listed.
|
||||
///
|
||||
static function update_filelist()
|
||||
dfref saveDF = GetDataFolderDFR()
|
||||
|
||||
string hdf_files, itx_files, all_files
|
||||
string all_files
|
||||
wave /t wtFiles = $(package_path + "wtFiles")
|
||||
wave wSelectedFiles = $(package_path + "wSelectedFiles")
|
||||
variable nn
|
||||
|
||||
PathInfo pearl_explorer_filepath
|
||||
if (v_flag == 1)
|
||||
hdf_files = IndexedFile(pearl_explorer_filepath, -1, ".h5")
|
||||
itx_files = IndexedFile(pearl_explorer_filepath, -1, ".itx")
|
||||
all_files = hdf_files + itx_files
|
||||
all_files = SortList(hdf_files + itx_files, ";", 4)
|
||||
all_files = IndexedFile(pearl_explorer_filepath, -1, "????")
|
||||
nn = ItemsInList(all_files)
|
||||
else
|
||||
all_files = ""
|
||||
nn = 0
|
||||
endif
|
||||
|
||||
redimension /n=(nn) wtFiles, wSelectedFiles
|
||||
if (nn > 0)
|
||||
wtFiles = StringFromList(p, all_files)
|
||||
wSelectedFiles = 0
|
||||
endif
|
||||
make /n=(nn) /t /free wtAllFiles
|
||||
wtAllFiles = StringFromList(p, all_files)
|
||||
Extract /o /t wtAllFiles, wtFiles, pearl_file_type(wtAllFiles[p])
|
||||
Sort /A /R wtFiles, wtFiles
|
||||
|
||||
redimension /n=(numpnts(wtFiles)) wSelectedFiles
|
||||
wSelectedFiles = 0
|
||||
|
||||
setdatafolder saveDF
|
||||
end
|
||||
@ -200,12 +256,24 @@ static function preview_file(filename)
|
||||
string filename
|
||||
|
||||
dfref saveDF = GetDataFolderDFR()
|
||||
|
||||
if (StringMatch(filename, "*.h5"))
|
||||
wave /z image = preview_hdf_file(filename)
|
||||
elseif (StringMatch(filename, "*.itx"))
|
||||
wave /z image = preview_itx_file(filename)
|
||||
endif
|
||||
|
||||
variable ft = pearl_file_type(filename)
|
||||
switch(ft)
|
||||
case 1:
|
||||
wave /z image = preview_pshell_file(filename)
|
||||
break
|
||||
case 2:
|
||||
wave /z image = preview_hdf_file(filename)
|
||||
break
|
||||
case 3:
|
||||
wave /z image = preview_itx_file(filename)
|
||||
break
|
||||
case 4:
|
||||
wave /z image = preview_mtrx_file(filename)
|
||||
break
|
||||
default:
|
||||
wave /z image = $""
|
||||
endswitch
|
||||
|
||||
if (WaveExists(image))
|
||||
string graphname = show_preview_graph(image)
|
||||
@ -222,6 +290,50 @@ static function preview_file(filename)
|
||||
endif
|
||||
|
||||
setdatafolder saveDF
|
||||
return 0
|
||||
end
|
||||
|
||||
/// load the preview of a PShell HDF5 file.
|
||||
///
|
||||
/// 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.
|
||||
@ -293,6 +405,63 @@ static function /wave preview_itx_file(filename)
|
||||
return preview_image
|
||||
end
|
||||
|
||||
/// load the preview of a Matrix STM file.
|
||||
///
|
||||
/// the preview is loaded to the preview_image wave in the pearl_explorer data folder.
|
||||
///
|
||||
/// the s_file_info string is updated with information about the scan dimensions.
|
||||
///
|
||||
/// this function requires the MatrixFileReader.xop and pearl-matrix-import.ipf to be loaded.
|
||||
/// otherwise it will return an empty wave reference.
|
||||
///
|
||||
/// @param filename name of a file in the directory specified by the pearl_explorer_filepath path object.
|
||||
///
|
||||
/// @return wave reference of the preview image.
|
||||
/// empty wave reference if the function failed.
|
||||
///
|
||||
static function /wave preview_mtrx_file(filename)
|
||||
string filename
|
||||
|
||||
#if exists("MFR_OpenResultFile")
|
||||
dfref saveDF = GetDataFolderDFR()
|
||||
setdatafolder $package_path
|
||||
variable /g V_MatrixFileReaderOverwrite = 1
|
||||
variable /g V_MatrixFileReaderFolder = 0
|
||||
variable /g V_MatrixFileReaderDouble = 0
|
||||
svar s_preview_file
|
||||
svar s_preview_source
|
||||
string datanames
|
||||
string dataname
|
||||
datanames = mtrx_load_preview("preview", "pearl_explorer_filepath", filename)
|
||||
if (strlen(datanames) > 0)
|
||||
s_preview_file = filename
|
||||
|
||||
dataname = StringFromList(0, datanames)
|
||||
wave data = $dataname
|
||||
duplicate /o $dataname, preview_image
|
||||
s_preview_source = StringByKey("Dataset", note(data), "=", "\r")
|
||||
|
||||
svar /z s_file_info
|
||||
if (svar_exists(s_file_info))
|
||||
s_file_info = ""
|
||||
endif
|
||||
|
||||
variable i
|
||||
variable n = ItemsInList(datanames)
|
||||
string s
|
||||
for (i = 0; i < n; i += 1)
|
||||
s = StringFromList(i, datanames)
|
||||
killwaves /z $s
|
||||
endfor
|
||||
endif
|
||||
wave /z preview_image
|
||||
setdatafolder saveDF
|
||||
#else
|
||||
wave /z preview_image = $""
|
||||
#endif
|
||||
return preview_image
|
||||
end
|
||||
|
||||
static function extract_preview_image(data, preview)
|
||||
// extracts a preview image from a wave of arbitrary dimension
|
||||
wave data
|
||||
@ -698,18 +867,21 @@ static function /s show_preview_graph(data, [xdata])
|
||||
svar s_profiles_graph
|
||||
svar s_preview_file
|
||||
svar s_preview_source
|
||||
svar s_preview_trace_graph
|
||||
|
||||
if ((strlen(s_profiles_graph) > 0) && (WinType(s_profiles_graph) == 1))
|
||||
KillWindow $s_profiles_graph
|
||||
endif
|
||||
if ((strlen(s_preview_trace_graph) > 0) && (WinType(s_preview_trace_graph) == 1))
|
||||
KillWindow $s_preview_trace_graph
|
||||
endif
|
||||
|
||||
string graphname
|
||||
if (wavedims(data) == 2)
|
||||
if ((strlen(s_profiles_graph) > 0) && (WinType(s_profiles_graph) == 1))
|
||||
ad_update_profiles(data)
|
||||
else
|
||||
s_profiles_graph = ad_display_profiles(data)
|
||||
ModifyGraph /w=$s_profiles_graph /z wbRGB=(48640,56832,60160)
|
||||
endif
|
||||
s_profiles_graph = ad_display_profiles(data)
|
||||
ModifyGraph /w=$s_profiles_graph /z wbRGB=(48640,56832,60160)
|
||||
graphname = s_profiles_graph
|
||||
elseif (wavedims(data) == 1)
|
||||
svar s_preview_trace_graph
|
||||
duplicate /o data, preview_trace
|
||||
if (!ParamIsDefault(xdata))
|
||||
duplicate /o xdata, preview_trace_x
|
||||
@ -718,20 +890,8 @@ static function /s show_preview_graph(data, [xdata])
|
||||
preview_trace_x = x
|
||||
setscale d 0, 0, WaveUnits(data, 0), preview_trace_x
|
||||
endif
|
||||
if ((strlen(s_preview_trace_graph) == 0) || (WinType(s_preview_trace_graph) != 1))
|
||||
display /n=pearl_explorer_1d /k=1 preview_trace vs preview_trace_x as "Preview"
|
||||
s_preview_trace_graph = s_name
|
||||
ModifyGraph /w=$s_preview_trace_graph wbRGB=(48640,56832,60160)
|
||||
ModifyGraph /w=$s_preview_trace_graph rgb[0]=(0,0,0)
|
||||
ModifyGraph /w=$s_preview_trace_graph grid=2
|
||||
ModifyGraph /w=$s_preview_trace_graph mirror=1
|
||||
ModifyGraph /w=$s_preview_trace_graph minor=1
|
||||
ModifyGraph /w=$s_preview_trace_graph axThick=0.5
|
||||
ModifyGraph /w=$s_preview_trace_graph gridRGB=(52224,52224,52224)
|
||||
ModifyGraph /w=$s_preview_trace_graph gridHair=0
|
||||
ModifyGraph /w=$s_preview_trace_graph tick=0
|
||||
ModifyGraph /w=$s_preview_trace_graph btLen=4
|
||||
endif
|
||||
s_preview_trace_graph = display_preview_trace(preview_trace_x, preview_trace)
|
||||
ModifyGraph /w=$s_preview_trace_graph wbRGB=(48640,56832,60160)
|
||||
graphname = s_preview_trace_graph
|
||||
else
|
||||
return ""
|
||||
@ -747,6 +907,39 @@ static function /s show_preview_graph(data, [xdata])
|
||||
return graphname
|
||||
end
|
||||
|
||||
static function /s display_preview_trace(xtrace, ytrace)
|
||||
wave xtrace
|
||||
wave ytrace
|
||||
|
||||
display /n=pearl_explorer_1d /k=1 ytrace vs xtrace as "Preview"
|
||||
string graphname = s_name
|
||||
ModifyGraph /w=$graphname rgb[0]=(0,0,0)
|
||||
ModifyGraph /w=$graphname grid=2
|
||||
ModifyGraph /w=$graphname mirror=1
|
||||
ModifyGraph /w=$graphname minor=1
|
||||
ModifyGraph /w=$graphname axThick=0.5
|
||||
ModifyGraph /w=$graphname gridRGB=(52224,52224,52224)
|
||||
ModifyGraph /w=$graphname gridHair=0
|
||||
ModifyGraph /w=$graphname tick=0
|
||||
ModifyGraph /w=$graphname btLen=4
|
||||
|
||||
// axis labels
|
||||
string labels = note(ytrace)
|
||||
string lab
|
||||
lab = StringByKey("AxisLabelX", labels, "=", "\r")
|
||||
if (!strlen(lab))
|
||||
lab = "X"
|
||||
endif
|
||||
Label /w=$graphname bottom lab + " (\\U)"
|
||||
lab = StringByKey("AxisLabelD", labels, "=", "\r")
|
||||
if (!strlen(lab))
|
||||
lab = "value"
|
||||
endif
|
||||
Label /w=$graphname left lab + " (\\U)"
|
||||
|
||||
return s_name
|
||||
end
|
||||
|
||||
static function load_selected_files([options])
|
||||
string options
|
||||
|
||||
@ -777,16 +970,32 @@ static function load_file(filename, [options])
|
||||
|
||||
dfref saveDF = GetDataFolderDFR()
|
||||
|
||||
if (StringMatch(filename, "*.h5"))
|
||||
if (ParamIsDefault(options))
|
||||
load_hdf_file(filename)
|
||||
else
|
||||
load_hdf_file(filename, options=options)
|
||||
endif
|
||||
elseif (StringMatch(filename, "*.itx"))
|
||||
load_itx_file(filename)
|
||||
endif
|
||||
|
||||
variable ft = pearl_file_type(filename)
|
||||
switch(ft)
|
||||
case 1:
|
||||
if (ParamIsDefault(options))
|
||||
load_pshell_file(filename)
|
||||
else
|
||||
load_pshell_file(filename, options=options)
|
||||
endif
|
||||
break
|
||||
case 2:
|
||||
if (ParamIsDefault(options))
|
||||
load_hdf_file(filename)
|
||||
else
|
||||
load_hdf_file(filename, options=options)
|
||||
endif
|
||||
break
|
||||
case 3:
|
||||
load_itx_file(filename)
|
||||
break
|
||||
case 4:
|
||||
load_mtrx_file(filename)
|
||||
break
|
||||
default:
|
||||
break
|
||||
endswitch
|
||||
|
||||
setdatafolder saveDF
|
||||
end
|
||||
|
||||
@ -796,7 +1005,7 @@ static function prompt_hdf_options(options)
|
||||
string mode = StringByKey("mode", options, ":", ";")
|
||||
string reduction_func = StringByKey("reduction_func", options, ":", ";")
|
||||
|
||||
string modes = "adh5_load_reduced"
|
||||
string modes = "load_reduced"
|
||||
string reduction_functions = adh5_list_reduction_funcs()
|
||||
|
||||
if (strlen(mode) == 0)
|
||||
@ -817,17 +1026,19 @@ static function prompt_hdf_options(options)
|
||||
return v_flag // 0 = OK, 1 = cancel
|
||||
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)
|
||||
// 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 ¶m
|
||||
|
||||
return 0
|
||||
@ -847,6 +1058,58 @@ function prompt_func_params(func_name, func_param)
|
||||
endif
|
||||
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
|
||||
print reduction_func, 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])
|
||||
string filename
|
||||
string options
|
||||
@ -873,12 +1136,13 @@ static function /df load_hdf_file(filename, [options])
|
||||
string mode = StringByKey("mode", options, ":", ";")
|
||||
|
||||
strswitch(mode)
|
||||
case "adh5_load_reduced":
|
||||
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
|
||||
print reduction_func, reduction_params
|
||||
loaded_filename = adh5_load_reduced(nickname, "pearl_explorer_filepath", filename, $reduction_func, reduction_params)
|
||||
endif
|
||||
break
|
||||
@ -936,6 +1200,32 @@ static function /df load_itx_file(filename, [options])
|
||||
return actDF
|
||||
end
|
||||
|
||||
/// load a matrix (STM) data file
|
||||
///
|
||||
///
|
||||
static function /df load_mtrx_file(filename, [options])
|
||||
string filename
|
||||
string options
|
||||
|
||||
dfref saveDF = GetDataFolderDFR()
|
||||
dfref dataDF = $""
|
||||
|
||||
#if exists("MFR_OpenResultFile")
|
||||
setdatafolder root:
|
||||
string datasets = ""
|
||||
datasets = mtrx_load_file("pearl_explorer_filepath", filename)
|
||||
if (strlen(datasets) > 0)
|
||||
string /g pearl_explorer_import = "load_mtrx_file"
|
||||
string s1 = StringFromList(0, datasets)
|
||||
wave w1 = $s1
|
||||
dataDF = GetWavesDataFolderDFR(w1)
|
||||
endif
|
||||
#endif
|
||||
|
||||
setdatafolder saveDF
|
||||
return dataDF
|
||||
end
|
||||
|
||||
function /s itx_suggest_foldername(filename, [ignoredate,sourcename,unique])
|
||||
// suggests the name of a data folder based on a file name
|
||||
// if the file name follows the naming convention source-date-index.extension,
|
||||
@ -1306,6 +1596,9 @@ static function bp_dataset_folder(ba) : ButtonControl
|
||||
string cmd
|
||||
sprintf cmd, "setdatafolder root:%s", PossiblyQuoteName(dataset)
|
||||
execute /q /z cmd
|
||||
cmd = "setdatafolder :scan1"
|
||||
execute /q /z cmd
|
||||
sprintf cmd, "setdatafolder %s", GetDataFolder(1)
|
||||
print cmd
|
||||
endif
|
||||
break
|
||||
|
@ -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
|
1297
pearl/pearl-elog.ipf
1297
pearl/pearl-elog.ipf
File diff suppressed because it is too large
Load Diff
@ -454,7 +454,7 @@ function Au4f(w, x): fitfunc
|
||||
vc1 = w[ip] / sqrt(pi) * vc2
|
||||
vc3 = w[ip+1]
|
||||
vc4 = vc2 * w[ip+2] / 2
|
||||
v += vc1 * Voigt(vc2 * (x - vc3), vc4)
|
||||
v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
|
||||
endfor
|
||||
|
||||
return v
|
||||
@ -491,25 +491,25 @@ function Au4f_2p2(w, x): fitfunc
|
||||
vc1 = w[3] / sqrt(pi) * vc2
|
||||
vc3 = w[4]
|
||||
vc4 = vc2 * w[5] / 2
|
||||
v += vc1 * Voigt(vc2 * (x - vc3), vc4)
|
||||
v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
|
||||
|
||||
// 5/2 surface
|
||||
vc1 = w[3] / sqrt(pi) * vc2 * w[9]
|
||||
vc3 = w[4] + w[10]
|
||||
vc4 = vc2 * w[5] / 2
|
||||
v += vc1 * Voigt(vc2 * (x - vc3), vc4)
|
||||
v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
|
||||
|
||||
// 7/2 bulk
|
||||
vc1 = w[6] / sqrt(pi) * vc2
|
||||
vc3 = w[7]
|
||||
vc4 = vc2 * w[8] / 2
|
||||
v += vc1 * Voigt(vc2 * (x - vc3), vc4)
|
||||
v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
|
||||
|
||||
// 7/2 surface
|
||||
vc1 = w[6] / sqrt(pi) * vc2 * w[9]
|
||||
vc3 = w[7] + w[10]
|
||||
vc4 = vc2 * w[8] / 2
|
||||
v += vc1 * Voigt(vc2 * (x - vc3), vc4)
|
||||
v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
|
||||
|
||||
return v
|
||||
|
||||
@ -578,37 +578,37 @@ function Au4f_2p3(w, x): fitfunc
|
||||
vc1 = w[3] / sqrt(pi) * vc2
|
||||
vc3 = w[4]
|
||||
vc4 = vc2 * w[5] / 2
|
||||
v += vc1 * Voigt(vc2 * (x - vc3), vc4)
|
||||
v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
|
||||
|
||||
// 5/2 surface
|
||||
vc1 = w[3] / sqrt(pi) * vc2 * w[9]
|
||||
vc3 = w[4] + w[10]
|
||||
vc4 = vc2 * w[5] / 2
|
||||
v += vc1 * Voigt(vc2 * (x - vc3), vc4)
|
||||
v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
|
||||
|
||||
// 5/2 2nd layer
|
||||
vc1 = w[3] / sqrt(pi) * vc2 * w[11]
|
||||
vc3 = w[4] + w[12]
|
||||
vc4 = vc2 * w[5] / 2
|
||||
v += vc1 * Voigt(vc2 * (x - vc3), vc4)
|
||||
v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
|
||||
|
||||
// 7/2 bulk
|
||||
vc1 = w[6] / sqrt(pi) * vc2
|
||||
vc3 = w[7]
|
||||
vc4 = vc2 * w[8] / 2
|
||||
v += vc1 * Voigt(vc2 * (x - vc3), vc4)
|
||||
v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
|
||||
|
||||
// 7/2 surface
|
||||
vc1 = w[6] / sqrt(pi) * vc2 * w[9]
|
||||
vc3 = w[7] + w[10]
|
||||
vc4 = vc2 * w[8] / 2
|
||||
v += vc1 * Voigt(vc2 * (x - vc3), vc4)
|
||||
v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
|
||||
|
||||
// 7/2 2nd layer
|
||||
vc1 = w[6] / sqrt(pi) * vc2 * w[11]
|
||||
vc3 = w[7] + w[12]
|
||||
vc4 = vc2 * w[8] / 2
|
||||
v += vc1 * Voigt(vc2 * (x - vc3), vc4)
|
||||
v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
|
||||
|
||||
return v
|
||||
|
||||
|
900
pearl/pearl-matrix-import.ipf
Normal file
900
pearl/pearl-matrix-import.ipf
Normal file
@ -0,0 +1,900 @@
|
||||
#pragma rtGlobals=3
|
||||
#pragma version = 1.00
|
||||
#pragma IgorVersion = 6.36
|
||||
#pragma ModuleName = PearlMatrixImport
|
||||
|
||||
// author: matthias.muntwiler@psi.ch
|
||||
// Copyright (c) 2016 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 data file import for omicron matrix (STM) files
|
||||
///
|
||||
/// the matrix file import requires the matrix file reader XOP by thomas braun
|
||||
/// (http://www.igorexchange.com/project/matrixFileReader)
|
||||
/// which in turn requires an installation of vernissage by omicron nanotechnology.
|
||||
///
|
||||
/// @warning EXPERIMENTAL
|
||||
/// the matrix import module and its interface may change radically in future revisions!
|
||||
///
|
||||
/// @author matthias muntwiler, matthias.muntwiler@psi.ch
|
||||
///
|
||||
/// @copyright 2016 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 PearlMatrixImport
|
||||
/// @brief data file import for omicron matrix (STM) files
|
||||
///
|
||||
/// PearlMatrixImport is declared in @ref pearl-matrix-import.ipf.
|
||||
|
||||
static strconstant package_name = "pearl_matrix_import"
|
||||
static strconstant package_path = "root:packages:pearl_matrix_import:"
|
||||
|
||||
static strconstant ks_filematch_mtrx = "*_mtrx"
|
||||
|
||||
/// initialize the package data folder.
|
||||
///
|
||||
///
|
||||
static function init_package()
|
||||
|
||||
dfref savedf = getdatafolderdfr()
|
||||
|
||||
setdatafolder root:
|
||||
newdatafolder /o/s packages
|
||||
newdatafolder /o/s $package_name
|
||||
|
||||
variable /g loglevel = 3
|
||||
string /g dataFilePath = ""
|
||||
string /g resultFilePath = ""
|
||||
variable /g runCycle = 0
|
||||
variable /g scanCycle = 0
|
||||
string /g channelName = ""
|
||||
variable /g brickletID = 0
|
||||
variable /g V_MatrixFileReaderOverwrite = 1
|
||||
variable /g V_MatrixFileReaderFolder = 0
|
||||
variable /g V_MatrixFileReaderDouble = 0
|
||||
|
||||
setdatafolder savedf
|
||||
return 0
|
||||
end
|
||||
|
||||
/// check that the package data folder exists
|
||||
///
|
||||
/// initialize the package if the folder does not exist.
|
||||
///
|
||||
static function check_package_folder()
|
||||
dfref df_pack = $(package_path)
|
||||
if (DataFolderRefStatus(df_pack))
|
||||
svar /sdfr=df_pack /z resultFilePath
|
||||
if (!svar_exists(resultFilePath))
|
||||
init_package()
|
||||
endif
|
||||
else
|
||||
init_package()
|
||||
endif
|
||||
end
|
||||
|
||||
/// initialize the package and reload preferences after an experiment is loaded.
|
||||
static function AfterFileOpenHook(refNum,file,pathName,type,creator,kind)
|
||||
Variable refNum,kind
|
||||
String file,pathName,type,creator
|
||||
if( (kind >= 1) && (kind <= 2))
|
||||
init_package()
|
||||
//load_prefs()
|
||||
endif
|
||||
return 0
|
||||
end
|
||||
|
||||
/// open a matrix file that was dropped into Igor.
|
||||
///
|
||||
/// preliminary implementation.
|
||||
/// this should rather load the entire file and display a preview.
|
||||
/// graph windows should be reused by subsequent loads.
|
||||
/// also decide on a data saving location.
|
||||
///
|
||||
static function BeforeFileOpenHook(refNum,fileName,path,type,creator,kind)
|
||||
Variable refNum,kind
|
||||
String fileName,path,type,creator
|
||||
|
||||
Variable handledOpen = 0
|
||||
if (StringMatch(fileName, ks_filematch_mtrx))
|
||||
setdatafolder root:
|
||||
newdatafolder /o /s matrix
|
||||
mtrx_load_preview("matrix", path, fileName)
|
||||
handledOpen = 1
|
||||
endif
|
||||
return handledOpen
|
||||
End
|
||||
|
||||
/// generate elog message from bricklet metadata
|
||||
///
|
||||
/// @param metadata two-column text wave
|
||||
///
|
||||
function /s matrix_format_elog_message(metadata)
|
||||
wave /t metadata
|
||||
|
||||
string key
|
||||
string value
|
||||
variable nkeys = dimsize(metadata, 0)
|
||||
variable ikey
|
||||
string message_keys
|
||||
message_keys = "resultFileName;sampleName;channelName;"
|
||||
message_keys += "XYScanner.Points.value;XYScanner.Raster_Time.value;XYScanner.Raster_Time.unit;XYScanner.Width.value;XYScanner.Width.unit;XYScanner.Height.value;XYScanner.Height.unit;"
|
||||
message_keys += "GapVoltageControl.Voltage.value;GapVoltageControl.Voltage.unit;"
|
||||
message_keys += "Regulator.Loop_Gain_1_I.value;Regulator.Loop_Gain_1_I.unit;Regulator.Setpoint_1.value;Regulator.Setpoint_1.unit;"
|
||||
message_keys += "Spectroscopy.Device_1_Start.value;Spectroscopy.Device_1_Start.unit;Spectroscopy.Spectroscopy_Mode.value;"
|
||||
string message
|
||||
|
||||
message_keys = ""
|
||||
for (ikey = 0; ikey < nkeys; ikey += 1)
|
||||
key = metadata[ikey][0]
|
||||
value = metadata[ikey][1]
|
||||
if (WhichListItem(key, message_keys) >= 0)
|
||||
message += key + " = " + value + "\r"
|
||||
endif
|
||||
endfor
|
||||
end
|
||||
|
||||
function matrix_preview_2d(data, metadata)
|
||||
wave data
|
||||
wave /t metadata
|
||||
|
||||
Display
|
||||
AppendImage data
|
||||
ModifyImage data ctab= {*,*,Mud,0}
|
||||
ModifyGraph margin(left)=30,margin(bottom)=30,margin(top)=5,margin(right)=5,height={Plan,1,left,bottom}
|
||||
ModifyGraph mirror=2
|
||||
ModifyGraph nticks=3
|
||||
ModifyGraph axThick=0.5
|
||||
ModifyGraph btLen=4
|
||||
|
||||
end
|
||||
|
||||
/// load the preview of a Matrix data file
|
||||
///
|
||||
/// the preview is loaded to the preview_image wave in the pearl_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_matrix_file(filename)
|
||||
string filename
|
||||
|
||||
dfref saveDF = GetDataFolderDFR()
|
||||
setdatafolder $package_path
|
||||
svar s_preview_file
|
||||
svar s_preview_source
|
||||
mtrx_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 = mtrx_load_info("pearl_explorer_filepath", filename)
|
||||
else
|
||||
s_file_info = ""
|
||||
endif
|
||||
|
||||
setdatafolder saveDF
|
||||
return preview_image
|
||||
end
|
||||
|
||||
/// from matrixfilereader help
|
||||
Structure errorCode
|
||||
int32 SUCCESS
|
||||
int32 UNKNOWN_ERROR
|
||||
int32 ALREADY_FILE_OPEN
|
||||
int32 EMPTY_RESULTFILE
|
||||
int32 FILE_NOT_READABLE
|
||||
int32 NO_NEW_BRICKLETS
|
||||
int32 WRONG_PARAMETER
|
||||
int32 INTERNAL_ERROR_CONVERTING_DATA
|
||||
int32 NO_FILE_OPEN
|
||||
int32 INVALID_RANGE
|
||||
int32 WAVE_EXIST
|
||||
EndStructure
|
||||
|
||||
/// from matrixfilereader help
|
||||
static Function initStruct(errorCode)
|
||||
Struct errorCode &errorCode
|
||||
|
||||
errorCode.SUCCESS =0
|
||||
errorCode.UNKNOWN_ERROR=10001
|
||||
errorCode.ALREADY_FILE_OPEN=10002
|
||||
errorCode.EMPTY_RESULTFILE=10004
|
||||
errorCode.FILE_NOT_READABLE=10008
|
||||
errorCode.NO_NEW_BRICKLETS=10016
|
||||
errorCode.WRONG_PARAMETER=10032
|
||||
errorCode.INTERNAL_ERROR_CONVERTING_DATA=10064
|
||||
errorCode.NO_FILE_OPEN=10128
|
||||
errorCode.INVALID_RANGE=10256
|
||||
errorCode.WAVE_EXIST=10512
|
||||
|
||||
end
|
||||
|
||||
/// load all data from a Matrix data file.
|
||||
///
|
||||
function mtrx_load_all()
|
||||
|
||||
struct errorCode errorCode
|
||||
initStruct(errorCode)
|
||||
|
||||
#if exists("MFR_OpenResultFile")
|
||||
MFR_OpenResultFile
|
||||
if(V_flag != errorCode.SUCCESS)
|
||||
MFR_GetXOPErrorMessage
|
||||
return -1
|
||||
endif
|
||||
|
||||
MFR_GetBrickletData
|
||||
if(V_flag != errorCode.SUCCESS)
|
||||
MFR_GetXOPErrorMessage
|
||||
return -1
|
||||
endif
|
||||
|
||||
MFR_GetBrickletMetaData
|
||||
if(V_flag != errorCode.SUCCESS)
|
||||
MFR_GetXOPErrorMessage
|
||||
return -1
|
||||
endif
|
||||
|
||||
return 0
|
||||
#else
|
||||
return -1
|
||||
#endif
|
||||
end
|
||||
|
||||
/// parse matrix file names
|
||||
///
|
||||
/// parse matrix file names for result name, run cycle, scan cycle, and channel.
|
||||
///
|
||||
/// @param fileName matrix result or data file name (without path).
|
||||
///
|
||||
/// @param resultFile (out) base name of the result file.
|
||||
/// append "_%04u.mtrx" to get the actual result file.
|
||||
/// we do not know the chain link number at this stage.
|
||||
///
|
||||
/// @param runCycle (out) run cycle number. necessary to look up the bricklet ID.
|
||||
///
|
||||
/// @param scanCycle (out) scan cycle number. necessary to look up the bricklet ID.
|
||||
///
|
||||
/// @param channel (out) channel name.
|
||||
///
|
||||
/// @return file type
|
||||
/// @arg 0 result file (logbook)
|
||||
/// @arg 1 result data file (bricklet)
|
||||
///
|
||||
/// result file names look like:
|
||||
/// default_2015Apr20-124353_STM-STM_AtomManipulation_0001.mtrx,
|
||||
/// default_2015Apr20-124353_STM-STM_AtomManipulation_0002.mtrx, etc.
|
||||
/// the function returns the first part up to the experiment name ("AtomManipulation" in the examples).
|
||||
/// all other return values set to defaults and must not be regarded.
|
||||
///
|
||||
/// result data files look like:
|
||||
/// default_2015Apr20-124353_STM-STM_AtomManipulation--136_1.Aux1(V)_mtrx,
|
||||
/// default_2015Apr20-124353_STM-STM_AtomManipulation--136_1.I(V)_mtrx,
|
||||
/// default_2015Apr20-124353_STM-STM_AtomManipulation--14_1.I_mtrx,
|
||||
/// default_2015Apr20-124353_STM-STM_AtomManipulation--14_1.Z_mtrx, etc.
|
||||
/// the function returns all results as described in the parameter list.
|
||||
///
|
||||
function mtrx_parse_filename(fileName, resultFile, runCycle, scanCycle, channel)
|
||||
string fileName
|
||||
string &resultFile
|
||||
variable &runCycle
|
||||
variable &scanCycle
|
||||
string &channel
|
||||
|
||||
variable fileType = 0
|
||||
resultFile = ""
|
||||
channel = ""
|
||||
runCycle = 0
|
||||
scanCycle = 0
|
||||
|
||||
string regexp = ""
|
||||
string index1 = ""
|
||||
string index2 = ""
|
||||
string extension = ""
|
||||
|
||||
if (StringMatch(fileName, "*.mtrx"))
|
||||
regexp = "(.+)_([[:digit:]]+)\.(.+)"
|
||||
SplitString /E=regexp fileName, resultFile, index1, extension
|
||||
fileType = 0
|
||||
else
|
||||
regexp = "(.+)--([[:digit:]]+)_([[:digit:]]+)\.((.+)_mtrx)"
|
||||
SplitString /E=regexp fileName, resultFile, index1, index2, extension, channel
|
||||
fileType = 1
|
||||
runCycle = str2num(index1)
|
||||
scanCycle = str2num(index2)
|
||||
endif
|
||||
|
||||
return fileType
|
||||
end
|
||||
|
||||
/// split a matrix filename and return the first three parts
|
||||
///
|
||||
/// we assume that the second (third) part contains the date (time).
|
||||
/// the parts are separated by dash or underscore.
|
||||
///
|
||||
function /s mtrx_split_filename(fileName, prefix, datepart, timepart)
|
||||
string fileName
|
||||
string &prefix
|
||||
string &datepart
|
||||
string &timepart
|
||||
|
||||
string regexp
|
||||
regexp = "([[:alpha:][:digit:]]+)[-_]([[:alpha:][:digit:]]+)[-_]([[:alpha:][:digit:]]+)[-_].+"
|
||||
SplitString /E=regexp fileName, prefix, datepart, timepart
|
||||
return datepart
|
||||
end
|
||||
|
||||
/// create or look up a data folder based on a matrix file name.
|
||||
///
|
||||
/// the name of the folder is mtrx_date_time, where date and time are parsed from the file name.
|
||||
/// for this to work, the file name must consist of at least three parts that are separated by dash or underscore.
|
||||
/// the second (third) part contains the date (time).
|
||||
/// date and time are copied as strings.
|
||||
///
|
||||
/// if the data folder exists, a reference to the existing folder is returned.
|
||||
///
|
||||
/// @param fileName name of the result or data file.
|
||||
///
|
||||
/// @param df_base (optional) base data folder.
|
||||
/// default: current folder.
|
||||
///
|
||||
/// @return reference of the newly created or existing data folder.
|
||||
///
|
||||
function /df mtrx_create_folder(fileName, [df_base])
|
||||
string fileName
|
||||
dfref df_base
|
||||
|
||||
if (ParamIsDefault(df_base))
|
||||
df_base = GetDataFolderDFR()
|
||||
endif
|
||||
|
||||
string prefix
|
||||
string datepart
|
||||
string timepart
|
||||
string folderName
|
||||
|
||||
mtrx_split_filename(fileName, prefix, datepart, timepart)
|
||||
folderName = "mtrx_" + datepart + "_" + timepart
|
||||
folderName = CleanupName(folderName, 0)
|
||||
|
||||
dfref df_save = GetDataFolderDFR()
|
||||
setdatafolder root:
|
||||
newdatafolder /o /s $foldername
|
||||
dfref df = GetDataFolderDFR()
|
||||
|
||||
setdatafolder df_save
|
||||
return df
|
||||
end
|
||||
|
||||
/// create a data folder for bricklet data.
|
||||
///
|
||||
/// the name of the folder is, for example "r23s2" where the first (second) number is the run (scan) cycle.
|
||||
/// run cycle and scan cycle numbers are taken from the open matrix file unless overridden by optional arguments.
|
||||
///
|
||||
/// if the data folder exists, a reference to the existing folder is returned.
|
||||
/// if one of the run or scan cycle numbers is lower than 1, the base folder is returned.
|
||||
///
|
||||
/// @param df_base (optional) base data folder.
|
||||
/// default: current folder.
|
||||
///
|
||||
/// @param runCycle (optional) run cycle number. must be >= 1.
|
||||
/// default: from last mtrx_open_file call.
|
||||
///
|
||||
/// @param scanCycle (optional) scan cycle number. must be >= 1.
|
||||
/// default: from last mtrx_open_file call.
|
||||
///
|
||||
/// @return reference of the newly created or existing data folder.
|
||||
///
|
||||
function /df mtrx_get_cycle_folder([df_base, runCycle, scanCycle])
|
||||
dfref df_base
|
||||
variable runCycle
|
||||
variable scanCycle
|
||||
|
||||
dfref df_save = GetDataFolderDFR()
|
||||
dfref df_pack = $(package_path)
|
||||
if (ParamIsDefault(df_base))
|
||||
df_base = GetDataFolderDFR()
|
||||
endif
|
||||
if (ParamIsDefault(runCycle))
|
||||
nvar /sdfr=df_pack defRunCycle = runCycle
|
||||
runCycle = defRunCycle
|
||||
endif
|
||||
if (ParamIsDefault(scanCycle))
|
||||
nvar /sdfr=df_pack defScanCycle = scanCycle
|
||||
scanCycle = defScanCycle
|
||||
endif
|
||||
|
||||
string dfname
|
||||
if ((runCycle >= 1) && (scanCycle >= 1))
|
||||
sprintf dfname, "r%us%u", runCycle, scanCycle
|
||||
setdatafolder df_base
|
||||
dfref df = $dfname
|
||||
if (DataFolderRefStatus(df) == 0)
|
||||
newdatafolder $dfname
|
||||
dfref df = $dfname
|
||||
endif
|
||||
else
|
||||
dfref df = df_base
|
||||
endif
|
||||
|
||||
setdatafolder df_save
|
||||
return df
|
||||
end
|
||||
|
||||
/// find out bricklet ID of a file
|
||||
///
|
||||
/// @warning EXPERIMENTAL
|
||||
/// the code of this function is inefficient.
|
||||
/// the function may be removed in a later version.
|
||||
///
|
||||
/// @param resultFile base name of result file without chain link number and extension.
|
||||
/// as returned by mtrx_parse_filename.
|
||||
///
|
||||
/// @param runCycle requested run cycle.
|
||||
/// 0 = first available.
|
||||
///
|
||||
/// @param scanCycle requested scan cycle.
|
||||
/// 0 = first available.
|
||||
///
|
||||
/// @param channel channel name. for example: "I", "Z", "Aux(V)", etc.
|
||||
/// empty string: first available.
|
||||
///
|
||||
/// @return bricklet ID, or -1 if an error occurred.
|
||||
///
|
||||
function mtrx_file_brickletID(resultFile, runCycle, scanCycle, channel)
|
||||
string resultFile
|
||||
variable runCycle
|
||||
variable scanCycle
|
||||
string channel
|
||||
|
||||
dfref df_overview = NewFreeDataFolder()
|
||||
variable link = 1
|
||||
variable id = -1
|
||||
variable idx = 0
|
||||
|
||||
string resultFileName
|
||||
#if exists("MFR_OpenResultFile")
|
||||
struct errorCode errorCode
|
||||
initStruct(errorCode)
|
||||
do
|
||||
sprintf resultFileName, "%s_%04u.mtrx", resultFile, link
|
||||
MFR_OpenResultFile /K resultFileName
|
||||
if(V_flag != errorCode.SUCCESS)
|
||||
return -1
|
||||
endif
|
||||
MFR_CreateOverviewTable /DEST=df_overview
|
||||
// dimension labels are: brickletID, scanCycleCount, runCycleCount, sequenceID, dimension, channelName
|
||||
wave /t /sdfr=df_overview overviewTable
|
||||
make /n=(dimsize(overviewTable, 0)) /i /u /free runcycles, scancycles, ids, match
|
||||
make /n=(dimsize(overviewTable, 0)) /t /free channels
|
||||
ids = str2num(overviewtable[p][%brickletID])
|
||||
if (runcycle > 0)
|
||||
runcycles = str2num(overviewtable[p][%runCycleCount])
|
||||
else
|
||||
runcycles = runcycle
|
||||
endif
|
||||
if (scancycle > 0)
|
||||
scancycles = str2num(overviewtable[p][%scanCycleCount])
|
||||
else
|
||||
scancycles = scancycle
|
||||
endif
|
||||
if (strlen(channel) > 0)
|
||||
channels = overviewTable[p][%channelName]
|
||||
else
|
||||
channels = channel
|
||||
endif
|
||||
Extract /FREE ids, match_ids, (scancycles == scanCycle) && (runcycles == runCycle) && (cmpstr(channels, channel) == 0)
|
||||
if (numpnts(match_ids) > 0)
|
||||
id = match_ids[0]
|
||||
else
|
||||
link += 1
|
||||
endif
|
||||
while (id < 0)
|
||||
#endif
|
||||
return id
|
||||
end
|
||||
|
||||
/// open a matrix result or data file
|
||||
///
|
||||
/// this function opens a matrix result file (.mtrx) or data file (.*_mtrx).
|
||||
///
|
||||
/// if a data file is selected, the function locates the corresponding result file, opens it,
|
||||
/// and looks up the bricklet ID of the data file.
|
||||
/// if a result file is selected, the function opens it but does not look up bricklet IDs.
|
||||
///
|
||||
/// the result file remains open and can be accessed using the mtrx_ functions or MFR_ operations.
|
||||
/// once a result file is open, you can easily access any bricklets linked to it,
|
||||
/// i.e., any run cycle, scan cycle, and channel.
|
||||
///
|
||||
/// the function stores information about the opened file in a global package data folder.
|
||||
/// if the same result file is opened again later, the information is reused and the file not read again.
|
||||
/// this may cause problems if the file has been modified in the meantime,
|
||||
/// or if the cached data become corrupt for some reason.
|
||||
/// the function detects if a data file is not linked in the open result file, and updates the cache.
|
||||
/// in other situations it may be necessary to force a reload.
|
||||
///
|
||||
/// @todo fix possible cache issues, add an option to override the cache.
|
||||
///
|
||||
/// @param pathName igor path name or empty string.
|
||||
///
|
||||
/// @param fileName file name, with or without path, or empty string.
|
||||
///
|
||||
/// @return file type
|
||||
/// @arg 0 result file (logbook)
|
||||
/// @arg 1 result data file (bricklet)
|
||||
/// @arg -1 error, no data loaded
|
||||
/// @arg -2 matrixfilereader.xop not installed
|
||||
///
|
||||
function mtrx_open_file(pathName, fileNameOrPath)
|
||||
string pathName
|
||||
string fileNameOrPath
|
||||
|
||||
check_package_folder()
|
||||
dfref df_save = GetDataFolderDFR()
|
||||
dfref df_pack = $(package_path)
|
||||
svar /sdfr=df_pack dataFilePath
|
||||
svar /sdfr=df_pack resultFilePath
|
||||
nvar /sdfr=df_pack runCycle
|
||||
nvar /sdfr=df_pack scanCycle
|
||||
svar /sdfr=df_pack channelName
|
||||
nvar /sdfr=df_pack brickletID
|
||||
|
||||
string loc_resultFileName
|
||||
string loc_resultFilePath
|
||||
variable loc_runCycle
|
||||
variable loc_scanCycle
|
||||
string loc_channelName
|
||||
|
||||
// make sure we have a valid and complete file path
|
||||
GetFileFolderInfo /P=$pathName /Q /Z=2 fileNameOrPath
|
||||
string filePath
|
||||
if ((v_flag == 0) && (v_isFile))
|
||||
filePath = s_path
|
||||
else
|
||||
return -1
|
||||
endif
|
||||
|
||||
// get base file name
|
||||
string fileName
|
||||
string fileDir
|
||||
string baseFileName
|
||||
variable fileType
|
||||
fileName = ParseFilePath(0, filePath, ":", 1, 0)
|
||||
fileDir = ParseFilePath(1, filePath, ":", 1, 0)
|
||||
fileType = mtrx_parse_filename(fileName, baseFileName, loc_runCycle, loc_scanCycle, loc_channelName)
|
||||
|
||||
variable link = 1
|
||||
variable id = -1
|
||||
variable result = -1
|
||||
variable using_cache = 0
|
||||
|
||||
struct errorCode errorCode
|
||||
initStruct(errorCode)
|
||||
do
|
||||
sprintf loc_resultFileName, "%s_%04u.mtrx", baseFileName, link
|
||||
loc_resultFilePath = fileDir + loc_resultFileName
|
||||
#if exists("MFR_OpenResultFile")
|
||||
if ((strlen(resultFilePath) == 0) || (cmpstr(loc_resultFilePath, resultFilePath) != 0))
|
||||
MFR_OpenResultFile /K loc_resultFilePath
|
||||
if(V_flag != errorCode.SUCCESS)
|
||||
MFR_GetXOPErrorMessage
|
||||
result = -1
|
||||
break
|
||||
endif
|
||||
resultFilePath = loc_resultFilePath
|
||||
if (fileType == 1)
|
||||
dataFilePath = filePath
|
||||
else
|
||||
dataFilePath = ""
|
||||
endif
|
||||
runCycle = 0
|
||||
scanCycle = 0
|
||||
channelName = ""
|
||||
brickletID = 0
|
||||
MFR_CreateOverviewTable /DEST=df_pack
|
||||
if(V_flag != errorCode.SUCCESS)
|
||||
MFR_GetXOPErrorMessage
|
||||
result = -1
|
||||
break
|
||||
endif
|
||||
using_cache = 0
|
||||
else
|
||||
using_cache = 1
|
||||
endif
|
||||
#else
|
||||
print "matrixfilereader.xop not installed"
|
||||
result = -2
|
||||
break
|
||||
#endif
|
||||
// dimension labels are: brickletID, scanCycleCount, runCycleCount, sequenceID, dimension, channelName
|
||||
wave /t /sdfr=df_pack overviewTable
|
||||
make /n=(dimsize(overviewTable, 0)) /i /u /o df_pack:runCycles, df_pack:scanCycles, df_pack:ids
|
||||
make /n=(dimsize(overviewTable, 0)) /t /o df_pack:channels
|
||||
wave /sdfr=df_pack ids, runCycles, scanCycles
|
||||
wave /t /sdfr=df_pack channels
|
||||
ids = str2num(overviewtable[p][%brickletID])
|
||||
runCycles = str2num(overviewtable[p][%runCycleCount])
|
||||
scanCycles = str2num(overviewtable[p][%scanCycleCount])
|
||||
channels = overviewTable[p][%channelName]
|
||||
result = fileType
|
||||
|
||||
// if a data file is opened, make sure we found the right result file
|
||||
if ((loc_runCycle > 0) && (loc_scanCycle > 0))
|
||||
Extract /FREE ids, match_ids, (runCycles == loc_runCycle) && (scanCycles == loc_scanCycle) && (cmpstr(channels, loc_channelName) == 0)
|
||||
if (numpnts(match_ids) > 0)
|
||||
id = match_ids[0]
|
||||
runCycle = loc_runCycle
|
||||
scanCycle = loc_scanCycle
|
||||
channelName = loc_channelName
|
||||
brickletID = id
|
||||
break
|
||||
elseif (using_cache)
|
||||
resultFilePath = ""
|
||||
else
|
||||
link += 1
|
||||
endif
|
||||
else
|
||||
break
|
||||
endif
|
||||
while (id < 0)
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
/// load a preview image from a Matrix data file.
|
||||
///
|
||||
/// the data wave is loaded into the current data folder.
|
||||
///
|
||||
/// @param destName destination wave name. the wave is created in the current data folder.
|
||||
///
|
||||
/// @param pathName igor symbolic path name. can be empty if the path is specified in FileName or a dialog box should be displayed
|
||||
///
|
||||
/// @param fileName if empty a dialog box shows up
|
||||
/// the file name must adhere to the format
|
||||
/// "{prefix}-{date}-{time}-{anything}--{run_cycle}_{scan_cycle}.{extension}".
|
||||
/// the first three seperators can alternatively be underscores.
|
||||
/// it may be necessary to change the configuration of the Matrix application.
|
||||
///
|
||||
/// @param traces (currently not used) semicolon-separated list of preferred traces.
|
||||
/// the items of the list are match strings for the Igor StringMatch function.
|
||||
/// only the first matching trace is loaded from the file.
|
||||
/// default: "*Up;*Down;*ReUp;*ReDown;"
|
||||
///
|
||||
/// @return semicolon-separated list of loaded waves including partial path from current data folder.
|
||||
///
|
||||
function /s mtrx_load_preview(destName, pathName, fileName, [traces])
|
||||
string destName
|
||||
string pathName
|
||||
string fileName
|
||||
string traces
|
||||
|
||||
if (ParamIsDefault(traces))
|
||||
traces = "*Up;*Down;*ReUp;*ReDown;"
|
||||
endif
|
||||
|
||||
dfref df_save = GetDataFolderDFR()
|
||||
|
||||
string datanames = ""
|
||||
string datapaths = ""
|
||||
variable filestatus = mtrx_open_file(pathName, fileName)
|
||||
if (filestatus != 1)
|
||||
return ""
|
||||
endif
|
||||
|
||||
dfref df_pack = $(package_path)
|
||||
svar /sdfr=df_pack dataFilePath
|
||||
svar /sdfr=df_pack resultFilePath
|
||||
nvar /sdfr=df_pack runCycle
|
||||
nvar /sdfr=df_pack scanCycle
|
||||
svar /sdfr=df_pack channelName
|
||||
nvar /sdfr=df_pack brickletID
|
||||
|
||||
#if exists("MFR_OpenResultFile")
|
||||
dfref df_data = df_save
|
||||
variable /g df_data:V_MatrixFileReaderOverwrite = 1
|
||||
variable /g df_data:V_MatrixFileReaderFolder = 0
|
||||
variable /g df_data:V_MatrixFileReaderDouble = 0
|
||||
struct errorCode errorCode
|
||||
initStruct(errorCode)
|
||||
MFR_GetBrickletData /N=destName /R=(brickletID) /S=2 /DEST=df_data
|
||||
if(V_flag == errorCode.SUCCESS)
|
||||
datanames = S_waveNames
|
||||
variable i
|
||||
variable n = ItemsInList(datanames)
|
||||
string s
|
||||
s = StringFromList(0, datanames)
|
||||
wave data = $s
|
||||
mtrx_scale_dataset(data)
|
||||
if (WaveDims(data) == 2)
|
||||
subtract_line_bg(data)
|
||||
endif
|
||||
datapaths = AddListItem(GetWavesDataFolder(data, 4), datapaths, ";", inf)
|
||||
for (i = 1; i < n; i += 1)
|
||||
s = StringFromList(i, datanames)
|
||||
killwaves /z $s
|
||||
endfor
|
||||
else
|
||||
MFR_GetXOPErrorMessage
|
||||
endif
|
||||
//MFR_GetBrickletMetaData /N=ANickName /R=(brickletID) // /DEST=dfref
|
||||
#else
|
||||
print "matrixfilereader.xop not installed"
|
||||
#endif
|
||||
|
||||
setdatafolder df_save
|
||||
return datapaths
|
||||
end
|
||||
|
||||
/// load all data from a Matrix data file.
|
||||
///
|
||||
/// the data wave is loaded into a sub-subfolder the current data folder.
|
||||
/// the relative path has the format ":mtrx_{date}_{time}:r{run_cycle}s{scan_cycle}",
|
||||
/// where the parameters {date}, {time}, {run_cycle} and {scan_cycle} are copied from the file name.
|
||||
/// the file name must be formatted according to the specifications set out below.
|
||||
///
|
||||
/// @param pathName igor symbolic path name. can be empty if the path is specified in FileName or a dialog box should be displayed
|
||||
///
|
||||
/// @param fileName if empty a dialog box shows up
|
||||
/// the file name must adhere to the format
|
||||
/// "{prefix}-{date}-{time}-{anything}--{run_cycle}_{scan_cycle}.{extension}".
|
||||
/// the first three seperators can alternatively be underscores.
|
||||
/// it may be necessary to change the configuration of the Matrix application.
|
||||
///
|
||||
/// @param traces (currently not used) semicolon-separated list of preferred traces.
|
||||
/// the items of the list are match strings for the Igor StringMatch function.
|
||||
/// only matching traces are loaded from the file.
|
||||
/// default: "*Up;*Down;*ReUp;*ReDown;"
|
||||
///
|
||||
/// @return semicolon-separated list of loaded waves including partial path from current data folder.
|
||||
///
|
||||
function /s mtrx_load_file(pathName, fileName, [traces])
|
||||
string pathName
|
||||
string fileName
|
||||
string traces
|
||||
|
||||
if (ParamIsDefault(traces))
|
||||
traces = "*Up;*Down;*ReUp;*ReDown;"
|
||||
endif
|
||||
|
||||
dfref df_save = GetDataFolderDFR()
|
||||
|
||||
string datanames = ""
|
||||
string datapaths = ""
|
||||
variable filestatus = mtrx_open_file(pathName, fileName)
|
||||
if (filestatus != 1)
|
||||
return ""
|
||||
endif
|
||||
|
||||
dfref df_pack = $(package_path)
|
||||
svar /sdfr=df_pack dataFilePath
|
||||
svar /sdfr=df_pack resultFilePath
|
||||
nvar /sdfr=df_pack runCycle
|
||||
nvar /sdfr=df_pack scanCycle
|
||||
svar /sdfr=df_pack channelName
|
||||
nvar /sdfr=df_pack brickletID
|
||||
|
||||
#if exists("MFR_OpenResultFile")
|
||||
string resultFileName = ParseFilePath(0, resultFilePath, ":", 1, 0)
|
||||
dfref df_result = mtrx_create_folder(resultFileName, df_base=df_save)
|
||||
dfref df_data = mtrx_get_cycle_folder(df_base = df_result)
|
||||
variable /g df_data:V_MatrixFileReaderOverwrite = 1
|
||||
variable /g df_data:V_MatrixFileReaderFolder = 0
|
||||
variable /g df_data:V_MatrixFileReaderDouble = 0
|
||||
|
||||
struct errorCode errorCode
|
||||
initStruct(errorCode)
|
||||
string name
|
||||
name = CleanupName(channelName, 0)
|
||||
MFR_GetBrickletData /N=name /R=(brickletID) /DEST=df_data
|
||||
if(V_flag == errorCode.SUCCESS)
|
||||
datanames = S_waveNames
|
||||
variable i
|
||||
variable n = ItemsInList(datanames)
|
||||
string s
|
||||
for (i = 0; i < n; i += 1)
|
||||
s = StringFromList(i, datanames)
|
||||
wave /sdfr=df_data data = $s
|
||||
mtrx_scale_dataset(data)
|
||||
datapaths = AddListItem(GetWavesDataFolder(data, 4), datapaths, ";", inf)
|
||||
endfor
|
||||
else
|
||||
MFR_GetXOPErrorMessage
|
||||
endif
|
||||
//MFR_GetBrickletMetaData /N=ANickName /R=(brickletID) // /DEST=dfref
|
||||
#else
|
||||
print "matrixfilereader.xop not installed"
|
||||
#endif
|
||||
|
||||
setdatafolder df_save
|
||||
return datapaths
|
||||
end
|
||||
|
||||
function mtrx_scale_dataset(data)
|
||||
wave data
|
||||
|
||||
dfref df_pack = $(package_path)
|
||||
nvar /sdfr=df_pack runCycle
|
||||
nvar /sdfr=df_pack scanCycle
|
||||
svar /sdfr=df_pack channelName
|
||||
nvar /sdfr=df_pack brickletID
|
||||
|
||||
string scanDir = StringFromList(2, NameOfWave(data), "_")
|
||||
if (WaveDims(data) == 2)
|
||||
Note data, "AxisLabelX=X"
|
||||
Note data, "AxisLabelY=Y"
|
||||
endif
|
||||
Note data, "AxisLabelD=" + channelName
|
||||
string title
|
||||
sprintf title, "%u-%u %s %s", runCycle, scanCycle, channelName, scanDir
|
||||
Note data, "Dataset=" + title
|
||||
end
|
||||
|
||||
/// load descriptive info from a Matrix data file.
|
||||
///
|
||||
/// the info string lists the following information for each scan contained in the file:
|
||||
/// - path of the scan group inside the file.
|
||||
/// - number of scan positions.
|
||||
/// - dataset names of scan positioners.
|
||||
/// - dataset names of detectors.
|
||||
///
|
||||
/// @param APathName igor symbolic path name. can be empty if the path is specified in AFileName or a dialog box should be displayed
|
||||
///
|
||||
/// @param AFileName if empty a dialog box shows up
|
||||
///
|
||||
/// @return newline terminated string.
|
||||
///
|
||||
function /s mtrx_load_info(APathName, AFileName)
|
||||
string APathName
|
||||
string AFileName
|
||||
|
||||
dfref saveDF = GetDataFolderDFR()
|
||||
dfref fileDF = NewFreeDataFolder()
|
||||
setdatafolder fileDF
|
||||
|
||||
variable fileID
|
||||
string filepath
|
||||
string scanpaths
|
||||
variable nscans
|
||||
variable iscan
|
||||
string scanpath
|
||||
string info = ""
|
||||
|
||||
|
||||
setdatafolder saveDF
|
||||
return info
|
||||
end
|
||||
|
||||
/// remove linear background line-by-line
|
||||
///
|
||||
function subtract_line_bg(img)
|
||||
wave img
|
||||
|
||||
variable nx = dimsize(img, 0)
|
||||
variable ny = dimsize(img, 1)
|
||||
variable iy
|
||||
make /n=(nx) /free line, fit
|
||||
for (iy = 0; iy < ny; iy += 1)
|
||||
line = img[p][iy]
|
||||
if (numtype(sum(line)) == 0)
|
||||
CurveFit /N /Q /NTHR=0 line line /D=fit
|
||||
img[][iy] = line[p] - fit[p]
|
||||
endif
|
||||
endfor
|
||||
end
|
@ -55,10 +55,8 @@ menu "PEARL"
|
||||
end
|
||||
|
||||
submenu "Services"
|
||||
PearlMenuEnableFunc("pearl_elog") + "ELOG Experiments", /Q, pearl_elog("Experiments")
|
||||
help = {"Create entries in ELOG experiments logbook"}
|
||||
PearlMenuEnableFunc("pearl_elog") + "ELOG Calculations", /Q, pearl_elog("Calculations")
|
||||
help = {"Create entries in ELOG calculations logbook"}
|
||||
PearlMenuEnableFunc("pearl_elog") + "Open ELOG Panel", /Q, pearl_elog("")
|
||||
help = {"Open an ELOG panel to send entries to an ELOG logbook"}
|
||||
end
|
||||
|
||||
submenu "Sample Preparation"
|
||||
|
@ -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
|
2403
pearl/pearl-pshell-import.ipf
Normal file
2403
pearl/pearl-pshell-import.ipf
Normal file
File diff suppressed because it is too large
Load Diff
@ -703,3 +703,99 @@ function scienta_poly_bg(w, e, a): fitfunc
|
||||
|
||||
return bg * (base + pk1 + pk2 + pk3)
|
||||
end
|
||||
|
||||
/// parameter dialog for the redim_linbg_reduction() function
|
||||
///
|
||||
/// @param param parameter string in a key1=value1;key2=value2;... list.
|
||||
/// the parameter string is passed by reference.
|
||||
/// see redim_linbg_reduction() for a description of parameters.
|
||||
///
|
||||
/// @return zero if the user clicked OK, non-zero if the user clicked Cancel.
|
||||
///
|
||||
function prompt_redim_linbg_reduction(param)
|
||||
string ¶m
|
||||
|
||||
variable Lcrop = NumberByKey("Lcrop", param, "=", ";")
|
||||
variable Lsize = NumberByKey("Lsize", param, "=", ";")
|
||||
variable Hcrop = NumberByKey("Hcrop", param, "=", ";")
|
||||
variable Hsize = NumberByKey("Hsize", param, "=", ";")
|
||||
variable Cpos = NumberByKey("Cpos", param, "=", ";")
|
||||
variable Csize = NumberByKey("Csize", param, "=", ";")
|
||||
|
||||
prompt Lcrop, "Lower cropping region"
|
||||
prompt Hcrop, "Upper cropping region"
|
||||
prompt Lsize, "Lower background region"
|
||||
prompt Hsize, "Upper background region"
|
||||
prompt Cpos, "Center position"
|
||||
prompt Csize, "Center integration region"
|
||||
|
||||
doprompt "redim_linbg_reduction Parameters", lcrop, hcrop, lsize, hsize, cpos, csize
|
||||
if (v_flag == 0)
|
||||
param = ReplaceNumberByKey("Lcrop", param, Lcrop, "=", ";")
|
||||
param = ReplaceNumberByKey("Lsize", param, Lsize, "=", ";")
|
||||
param = ReplaceNumberByKey("Hcrop", param, Hcrop, "=", ";")
|
||||
param = ReplaceNumberByKey("Hsize", param, Hsize, "=", ";")
|
||||
param = ReplaceNumberByKey("Cpos", param, Cpos, "=", ";")
|
||||
param = ReplaceNumberByKey("Csize", param, Csize, "=", ";")
|
||||
endif
|
||||
|
||||
return v_flag
|
||||
end
|
||||
|
||||
/// linear background reduction function for incorrectly dimensioned scienta image
|
||||
///
|
||||
/// if the energy step size does not divide the energy range to an integer number,
|
||||
/// the scienta image is exported with the wrong array size.
|
||||
/// this can be fixed by redimensioning the array.
|
||||
///
|
||||
/// the current implementation works in the case where dimension 0 needs to be incremented.
|
||||
/// the function may be generalized to dimension 1 and/or decrementing by additional parameters.
|
||||
/// it is not known yet whether a generalization is needed or whether it can cover all cases.
|
||||
///
|
||||
/// background subtraction and peak integration is the same as by the int_linbg_reduction() function.
|
||||
///
|
||||
/// @param source source wave
|
||||
/// Scienta detector image, energy axis along X, angle axis along Y
|
||||
///
|
||||
/// @param dest1 destination wave 1
|
||||
///
|
||||
/// @param dest2 destination wave 2
|
||||
/// each wave is a one-dimensional intensity distribution
|
||||
/// the function may redimension these waves to one of the image dimensions
|
||||
/// (it must be clear to the user which dimension this is).
|
||||
/// the meaning of 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 param parameter string in a key1=value1;key2=value2;... list.
|
||||
/// the parameter string is passed by reference.
|
||||
///
|
||||
/// all region parameters are relative to the image size (0...1).
|
||||
/// @arg Lcrop size of the lower cropping region
|
||||
/// @arg Hcrop size of the upper cropping region
|
||||
/// @arg Lsize size of the lower background integration region
|
||||
/// @arg Hsize size of the upper background integration region
|
||||
/// @arg Cpos center position of the of the peak integration region
|
||||
/// @arg Csize size of the peak integration region
|
||||
///
|
||||
/// typical values (peak centered on detector, FWHM ~ 20 % of image)
|
||||
/// Lcrop=0.11;Hcrop=0.11;Lsize=0.2;Hsize=0.2;Cpos=0.5;Csize=0.2
|
||||
///
|
||||
/// @return zero if successful, non-zero if an error occurs.
|
||||
///
|
||||
threadsafe function redim_linbg_reduction(source, dest1, dest2, param)
|
||||
wave source
|
||||
wave dest1, dest2
|
||||
string ¶m
|
||||
|
||||
variable nx = dimsize(source, 0)
|
||||
variable ny = dimsize(source, 1)
|
||||
|
||||
duplicate /free source, source_redim
|
||||
redimension /n=(nx * ny) source_redim
|
||||
nx += 1
|
||||
redimension /n=(nx, ny) source_redim
|
||||
|
||||
return int_linbg_reduction(source_redim, dest1, dest2, param)
|
||||
end
|
||||
|
||||
|
Binary file not shown.
Reference in New Issue
Block a user