new user distribution of PEARL procedures
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
*~
|
||||
~*
|
||||
*.bak
|
||||
*.ipfT*
|
||||
doc/html/*
|
||||
doc/latex/*
|
2381
doc/Doxyfile
Normal file
2381
doc/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
194
doc/DoxygenLayout.xml
Normal file
194
doc/DoxygenLayout.xml
Normal file
@ -0,0 +1,194 @@
|
||||
<doxygenlayout version="1.0">
|
||||
<!-- Generated by doxygen 1.8.9.1 -->
|
||||
<!-- Navigation index tabs for HTML output -->
|
||||
<navindex>
|
||||
<tab type="mainpage" visible="yes" title=""/>
|
||||
<tab type="pages" visible="yes" title="" intro=""/>
|
||||
<tab type="modules" visible="yes" title="Packages" intro="Packages are collections of procedure files to be loaded together. PEARL defines the following packages:"/>
|
||||
<tab type="namespaces" visible="yes" title="">
|
||||
<tab type="namespacelist" visible="yes" title="" intro=""/>
|
||||
<tab type="namespacemembers" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="classes" visible="no" title="">
|
||||
<tab type="classlist" visible="yes" title="" intro=""/>
|
||||
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
|
||||
<tab type="hierarchy" visible="yes" title="" intro=""/>
|
||||
<tab type="classmembers" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="files" visible="yes" title="">
|
||||
<tab type="filelist" visible="yes" title="" intro=""/>
|
||||
<tab type="globals" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="examples" visible="yes" title="" intro=""/>
|
||||
</navindex>
|
||||
|
||||
<!-- Layout definition for a class page -->
|
||||
<class>
|
||||
<briefdescription visible="yes"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<inheritancegraph visible="$CLASS_GRAPH"/>
|
||||
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
|
||||
<memberdecl>
|
||||
<nestedclasses visible="yes" title=""/>
|
||||
<publictypes title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<publicslots title=""/>
|
||||
<signals title=""/>
|
||||
<publicmethods title=""/>
|
||||
<publicstaticmethods title=""/>
|
||||
<publicattributes title=""/>
|
||||
<publicstaticattributes title=""/>
|
||||
<protectedtypes title=""/>
|
||||
<protectedslots title=""/>
|
||||
<protectedmethods title=""/>
|
||||
<protectedstaticmethods title=""/>
|
||||
<protectedattributes title=""/>
|
||||
<protectedstaticattributes title=""/>
|
||||
<packagetypes title=""/>
|
||||
<packagemethods title=""/>
|
||||
<packagestaticmethods title=""/>
|
||||
<packageattributes title=""/>
|
||||
<packagestaticattributes title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
<privatetypes title=""/>
|
||||
<privateslots title=""/>
|
||||
<privatemethods title=""/>
|
||||
<privatestaticmethods title=""/>
|
||||
<privateattributes title=""/>
|
||||
<privatestaticattributes title=""/>
|
||||
<friends title=""/>
|
||||
<related title="" subtitle=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<constructors title=""/>
|
||||
<functions title=""/>
|
||||
<related title=""/>
|
||||
<variables title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
</memberdef>
|
||||
<allmemberslink visible="yes"/>
|
||||
<usedfiles visible="$SHOW_USED_FILES"/>
|
||||
<authorsection visible="yes"/>
|
||||
</class>
|
||||
|
||||
<!-- Layout definition for a namespace page -->
|
||||
<namespace>
|
||||
<briefdescription visible="yes"/>
|
||||
<memberdecl>
|
||||
<nestednamespaces visible="yes" title=""/>
|
||||
<constantgroups visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</namespace>
|
||||
|
||||
<!-- Layout definition for a file page -->
|
||||
<file>
|
||||
<briefdescription visible="yes"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<includegraph visible="$INCLUDE_GRAPH"/>
|
||||
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
|
||||
<sourcelink visible="yes"/>
|
||||
<memberdecl>
|
||||
<classes visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<constantgroups visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection/>
|
||||
</file>
|
||||
|
||||
<!-- Layout definition for a group page -->
|
||||
<group>
|
||||
<briefdescription visible="yes"/>
|
||||
<groupgraph visible="$GROUP_GRAPHS"/>
|
||||
<memberdecl>
|
||||
<nestedgroups visible="yes" title=""/>
|
||||
<dirs visible="yes" title=""/>
|
||||
<files visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<pagedocs/>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</group>
|
||||
|
||||
<!-- Layout definition for a directory page -->
|
||||
<directory>
|
||||
<briefdescription visible="yes"/>
|
||||
<directorygraph visible="yes"/>
|
||||
<memberdecl>
|
||||
<dirs visible="yes"/>
|
||||
<files visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
</directory>
|
||||
</doxygenlayout>
|
242
doc/doxygen-filter-ipf.awk
Normal file
242
doc/doxygen-filter-ipf.awk
Normal file
@ -0,0 +1,242 @@
|
||||
# Proof of concept implementation for using doxygen to document Igor Pro procedures
|
||||
# This awk script serves as input filter for Igor procedures and produces a C-ish version of the declarations
|
||||
# Tested with Igor Pro 6.34A and doxygen 1.8.7
|
||||
#
|
||||
# Thomas Braun: 9/2014
|
||||
# Version: 0.23
|
||||
|
||||
# Supported Features:
|
||||
# -Functions
|
||||
# -Macros
|
||||
# -File constants
|
||||
# -Menu items are currently ignored
|
||||
|
||||
# TODO
|
||||
# - don't delete the function/macro subType
|
||||
|
||||
BEGIN{
|
||||
# allows to bail out for code found outside of functions/macros
|
||||
DO_WARN=0
|
||||
IGNORECASE=1
|
||||
output=""
|
||||
warning=""
|
||||
|
||||
menuEndCount=0
|
||||
}
|
||||
|
||||
# Remove whitespace at beginning and end of string
|
||||
# Return the whitespace in front of the string in the
|
||||
# global variable frontSpace to be able
|
||||
# to reconstruct the indentation
|
||||
function trim(str)
|
||||
{
|
||||
if(match(str, /^[[:space:]]+/))
|
||||
{
|
||||
frontSpace = substr(str, 1, RLENGTH)
|
||||
str = substr(str, RLENGTH + 1)
|
||||
}
|
||||
else
|
||||
frontSpace = ""
|
||||
|
||||
gsub(/[[:space:]]+$/,"",str)
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
# Split an already trimmed line into words
|
||||
# Returns the number of words
|
||||
function splitIntoWords(str, a, numEntries)
|
||||
{
|
||||
return split(str,a,/[[:space:],&*]+/)
|
||||
}
|
||||
|
||||
# Split params into words and prefix each with "__Param__$i"
|
||||
# where $i is increased for every parameter
|
||||
# Returns the concatenation of all prefixed parameters
|
||||
function handleParameter(params, a, i, iOpt, str, entry)
|
||||
{
|
||||
numParams = splitIntoWords(params, a)
|
||||
str=""
|
||||
entry=""
|
||||
iOpt=numParams
|
||||
for(i=1; i <= numParams; i++)
|
||||
{
|
||||
# convert igor optional parameters to something doxygen understands
|
||||
# igor dictates that the optional arguments are the last arguments,
|
||||
# meaning no normal argument can follow the optional arguments
|
||||
if(gsub(/[\[\]]/,"",a[i]) || i > iOpt)
|
||||
{
|
||||
iOpt = i
|
||||
entry = a[i] " = defaultValue"
|
||||
}
|
||||
else
|
||||
entry = a[i]
|
||||
|
||||
str = str "__Param__" i " " entry
|
||||
if(i < numParams)
|
||||
str = str ", "
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
{
|
||||
# split current line into code and comment
|
||||
if(match($0,/\/\/.*/))
|
||||
{
|
||||
code=substr($0,0,RSTART-1)
|
||||
comment=substr($0,RSTART,RLENGTH)
|
||||
}
|
||||
else
|
||||
{
|
||||
code=$0
|
||||
comment=""
|
||||
}
|
||||
# remove whitespace from front and back
|
||||
code=trim(code)
|
||||
|
||||
# begin of macro definition
|
||||
if(!insideFunction && !insideMacro && ( match(code,/^Window/)|| match(code,/^Proc/) || match(code,/^Macro/) ) )
|
||||
{
|
||||
insideMacro=1
|
||||
gsub(/^Window/,"void",code)
|
||||
gsub(/^Macro/,"void",code)
|
||||
gsub(/^Proc/,"void",code)
|
||||
|
||||
# add opening bracket, this also throws away any function subType
|
||||
gsub(/\).*/,"){",code)
|
||||
}
|
||||
# end of macro definition
|
||||
else if(!insideFunction && insideMacro && ( match(code,/^EndMacro$/) || match(code,/^End$/) ) )
|
||||
{
|
||||
insideMacro=0
|
||||
code = "}"
|
||||
}
|
||||
# begin of function declaration
|
||||
else if(!insideFunction && ( match(code,/[[:space:]]function[\/[[:space:]]/) || match(code,/^function[\/[[:space:]]/) ) )
|
||||
{
|
||||
insideFunction=1
|
||||
# remove whitespace between function and return type flag
|
||||
gsub(/function[[:space:]]*\//,"function/",code)
|
||||
|
||||
# different return types
|
||||
gsub(/function /,"variable ",code)
|
||||
gsub(/function\/df/,"dfr",code)
|
||||
gsub(/function\/wave/,"wave",code)
|
||||
gsub(/function\/c/,"complex",code)
|
||||
gsub(/function\/s/,"string",code)
|
||||
gsub(/function\/t/,"string",code) # deprecated definition of string return type
|
||||
gsub(/function\/d/,"variable",code)
|
||||
|
||||
# add opening bracket, this also throws away any function subType
|
||||
gsub(/\).*/,"){",code)
|
||||
|
||||
# do we have function parameters
|
||||
if(match(code,/\(.*[a-z]+.*\)/))
|
||||
{
|
||||
paramStr = substr(code,RSTART+1,RLENGTH-2)
|
||||
|
||||
paramStrWithTypes = handleParameter(paramStr, params)
|
||||
paramsToHandle = numParams
|
||||
# print "paramStr __ " paramStr
|
||||
# print "paramStrWithTypes __ " paramStrWithTypes
|
||||
# print "paramsToHandle __ " paramsToHandle
|
||||
|
||||
code = substr(code,0,RSTART) "" paramStrWithTypes "" substr(code,RSTART+RLENGTH-1)
|
||||
}
|
||||
}
|
||||
else if(insideFunction && paramsToHandle > 0)
|
||||
{
|
||||
numEntries = splitIntoWords(code,entries)
|
||||
|
||||
# printf("Found %d words in line \"%s\"\n",numEntries,code)
|
||||
for(i=2; i <= numEntries; i++)
|
||||
for(j=1; j <= numParams; j++)
|
||||
{
|
||||
variableName = entries[i]
|
||||
if( entries[i] == params[j] )
|
||||
{
|
||||
paramsToHandle--
|
||||
# now replace __Param__$i with the real parameter type
|
||||
if(entries[1] == "struct")
|
||||
paramType = entries[2]
|
||||
else
|
||||
paramType = tolower(entries[1])
|
||||
|
||||
# add asterisk for call-by-reference parameters
|
||||
if(match(code,/\&/))
|
||||
paramType = paramType "*"
|
||||
|
||||
output = gensub("__Param__" j " ",paramType " ","g",output)
|
||||
# printf("Found parameter type %s at index %d\n",paramType,j)
|
||||
}
|
||||
}
|
||||
}
|
||||
# end of function declaration
|
||||
else if(insideFunction && match(code,/^end$/))
|
||||
{
|
||||
insideFunction=0
|
||||
code = "}"
|
||||
}
|
||||
|
||||
# structure declaration
|
||||
if(!insideFunction && !insideMacro && ( match(code,/[[:space:]]structure[[:space:]]/) || match(code,/^structure[[:space:]]/) ) )
|
||||
{
|
||||
insideStructure=1
|
||||
gsub(/structure/,"struct",code)
|
||||
code = code "{"
|
||||
}
|
||||
|
||||
if(insideStructure && match(code,/EndStructure/))
|
||||
{
|
||||
insideStructure=0
|
||||
code = "}"
|
||||
}
|
||||
|
||||
# menu definition
|
||||
# submenues can be nested in menus. Therefore we have to keep track
|
||||
# of the number of expected "End" keywords
|
||||
if(!insideFunction && !insideMacro && ( match(code,/\yMenu\y/) || match(code,/\ySubMenu\y/) ))
|
||||
{
|
||||
menuEndCount++
|
||||
insideMenu=1
|
||||
}
|
||||
|
||||
if(insideMenu && match(code,/\yEnd[[:space:]]*/))
|
||||
{
|
||||
menuEndCount--
|
||||
if(menuEndCount == 0)
|
||||
{
|
||||
insideMenu=0
|
||||
code = ""
|
||||
}
|
||||
}
|
||||
|
||||
# global constants
|
||||
gsub(/\ystrconstant\y/,"const string",code)
|
||||
gsub(/\yconstant\y/,"const variable",code)
|
||||
# prevent that doxygen sees elseif as a function call
|
||||
gsub(/\yelseif\y/,"else if",code)
|
||||
|
||||
# code outside of function/macro definitions is "translated" into statements
|
||||
if(!insideFunction && !insideMacro && !insideMenu && code != "" && substr(code,0,1) != "#")
|
||||
{
|
||||
if(code != "}" && !insideStructure && DO_WARN)
|
||||
warning = warning "\n" "warning " NR ": outside code \"" code "\""
|
||||
|
||||
code = code ";"
|
||||
}
|
||||
|
||||
if(!insideMenu)
|
||||
{
|
||||
output = output frontSpace code comment
|
||||
}
|
||||
|
||||
output = output "\n"
|
||||
}
|
||||
|
||||
END{
|
||||
print output
|
||||
|
||||
if(DO_WARN)
|
||||
print warning
|
||||
}
|
27
doc/makefile
Normal file
27
doc/makefile
Normal file
@ -0,0 +1,27 @@
|
||||
SHELL=/bin/sh
|
||||
|
||||
# makefile for PEARL procedures documentation
|
||||
#
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .cpp .cxx .exe .f .h .i .o .py .pyf .so .html
|
||||
.PHONY: all docs clean
|
||||
|
||||
DOX=doxygen
|
||||
DOXOPTS=
|
||||
LATEX_DIR=latex
|
||||
|
||||
all: docs
|
||||
|
||||
docs: doxygen pdf
|
||||
|
||||
doxygen:
|
||||
$(DOX) $(DOXOPTS) Doxyfile
|
||||
|
||||
pdf: doxygen
|
||||
-$(MAKE) -C $(LATEX_DIR)
|
||||
|
||||
clean:
|
||||
-rm latex/*
|
||||
-rm html/*
|
||||
|
17
doc/readme.txt
Normal file
17
doc/readme.txt
Normal file
@ -0,0 +1,17 @@
|
||||
this folder and subfolders contain the documentation of the PEARL procedures in HTML and PDF format.
|
||||
|
||||
the documentation is currently migrated to the doxygen format.
|
||||
descriptions may be incomplete until the migration is finished.
|
||||
|
||||
to compile the documentation the following pieces of software are required:
|
||||
|
||||
doxygen:
|
||||
http://www.doxygen.org/
|
||||
|
||||
gawk:
|
||||
http://gnuwin32.sourceforge.net/packages/gawk.htm (windows)
|
||||
|
||||
doxygen-filter-ipf.awk:
|
||||
http://www.igorexchange.com/project/doxIPFFilter
|
||||
|
||||
please see the original web sites for terms of use.
|
202
pearl/LICENSE.txt
Normal file
202
pearl/LICENSE.txt
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
6
pearl/NOTICE.txt
Normal file
6
pearl/NOTICE.txt
Normal file
@ -0,0 +1,6 @@
|
||||
PEARL Igor Procedures
|
||||
Copyright 2009-2014 Paul Scherrer Institut
|
||||
|
||||
This product includes software developed at the
|
||||
Paul Scherrer Institut, Villigen, Switzerland (http://www.psi.ch/).
|
||||
|
320
pearl/fermi-edge-analysis.ipf
Normal file
320
pearl/fermi-edge-analysis.ipf
Normal file
@ -0,0 +1,320 @@
|
||||
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
|
||||
#include "pearl-area-profiles"
|
||||
|
||||
// $Id$
|
||||
|
||||
/// @file
|
||||
/// @brief tools for analysing the Fermi edge measured by the Scienta EW4000 analyser.
|
||||
/// @ingroup ArpesPackage
|
||||
///
|
||||
/// proposed procedure
|
||||
///
|
||||
/// * angular normalization
|
||||
/// * fit curved fermi function
|
||||
/// * calculate corrected energy coordinates and map to single independent variable
|
||||
/// * fit normal fermi function
|
||||
///
|
||||
/// @author matthias muntwiler, matthias.muntwiler@psi.ch
|
||||
/// @author thomas dienel
|
||||
///
|
||||
/// @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
|
||||
|
||||
|
||||
function analyse_curved_edge(data)
|
||||
wave data // 2D counts data, x-scale = kinetic energy, y-scale = analyser angle
|
||||
variable guess_EF // initial guess of the Fermi level
|
||||
|
||||
dfref savedf = GetDataFolderDFR()
|
||||
dfref datadf = GetWavesDataFolderDFR(data)
|
||||
setdatafolder datadf
|
||||
|
||||
make /n=5 /d /o w_coef_int
|
||||
make /n=7 /d /o w_coef_curved
|
||||
|
||||
// 1) integrate data
|
||||
wave xint = ad_profile_x(data, -inf, inf, "", noavg=1)
|
||||
duplicate /free xint, xint_sig
|
||||
xint_sig = sqrt(xint * 4) / 4
|
||||
variable xmin = wavemin(xint)
|
||||
variable xmax = wavemax(xint)
|
||||
variable xmean = mean(xint)
|
||||
|
||||
// 2) fit integrated data for reference
|
||||
w_coef_int[0] = xmin
|
||||
w_coef_int[1] = 0
|
||||
w_coef_int[2] = xmax - xmin
|
||||
w_coef_int[3] = dimoffset(xint, 0) + dimdelta(xint, 0) * dimsize(xint, 0) / 2
|
||||
w_coef_int[4] = 100
|
||||
FuncFit /NTHR=0 FermiFuncLinDOS w_coef_int xint /D /I=1 /W=xint_sig
|
||||
wave w_sigma
|
||||
duplicate /o w_sigma, w_sigma_int
|
||||
|
||||
// 3) normalize data
|
||||
wave yavg = ad_profile_y(data, -inf, inf, "")
|
||||
variable ymean = mean(yavg)
|
||||
|
||||
duplicate /o data, data_norm, data_sig
|
||||
data_sig = sqrt(data * 4) / 4
|
||||
data_norm = data_norm * ymean / yavg[q]
|
||||
data_sig = data_sig * ymean / yavg[q]
|
||||
|
||||
// 4) fit normalized data
|
||||
wave xavg = ad_profile_x(data, -inf, inf, "")
|
||||
xmin = wavemin(xavg)
|
||||
xmax = wavemax(xavg)
|
||||
xmean = mean(xavg)
|
||||
|
||||
w_coef_curved[0] = {0, 0, 1, 95.5, 100, 0, -0.0001}
|
||||
w_coef_curved[0] = xmin
|
||||
w_coef_curved[2] = xmax - xmin
|
||||
w_coef_curved[3] = w_coef_int[3]
|
||||
w_coef_curved[4] = w_coef_int[4]
|
||||
|
||||
//variable box = min(11, numpnts(xavg) / 5)
|
||||
//FindLevel /B=(box) /EDGE=2 /Q xavg, (xmin + xmax) / 2
|
||||
//if (v_flag == 0)
|
||||
// w_coef_curved[3] = v_levelx
|
||||
//else
|
||||
// w_coef_curved[3] = dimoffset(data, 0) + dimdelta(data, 0) * dimsize(data, 0) / 2
|
||||
//endif
|
||||
|
||||
duplicate /o data_norm, fit_data_norm
|
||||
FuncFitMD /X=1 /NTHR=0 FermiFuncLinDOS_2Dcorr w_coef_curved data_norm /D=fit_data_norm /I=1 /W=data_sig
|
||||
wave w_sigma
|
||||
duplicate /o w_sigma, w_sigma_curved
|
||||
|
||||
display /k=1; appendimage data_norm
|
||||
ModifyImage data_norm ctab= {xmin,xmax,Grays,0}
|
||||
AppendMatrixContour fit_data_norm
|
||||
|
||||
setdatafolder savedf
|
||||
return 0
|
||||
end
|
||||
|
||||
function record_results(index)
|
||||
variable index
|
||||
|
||||
dfref savedf = GetDataFolderDFR()
|
||||
wave /sdfr=root: Tint, Tint_sig, Tcurv, Tcurv_sig, EFcurv, EFcurv_sig
|
||||
wave w_coef_int, w_coef_curved
|
||||
wave w_sigma_int, w_sigma_curved
|
||||
|
||||
Tint[index] = w_coef_int[4]
|
||||
Tint_sig[index] = w_sigma_int[4]
|
||||
Tcurv[index] = w_coef_curved[4]
|
||||
Tcurv_sig[index] = w_sigma_curved[4]
|
||||
EFcurv[index] = w_coef_curved[3]
|
||||
EFcurv_sig[index] = w_sigma_curved[3]
|
||||
|
||||
setdatafolder savedf
|
||||
end
|
||||
|
||||
function integrate_curved_edge(data, data_sig)
|
||||
wave data
|
||||
wave /z data_sig
|
||||
//wave coef
|
||||
|
||||
string name = nameofwave(data)
|
||||
|
||||
duplicate /o data, data_out
|
||||
redimension /n=(dimsize(data,0)) data_out
|
||||
data_out = 0
|
||||
|
||||
if (waveexists(data_sig))
|
||||
duplicate /o data_sig, sig_out
|
||||
redimension /n=(dimsize(data,0)) sig_out
|
||||
sig_out = 0
|
||||
endif
|
||||
|
||||
wave ywgt = ad_profile_y(data, -inf, inf, "", noavg=1)
|
||||
ywgt = 1 / ywgt / 4
|
||||
//ywgt = 1 / 4
|
||||
variable sum_ywgt = sum(ywgt)
|
||||
|
||||
variable nx = dimsize(data, 0)
|
||||
variable ny = dimsize(data, 1)
|
||||
variable iy
|
||||
variable yy
|
||||
variable dx
|
||||
variable dy
|
||||
variable dp
|
||||
variable dp_min = 0
|
||||
|
||||
wave PassEnergy = :attr:PassEnergy
|
||||
wave NumSlices = :attr:NumSlices
|
||||
|
||||
for (iy = 0; iy < ny; iy += 1)
|
||||
dy = dimoffset(data, 1) + dimdelta(data, 1) * iy
|
||||
dy = dy / dimdelta(data, 1)
|
||||
dx = slit_shift(dy * 902 / NumSlices[0], PassEnergy[0])
|
||||
dp = round(dx / dimdelta(data, 0)) // <= 0
|
||||
dp_min = min(dp_min, dp)
|
||||
|
||||
data_out[] = p+dp >= 0 ? data_out + data[p+dp][iy] * ywgt[iy] : data_out
|
||||
|
||||
if (waveexists(data_sig))
|
||||
sig_out = p+dp >= 0 ? sig_out + data_sig[p+dp][iy] * ywgt[iy] : sig_out
|
||||
endif
|
||||
endfor
|
||||
|
||||
data_out /= sum_ywgt
|
||||
data_out[0, -dp_min][] = nan
|
||||
|
||||
if (waveexists(sig_out))
|
||||
sig_out /= sum_ywgt
|
||||
//sig_out[0, -dp_min] = nan
|
||||
endif
|
||||
end
|
||||
|
||||
function slit_correction(data, data_out, epass)
|
||||
wave data // must be image with original dimensions (no cropping!)
|
||||
wave /z data_out // 2D or 1D wave to receive the result
|
||||
// X dimension must be identical to the one of data
|
||||
// if 2D, Y dimension must be either identical to the one of data
|
||||
// if 1D, the result will be the sum of the corrected slices
|
||||
variable epass // pass energy
|
||||
|
||||
if (!WaveExists(data_out))
|
||||
string name = nameofwave(data) + "_corr"
|
||||
duplicate /o data, $name
|
||||
wave data_out = $name
|
||||
//redimension /n=(dimsize(data,0)) data_out
|
||||
endif
|
||||
data_out = 0
|
||||
|
||||
variable nx = dimsize(data, 0)
|
||||
variable ny = dimsize(data, 1)
|
||||
variable iy
|
||||
variable yy
|
||||
variable dx
|
||||
variable dy
|
||||
variable dp
|
||||
variable dp_min = 0
|
||||
|
||||
for (iy = 0; iy < ny; iy += 1)
|
||||
dy = dimoffset(data, 1) + dimdelta(data, 1) * iy
|
||||
dy = dy / dimdelta(data, 1)
|
||||
dx = slit_shift(dy * 902 / ny, epass)
|
||||
dp = round(dx / dimdelta(data, 0)) // <= 0
|
||||
dp_min = min(dp_min, dp)
|
||||
|
||||
if (wavedims(data_out) >= 2)
|
||||
data_out[][iy] = p+dp >= 0 ? data_out + data[p+dp][iy] : data_out
|
||||
else
|
||||
data_out = p+dp >= 0 ? data_out + data[p+dp][iy] : data_out
|
||||
endif
|
||||
endfor
|
||||
|
||||
data_out[0, -dp_min][] = nan
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
threadsafe Function FermiFuncLinDOS2D_corr(w,x,y) : FitFunc
|
||||
// linear density of states below Fermi level
|
||||
// 2D data with corrections:
|
||||
// - straight slit (slit shift)
|
||||
// - transmission function (polynomial)
|
||||
//------------------------------------------------------------------------------
|
||||
Wave w; Variable x; variable y
|
||||
// w[0] = background far above the fermi level
|
||||
// w[1] = slope of the linear background
|
||||
// w[2] = amplitude
|
||||
// w[3] = fermi level in eV
|
||||
// w[4] = temperature in K
|
||||
// w[5] = transmission - linear term
|
||||
// w[6] = transmission - quadratic term
|
||||
// w[7] = transmission - cubic term
|
||||
// w[8] = pass energy (hold this value)
|
||||
// w[9] = y scale: pixels / unit of y
|
||||
|
||||
variable pos = w[3] + slit_shift(y * w[9], w[8])
|
||||
variable transm = 1 + w[5] * y + w[6] * y^2 + w[7] * y^3
|
||||
variable fermi = (w[1] * min(x - pos, 0) + w[2]) / ( exp( (x - pos) / (kBoltzmann * w[4]) ) + 1.0 )
|
||||
return transm * (fermi + w[0])
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
threadsafe Function FermiFuncLinDOS_2Dcorr_old(w,x,y) : FitFunc
|
||||
// linear density of states below Fermi level
|
||||
// 2D data with a polynomial shift of the Fermi level in the second dimension
|
||||
//------------------------------------------------------------------------------
|
||||
Wave w; Variable x; variable y
|
||||
// w[0] = background far above the fermi level
|
||||
// w[1] = slope of the linear background
|
||||
// w[2] = amplitude
|
||||
// w[3] = fermi level in eV
|
||||
// w[4] = temperature in K
|
||||
// w[5] = shift - linear term
|
||||
// w[6] = shift - quadratic term
|
||||
|
||||
variable pos = w[3] + w[5] * y + w[6] * y^2
|
||||
return w[0] + (w[1] * min(x - pos, 0) + w[2]) / ( exp( (x - pos) / (kBoltzmann * w[4]) ) + 1.0 )
|
||||
end
|
||||
|
||||
/// MCP radius seen by the camera in pixels
|
||||
static constant mcp_radius_pix = 555
|
||||
/// physical size (radius) of the MCP in mm
|
||||
static constant mcp_radius_mm = 20
|
||||
/// physical size (radius) of the hemisphere in mm
|
||||
static constant hemi_radius_mm = 200
|
||||
/// energy range imaged on MCP relative to the pass energy
|
||||
static constant mcp_radius_epass = 0.04
|
||||
|
||||
threadsafe function slit_shift(ypix, epass)
|
||||
// calculates the energy shift due to straight slit
|
||||
// the radius of the curve is 1/2 of the hemisphere radius
|
||||
variable ypix // vertical (angle/position) pixels distance from center
|
||||
// = slice coordinate * 902 / number of slices
|
||||
variable epass // pass energy
|
||||
|
||||
variable rpix = mcp_radius_pix * hemi_radius_mm / mcp_radius_mm
|
||||
//variable rpix = mcp_radius_pix * hemi_radius_mm / 2 / mcp_radius_mm
|
||||
variable rene = epass * mcp_radius_epass * hemi_radius_mm / 2 / mcp_radius_mm
|
||||
|
||||
variable isin = asin(ypix / rpix)
|
||||
variable dene = rene * (cos(isin) - 1)
|
||||
|
||||
return dene
|
||||
end
|
||||
|
||||
function show_shift(data)
|
||||
wave data
|
||||
variable epass
|
||||
|
||||
variable ny = dimsize(data, 1)
|
||||
make /o /n=(ny) shift_x
|
||||
setscale /i x -ny/2, ny/2, "", shift_x
|
||||
wave PassEnergy = :attr:PassEnergy
|
||||
wave NumSlices = :attr:NumSlices
|
||||
|
||||
shift_x = slit_shift(x * 902 / NumSlices[0], PassEnergy[0])
|
||||
|
||||
variable ecenter = dimoffset(data, 0) + dimdelta(data, 0) * dimsize(data, 0) / 2
|
||||
shift_x += ecenter
|
||||
end
|
||||
|
||||
/// calculate the energy resolution of the analyser
|
||||
///
|
||||
/// @param epass pass energy in eV
|
||||
/// @param slit analyser entrance slit in mm
|
||||
///
|
||||
/// @return energy resolution (FWHM)
|
||||
function analyser_energy_resolution(epass, slit)
|
||||
variable epass
|
||||
variable slit
|
||||
|
||||
variable respow
|
||||
if (epass < 4)
|
||||
respow = 1110
|
||||
elseif (epass < 8)
|
||||
respow = 1400
|
||||
else
|
||||
respow = 1750
|
||||
endif
|
||||
|
||||
return epass * max(0.2, slit) / 0.2 / respow
|
||||
end
|
80
pearl/pearl-anglescan-process-test.ipf
Normal file
80
pearl/pearl-anglescan-process-test.ipf
Normal file
@ -0,0 +1,80 @@
|
||||
#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
|
2236
pearl/pearl-anglescan-process.ipf
Normal file
2236
pearl/pearl-anglescan-process.ipf
Normal file
File diff suppressed because it is too large
Load Diff
1258
pearl/pearl-anglescan-tracker.ipf
Normal file
1258
pearl/pearl-anglescan-tracker.ipf
Normal file
File diff suppressed because it is too large
Load Diff
1508
pearl/pearl-anneal.ipf
Normal file
1508
pearl/pearl-anneal.ipf
Normal file
File diff suppressed because it is too large
Load Diff
1668
pearl/pearl-area-display.ipf
Normal file
1668
pearl/pearl-area-display.ipf
Normal file
File diff suppressed because it is too large
Load Diff
1613
pearl/pearl-area-import.ipf
Normal file
1613
pearl/pearl-area-import.ipf
Normal file
File diff suppressed because it is too large
Load Diff
368
pearl/pearl-area-live.ipf
Normal file
368
pearl/pearl-area-live.ipf
Normal file
@ -0,0 +1,368 @@
|
||||
#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
|
454
pearl/pearl-area-profiles-test.ipf
Normal file
454
pearl/pearl-area-profiles-test.ipf
Normal file
@ -0,0 +1,454 @@
|
||||
#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
|
615
pearl/pearl-area-profiles.ipf
Normal file
615
pearl/pearl-area-profiles.ipf
Normal file
@ -0,0 +1,615 @@
|
||||
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
|
||||
#pragma IgorVersion = 6.1
|
||||
#pragma ModuleName = PearlAreaProfiles
|
||||
#pragma version = 1.05
|
||||
|
||||
/// @file
|
||||
/// @brief profile extraction for multi-dimensional datasets acquired from area detectors.
|
||||
/// @ingroup ArpesPackage
|
||||
///
|
||||
///
|
||||
///
|
||||
/// @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 PearlAreaProfiles
|
||||
/// @brief profile extraction for multi-dimensional datasets acquired from area detectors.
|
||||
///
|
||||
/// PearlAnglescanTracker is declared in @ref pearl-area-profiles.ipf.
|
||||
///
|
||||
|
||||
/// 1D cut through 3D dataset, integrate in normal dimensions
|
||||
///
|
||||
/// @param dataset
|
||||
/// @param x1, x2, y1, y2, z1, z2
|
||||
/// coordinates of integration region
|
||||
/// by default, the coordinates use wave scaling
|
||||
/// coordinates of rod dimensions (to be preserved) must be nan
|
||||
/// coordinate pairs don't have to be ordered, i.e. both x1 <= x2 and x1 >= x2 are allowed.
|
||||
/// @param destname
|
||||
/// name of destination wave. to be created in current data folder.
|
||||
/// if empty, the function returns a free wave
|
||||
/// @param noavg
|
||||
/// non-zero = calculate the sum, default = 0
|
||||
/// as of version 1.05, this option should rather be called "calc_sum" or similar.
|
||||
/// it is noavg for compatibility with older code.
|
||||
/// @param sdev
|
||||
/// non-zero = calculate the standard deviation, default = 0
|
||||
/// by default, the function calculates the average of the integration region
|
||||
/// set either the noavg or sdev option to select the sum or the standard deviation, respectively.
|
||||
/// if both options are set, noavg (sum) takes precedence.
|
||||
/// @param pscale
|
||||
/// scaling of the slab coordinates x1, x2, ..., z2:
|
||||
/// zero or default = wave scaling, non-zero = point scaling
|
||||
///
|
||||
/// @remark
|
||||
/// * version 1.02: the specification of the destination coordinates has changed
|
||||
/// * version 1.04: the function returns an empty wave reference if an error occurred
|
||||
///
|
||||
threadsafe function /wave ad_extract_rod(dataset, x1, x2, y1, y2, z1, z2, destname, [noavg, sdev, pscale])
|
||||
wave dataset
|
||||
variable x1, x2, y1, y2, z1, z2
|
||||
string destname
|
||||
variable noavg
|
||||
variable sdev
|
||||
variable pscale
|
||||
|
||||
if (wavedims(dataset) != 3)
|
||||
return $""
|
||||
endif
|
||||
if (ParamIsDefault(noavg))
|
||||
noavg = 0
|
||||
endif
|
||||
if (ParamIsDefault(sdev))
|
||||
sdev = 0
|
||||
endif
|
||||
if (ParamIsDefault(pscale))
|
||||
pscale = 0
|
||||
endif
|
||||
|
||||
variable p1, p2, q1, q2, r1, r2
|
||||
if (pscale)
|
||||
p1 = x1
|
||||
p2 = x2
|
||||
q1 = y1
|
||||
q2 = y2
|
||||
r1 = z1
|
||||
r2 = z2
|
||||
else
|
||||
p1 = round((x1 - DimOffset(dataset, 0)) / DimDelta(dataset, 0))
|
||||
p2 = round((x2 - DimOffset(dataset, 0)) / DimDelta(dataset, 0))
|
||||
q1 = round((y1 - DimOffset(dataset, 1)) / DimDelta(dataset, 1))
|
||||
q2 = round((y2 - DimOffset(dataset, 1)) / DimDelta(dataset, 1))
|
||||
r1 = round((z1 - DimOffset(dataset, 2)) / DimDelta(dataset, 2))
|
||||
r2 = round((z2 - DimOffset(dataset, 2)) / DimDelta(dataset, 2))
|
||||
endif
|
||||
|
||||
if ((numtype(p1) == 2) || (numtype(p2) == 2))
|
||||
return ad_extract_rod_x(dataset, min(q1, q2), max(q1, q2), min(r1, r2), max(r1, r2), destname, noavg=noavg, sdev=sdev)
|
||||
elseif ((numtype(q1) == 2) || (numtype(q2) == 2))
|
||||
return ad_extract_rod_y(dataset, min(p1, p2), max(p1, p2), min(r1, r2), max(r1, r2), destname, noavg=noavg, sdev=sdev)
|
||||
elseif ((numtype(r1) == 2) || (numtype(r2) == 2))
|
||||
return ad_extract_rod_z(dataset, min(p1, p2), max(p1, p2), min(q1, q2), max(q1, q2), destname, noavg=noavg, sdev=sdev)
|
||||
else
|
||||
return $""
|
||||
endif
|
||||
end
|
||||
|
||||
/// 1D cut through 3D dataset along X dimension.
|
||||
///
|
||||
/// see ad_extract_rod() for descriptions of common parameters.
|
||||
threadsafe function /wave ad_extract_rod_x(dataset, q1, q2, r1, r2, destname, [noavg, sdev])
|
||||
wave dataset
|
||||
variable q1, q2, r1, r2
|
||||
// -inf < q1 < q2 < +inf, -inf < r1 < r2 < +inf
|
||||
string destname
|
||||
variable noavg
|
||||
variable sdev
|
||||
|
||||
if (ParamIsDefault(noavg))
|
||||
noavg = 0
|
||||
endif
|
||||
if (ParamIsDefault(sdev))
|
||||
sdev = 0
|
||||
endif
|
||||
variable avg = !noavg && !sdev
|
||||
|
||||
q1 = max(q1, 0)
|
||||
q2 = min(q2, dimsize(dataset, 1) - 1)
|
||||
r1 = max(r1, 0)
|
||||
r2 = min(r2, dimsize(dataset, 2) - 1)
|
||||
|
||||
if (strlen(destname) > 0)
|
||||
duplicate /r=[][q1,q1][r1,r1]/o dataset, $destname
|
||||
wave w_dest = $destname
|
||||
else
|
||||
duplicate /r=[][q1,q1][r1,r1] /free dataset, w_dest
|
||||
endif
|
||||
redimension /n=(dimsize(w_dest, 0)) w_dest
|
||||
setscale /p x dimoffset(dataset, 0), dimdelta(dataset, 0), waveunits(dataset, 0), w_dest
|
||||
|
||||
w_dest = 0
|
||||
variable qq, rr
|
||||
variable nn = 0
|
||||
for (qq = q1; qq <= q2; qq += 1)
|
||||
for (rr = r1; rr <= r2; rr += 1)
|
||||
w_dest += dataset[p][qq][rr]
|
||||
nn += 1
|
||||
endfor
|
||||
endfor
|
||||
|
||||
if (sdev)
|
||||
duplicate /free w_dest, w_squares
|
||||
w_squares = 0
|
||||
for (qq = q1; qq <= q2; qq += 1)
|
||||
for (rr = r1; rr <= r2; rr += 1)
|
||||
w_squares += dataset[p][qq][rr]^2
|
||||
endfor
|
||||
endfor
|
||||
endif
|
||||
|
||||
if (avg)
|
||||
w_dest /= nn
|
||||
elseif (sdev)
|
||||
w_dest = sqrt( (w_squares - w_dest^2 / nn) / (nn - 1) )
|
||||
endif
|
||||
|
||||
return w_dest
|
||||
end
|
||||
|
||||
/// 1D cut through 3D dataset along Y dimension.
|
||||
///
|
||||
/// see ad_extract_rod() for descriptions of common parameters.
|
||||
threadsafe function /wave ad_extract_rod_y(dataset, p1, p2, r1, r2, destname, [noavg, sdev])
|
||||
wave dataset
|
||||
variable p1, p2, r1, r2
|
||||
// 0 <= p1 < p2 < dimsize(0), 0 <= r1 < r2 < dimsize(2)
|
||||
string destname
|
||||
variable noavg
|
||||
variable sdev
|
||||
|
||||
if (ParamIsDefault(noavg))
|
||||
noavg = 0
|
||||
endif
|
||||
if (ParamIsDefault(sdev))
|
||||
sdev = 0
|
||||
endif
|
||||
variable avg = !noavg && !sdev
|
||||
|
||||
p1 = max(p1, 0)
|
||||
p2 = min(p2, dimsize(dataset, 0) - 1)
|
||||
r1 = max(r1, 0)
|
||||
r2 = min(r2, dimsize(dataset, 2) - 1)
|
||||
|
||||
if (strlen(destname) > 0)
|
||||
duplicate /r=[p1,p1][][r1,r1]/o dataset, $destname
|
||||
wave w_dest = $destname
|
||||
else
|
||||
duplicate /r=[p1,p1][][r1,r1] /free dataset, w_dest
|
||||
endif
|
||||
redimension /n=(dimsize(w_dest, 1)) w_dest
|
||||
setscale /p x dimoffset(dataset, 1), dimdelta(dataset, 1), waveunits(dataset, 1), w_dest
|
||||
|
||||
w_dest = 0
|
||||
variable pp, rr
|
||||
variable nn = 0
|
||||
for (pp = p1; pp <= p2; pp += 1)
|
||||
for (rr = r1; rr <= r2; rr += 1)
|
||||
w_dest += dataset[pp][p][rr]
|
||||
nn += 1
|
||||
endfor
|
||||
endfor
|
||||
|
||||
if (sdev)
|
||||
duplicate /free w_dest, w_squares
|
||||
w_squares = 0
|
||||
for (pp = p1; pp <= p2; pp += 1)
|
||||
for (rr = r1; rr <= r2; rr += 1)
|
||||
w_squares += dataset[pp][p][rr]^2
|
||||
nn += 1
|
||||
endfor
|
||||
endfor
|
||||
endif
|
||||
|
||||
if (avg)
|
||||
w_dest /= nn
|
||||
elseif (sdev)
|
||||
w_dest = sqrt( (w_squares - w_dest^2 / nn) / (nn - 1) )
|
||||
endif
|
||||
|
||||
return w_dest
|
||||
end
|
||||
|
||||
/// 1D cut through 3D dataset along Z dimension.
|
||||
///
|
||||
/// see ad_extract_rod() for descriptions of common parameters.
|
||||
threadsafe function /wave ad_extract_rod_z(dataset, p1, p2, q1, q2, destname, [noavg, sdev])
|
||||
wave dataset
|
||||
variable p1, p2, q1, q2
|
||||
// 0 <= p1 < p2 < dimsize(0), 0 <= q1 < q2 < dimsize(1)
|
||||
string destname
|
||||
variable noavg
|
||||
variable sdev
|
||||
|
||||
if (ParamIsDefault(noavg))
|
||||
noavg = 0
|
||||
endif
|
||||
if (ParamIsDefault(sdev))
|
||||
sdev = 0
|
||||
endif
|
||||
variable avg = !noavg && !sdev
|
||||
|
||||
p1 = max(p1, 0)
|
||||
p2 = min(p2, dimsize(dataset, 0) - 1)
|
||||
q1 = max(q1, 0)
|
||||
q2 = min(q2, dimsize(dataset, 1) - 1)
|
||||
|
||||
if (strlen(destname) > 0)
|
||||
duplicate /r=[p1,p1][q1,q1][]/o dataset, $destname
|
||||
wave w_dest = $destname
|
||||
else
|
||||
duplicate /r=[p1,p1][q1,q1][] /free dataset, w_dest
|
||||
endif
|
||||
redimension /n=(dimsize(w_dest, 2)) w_dest
|
||||
setscale /p x dimoffset(dataset, 2), dimdelta(dataset, 2), waveunits(dataset, 2), w_dest
|
||||
|
||||
w_dest = 0
|
||||
variable pp, qq
|
||||
variable nn = 0
|
||||
for (pp = p1; pp <= p2; pp += 1)
|
||||
for (qq = q1; qq <= q2; qq += 1)
|
||||
w_dest += dataset[pp][qq][p]
|
||||
nn += 1
|
||||
endfor
|
||||
endfor
|
||||
|
||||
if (sdev)
|
||||
duplicate /free w_dest, w_squares
|
||||
w_squares = 0
|
||||
for (pp = p1; pp <= p2; pp += 1)
|
||||
for (qq = q1; qq <= q2; qq += 1)
|
||||
w_squares += dataset[pp][qq][p]^2
|
||||
nn += 1
|
||||
endfor
|
||||
endfor
|
||||
endif
|
||||
|
||||
if (avg)
|
||||
w_dest /= nn
|
||||
elseif (sdev)
|
||||
w_dest = sqrt( (w_squares - w_dest^2 / nn) / (nn - 1) )
|
||||
endif
|
||||
|
||||
return w_dest
|
||||
end
|
||||
|
||||
/// 2D cut through 3D dataset, integrate in normal dimension
|
||||
///
|
||||
/// @param dataset
|
||||
/// @param x1, x2, y1, y2, z1, z2
|
||||
/// coordinates of integration region.
|
||||
/// by default, the coordinates use wave scaling.
|
||||
/// coordinates of slab dimensions (to be preserved) must be nan.
|
||||
/// coordinate pairs don't have to be ordered, i.e. both x1 <= x2 and x1 >= x2 are allowed.
|
||||
/// coordinates can be out of range (-inf and +inf allowed) to select the whole range.
|
||||
/// @param destname
|
||||
/// name of destination wave. to be created in current data folder.
|
||||
/// if empty, the function returns a free wave.
|
||||
/// @param noavg
|
||||
/// zero or default = average, non-zero = sum.
|
||||
/// @param pscale
|
||||
/// scaling of the slab coordinates x1, x2, ..., z2:
|
||||
/// zero or default = wave scaling, non-zero = point scaling.
|
||||
///
|
||||
/// @remark
|
||||
/// * version 1.02: the specification of the destination coordinates has changed
|
||||
/// * version 1.04: the function returns an empty wave reference if an error occurred
|
||||
///
|
||||
threadsafe function /wave ad_extract_slab(dataset, x1, x2, y1, y2, z1, z2, destname, [noavg, pscale])
|
||||
wave dataset
|
||||
variable x1, x2, y1, y2, z1, z2
|
||||
string destname
|
||||
variable noavg
|
||||
variable pscale
|
||||
|
||||
if (wavedims(dataset) != 3)
|
||||
return $""
|
||||
endif
|
||||
if (ParamIsDefault(noavg))
|
||||
noavg = 0
|
||||
endif
|
||||
if (ParamIsDefault(pscale))
|
||||
pscale = 0
|
||||
endif
|
||||
|
||||
variable p1, p2, q1, q2, r1, r2
|
||||
if (pscale)
|
||||
p1 = x1
|
||||
p2 = x2
|
||||
q1 = y1
|
||||
q2 = y2
|
||||
r1 = z1
|
||||
r2 = z2
|
||||
else
|
||||
p1 = round((x1 - DimOffset(dataset, 0)) / DimDelta(dataset, 0))
|
||||
p2 = round((x2 - DimOffset(dataset, 0)) / DimDelta(dataset, 0))
|
||||
q1 = round((y1 - DimOffset(dataset, 1)) / DimDelta(dataset, 1))
|
||||
q2 = round((y2 - DimOffset(dataset, 1)) / DimDelta(dataset, 1))
|
||||
r1 = round((z1 - DimOffset(dataset, 2)) / DimDelta(dataset, 2))
|
||||
r2 = round((z2 - DimOffset(dataset, 2)) / DimDelta(dataset, 2))
|
||||
endif
|
||||
|
||||
if ((numtype(p1) < 2) && (numtype(p2) < 2))
|
||||
return ad_extract_slab_x(dataset, min(p1, p2), max(p1, p2), destname, noavg=noavg)
|
||||
elseif ((numtype(q1) < 2) && (numtype(q2) < 2))
|
||||
return ad_extract_slab_y(dataset, min(q1, q2), max(q1, q2), destname, noavg=noavg)
|
||||
elseif ((numtype(r1) < 2) && (numtype(r2) < 2))
|
||||
return ad_extract_slab_z(dataset, min(r1, r2), max(r1, r2), destname, noavg=noavg)
|
||||
else
|
||||
return $""
|
||||
endif
|
||||
end
|
||||
|
||||
threadsafe function /wave ad_extract_slab_x(dataset, p1, p2, destname, [noavg])
|
||||
wave dataset
|
||||
variable p1, p2
|
||||
// x coordinate range (point scaling) to be integrated
|
||||
// -inf <= p1 < p2 <= +inf
|
||||
string destname // name of destination wave. to be created in current data folder. overrides existing.
|
||||
// if empty, the function returns a free wave
|
||||
variable noavg // zero or default = average, non-zero = sum
|
||||
|
||||
if (ParamIsDefault(noavg))
|
||||
noavg = 0
|
||||
endif
|
||||
p1 = max(p1, 0)
|
||||
p2 = min(p2, dimsize(dataset, 0) - 1)
|
||||
|
||||
if (strlen(destname) > 0)
|
||||
duplicate /r=[p1,p1][][]/o dataset, $destname
|
||||
wave w_dest = $destname
|
||||
else
|
||||
duplicate /r=[p1,p1][][] /free dataset, w_dest
|
||||
endif
|
||||
redimension /n=(dimsize(w_dest, 1), dimsize(w_dest, 2)) w_dest
|
||||
setscale /p x dimoffset(dataset, 1), dimdelta(dataset, 1), waveunits(dataset, 1), w_dest
|
||||
setscale /p y dimoffset(dataset, 2), dimdelta(dataset, 2), waveunits(dataset, 2), w_dest
|
||||
|
||||
w_dest = 0
|
||||
variable pp
|
||||
variable nn = 0
|
||||
for (pp = p1; pp <= p2; pp += 1)
|
||||
w_dest += dataset[pp][p][q]
|
||||
nn += 1
|
||||
endfor
|
||||
|
||||
if (noavg == 0)
|
||||
w_dest /= nn
|
||||
endif
|
||||
|
||||
return w_dest
|
||||
end
|
||||
|
||||
threadsafe function /wave ad_extract_slab_y(dataset, q1, q2, destname, [noavg])
|
||||
wave dataset
|
||||
variable q1, q2
|
||||
// y coordinate range (point scaling) to be integrated
|
||||
// -inf <= q1 < q2 <= +inf
|
||||
string destname // name of destination wave. to be created in current data folder. overrides existing.
|
||||
// if empty, the function returns a free wave
|
||||
variable noavg // zero or default = average, non-zero = sum
|
||||
|
||||
if (ParamIsDefault(noavg))
|
||||
noavg = 0
|
||||
endif
|
||||
q1 = max(q1, 0)
|
||||
q2 = min(q2, dimsize(dataset, 1) - 1)
|
||||
|
||||
if (strlen(destname) > 0)
|
||||
duplicate /r=[][q1,q1][]/o dataset, $destname
|
||||
wave w_dest = $destname
|
||||
else
|
||||
duplicate /r=[][q1,q1][] /free dataset, w_dest
|
||||
endif
|
||||
redimension /n=(dimsize(w_dest, 0), dimsize(w_dest, 2)) w_dest
|
||||
setscale /p x dimoffset(dataset, 0), dimdelta(dataset, 0), waveunits(dataset, 0), w_dest
|
||||
setscale /p y dimoffset(dataset, 2), dimdelta(dataset, 2), waveunits(dataset, 2), w_dest
|
||||
|
||||
w_dest = 0
|
||||
variable qq
|
||||
variable nn = 0
|
||||
for (qq = q1; qq <= q2; qq += 1)
|
||||
w_dest += dataset[p][qq][q]
|
||||
nn += 1
|
||||
endfor
|
||||
|
||||
if (noavg == 0)
|
||||
w_dest /= nn
|
||||
endif
|
||||
|
||||
return w_dest
|
||||
end
|
||||
|
||||
threadsafe function /wave ad_extract_slab_z(dataset, r1, r2, destname, [noavg])
|
||||
wave dataset
|
||||
variable r1, r2
|
||||
// z coordinate range (point scaling) to be integrated
|
||||
// -inf <= r1 < r2 <= +inf
|
||||
string destname // name of destination wave. to be created in current data folder. overrides existing.
|
||||
// if empty, the function returns a free wave
|
||||
variable noavg // zero or default = average, non-zero = sum
|
||||
|
||||
if (ParamIsDefault(noavg))
|
||||
noavg = 0
|
||||
endif
|
||||
r1 = max(r1, 0)
|
||||
r2 = min(r2, dimsize(dataset, 2) - 1)
|
||||
|
||||
if (strlen(destname) > 0)
|
||||
duplicate /r=[][][r1,r1]/o dataset, $destname
|
||||
wave w_dest = $destname
|
||||
else
|
||||
duplicate /r=[][][r1,r1] /free dataset, w_dest
|
||||
endif
|
||||
redimension /n=(dimsize(w_dest, 0), dimsize(w_dest, 1)) w_dest
|
||||
setscale /p x dimoffset(dataset, 0), dimdelta(dataset, 0), waveunits(dataset, 0), w_dest
|
||||
setscale /p y dimoffset(dataset, 1), dimdelta(dataset, 1), waveunits(dataset, 1), w_dest
|
||||
|
||||
w_dest = 0
|
||||
variable rr
|
||||
variable nn = 0
|
||||
for (rr = r1; rr <= r2; rr += 1)
|
||||
w_dest += dataset[p][q][rr]
|
||||
nn += 1
|
||||
endfor
|
||||
|
||||
if (noavg == 0)
|
||||
w_dest /= nn
|
||||
endif
|
||||
|
||||
return w_dest
|
||||
end
|
||||
|
||||
/// 1D cut through 2D dataset along X dimension, new destination wave.
|
||||
///
|
||||
threadsafe function /wave ad_profile_x(dataset, q1, q2, destname, [noavg])
|
||||
wave dataset
|
||||
variable q1, q2 // -inf <= q1 < q2 <= +inf
|
||||
// deprecated: q2 = -1 stands for dimsize(0) - 1
|
||||
string destname // name of destination wave. to be created in current data folder. overrides existing.
|
||||
// if empty, the function returns a free wave
|
||||
variable noavg // zero or default = average, non-zero = sum
|
||||
|
||||
if (ParamIsDefault(noavg))
|
||||
noavg = 0
|
||||
endif
|
||||
|
||||
if (strlen(destname) > 0)
|
||||
duplicate /r=[0,0][] /o dataset, $destname
|
||||
wave w_dest = $destname
|
||||
else
|
||||
duplicate /r=[0,0][] /free dataset, w_dest
|
||||
endif
|
||||
|
||||
return ad_profile_x_w(dataset, q1, q2, w_dest, noavg=noavg)
|
||||
end
|
||||
|
||||
/// 1D cut through 2D dataset along X dimension, existing destination wave.
|
||||
///
|
||||
threadsafe function /wave ad_profile_x_w(dataset, q1, q2, destwave, [noavg])
|
||||
wave dataset
|
||||
variable q1, q2 // -inf <= q1 < q2 <= +inf
|
||||
// deprecated: q2 = -1 stands for dimsize(0) - 1
|
||||
wave destwave // existing destination wave
|
||||
variable noavg // zero or default = average, non-zero = sum
|
||||
|
||||
if (ParamIsDefault(noavg))
|
||||
noavg = 0
|
||||
endif
|
||||
|
||||
redimension /n=(dimsize(dataset, 0)) destwave
|
||||
setscale /p x dimoffset(dataset, 0), dimdelta(dataset, 0), waveunits(dataset, 0), destwave
|
||||
setscale d 0, 0, waveunits(dataset, -1), destwave
|
||||
|
||||
q1 = max(q1, 0)
|
||||
if (q2 < 0)
|
||||
q2 = inf
|
||||
endif
|
||||
q2 = min(q2, dimsize(dataset, 1) - 1)
|
||||
|
||||
destwave = 0
|
||||
variable qq
|
||||
variable nn = 0
|
||||
for (qq = q1; qq <= q2; qq += 1)
|
||||
destwave += dataset[p][qq]
|
||||
nn += 1
|
||||
endfor
|
||||
|
||||
if (noavg == 0)
|
||||
destwave /= nn
|
||||
endif
|
||||
|
||||
return destwave
|
||||
end
|
||||
|
||||
/// 1D cut through 2D dataset along Y dimension, new destination wave.
|
||||
///
|
||||
threadsafe function /wave ad_profile_y(dataset, p1, p2, destname, [noavg])
|
||||
wave dataset
|
||||
variable p1, p2 // -inf <= p1 < p2 < inf
|
||||
// deprecated: p2 = -1 stands for dimsize(0) - 1
|
||||
string destname // name of destination wave. to be created in current data folder. overrides existing.
|
||||
// if empty, the function returns a free wave
|
||||
variable noavg // zero or default = average, non-zero = sum
|
||||
|
||||
if (ParamIsDefault(noavg))
|
||||
noavg = 0
|
||||
endif
|
||||
|
||||
if (strlen(destname) > 0)
|
||||
duplicate /r=[][0,0] /o dataset, $destname
|
||||
wave w_dest = $destname
|
||||
else
|
||||
duplicate /r=[][0,0] /free dataset, w_dest
|
||||
endif
|
||||
MatrixTranspose w_dest
|
||||
|
||||
return ad_profile_y_w(dataset, p1, p2, w_dest, noavg=noavg)
|
||||
end
|
||||
|
||||
/// 1D cut through 2D dataset along X dimension, existing destination wave.
|
||||
///
|
||||
threadsafe function /wave ad_profile_y_w(dataset, p1, p2, destwave, [noavg])
|
||||
wave dataset
|
||||
variable p1, p2 // -inf <= p1 < p2 < inf
|
||||
// deprecated: p2 = -1 stands for dimsize(0) - 1
|
||||
wave destwave // existing destination wave
|
||||
variable noavg // zero or default = average, non-zero = sum
|
||||
|
||||
if (ParamIsDefault(noavg))
|
||||
noavg = 0
|
||||
endif
|
||||
|
||||
redimension /n=(dimsize(dataset, 1)) destwave
|
||||
setscale /p x dimoffset(dataset, 1), dimdelta(dataset, 1), waveunits(dataset, 1), destwave
|
||||
setscale d 0, 0, waveunits(dataset, -1), destwave
|
||||
|
||||
p1 = max(p1, 0)
|
||||
if (p2 < 0)
|
||||
p2 = inf
|
||||
endif
|
||||
p2 = min(p2, dimsize(dataset, 0) - 1)
|
||||
|
||||
destwave = 0
|
||||
variable pp
|
||||
variable nn = 0
|
||||
for (pp = p1; pp <= p2; pp += 1)
|
||||
destwave += dataset[pp][p]
|
||||
nn += 1
|
||||
endfor
|
||||
|
||||
if (noavg == 0)
|
||||
destwave /= nn
|
||||
endif
|
||||
|
||||
return destwave
|
||||
end
|
||||
|
||||
threadsafe function calc_y_profile_mins(image)
|
||||
// experimental
|
||||
wave image
|
||||
|
||||
wave yminlocs = ad_profile_x(image, 0, 0, "ymins", noavg=1)
|
||||
variable nx = dimsize(image, 0)
|
||||
variable ix
|
||||
for (ix = 0; ix < nx; ix += 1)
|
||||
wave profile = ad_profile_y(image, ix, ix, "", noavg=1)
|
||||
wavestats /q/m=1 profile
|
||||
yminlocs[ix] = v_minloc
|
||||
endfor
|
||||
end
|
152
pearl/pearl-arpes-scans.ipf
Normal file
152
pearl/pearl-arpes-scans.ipf
Normal file
@ -0,0 +1,152 @@
|
||||
#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
|
90
pearl/pearl-arpes.ipf
Normal file
90
pearl/pearl-arpes.ipf
Normal file
@ -0,0 +1,90 @@
|
||||
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
|
||||
#pragma IgorVersion = 6.1
|
||||
#pragma ModuleName = PearlArpes
|
||||
#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-area-import" // import data files generated by area detector software
|
||||
#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
|
||||
#include "pearl-scienta-preprocess" // pre-processing functions for Scienta detector images
|
||||
#include "pearl-elog"
|
||||
#if exists("pvOpen")
|
||||
#include "pearl-area-live" // live view of area detector
|
||||
#include "pearl-epics" // EPICS access under Igor
|
||||
#include "pearl-arpes-scans" // run ARPES scans under Igor
|
||||
#endif
|
||||
|
||||
// $Id$
|
||||
//
|
||||
// author: matthias.muntwiler@psi.ch
|
||||
// Copyright (c) 2012-15 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 acquisition and analysis package for ARPES at PEARL.
|
||||
///
|
||||
/// this procedure defines the PEARL ARPES package
|
||||
/// the main purpose of this file is to load the necessary dependent procedures
|
||||
/// (see the include statements at the top)
|
||||
///
|
||||
/// @pre
|
||||
/// * HDF5 XOP must be loaded.
|
||||
/// * on-line data acquisition functionality requires the EPICS XOP to be loaded
|
||||
///
|
||||
/// @author matthias muntwiler, matthias.muntwiler@psi.ch
|
||||
///
|
||||
/// @copyright 2012-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 PearlArpes
|
||||
/// @brief data acquisition and analysis package for ARPES at PEARL.
|
||||
///
|
||||
/// PearlArpes is declared in @ref pearl-arpes.ipf.
|
||||
///
|
||||
|
||||
/// @defgroup ArpesPackage ARPES package
|
||||
/// @brief data acquisition and analysis package for ARPES at PEARL.
|
||||
///
|
||||
/// The purpose of a package is to load a bunch of dependent procedure files.
|
||||
/// The ARPES package loads the following files
|
||||
/// which are helpful when working with ARPES data
|
||||
/// (any data from the Scienta analyser, that is) from PEARL.
|
||||
///
|
||||
/// * pearl-area-import.ipf
|
||||
/// * pearl-area-display.ipf
|
||||
/// * pearl-area-profiles.ipf
|
||||
/// * pearl-data-explorer.ipf
|
||||
/// * pearl-scienta-preprocess.ipf
|
||||
/// * pearl-anglescan-process.ipf
|
||||
/// * pearl-anglescan-tracker.ipf
|
||||
/// * pearl-elog.ipf
|
||||
///
|
||||
/// Most of these files require the HDF5.XOP.
|
||||
/// The following files are loaded if the EPICS.XOP is present:
|
||||
///
|
||||
/// * pearl-area-live.ipf
|
||||
/// * pearl-epics.ipf
|
||||
/// * pearl-arpes-scans.ipf
|
||||
///
|
||||
|
||||
/// initializes package data once when the procedure is first loaded
|
||||
static function AfterCompiledHook()
|
||||
|
||||
dfref savefolder = GetDataFolderDFR()
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
function UnloadPearlArpesPackage()
|
||||
execute /p/q/z "DELETEINCLUDE \"pearl-arpes\""
|
||||
execute /p/q/z "COMPILEPROCEDURES "
|
||||
end
|
1449
pearl/pearl-data-explorer.ipf
Normal file
1449
pearl/pearl-data-explorer.ipf
Normal file
File diff suppressed because it is too large
Load Diff
28
pearl/pearl-data-export.ipf
Normal file
28
pearl/pearl-data-export.ipf
Normal file
@ -0,0 +1,28 @@
|
||||
#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
|
1261
pearl/pearl-elog.ipf
Normal file
1261
pearl/pearl-elog.ipf
Normal file
File diff suppressed because it is too large
Load Diff
715
pearl/pearl-fitfuncs.ipf
Normal file
715
pearl/pearl-fitfuncs.ipf
Normal file
@ -0,0 +1,715 @@
|
||||
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
|
||||
#pragma IgorVersion = 6.2
|
||||
#pragma ModuleName = PearlFitFuncs
|
||||
#pragma version = 1.01
|
||||
|
||||
// various fit functions for photoelectron spectroscopy
|
||||
|
||||
// $Id$
|
||||
// author: matthias.muntwiler@psi.ch
|
||||
// Copyright (c) 2013-14 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
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Doniach-Sunjic fit functions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
threadsafe function DoniachSunjic(x, amp, pos, sing, fwhm)
|
||||
// Doniach-Sunjic line shape
|
||||
// [S. Doniach, M. Sunjic, J. Phys. C 3 (1970) 285]
|
||||
variable x // independent variable
|
||||
variable amp // amplitude
|
||||
variable pos // position
|
||||
variable sing // singularity index (0 <= sing < 1)
|
||||
variable fwhm // width
|
||||
|
||||
variable nom, denom
|
||||
nom = cos(pi * sing / 2 + (1 - sing) * atan((x - pos) / fwhm * 2))
|
||||
denom = ((x - pos)^2 + fwhm^2 / 4)^((1 - sing) / 2)
|
||||
|
||||
return amp * nom / denom * fwhm / 2
|
||||
end
|
||||
|
||||
threadsafe function ds1_bg(w, x): FitFunc
|
||||
// Doniach-Sunjic fit function
|
||||
// 0 <= sing < 1
|
||||
wave w // coefficients - see below
|
||||
variable x // independent variable
|
||||
|
||||
//CurveFitDialog/ These comments were created by the Curve Fitting dialog. Altering them will
|
||||
//CurveFitDialog/ make the function less convenient to work with in the Curve Fitting dialog.
|
||||
//CurveFitDialog/ Equation:
|
||||
//CurveFitDialog/ f(x) = DoniachSunjic(x, amp, pos, sing, fwhm) + bg
|
||||
//CurveFitDialog/ End of Equation
|
||||
//CurveFitDialog/ Independent Variables 1
|
||||
//CurveFitDialog/ x
|
||||
//CurveFitDialog/ Coefficients 5
|
||||
//CurveFitDialog/ w[0] = bg
|
||||
//CurveFitDialog/ w[1] = amp
|
||||
//CurveFitDialog/ w[2] = pos
|
||||
//CurveFitDialog/ w[3] = sing
|
||||
//CurveFitDialog/ w[4] = FWHM
|
||||
|
||||
return DoniachSunjic(x, w[1], w[2], w[3], w[4]) + w[0]
|
||||
end
|
||||
|
||||
threadsafe function ds2_bg(w,x) : FitFunc
|
||||
Wave w
|
||||
Variable x
|
||||
|
||||
//CurveFitDialog/ These comments were created by the Curve Fitting dialog. Altering them will
|
||||
//CurveFitDialog/ make the function less convenient to work with in the Curve Fitting dialog.
|
||||
//CurveFitDialog/ Equation:
|
||||
//CurveFitDialog/ f(x) = w_0+( w_1*cos(pi*w_3/2+(1-w_3)*atan((x-w_2)/w_4)))/(((x-w_2)^2+w_4^2)^((1-w_3)/2)) +(w_5*cos(pi*w_7/2+(1-w_7)*atan((x-(w_6))/w_8)))/(((x-w_6)^2+w_8^2)^((1-w_7)/2))
|
||||
//CurveFitDialog/ End of Equation
|
||||
//CurveFitDialog/ Independent Variables 1
|
||||
//CurveFitDialog/ x
|
||||
//CurveFitDialog/ Coefficients 9
|
||||
//CurveFitDialog/ w[0] = bg
|
||||
//CurveFitDialog/ w[1] = amp1
|
||||
//CurveFitDialog/ w[2] = pos1
|
||||
//CurveFitDialog/ w[3] = sing1
|
||||
//CurveFitDialog/ w[4] = wid1
|
||||
//CurveFitDialog/ w[5] = amp2
|
||||
//CurveFitDialog/ w[6] = pos2
|
||||
//CurveFitDialog/ w[7] = sing2
|
||||
//CurveFitDialog/ w[8] = wid2
|
||||
|
||||
variable ds1 = DoniachSunjic(x, w[1], w[2], w[3], w[4])
|
||||
variable ds2 = DoniachSunjic(x, w[5], w[6], w[7], w[8])
|
||||
|
||||
return w[0] + ds1 + ds2
|
||||
End
|
||||
|
||||
Function ds4_bg(w,x) : FitFunc
|
||||
Wave w
|
||||
Variable x
|
||||
|
||||
//CurveFitDialog/ These comments were created by the Curve Fitting dialog. Altering them will
|
||||
//CurveFitDialog/ make the function less convenient to work with in the Curve Fitting dialog.
|
||||
//CurveFitDialog/ Equation:
|
||||
//CurveFitDialog/ f(x) = w_0+( w_1*cos(pi*w_3/2+(1-w_3)*atan((x-w_2)/w_4)))/(((x-w_2)^2+w_4^2)^((1-w_3)/2)) +(w_5*cos(pi*w_7/2+(1-w_7)*atan((x-(w_6))/w_8)))/(((x-w_6)^2+w_8^2)^((1-w_7)/2)) +( w_9*cos(pi*w_11/2+(1-w_11)*atan((x-w_10)/w_12)))/(((x-w_10)^2+w_12^2)^((1-w_11)/2)) +( w_13*cos(pi*w_15/2+(1-w_15)*atan((x-w_14)/w_16)))/(((x-w_14)^2+w_16^2)^((1-w_15)/2))
|
||||
//CurveFitDialog/ End of Equation
|
||||
//CurveFitDialog/ Independent Variables 1
|
||||
//CurveFitDialog/ x
|
||||
//CurveFitDialog/ Coefficients 17
|
||||
//CurveFitDialog/ w[0] = w_0
|
||||
//CurveFitDialog/ w[1] = w_11
|
||||
//CurveFitDialog/ w[2] = w_12
|
||||
//CurveFitDialog/ w[3] = w_13
|
||||
//CurveFitDialog/ w[4] = w_14
|
||||
//CurveFitDialog/ w[5] = w_21
|
||||
//CurveFitDialog/ w[6] = w_22
|
||||
//CurveFitDialog/ w[7] = w_23
|
||||
//CurveFitDialog/ w[8] = w_24
|
||||
//CurveFitDialog/ w[9] = w_31
|
||||
//CurveFitDialog/ w[10] = w_32
|
||||
//CurveFitDialog/ w[11] = w_33
|
||||
//CurveFitDialog/ w[12] = w_34
|
||||
//CurveFitDialog/ w[13] = w_41
|
||||
//CurveFitDialog/ w[14] = w_42
|
||||
//CurveFitDialog/ w[15] = w_43
|
||||
//CurveFitDialog/ w[16] = w_44
|
||||
Variable ds1, ds2, ds3, ds4
|
||||
ds1=( w[1]*cos(pi*w[3]/2+(1-w[3])*atan((x-w[2])/w[4])))/(((x-w[2])^2+w[4]^2)^((1-w[3])/2))
|
||||
ds2=( w[5]*cos(pi*w[7]/2+(1-w[7])*atan((x-w[6])/w[8])))/(((x-w[6])^2+w[8]^2)^((1-w[7])/2))
|
||||
ds3=( w[9]*cos(pi*w[11]/2+(1-w[11])*atan((x-w[10])/w[12])))/(((x-w[10])^2+w[12]^2)^((1-w[11])/2))
|
||||
ds4=( w[13]*cos(pi*w[15]/2+(1-w[15])*atan((x-w[14])/w[16])))/(((x-w[14])^2+w[16]^2)^((1-w[15])/2))
|
||||
|
||||
|
||||
return w[0]+ds1+ds2+ds3+ds4
|
||||
|
||||
|
||||
End
|
||||
|
||||
Function ds6_bg(w,x) : FitFunc
|
||||
Wave w
|
||||
Variable x
|
||||
|
||||
//CurveFitDialog/ These comments were created by the Curve Fitting dialog. Altering them will
|
||||
//CurveFitDialog/ make the function less convenient to work with in the Curve Fitting dialog.
|
||||
//CurveFitDialog/ Equation:
|
||||
//CurveFitDialog/
|
||||
//CurveFitDialog/ Variable g, ds1, ds2, ds3, ds4, ds5, ds6
|
||||
//CurveFitDialog/ ds1=( w_11*cos(pi*w_13/2+(1-w_13)*atan((x-w_12)/w_14)))/(((x-w_12)^2+w_14^2)^((1-w_13)/2))
|
||||
//CurveFitDialog/ ds2=( w_21*cos(pi*w_23/2+(1-w_23)*atan((x-w_22)/w_24)))/(((x-w_22)^2+w_24^2)^((1-w_23)/2))
|
||||
//CurveFitDialog/ ds3=( w_31*cos(pi*w_33/2+(1-w_33)*atan((x-w_32)/w_34)))/(((x-w_32)^2+w_34^2)^((1-w_33)/2))
|
||||
//CurveFitDialog/ ds4=( w_41*cos(pi*w_43/2+(1-w_43)*atan((x-w_42)/w_44)))/(((x-w_42)^2+w_44^2)^((1-w_43)/2))
|
||||
//CurveFitDialog/ ds5=( w_51*cos(pi*w_53/2+(1-w_53)*atan((x-w_52)/w_54)))/(((x-w_52)^2+w_54^2)^((1-w_53)/2))
|
||||
//CurveFitDialog/ ds6=( w_61*cos(pi*w_63/2+(1-w_63)*atan((x-w_62)/w_64)))/(((x-w_62)^2+w_64^2)^((1-w_63)/2))
|
||||
//CurveFitDialog/
|
||||
//CurveFitDialog/ f(x) =w_0+ds1+ds2+ds3+ds4+ds5+ds6
|
||||
//CurveFitDialog/
|
||||
//CurveFitDialog/ End of Equation
|
||||
//CurveFitDialog/ Independent Variables 1
|
||||
//CurveFitDialog/ x
|
||||
//CurveFitDialog/ Coefficients 25
|
||||
//CurveFitDialog/ w[0] = w_0
|
||||
//CurveFitDialog/ w[1] = w_11
|
||||
//CurveFitDialog/ w[2] = w_12
|
||||
//CurveFitDialog/ w[3] = w_13
|
||||
//CurveFitDialog/ w[4] = w_14
|
||||
//CurveFitDialog/ w[5] = w_21
|
||||
//CurveFitDialog/ w[6] = w_22
|
||||
//CurveFitDialog/ w[7] = w_23
|
||||
//CurveFitDialog/ w[8] = w_24
|
||||
//CurveFitDialog/ w[9] = w_31
|
||||
//CurveFitDialog/ w[10] = w_32
|
||||
//CurveFitDialog/ w[11] = w_33
|
||||
//CurveFitDialog/ w[12] = w_34
|
||||
//CurveFitDialog/ w[13] = w_41
|
||||
//CurveFitDialog/ w[14] = w_42
|
||||
//CurveFitDialog/ w[15] = w_43
|
||||
//CurveFitDialog/ w[16] = w_44
|
||||
//CurveFitDialog/ w[17] = w_51
|
||||
//CurveFitDialog/ w[18] = w_52
|
||||
//CurveFitDialog/ w[19] = w_53
|
||||
//CurveFitDialog/ w[20] = w_54
|
||||
//CurveFitDialog/ w[21] = w_61
|
||||
//CurveFitDialog/ w[22] = w_62
|
||||
//CurveFitDialog/ w[23] = w_63
|
||||
//CurveFitDialog/ w[24] = w_64
|
||||
|
||||
|
||||
Variable ds1, ds2, ds3, ds4, ds5, ds6
|
||||
ds1=( w[1]*cos(pi*w[3]/2+(1-w[3])*atan((x-w[2])/w[4])))/(((x-w[2])^2+w[4]^2)^((1-w[3])/2))
|
||||
ds2=( w[5]*cos(pi*w[7]/2+(1-w[7])*atan((x-w[6])/w[8])))/(((x-w[6])^2+w[8]^2)^((1-w[7])/2))
|
||||
ds3=( w[9]*cos(pi*w[11]/2+(1-w[11])*atan((x-w[10])/w[12])))/(((x-w[10])^2+w[12]^2)^((1-w[11])/2))
|
||||
ds4=( w[13]*cos(pi*w[15]/2+(1-w[15])*atan((x-w[14])/w[16])))/(((x-w[14])^2+w[16]^2)^((1-w[15])/2))
|
||||
ds5=( w[17]*cos(pi*w[19]/2+(1-w[19])*atan((x-w[18])/w[20])))/(((x-w[18])^2+w[20]^2)^((1-w[19])/2))
|
||||
ds6=( w[21]*cos(pi*w[23]/2+(1-w[23])*atan((x-w[22])/w[24])))/(((x-w[22])^2+w[24]^2)^((1-w[23])/2))
|
||||
|
||||
return w[0]+ds1+ds2+ds3+ds4+ds5+ds6
|
||||
|
||||
End
|
||||
|
||||
structure DoniachSunjicStruct
|
||||
// data structure for DoniachSunjicBroadS structural function fit
|
||||
|
||||
// waves populated by the FuncFit operation
|
||||
wave pw
|
||||
wave yw
|
||||
wave xw
|
||||
|
||||
// convolution parameters to be set upon creation of the structure
|
||||
variable precision
|
||||
variable oversampling
|
||||
|
||||
// auxiliary fields used internally by DoniachSunjicBroadS
|
||||
// do not touch these
|
||||
wave xdw
|
||||
wave model
|
||||
wave broadening
|
||||
wave convolution
|
||||
EndStructure
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
threadsafe function DoniachSunjicBroadS(s) : FitFunc
|
||||
//------------------------------------------------------------------------------
|
||||
// Two-peak (bulk + surface) Doniach-Sunjic line shape with Gaussian broadening (convolution).
|
||||
// Hold parameter 5 at 0 to fit just one peak.
|
||||
|
||||
// Structural fit function for efficient fitting in procedures.
|
||||
// Calculating the convolution requires auxiliary waves and additional, non-fitting parameters.
|
||||
// To eliminate the time-consuming overhead of creating and killing the auxiliary waves,
|
||||
// these waves are held in the fitting structure.
|
||||
|
||||
// Caution: The function on its own is thread-safe.
|
||||
// However, since FuncFit uses the same structure in all threads, the fitting cannot run in parallel.
|
||||
// Set /NTHR=1.
|
||||
|
||||
// See also Fit_DoniachSunjicBroad (example), DoniachSunjicBroad (conventional fit function)
|
||||
Struct DoniachSunjicStruct &s
|
||||
|
||||
// pw[0] = bulk amplitude
|
||||
// pw[1] = bulk position
|
||||
// pw[2] = Lorentzian FWHM
|
||||
// pw[3] = Donjach-Sunjic singularity index (0..1)
|
||||
// pw[4] = surface shift
|
||||
// pw[5] = surface/bulk ratio
|
||||
// pw[6] = Gaussian FWHM
|
||||
// pw[7] = constant background
|
||||
// pw[8] = linear background
|
||||
|
||||
wave xw = s.xw
|
||||
wave yw = s.yw
|
||||
wave pw = s.pw
|
||||
|
||||
variable precision = s.precision
|
||||
variable oversampling = s.oversampling
|
||||
|
||||
if (WaveExists(s.xdw))
|
||||
wave xdw = s.xdw
|
||||
wave model = s.model
|
||||
wave broadening = s.broadening
|
||||
wave convolution = s.convolution
|
||||
else
|
||||
make /n=0 /free xdw, model, broadening, convolution
|
||||
redimension /d xdw, model, broadening, convolution
|
||||
wave fs.xdw = xdw
|
||||
wave fs.model = model
|
||||
wave fs.broadening = broadening
|
||||
wave fs.convolution = convolution
|
||||
endif
|
||||
|
||||
// calculate wave spacing based on minimum spacing of desired x points
|
||||
differentiate /p xw /d=xdw
|
||||
xdw = abs(xdw)
|
||||
variable xd = wavemin(xdw) / oversampling
|
||||
|
||||
// calculate broadening wave size based on width and precision variable
|
||||
variable x0b = pw[6] * precision
|
||||
variable nb = 2 * floor(x0b / xd) + 1
|
||||
|
||||
// calculate model size based on desired range for yw
|
||||
variable x0m = max(abs(wavemax(xw) - pw[1]), abs(wavemin(xw) - pw[1])) + x0b
|
||||
variable nm = 2 * floor(x0m / xd) + 1
|
||||
nb = min(nb, nm * 10) // limit wave size to avoid runtime errors for unphysically large parameter
|
||||
|
||||
// create and calculate initial waves, normalize exponential
|
||||
redimension /n=(nb) broadening
|
||||
redimension /n=(nm) model
|
||||
setscale/i x -x0b, x0b, "", broadening
|
||||
setscale/i x -x0m, x0m, "", model
|
||||
|
||||
broadening = exp( - (x / pw[6])^2 * 4 * ln(2))
|
||||
variable nrm = area(broadening)
|
||||
broadening /= nrm
|
||||
model = DoniachSunjic(x, 1, 0, pw[3], pw[2]) // bulk
|
||||
model += DoniachSunjic(x, pw[5], pw[4], pw[3], pw[2]) // surface
|
||||
|
||||
// calculate the convolution
|
||||
Convolve /a broadening, model
|
||||
variable scale = pw[0] / wavemax(model)
|
||||
model *= scale
|
||||
|
||||
// prepare output
|
||||
nm = numpnts(model)
|
||||
x0m = xd * (nm - 1) / 2
|
||||
setscale/i x -x0m, x0m, "", model
|
||||
|
||||
yw = model(xw[p] - pw[1]) + pw[7] + pw[8] * xw[p]
|
||||
yw = numtype(yw) ? 0 : yw
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
function DoniachSunjicBroad(pw, yw, xw) : FitFunc
|
||||
//------------------------------------------------------------------------------
|
||||
// Two-peak (bulk + surface) Doniach-Sunjic line shape with Gaussian broadening (convolution).
|
||||
// Hold parameter 5 at 0 to fit just one peak.
|
||||
// Conventional fit function for use with the curve-fitting dialog.
|
||||
// Compared to DoniachSunjicBroadS this function incurs extra overhead
|
||||
// because auxiliary waves are created and killed between function calls.
|
||||
// See also DoniachSunjicBroadS (optimized structural fit function)
|
||||
Wave pw
|
||||
Wave yw
|
||||
Wave xw
|
||||
|
||||
// pw[0] = bulk amplitude
|
||||
// pw[1] = bulk position
|
||||
// pw[2] = Lorentzian FWHM
|
||||
// pw[3] = Donjach-Sunjic singularity index (0..1)
|
||||
// pw[4] = surface shift
|
||||
// pw[5] = surface/bulk ratio
|
||||
// pw[6] = Gaussian FWHM
|
||||
// pw[7] = constant background
|
||||
// pw[8] = linear background
|
||||
|
||||
// set up data structure
|
||||
struct DoniachSunjicStruct fs
|
||||
fs.precision = 5
|
||||
fs.oversampling = 4
|
||||
|
||||
wave fs.pw = pw
|
||||
wave fs.xw = xw
|
||||
wave fs.yw = yw
|
||||
|
||||
// create temporary calculation waves in a global folder
|
||||
dfref df = root:packages:pearl_fitfuncs:doniach_sunjic
|
||||
if (DataFolderRefStatus(df) == 0)
|
||||
newdatafolder root:packages:pearl_fitfuncs:doniach_sunjic
|
||||
dfref df = root:packages:pearl_fitfuncs:doniach_sunjic
|
||||
endif
|
||||
|
||||
wave /z /sdfr=df fs.xdw = xdw
|
||||
wave /z /sdfr=df fs.model = model
|
||||
wave /z /sdfr=df fs.broadening = broadening
|
||||
wave /z /sdfr=df fs.convolution = convolution
|
||||
|
||||
if (WaveExists(fs.xdw) == 0)
|
||||
dfref savedf = GetDataFolderDFR()
|
||||
setdatafolder df
|
||||
make /n=0 /d xdw, model, broadening, convolution
|
||||
wave fs.xdw = xdw
|
||||
wave fs.model = model
|
||||
wave fs.broadening = broadening
|
||||
wave fs.convolution = convolution
|
||||
setdatafolder savedf
|
||||
endif
|
||||
|
||||
// calculate
|
||||
DoniachSunjicBroadS(fs)
|
||||
|
||||
yw = fs.yw
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
function Calc_DoniachSunjicBroad(pw, yw)
|
||||
//------------------------------------------------------------------------------
|
||||
// Calculate the DoniachSunjicBroadS line shape
|
||||
Wave pw // coefficient wave
|
||||
Wave yw // output wave, correct x-scaling required on input
|
||||
|
||||
struct DoniachSunjicStruct fs
|
||||
fs.precision = 5
|
||||
fs.oversampling = 4
|
||||
|
||||
duplicate /free pw, fs.pw
|
||||
duplicate /free yw, fs.xw
|
||||
fs.xw = x
|
||||
duplicate /free yw, fs.yw
|
||||
|
||||
DoniachSunjicBroadS(fs)
|
||||
|
||||
yw = fs.yw
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Function Fit_DoniachSunjicBroad(pw, yw, xw, ww)
|
||||
//------------------------------------------------------------------------------
|
||||
// Fit the DoniachSunjicBroadS line shape.
|
||||
// The function applies constraints which assume that the energy scale is in eV.
|
||||
// Returns chi^2.
|
||||
wave pw // coefficient wave- pre-load it with initial guess
|
||||
wave yw
|
||||
wave /z xw
|
||||
wave /z ww // weights (standard deviation)
|
||||
|
||||
struct DoniachSunjicStruct fs
|
||||
fs.precision = 5
|
||||
fs.oversampling = 4
|
||||
|
||||
duplicate /free pw, fs.pw
|
||||
if (WaveExists(xw))
|
||||
duplicate /free xw, fs.xw
|
||||
else
|
||||
duplicate /free yw, fs.xw
|
||||
fs.xw = x
|
||||
endif
|
||||
duplicate /free yw, fs.yw
|
||||
|
||||
variable v_chisq = nan
|
||||
variable V_FitMaxIters = 100
|
||||
make /n=1 /t /free constraints = {"K0 >= 0", "K2 > 0", "K2 < 10", "K3 >= 0", "K3 < 1", "K4 >= -10", "K4 <= 10", "K5 >= 0", "K5 <= 1", "K6 >= 0", "K6 < 10"}
|
||||
// note: only single thread allowed
|
||||
FuncFit /NTHR=1 DoniachSunjicBroadS, pw, yw /X=xw /D /STRC=fs /C=constraints /NWOK /I=1 /W=ww
|
||||
|
||||
return v_chisq
|
||||
End
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// peak-specific fit functions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
function Au4f(w, x): fitfunc
|
||||
// fit function for a nitrogen 1s-pi* absorption spectrum
|
||||
// modelled as multiple Voigt shapes on a constant background
|
||||
// similar to the Igor VoigtFit function
|
||||
// but with a constant gaussian width (instrumental broadening) for all peaks
|
||||
// gaussian and lorentzian widths are specified as FWHM
|
||||
wave w // parameters
|
||||
// w[0] constant background
|
||||
// w[1] linear background
|
||||
// w[2] global gaussian FWHM
|
||||
// w[3 + 0 + (n-1) * 3] peak n area
|
||||
// w[3 + 1 + (n-1) * 3] peak n position
|
||||
// w[3 + 2 + (n-1) * 3] peak n lorentzian FWHM
|
||||
// length of wave defines number of peaks
|
||||
|
||||
// for compatibility with older code the linear background term can be omitted.
|
||||
// if the number of parameters divides by 3, the linear background term is added,
|
||||
// otherwise only the constant background.
|
||||
variable x
|
||||
|
||||
variable np = 15
|
||||
variable ip, ip0
|
||||
|
||||
variable bg = w[0]
|
||||
variable v = bg
|
||||
if (mod(np, 3) == 0)
|
||||
v += w[1] * x
|
||||
ip0 = 3
|
||||
else
|
||||
ip0 = 2
|
||||
endif
|
||||
|
||||
variable vc1, vc2, vc3, vc4
|
||||
vc2 = 2 * sqrt(ln(2)) / w[ip0-1]
|
||||
for (ip = ip0; ip < np; ip += 3)
|
||||
vc1 = w[ip] / sqrt(pi) * vc2
|
||||
vc3 = w[ip+1]
|
||||
vc4 = vc2 * w[ip+2] / 2
|
||||
v += vc1 * Voigt(vc2 * (x - vc3), vc4)
|
||||
endfor
|
||||
|
||||
return v
|
||||
|
||||
end
|
||||
|
||||
function Au4f_2p2(w, x): fitfunc
|
||||
// Au 4f 5/2 and 7/2 2-component Voigt fit with a common gaussian width
|
||||
// gaussian and lorentzian widths are specified as FWHM
|
||||
wave w // parameters
|
||||
// w[0] constant background
|
||||
// w[1] linear background
|
||||
// w[2] global gaussian FWHM
|
||||
// w[3] 5/2 bulk area
|
||||
// w[4] 5/2 bulk position
|
||||
// w[5] 5/2 lorentzian FWHM
|
||||
// w[6] 7/2 bulk area
|
||||
// w[7] 7/2 bulk position
|
||||
// w[8] 7/2 lorentzian FWHM
|
||||
// w[9] surface/bulk area ratio
|
||||
// w[10] surface core level shift
|
||||
variable x
|
||||
|
||||
variable bg = w[0] + w[1] * x
|
||||
variable v = bg
|
||||
|
||||
variable vc1 // amplitude
|
||||
variable vc2 // width
|
||||
variable vc3 // position
|
||||
variable vc4 // shape
|
||||
vc2 = 2 * sqrt(ln(2)) / w[2]
|
||||
|
||||
// 5/2 bulk
|
||||
vc1 = w[3] / sqrt(pi) * vc2
|
||||
vc3 = w[4]
|
||||
vc4 = vc2 * w[5] / 2
|
||||
v += vc1 * Voigt(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)
|
||||
|
||||
// 7/2 bulk
|
||||
vc1 = w[6] / sqrt(pi) * vc2
|
||||
vc3 = w[7]
|
||||
vc4 = vc2 * w[8] / 2
|
||||
v += vc1 * Voigt(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)
|
||||
|
||||
return v
|
||||
|
||||
end
|
||||
|
||||
function ShowComponents_Au4f_2p2(coef_wave, fit_wave)
|
||||
wave coef_wave
|
||||
wave fit_wave
|
||||
|
||||
duplicate /free coef_wave, coef1, coef2
|
||||
coef1[9] = 0
|
||||
coef2[3] *= coef_wave[9]
|
||||
coef2[4] += coef_wave[10]
|
||||
coef2[6] *= coef_wave[9]
|
||||
coef2[7] += coef_wave[10]
|
||||
coef2[9] = 0
|
||||
|
||||
string s_fit_wave = NameOfWave(fit_wave)
|
||||
string s_fit_p1 = s_fit_wave + "_p1"
|
||||
string s_fit_p2 = s_fit_wave + "_p2"
|
||||
duplicate /o fit_wave, $(s_fit_p1) /wave=fit_p1
|
||||
duplicate /o fit_wave, $(s_fit_p2) /wave=fit_p2
|
||||
|
||||
fit_p1 = Au4f_2p2(coef1, x)
|
||||
fit_p2 = Au4f_2p2(coef2, x)
|
||||
|
||||
string traces = TraceNameList("", ";", 1)
|
||||
if ((WhichListItem(s_fit_wave, traces, ";") >= 0) && (WhichListItem(s_fit_p1, traces, ";") < 0))
|
||||
appendtograph fit_p1, fit_p2
|
||||
ModifyGraph lstyle($s_fit_p1)=2
|
||||
ModifyGraph lstyle($s_fit_p2)=2
|
||||
ModifyGraph rgb($s_fit_p1)=(0,0,65280)
|
||||
ModifyGraph rgb($s_fit_p2)=(0,0,65280)
|
||||
endif
|
||||
end
|
||||
|
||||
function Au4f_2p3(w, x): fitfunc
|
||||
// Au 4f 5/2 and 7/2 3-component Voigt fit with a common gaussian width
|
||||
// gaussian and lorentzian widths are specified as FWHM
|
||||
wave w // parameters
|
||||
// w[0] constant background
|
||||
// w[1] linear background
|
||||
// w[2] global gaussian FWHM
|
||||
// w[3] 5/2 bulk area
|
||||
// w[4] 5/2 bulk position
|
||||
// w[5] 5/2 lorentzian FWHM
|
||||
// w[6] 7/2 bulk area
|
||||
// w[7] 7/2 bulk position
|
||||
// w[8] 7/2 lorentzian FWHM
|
||||
// w[9] surface/bulk area ratio
|
||||
// w[10] surface core level shift
|
||||
// w[11] 2nd layer/bulk area ratio
|
||||
// w[12] 2nd layer core level shift
|
||||
variable x
|
||||
|
||||
variable bg = w[0] + w[1] * x
|
||||
variable v = bg
|
||||
|
||||
variable vc1 // amplitude
|
||||
variable vc2 // width
|
||||
variable vc3 // position
|
||||
variable vc4 // shape
|
||||
vc2 = 2 * sqrt(ln(2)) / w[2]
|
||||
|
||||
// 5/2 bulk
|
||||
vc1 = w[3] / sqrt(pi) * vc2
|
||||
vc3 = w[4]
|
||||
vc4 = vc2 * w[5] / 2
|
||||
v += vc1 * Voigt(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)
|
||||
|
||||
// 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)
|
||||
|
||||
// 7/2 bulk
|
||||
vc1 = w[6] / sqrt(pi) * vc2
|
||||
vc3 = w[7]
|
||||
vc4 = vc2 * w[8] / 2
|
||||
v += vc1 * Voigt(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)
|
||||
|
||||
// 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)
|
||||
|
||||
return v
|
||||
|
||||
end
|
||||
|
||||
function ShowComponents_Au4f_2p3(coef_wave, fit_wave)
|
||||
wave coef_wave
|
||||
wave fit_wave
|
||||
|
||||
duplicate /free coef_wave, coef1, coef2, coef3
|
||||
coef1[9] = 0
|
||||
coef1[11] = 0
|
||||
|
||||
coef2[3] *= coef_wave[9]
|
||||
coef2[4] += coef_wave[10]
|
||||
coef2[6] *= coef_wave[9]
|
||||
coef2[7] += coef_wave[10]
|
||||
coef2[9] = 0
|
||||
coef2[11] = 0
|
||||
|
||||
coef3[3] *= coef_wave[11]
|
||||
coef3[4] += coef_wave[12]
|
||||
coef3[6] *= coef_wave[11]
|
||||
coef3[7] += coef_wave[12]
|
||||
coef3[9] = 0
|
||||
coef3[11] = 0
|
||||
|
||||
string s_fit_wave = NameOfWave(fit_wave)
|
||||
string s_fit_p1 = s_fit_wave + "_p1"
|
||||
string s_fit_p2 = s_fit_wave + "_p2"
|
||||
string s_fit_p3 = s_fit_wave + "_p3"
|
||||
duplicate /o fit_wave, $(s_fit_p1) /wave=fit_p1
|
||||
duplicate /o fit_wave, $(s_fit_p2) /wave=fit_p2
|
||||
duplicate /o fit_wave, $(s_fit_p3) /wave=fit_p3
|
||||
|
||||
fit_p1 = Au4f_2p2(coef1, x)
|
||||
fit_p2 = Au4f_2p2(coef2, x)
|
||||
fit_p3 = Au4f_2p2(coef3, x)
|
||||
|
||||
string traces = TraceNameList("", ";", 1)
|
||||
if ((WhichListItem(s_fit_wave, traces, ";") >= 0) && (WhichListItem(s_fit_p1, traces, ";") < 0))
|
||||
appendtograph fit_p1, fit_p2, fit_p3
|
||||
ModifyGraph lstyle($s_fit_p1)=2
|
||||
ModifyGraph lstyle($s_fit_p2)=2
|
||||
ModifyGraph lstyle($s_fit_p3)=2
|
||||
ModifyGraph rgb($s_fit_p1)=(0,0,65280)
|
||||
ModifyGraph rgb($s_fit_p2)=(0,0,65280)
|
||||
ModifyGraph rgb($s_fit_p3)=(0,0,65280)
|
||||
endif
|
||||
end
|
||||
|
||||
/// convolution of Fermi-Dirac distribution and a Gaussian.
|
||||
///
|
||||
/// @arg pw[0] = constant background
|
||||
/// @arg pw[1] = linear background
|
||||
/// @arg pw[2] = amplitude
|
||||
/// @arg pw[3] = Fermi level in eV
|
||||
/// @arg pw[4] = temperature in K
|
||||
/// @arg pw[5] = gaussian width = FWHM / 1.66511
|
||||
///
|
||||
function FermiGaussConv(pw, yw, xw) : FitFunc
|
||||
WAVE pw, yw, xw
|
||||
|
||||
// half width of temporary gaussian wave is pw[5] multiplied by this factor (may be fractional)
|
||||
variable precision_g = 5
|
||||
variable oversampling = 4
|
||||
|
||||
// calculate wave spacing based on minimum spacing of desired x points
|
||||
duplicate /free xw, xdw
|
||||
differentiate /p xw /d=xdw
|
||||
xdw = abs(xdw)
|
||||
variable xd = wavemin(xdw) / oversampling
|
||||
|
||||
// calculate gausswave size based on pw[5] and precision variable
|
||||
variable x0g = pw[5] * precision_g
|
||||
variable ng = 2 * floor(x0g / xd) + 1
|
||||
|
||||
// calculate fermiwave size based on desired range for yw
|
||||
variable emax = wavemax(xw)
|
||||
variable emin = wavemin(xw)
|
||||
variable x0f = max(abs(emax - pw[3]), abs(emin - pw[3])) + x0g
|
||||
variable ne = 2 * floor(x0f / xd) + 1
|
||||
|
||||
// create and calculate initial waves, normalize exponential
|
||||
make /d /n=(ng) /free gausswave
|
||||
make /d /n=(ne) /free fermiwave
|
||||
setscale/i x -x0g, x0g, "", gausswave
|
||||
setscale/i x -x0f, x0f, "", fermiwave
|
||||
|
||||
gausswave = exp( - (x / pw[5] )^2 )
|
||||
fermiwave = 1 / (exp( x / (kBoltzmann * pw[4])) + 1.0 )
|
||||
|
||||
// calculate the convolution
|
||||
duplicate /free fermiwave, resultwave
|
||||
Convolve /a gausswave, resultwave
|
||||
variable rmax = wavemax(resultwave)
|
||||
resultwave /= rmax
|
||||
|
||||
// prepare output
|
||||
ng = numpnts(resultwave)
|
||||
x0g = xd * (ng - 1) / 2
|
||||
setscale/i x -x0g, x0g, "", resultwave
|
||||
|
||||
yw = pw[2] * resultwave(xw[p] - pw[3]) + pw[0] + pw[1] * xw[p]
|
||||
end
|
52
pearl/pearl-gui-tools.ipf
Normal file
52
pearl/pearl-gui-tools.ipf
Normal file
@ -0,0 +1,52 @@
|
||||
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
|
||||
#pragma IgorVersion = 6.1
|
||||
#pragma ModuleName = PearlGuiTools
|
||||
#pragma version = 1.01
|
||||
|
||||
// Miscellaneous GUI tools
|
||||
// * progress bar
|
||||
|
||||
// created: matthias.muntwiler@psi.ch, 2013-11-14
|
||||
// Copyright (c) 2013 Paul Scherrer Institut
|
||||
// $Id$
|
||||
|
||||
// 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
|
||||
|
||||
function display_progress_panel(title, message, progress_max)
|
||||
string title
|
||||
string message
|
||||
variable progress_max
|
||||
|
||||
NewPanel /K=1 /N=ProgressPanel /W=(200,200,402,260) as title
|
||||
TitleBox t_message,pos={2,2},size={189,13},title=message
|
||||
TitleBox t_message,frame=0
|
||||
ValDisplay vd_progress,pos={2,20},size={198,13}
|
||||
ValDisplay vd_progress,limits={0,progress_max,0},barmisc={0,0},mode= 3,value= _NUM:0
|
||||
Button b_abort,pos={74,38},size={50,20},title="Abort"
|
||||
DoUpdate /W=ProgressPanel /E=1
|
||||
end
|
||||
|
||||
function update_progress_panel(progress, [message, progress_max])
|
||||
// returns true if the user clicked the Abort button
|
||||
variable progress
|
||||
string message
|
||||
variable progress_max
|
||||
|
||||
if (!ParamIsDefault(message))
|
||||
TitleBox t_message,title=message,win=ProgressPanel
|
||||
endif
|
||||
if (ParamIsDefault(progress_max))
|
||||
ValDisplay vd_progress,value=_NUM:progress,win=ProgressPanel
|
||||
else
|
||||
ValDisplay vd_progress,limits={0,progress_max,0},value=_NUM:progress,win=ProgressPanel
|
||||
endif
|
||||
DoUpdate /W=ProgressPanel
|
||||
return (v_flag == 2)
|
||||
end
|
||||
|
||||
function kill_progress_panel()
|
||||
KillWindow ProgressPanel
|
||||
end
|
194
pearl/pearl-menu.ipf
Normal file
194
pearl/pearl-menu.ipf
Normal file
@ -0,0 +1,194 @@
|
||||
#pragma rtGlobals=1 // Use modern global access method.
|
||||
#pragma ModuleName = PearlMenu
|
||||
#pragma version = 1.01
|
||||
|
||||
// main menu for PEARL data acquisition and analysis packages
|
||||
|
||||
// $Id$
|
||||
// author: matthias.muntwiler@psi.ch
|
||||
// Copyright (c) 2013-14 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
|
||||
|
||||
menu "PEARL"
|
||||
|
||||
submenu "Data Files"
|
||||
PearlMenuEnableFunc("pearl_data_explorer") + "Data Explorer", /Q, pearl_data_explorer()
|
||||
help = {"Data explorer panel with file import and preview", "Requires ARPES package and HDF5 XOP"}
|
||||
PearlMenuEnableFunc("ad_load_dialog") + "AD HDF5", /Q, ad_load_dialog("")
|
||||
help = {"Import area detector HDF5 data file", "Requires ARPES package and HDF5 XOP"}
|
||||
end
|
||||
|
||||
submenu "On-the-Fly Data"
|
||||
PearlMenuEnableFunc("otf_rename_folders") + "Shorten OTF Folder Names", /Q, otf_rename_folders("010")
|
||||
help = {"Renames otf_xxxxxx_yyyyyy_zzzz data folders to otf_yyyyyy (removing date and suffix)", "Requires Optics package"}
|
||||
PearlMenuEnableFunc("otf_gather_batch") + "Gather OTF Batch", /Q, otf_gather_batch("current_ch1", "photonenergy", "otf_batch")
|
||||
help = {"Copies data from all otf_* folders into otf_batch folder", "Requires Optics package"}
|
||||
PearlMenuEnableFunc("PearlOpticsPreviewPanel") + "OTF Preview", /Q, PearlOpticsPreviewPanel()
|
||||
help = {"Opens a preview panel for OTF data in otf_* folders", "Requires Optics package"}
|
||||
end
|
||||
|
||||
submenu "Scienta Analyser"
|
||||
PearlMenuEnableFunc("ad_display_profiles") + "Scienta Live View", /Q, PearlLiveDisplay("X03DA-SCIENTA:", "EA", "(65280,54528,48896)")
|
||||
help = {"Display preview panel with latest image from Scienta", "Requires ARPES package and EPICS XOP"}
|
||||
PearlMenuEnableFunc("ast_setup") + "Angle Scan Tracker", /Q, PearlAnglescanTracker("X03DA-SCIENTA:", "(65280,54528,48896)")
|
||||
help = {"Preview of acquired angle scan data and current detection angles.", "Requires ARPES package and EPICS XOP"}
|
||||
end
|
||||
|
||||
submenu "Cameras"
|
||||
PearlMenuEnableFunc("ad_display_profiles") + "Exit Slit Live View", /Q, PearlLiveDisplay("X03DA-OP-PS1:", "OP", "(65280,54528,48896)")
|
||||
help = {"Display preview panel with latest image from Scienta", "Requires ARPES package and EPICS XOP"}
|
||||
PearlMenuEnableFunc("ad_display_profiles") + "Manipulator Live View", /Q, PearlLiveDisplay("X03DA-ES-PS1:", "ES", "(65280,54528,48896)")
|
||||
help = {"Display live panel of the exit slit camera", "Requires ARPES package and EPICS XOP"}
|
||||
end
|
||||
|
||||
submenu "Display"
|
||||
PearlMenuEnableFunc("ad_display_profiles") + "2D Profiles", /Q, Display2dProfiles()
|
||||
help = {"Profiles display of 2D data", "Requires ARPES package"}
|
||||
PearlMenuEnableFunc("ad_display_brick") + "3D Slicer", /Q, Display3dSlicer()
|
||||
help = {"Slice and profiles display of 3D data", "Requires ARPES package"}
|
||||
PearlMenuEnableFunc("ad_display_brick") + "3D Gizmo", /Q, DisplayGizmoSlicer()
|
||||
help = {"Gizmo display of 3D data", "Requires ARPES package"}
|
||||
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"}
|
||||
end
|
||||
|
||||
submenu "Sample Preparation"
|
||||
PearlMenuEnableFunc("ann_ramp_start") + "Annealing Ramp", /Q, panel_ramp_gen()
|
||||
help = {"Sample annealing ramp generator"}
|
||||
end
|
||||
|
||||
submenu "Packages"
|
||||
"Load ARPES Package", /Q, LoadPearlArpes()
|
||||
help = {"Data processing and analysis for ARPES experiments"}
|
||||
"Load Preparation Package", /Q, LoadPearlPreparation()
|
||||
help = {"Process control for sample preparation"}
|
||||
"Load Optics Package", /Q, LoadPearlOptics()
|
||||
help = {"Data processing and analysis for beamline commissioning"}
|
||||
end
|
||||
end
|
||||
|
||||
function /s PearlMenuEnableFunc(funcname)
|
||||
// checks whether a function name exists
|
||||
// and conditionally returns a prefix which disables the menu item
|
||||
// if the function does not exist
|
||||
string funcname
|
||||
if (exists(funcname) >= 3)
|
||||
return ""
|
||||
else
|
||||
return "("
|
||||
endif
|
||||
end
|
||||
|
||||
function LoadPearlOptics()
|
||||
execute /p/q/z "INSERTINCLUDE \"pearl-optics\""
|
||||
execute /p/q/z "COMPILEPROCEDURES "
|
||||
execute /p/q/z "PearlOpticsPanel#po_InitPanel()"
|
||||
execute /p/q/z "BuildMenu \"PEARL\""
|
||||
end
|
||||
|
||||
function LoadPearlArpes()
|
||||
execute /p/q/z "INSERTINCLUDE \"pearl-arpes\""
|
||||
execute /p/q/z "COMPILEPROCEDURES "
|
||||
execute /p/q/z "BuildMenu \"PEARL\""
|
||||
end
|
||||
|
||||
function LoadPearlPreparation()
|
||||
execute /p/q/z "INSERTINCLUDE \"pearl-preparation\""
|
||||
execute /p/q/z "COMPILEPROCEDURES "
|
||||
execute /p/q/z "BuildMenu \"PEARL\""
|
||||
end
|
||||
|
||||
function Display2dProfiles()
|
||||
dfref dfBefore = GetDataFolderDFR()
|
||||
Execute /q/z "CreateBrowser prompt=\"Select 2D wave\", showWaves=1, showVars=0, showStrs=0"
|
||||
dfref dfAfter = GetDataFolderDFR()
|
||||
SetDataFolder dfBefore
|
||||
|
||||
SVAR list = S_BrowserList
|
||||
NVAR flag = V_Flag
|
||||
|
||||
if ((flag != 0) && (ItemsInList(list) >= 1))
|
||||
string brickname = StringFromList(0, list)
|
||||
string cmd
|
||||
sprintf cmd, "ad_display_profiles(%s)", brickname
|
||||
execute /q/z cmd
|
||||
endif
|
||||
end
|
||||
|
||||
function Display3dSlicer()
|
||||
dfref dfBefore = GetDataFolderDFR()
|
||||
Execute /q/z "CreateBrowser prompt=\"Select 3D wave\", showWaves=1, showVars=0, showStrs=0"
|
||||
dfref dfAfter = GetDataFolderDFR()
|
||||
SetDataFolder dfBefore
|
||||
|
||||
SVAR list = S_BrowserList
|
||||
NVAR flag = V_Flag
|
||||
|
||||
if ((flag != 0) && (ItemsInList(list) >= 1))
|
||||
string brickname = StringFromList(0, list)
|
||||
string cmd
|
||||
sprintf cmd, "ad_display_slice(%s)", brickname
|
||||
execute /q/z cmd
|
||||
sprintf cmd, "ad_brick_slicer(%s)", brickname
|
||||
execute /q/z cmd
|
||||
endif
|
||||
end
|
||||
|
||||
function DisplayGizmoSlicer()
|
||||
dfref dfBefore = GetDataFolderDFR()
|
||||
Execute /q/z "CreateBrowser prompt=\"Select 3D wave\", showWaves=1, showVars=0, showStrs=0"
|
||||
dfref dfAfter = GetDataFolderDFR()
|
||||
SetDataFolder dfBefore
|
||||
|
||||
SVAR list = S_BrowserList
|
||||
NVAR flag = V_Flag
|
||||
|
||||
if ((flag != 0) && (ItemsInList(list) >= 1))
|
||||
string brickname = StringFromList(0, list)
|
||||
string cmd
|
||||
sprintf cmd, "ad_display_brick(%s)", brickname
|
||||
execute /q/z cmd
|
||||
sprintf cmd, "ad_brick_slicer(%s)", brickname
|
||||
execute /q/z cmd
|
||||
endif
|
||||
end
|
||||
|
||||
function PearlLiveDisplay(epicsname, nickname, wbRGB)
|
||||
string epicsname // base name of the detector, e.g. X03DA-SCIENTA:
|
||||
// image1: and cam1: are appended by the function
|
||||
// see ad_connect
|
||||
string nickname // nick name under which this detector is referred to in Igor
|
||||
// must be a valid data folder name
|
||||
// see ad_connect
|
||||
string wbRGB // window background color, e.g. "(32768,49152,55296)"
|
||||
string cmd
|
||||
sprintf cmd, "ad_connect(\"%s\", \"%s\")", epicsname, nickname
|
||||
execute /q/z cmd
|
||||
sprintf cmd, "ad_display_profiles(root:pearl_epics:%s:image)", nickname
|
||||
execute /q/z cmd
|
||||
sprintf cmd, "ModifyGraph wbRGB=%s", wbRGB
|
||||
execute /q/z cmd
|
||||
sprintf cmd, "add_roi_controls()"
|
||||
execute /q/z cmd
|
||||
end
|
||||
|
||||
function PearlAnglescanTracker(epicsname, wbRGB)
|
||||
string epicsname // base name of the detector, e.g. X03DA-SCIENTA:
|
||||
// image1: and cam1: are appended by the function
|
||||
// see ast_setup
|
||||
string wbRGB // window background color, e.g. "(32768,49152,55296)"
|
||||
string cmd
|
||||
sprintf cmd, "ast_setup()"
|
||||
execute /q/z cmd
|
||||
sprintf cmd, "ModifyGraph wbRGB=%s", wbRGB
|
||||
execute /q/z cmd
|
||||
end
|
314
pearl/pearl-otf-import.ipf
Normal file
314
pearl/pearl-otf-import.ipf
Normal file
@ -0,0 +1,314 @@
|
||||
#pragma rtGlobals=1 // Use modern global access method.
|
||||
#pragma IgorVersion = 6.1
|
||||
#pragma ModuleName = PearlOtfImport
|
||||
#pragma version = 1.01
|
||||
|
||||
// procedures for importing on-the-fly (OTF) scans
|
||||
// OTF scans are saved as ITX files
|
||||
// matthias muntwiler, 2013-02-22
|
||||
// $Id$
|
||||
|
||||
// introduction
|
||||
// the latest version of the PEARL OTF server saves data in igor text (ITX)
|
||||
// the files contain code which saves all data from one file into one data folder with a unique name
|
||||
// multiple files can be selected in the explorer and loaded by a double click
|
||||
|
||||
// description
|
||||
// OTF data folder names have the format otf_date_time_suffix, where only suffix is user-defined
|
||||
// thus, raw data folder names are unique
|
||||
// data folder names can be converted to a shorter format
|
||||
// an OTF data folder contains a wave for each measured quantity (detector)
|
||||
// and the IN, ID, IV, and IU waves for additional beamline parameters
|
||||
// detector waves must have a wave note containing the following key=value pairs:
|
||||
// PV=name of EPICS process variable
|
||||
// PhysicalType=physical type of the quantity in the same way as used by pearl-optics-import
|
||||
// Axis1=wave name of principal X axis
|
||||
|
||||
// convergence
|
||||
// while the file formats may be different, data files generated by the OTF and EPICS scan tools
|
||||
// shall ultimately produce the same data structures in an Igor experiment
|
||||
|
||||
function otf_load_itx_all(pathname)
|
||||
// loads all OTF files from a given path
|
||||
// this function is for older files (before 2013-03-01) which do not specify a destination data folder
|
||||
// newer files can be loaded by double click from the explorer
|
||||
// without the danger of overwriting data from other files
|
||||
string pathname
|
||||
string filename
|
||||
|
||||
if (strlen(pathname) <= 0)
|
||||
newpath /o/q otf_load_itx
|
||||
pathname = "otf_load_itx"
|
||||
endif
|
||||
string filelist = IndexedFile($pathname, -1, ".itx")
|
||||
filelist = ListMatch(filelist, "otf*.itx", ";")
|
||||
variable nfile = ItemsInList(filelist, ";")
|
||||
variable ifile
|
||||
for (ifile = 0; ifile < nfile; ifile += 1)
|
||||
filename = StringFromList(ifile, filelist, ";")
|
||||
otf_load_itx(pathname, filename)
|
||||
endfor
|
||||
end
|
||||
|
||||
function otf_load_itx_match(pathname, matchstr)
|
||||
// loads all OTF files from a given path whose names match a given string
|
||||
// this function is for older files (before 2013-03-01) which do not specify a destination data folder
|
||||
// newer files can be loaded by double click from the explorer
|
||||
// without the danger of overwriting data from other files
|
||||
string pathname
|
||||
string matchstr
|
||||
string filename
|
||||
|
||||
if (strlen(pathname) <= 0)
|
||||
newpath /o/q otf_load_itx
|
||||
pathname = "otf_load_itx"
|
||||
endif
|
||||
string filelist = IndexedFile($pathname, -1, ".itx")
|
||||
filelist = ListMatch(filelist, matchstr, ";")
|
||||
variable nfile = ItemsInList(filelist, ";")
|
||||
variable ifile
|
||||
for (ifile = 0; ifile < nfile; ifile += 1)
|
||||
filename = StringFromList(ifile, filelist, ";")
|
||||
otf_load_itx(pathname, filename)
|
||||
endfor
|
||||
end
|
||||
|
||||
function otf_load_itx(pathname, filename)
|
||||
// loads a specific OTF file
|
||||
// this function is for older files (before 2013-03-01) which do not specify a destination data folder
|
||||
// newer files can be loaded by double click from the explorer
|
||||
// without the danger of overwriting data from other files
|
||||
string pathname
|
||||
string filename
|
||||
|
||||
dfref savedf = GetDataFolderDFR()
|
||||
setdatafolder root:
|
||||
|
||||
newdatafolder /s/o otf_load_itx_temp
|
||||
if (strlen(pathname) > 0)
|
||||
LoadWave /O/P=$pathname/Q/T filename
|
||||
else
|
||||
LoadWave /O/Q/T filename
|
||||
endif
|
||||
if (v_flag)
|
||||
string foldername
|
||||
foldername = ParseFilePath(3, s_filename, "/", 0, 0)
|
||||
foldername = foldername[0,16]
|
||||
foldername = CleanupName(foldername, 0)
|
||||
//foldername = UniqueName(foldername, 11, 0)
|
||||
renamedatafolder root:otf_load_itx_temp, $foldername
|
||||
printf "loaded otf data from file %s into folder %s\r", s_filename, foldername
|
||||
endif
|
||||
|
||||
setdatafolder savedf
|
||||
end
|
||||
|
||||
function otf_gather_iterator(df, sdata)
|
||||
// data folder iterator used by otf_gather_batch
|
||||
dfref df
|
||||
string &sdata // key=value list of parameters
|
||||
// xwavematch
|
||||
// ywavematch
|
||||
// destfolder
|
||||
|
||||
string src_name
|
||||
string dst_name
|
||||
string src_folder
|
||||
string dst_folder
|
||||
string df_id
|
||||
string prefix, sdate, stime
|
||||
|
||||
setdatafolder df
|
||||
src_folder = GetDataFolder(0, df)
|
||||
sscanf src_folder, "%[^_]_%[0-9]_%[0-9]", prefix, sdate, stime
|
||||
df_id = ""
|
||||
if (strlen(sdate) > 0)
|
||||
df_id += "_" + sdate
|
||||
endif
|
||||
if (strlen(stime) > 0)
|
||||
df_id += "_" + stime
|
||||
endif
|
||||
dst_folder = StringByKey("destfolder", sdata)
|
||||
|
||||
src_name = StringByKey("xwavematch", sdata)
|
||||
src_name = WaveList(src_name, "", "")
|
||||
if (ItemsInList(src_name) >= 1)
|
||||
src_name = StringFromList(0, src_name)
|
||||
dst_name = dst_folder + src_name + df_id
|
||||
//print src_name, dst_name
|
||||
duplicate $src_name, $dst_name
|
||||
endif
|
||||
|
||||
src_name = StringByKey("ywavematch", sdata)
|
||||
src_name = WaveList(src_name, "", "")
|
||||
if (ItemsInList(src_name) >= 1)
|
||||
src_name = StringFromList(0, src_name)
|
||||
dst_name = dst_folder + src_name + df_id
|
||||
//print src_name, dst_name
|
||||
duplicate $src_name, $dst_name
|
||||
endif
|
||||
end
|
||||
|
||||
function otf_gather_batch(ywavematch, xwavematch, destfolder)
|
||||
// gathers (copies) OTF datasets in one data folder
|
||||
// can be used for example for the Igor batch curve fitting tool
|
||||
string ywavematch // match string identifies the y wave to be copied
|
||||
string xwavematch // match string identifies the x wave to be copied
|
||||
string destfolder // name of the destination data folder. folder does not have to exist.
|
||||
|
||||
return gather_batch("otf*", ywavematch, xwavematch, destfolder)
|
||||
end
|
||||
|
||||
function gather_batch(foldermatch, ywavematch, xwavematch, destfolder)
|
||||
// gathers (copies) OTF datasets in one data folder
|
||||
// can be used for example for the Igor batch curve fitting tool
|
||||
string foldermatch // match string to select data folders, e.g. "otf*"
|
||||
string ywavematch // match string identifies the y wave to be copied
|
||||
string xwavematch // match string identifies the x wave to be copied
|
||||
string destfolder // name of the destination data folder. folder does not have to exist.
|
||||
|
||||
dfref savedf = GetDataFolderDFR()
|
||||
newdatafolder /o/s $destfolder
|
||||
destfolder = GetDataFolder(1)
|
||||
|
||||
string iteratordata = ""
|
||||
iteratordata = ReplaceStringByKey("xwavematch", iteratordata, xwavematch)
|
||||
iteratordata = ReplaceStringByKey("ywavematch", iteratordata, ywavematch)
|
||||
iteratordata = ReplaceStringByKey("destfolder", iteratordata, destfolder)
|
||||
|
||||
setdatafolder savedf
|
||||
iteratordata = IterateDataFolders(foldermatch, otf_gather_iterator, iteratordata)
|
||||
|
||||
setdatafolder savedf
|
||||
end
|
||||
|
||||
function otf_rename_folders_iterator(df, sdata)
|
||||
// data folder iterator used by otf_rename_folders
|
||||
dfref df
|
||||
string &sdata // key=value list of parameters
|
||||
|
||||
string pattern = StringByKey("pattern", sdata)
|
||||
variable unique_index = NumberByKey("unique_index", sdata)
|
||||
string new_suffix = StringByKey("new_suffix", sdata)
|
||||
|
||||
string src_folder
|
||||
string dst_folder
|
||||
string sprefix, sdate, stime, ssuffix
|
||||
|
||||
setdatafolder df
|
||||
src_folder = GetDataFolder(0, df)
|
||||
sprefix = "otf"
|
||||
sscanf src_folder, "otf_%[0-9]_%[0-9]%s", sdate, stime, ssuffix
|
||||
// return early if folder name does not match the expected pattern
|
||||
if ((strlen(sdate) == 0) || (strlen(stime) == 0))
|
||||
return 1
|
||||
endif
|
||||
|
||||
dst_folder = sprefix
|
||||
if (cmpstr(pattern[0], "0") != 0)
|
||||
dst_folder += "_" + sdate
|
||||
endif
|
||||
if (cmpstr(pattern[1], "0") != 0)
|
||||
dst_folder += "_" + stime
|
||||
endif
|
||||
if (cmpstr(pattern[2], "0") != 0)
|
||||
if (strlen(new_suffix) > 0)
|
||||
ssuffix = "_" + new_suffix
|
||||
endif
|
||||
dst_folder += ssuffix
|
||||
endif
|
||||
|
||||
if ((unique_index > 0) || (CheckName(dst_folder, 11) != 0))
|
||||
dst_folder = UniqueName(dst_folder + "_", 11, unique_index)
|
||||
endif
|
||||
|
||||
setdatafolder ::
|
||||
print src_folder + " -> " + dst_folder
|
||||
RenameDataFolder $src_folder, $dst_folder
|
||||
return 0
|
||||
end
|
||||
|
||||
function otf_rename_folders(pattern, [unique_index, new_suffix, match_str])
|
||||
// renames OTF data folders by omitting parts of the file name
|
||||
string pattern // string of zeros and ones indicates which name parts to keep
|
||||
// pos 1: date
|
||||
// pos 2: time
|
||||
// pos 3: custom suffix
|
||||
variable unique_index // if you remove date and time,
|
||||
// this start index will be used to make names unique
|
||||
// if non-zero, new names will be forced to include a unique index
|
||||
// if zero (default), new names will get a unique index only in case of a conflict
|
||||
// optional, defaults to 0
|
||||
string new_suffix
|
||||
// replace old suffix by this one
|
||||
// if empty (default), the old suffix will be kept
|
||||
// optional, defaults to empty string
|
||||
string match_str // match folder name to rename
|
||||
// optional, defaults to "otf*" (matches all OTF folders)
|
||||
|
||||
dfref savedf = GetDataFolderDFR()
|
||||
|
||||
if (ParamIsDefault(unique_index))
|
||||
unique_index = 0
|
||||
endif
|
||||
if (ParamIsDefault(new_suffix))
|
||||
new_suffix = ""
|
||||
endif
|
||||
if (ParamIsDefault(match_str))
|
||||
match_str = "otf*"
|
||||
endif
|
||||
|
||||
string iteratordata = ""
|
||||
iteratordata = ReplaceStringByKey("pattern", iteratordata, pattern)
|
||||
iteratordata = ReplaceNumberByKey("unique_index", iteratordata, unique_index)
|
||||
iteratordata = ReplaceStringByKey("new_suffix", iteratordata, new_suffix)
|
||||
|
||||
iteratordata = IterateDataFolders(match_str, otf_rename_folders_iterator, iteratordata)
|
||||
|
||||
setdatafolder savedf
|
||||
end
|
||||
|
||||
function otf_interp(e1, e2, npts, smo)
|
||||
variable e1
|
||||
variable e2
|
||||
variable npts
|
||||
variable smo
|
||||
|
||||
wave ch1 = current_ch1
|
||||
wave ch2 = current_ch2
|
||||
wave pe = photonenergy
|
||||
wave cff
|
||||
wave rc = ringcurrent
|
||||
|
||||
duplicate /o ch1, current_ch1_int
|
||||
wave ch1i = current_ch1_int
|
||||
duplicate /o ch2, current_ch2_int
|
||||
wave ch2i = current_ch2_int
|
||||
duplicate /o pe, photonenergy_int
|
||||
wave pei = photonenergy_int
|
||||
duplicate /o cff, cff_int
|
||||
wave cffi = cff_int
|
||||
duplicate /o rc, ringcurrent_int
|
||||
wave rci = ringcurrent_int
|
||||
|
||||
redimension /n=(npts) ch1i, ch2i, pei, cffi, rci
|
||||
setscale /i x e1, e2, "eV", ch1i, ch2i, pei, cffi, rci
|
||||
|
||||
otf_smo_int(ch1, ch1i, pe, smo)
|
||||
otf_smo_int(ch2, ch2i, pe, smo)
|
||||
otf_smo_int(pe, pei, pe, smo)
|
||||
otf_smo_int(cff, cffi, pe, smo)
|
||||
otf_smo_int(rc, rci, pe, smo)
|
||||
end
|
||||
|
||||
function otf_smo_int(win, wout, wpe, smo)
|
||||
wave win
|
||||
wave wout
|
||||
wave wpe
|
||||
variable smo
|
||||
|
||||
//duplicate /o win, wtmp
|
||||
duplicate /free win, wtmp
|
||||
smooth /b /e=3 smo, wtmp
|
||||
wout = interp(x, wpe, wtmp)
|
||||
end
|
85
pearl/pearl-polar-coordinates.ipf
Normal file
85
pearl/pearl-polar-coordinates.ipf
Normal file
@ -0,0 +1,85 @@
|
||||
#pragma rtGlobals=3
|
||||
#pragma version = 1.1
|
||||
#pragma IgorVersion = 6.1
|
||||
#pragma ModuleName = PearlPolarCoordinates
|
||||
|
||||
// author: matthias.muntwiler@psi.ch
|
||||
// Copyright (c) 2011-13 Paul Scherrer Institut
|
||||
// $Id$
|
||||
|
||||
function cart2polar(xx, yy, zz, radius, theta, phi)
|
||||
// converts a 3-vector from Cartesian to polar coordinates
|
||||
variable xx, yy, zz
|
||||
variable &radius, &theta, &phi // angles in degrees
|
||||
|
||||
radius = sqrt(xx^2 + yy^2 + zz^2)
|
||||
|
||||
if (radius > 0)
|
||||
theta = acos(zz / radius) * 180 / pi
|
||||
else
|
||||
theta = 0
|
||||
endif
|
||||
|
||||
if (xx > 0)
|
||||
phi = atan(yy / xx) * 180 / pi
|
||||
elseif (xx < 0)
|
||||
phi = atan(yy / xx) * 180 / pi + 180
|
||||
else
|
||||
if (yy > 0)
|
||||
phi = 90
|
||||
else
|
||||
phi = 270
|
||||
endif
|
||||
endif
|
||||
end
|
||||
|
||||
function cart2polar_wave(in, out)
|
||||
// converts a wave of 3-vectors from Cartesian to polar coordinates
|
||||
wave in // wave with dimensions (3, N), N >= 1, (x, y, z)
|
||||
wave out // wave same dimensions as in, (radius, theta, phi)
|
||||
// angles in degrees
|
||||
|
||||
out[0][] = sqrt(in[0][q]^2 + in[1][q]^2 + in[2][q]^2)
|
||||
out[1][] = acos(in[2][q] / out[0][q]) * 180 / pi
|
||||
out[2][] = atan(in[1][q] / in[0][q]) * 180 / pi + 180 * (in[0][q] < 0)
|
||||
out[2][] = numtype(out[2][q]) == 0 ? out[2][q] : 90 + 180 * (in[1][q] < 0)
|
||||
end
|
||||
|
||||
function polar2cart(radius, theta, phi, xx, yy, zz)
|
||||
// converts a 3-vector from Cartesian to polar coordinates
|
||||
variable radius, theta, phi // angles in degrees
|
||||
variable &xx, &yy, &zz
|
||||
|
||||
xx = radius * sin(theta * pi / 180) * cos(phi * pi / 180)
|
||||
yy = radius * sin(theta * pi / 180) * sin(phi * pi / 180)
|
||||
zz = radius * cos(theta * pi / 180)
|
||||
end
|
||||
|
||||
function polar2cart_wave(in, out)
|
||||
// converts a wave of 3-vectors from polar to Cartesian coordinates
|
||||
wave in // wave with dimensions (3, N), N >= 1, (radius, theta, phi)
|
||||
// angles in degrees
|
||||
wave out // wave same dimensions as in, (x, y, z)
|
||||
|
||||
out[0][] = in[0][q] * sin(in[1][q] * pi / 180) * cos(in[2][q] * pi / 180)
|
||||
out[1][] = in[0][q] * sin(in[1][q] * pi / 180) * sin(in[2][q] * pi / 180)
|
||||
out[2][] = in[0][q] * cos(in[1][q] * pi / 180)
|
||||
end
|
||||
|
||||
function polar_distance(polar1, azim1, polar2, azim2)
|
||||
// returns the angle between two spherical coordinates
|
||||
variable polar1, azim1
|
||||
// angles in degrees
|
||||
variable polar2, azim2
|
||||
// angles in degrees
|
||||
|
||||
variable xx1, yy1, zz1
|
||||
variable xx2, yy2, zz2
|
||||
|
||||
polar2cart(1, polar1, azim1, xx1, yy1, zz1)
|
||||
polar2cart(1, polar2, azim2, xx2, yy2, zz2)
|
||||
|
||||
variable vv
|
||||
vv = (xx1 * xx2 + yy1 * yy2 + zz1 * zz2) / sqrt(xx1^2 + yy1^2 + zz1^2) / sqrt(xx2^2 + yy2^2 + zz2^2)
|
||||
return acos(vv) * 180 / pi
|
||||
end
|
73
pearl/pearl-preparation.ipf
Normal file
73
pearl/pearl-preparation.ipf
Normal file
@ -0,0 +1,73 @@
|
||||
#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
|
705
pearl/pearl-scienta-preprocess.ipf
Normal file
705
pearl/pearl-scienta-preprocess.ipf
Normal file
@ -0,0 +1,705 @@
|
||||
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
|
||||
#pragma IgorVersion = 6.1
|
||||
#pragma ModuleName = PearlScientaPreprocess
|
||||
#pragma version = 1.02
|
||||
|
||||
// $Id$
|
||||
// author: matthias.muntwiler@psi.ch
|
||||
// Copyright (c) 2013-14 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 preprocessing functions for Scienta detector images.
|
||||
/// @ingroup ArpesPackage
|
||||
///
|
||||
/// this procedure contains functions for data reduction
|
||||
/// and instrument-specific normalization.
|
||||
///
|
||||
/// @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 PearlScientaPreprocess
|
||||
/// @brief preprocessing functions for Scienta detector images.
|
||||
///
|
||||
/// PearlScientaPreprocess is declared in @ref pearl-scienta-preprocess.ipf.
|
||||
|
||||
function prompt_int_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 "int_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
|
||||
|
||||
function /s capture_int_linbg_cursors()
|
||||
// this function is for testing only, until we implement a proper interface
|
||||
string param = csr_int_linbg_reduction("")
|
||||
svar /z global_params = root:packages:pearl_explorer:s_reduction_params
|
||||
if (svar_exists(global_params))
|
||||
global_params = param
|
||||
endif
|
||||
return param
|
||||
end
|
||||
|
||||
function /s csr_int_linbg_reduction(win)
|
||||
// PRELIMINARY - function arguments may change
|
||||
|
||||
// sets reduction parameters from cursors in a graph.
|
||||
// an even number of cursors (2 or more) must be set on the image.
|
||||
// cursor names and order do not matter,
|
||||
// except that the alphabetically first cursor which is attached to an image selects the image.
|
||||
// the cursors mark the following positions, from innermost to outermost pair:
|
||||
// 1) low and high limits of peak region.
|
||||
// 2) peak-side boundary of lower and upper background region.
|
||||
// 3) lower and upper cropping region.
|
||||
|
||||
string win
|
||||
|
||||
// read all cursor positions
|
||||
variable ic
|
||||
string sc
|
||||
variable nc = 10
|
||||
make /n=(nc) /free positions
|
||||
variable np = 0
|
||||
wave /z image = $""
|
||||
string imagename = ""
|
||||
string tracename = ""
|
||||
string info
|
||||
|
||||
for (ic = 0; ic < nc; ic += 1)
|
||||
sc = num2char(char2num("A") + ic)
|
||||
wave /z wc = CsrWaveRef($sc, win)
|
||||
info = CsrInfo($sc, win)
|
||||
tracename = StringByKey("TNAME", info, ":", ";")
|
||||
if (waveexists(wc) && (wavedims(wc) == 2))
|
||||
if (!waveexists(image))
|
||||
wave image = wc
|
||||
imagename = tracename
|
||||
endif
|
||||
if (cmpstr(tracename, imagename) == 0)
|
||||
positions[np] = pcsr($sc, win)
|
||||
np += 1
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
|
||||
np = floor(np / 2) * 2 // ignore odd cursor
|
||||
redimension /n=(np) positions
|
||||
sort positions, positions
|
||||
// shift upper positions by one so that the rightmost pixel becomes 1.0
|
||||
positions = p >= np / 2 ? positions + 1 : positions
|
||||
positions = positions / dimsize(image, 0)
|
||||
|
||||
// map innermost cursor pair to peak center and size
|
||||
variable ip2 = np / 2
|
||||
variable ip1 = ip2 - 1
|
||||
variable Cpos = (positions[ip1] + positions[ip2]) / 2
|
||||
variable Csize = positions[ip2] - positions[ip1]
|
||||
if (ip1 >= 0)
|
||||
Cpos = (positions[ip1] + positions[ip2]) / 2
|
||||
Csize = positions[ip2] - positions[ip1]
|
||||
else
|
||||
// default: a small region in the center
|
||||
Cpos = 0.5
|
||||
Csize = 0.2
|
||||
endif
|
||||
|
||||
// background region
|
||||
ip1 -= 1
|
||||
ip2 += 1
|
||||
variable Lsize
|
||||
variable Hsize
|
||||
if (ip1 >= 0)
|
||||
Lsize = positions[ip1]
|
||||
Hsize = 1 - positions[ip2]
|
||||
else
|
||||
// default: everything outside the peak region
|
||||
Lsize = Cpos - Csize / 2
|
||||
Hsize = 1 - (Cpos + Csize / 2)
|
||||
endif
|
||||
|
||||
// crop region
|
||||
ip1 -= 1
|
||||
ip2 += 1
|
||||
variable Lcrop
|
||||
variable Hcrop
|
||||
if (ip1 >= 0)
|
||||
Lcrop = positions[ip1]
|
||||
Hcrop = 1 - positions[ip2]
|
||||
else
|
||||
// default: dead corners of the EW4000 at PEARL
|
||||
Lcrop = 0.11
|
||||
Hcrop = 0.11
|
||||
endif
|
||||
Lsize = max(Lsize - Lcrop, 0)
|
||||
Hsize = max(Hsize - Hcrop, 0)
|
||||
|
||||
string param = ""
|
||||
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, "=", ";")
|
||||
|
||||
return param
|
||||
end
|
||||
|
||||
function test_int_linbg(image)
|
||||
// useful for testing or manual processing
|
||||
// since the int_linbg_reduction function cannot be called from the command line directly.
|
||||
wave image
|
||||
|
||||
string param = ""
|
||||
prompt_int_linbg_reduction(param)
|
||||
|
||||
string data1_name = "test_data1"
|
||||
string data2_name = "test_data2"
|
||||
duplicate /o image, $data1_name, $data2_name
|
||||
wave w_data1 = $data1_name
|
||||
wave w_data2 = $data2_name
|
||||
|
||||
int_linbg_reduction(image, w_data1, w_data2, param)
|
||||
end
|
||||
|
||||
threadsafe function int_linbg_reduction(source, dest1, dest2, param)
|
||||
// data reduction function for adh5_load_reduced_detector
|
||||
// calculates the average pixel value of each angular slice
|
||||
// in one center and two background intervals.
|
||||
// a background value is calculated at the center position
|
||||
// by linear interpolation from the two background values.
|
||||
// returns the center minus linear background in dest1.
|
||||
// returns the Poisson one-sigma error in dest2.
|
||||
wave source // source wave
|
||||
// Scienta detector image, energy axis along X, angle axis along Y
|
||||
wave dest1, dest2 // destination waves
|
||||
// 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.
|
||||
string ¶m // parameters in a key1=value1;key2=value2;... list
|
||||
// all region parameters are relative to the image size (0...1)
|
||||
// Lcrop = size of the lower cropping region
|
||||
// Hcrop = size of the upper cropping region
|
||||
// Lsize = size of the lower background integration region
|
||||
// Hsize = size of the upper background integration region
|
||||
// Cpos = center position of the of the peak integration region
|
||||
// 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
|
||||
|
||||
variable nx = dimsize(source, 0)
|
||||
variable ny = dimsize(source, 1)
|
||||
|
||||
// read parameters
|
||||
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, "=", ";")
|
||||
|
||||
// validate parameters
|
||||
// background parameters are optional, center parameter is required.
|
||||
if (numtype(lcrop) != 0)
|
||||
lcrop = 0
|
||||
endif
|
||||
if (numtype(lsize) != 0)
|
||||
lsize = 0
|
||||
endif
|
||||
if (numtype(hcrop) != 0)
|
||||
hcrop = 0
|
||||
endif
|
||||
if (numtype(hsize) != 0)
|
||||
hsize = 0
|
||||
endif
|
||||
if (numtype(Cpos) != 0)
|
||||
return 1 // Cpos parameter missing
|
||||
endif
|
||||
if (numtype(Csize) != 0)
|
||||
return 2 // Csize parameter missing
|
||||
endif
|
||||
|
||||
variable lpos = lcrop + lsize / 2
|
||||
variable hpos = 1 - (hcrop + hsize / 2)
|
||||
|
||||
variable p0
|
||||
variable p1
|
||||
|
||||
adh5_setup_profile(source, dest1, 1)
|
||||
adh5_setup_profile(source, dest2, 1)
|
||||
|
||||
duplicate /free dest1, lbg, hbg
|
||||
if (lsize > 0)
|
||||
p0 = round(lcrop * nx)
|
||||
p1 = round((lcrop + lsize) * nx)
|
||||
ad_profile_y_w(source, p0, p1, lbg)
|
||||
else
|
||||
lbg = 0
|
||||
endif
|
||||
if (hsize > 0)
|
||||
p0 = round((1 - hcrop - hsize) * nx)
|
||||
p1 = round((1 - hcrop) * nx)
|
||||
ad_profile_y_w(source, p0, p1, hbg)
|
||||
else
|
||||
hbg = 0
|
||||
endif
|
||||
if (csize > 0)
|
||||
p0 = round((cpos - csize/2) * nx)
|
||||
p1 = round((cpos + csize/2) * nx)
|
||||
ad_profile_y_w(source, p0, p1, dest1)
|
||||
else
|
||||
dest1 = 0
|
||||
endif
|
||||
|
||||
variable scale = (cpos - lpos) / (hpos - lpos)
|
||||
dest2 = dest1
|
||||
dest1 -= scale * (hbg - lbg) + lbg
|
||||
dest2 = sqrt(dest2 + scale^2 * (hbg + lbg))
|
||||
return 0 // return zero if successful, non-zero if an error occurs
|
||||
end
|
||||
|
||||
function test_shockley_anglefit(image, branch)
|
||||
// apply the Shockley_anglefit function to a single image
|
||||
// useful for testing or manual processing
|
||||
// since the Shockley_anglefit function cannot be called from the command line directly.
|
||||
wave image
|
||||
variable branch // +1 or -1
|
||||
|
||||
string param = ""
|
||||
param = ReplaceStringByKey("branch", param, num2str(branch), "=", ";")
|
||||
|
||||
string s_branch
|
||||
if (branch >= 0)
|
||||
s_branch = "p"
|
||||
else
|
||||
s_branch = "n"
|
||||
endif
|
||||
string pkpos_name = "saf_pkpos_" + s_branch
|
||||
string pkwid_name = "saf_pkwid_" + s_branch
|
||||
duplicate /o image, $pkpos_name, $pkwid_name
|
||||
wave w_pkpos = $pkpos_name
|
||||
wave w_pkwid = $pkwid_name
|
||||
|
||||
shockley_anglefit(image, w_pkpos, w_pkwid, param)
|
||||
end
|
||||
|
||||
function prompt_Shockley_anglefit(param)
|
||||
string ¶m
|
||||
|
||||
variable branch = NumberByKey("branch", param, "=", ";")
|
||||
|
||||
prompt branch, "Branch (-1 or +1)"
|
||||
|
||||
doprompt "Shockley_anglefit_reduction Parameters", branch
|
||||
if (v_flag == 0)
|
||||
param = ReplaceNumberByKey("branch", param, branch, "=", ";")
|
||||
endif
|
||||
|
||||
return v_flag
|
||||
end
|
||||
|
||||
threadsafe function Shockley_anglefit(source, dest1, dest2, param)
|
||||
// data reduction function for adh5_load_reduced_detector
|
||||
// specialized for analysing the Cu(111) Shockley surface state
|
||||
// do curve fitting of one branch of the surface state
|
||||
// the result is peak position versus energy
|
||||
// TODO: this function contains hard-coded parameters. please generalize as necessary.
|
||||
wave source // source wave
|
||||
// Scienta detector image, energy axis along X, angle axis along Y
|
||||
// the apex of the surface state must be at angle 0
|
||||
wave dest1, dest2 // destination waves
|
||||
// dest1: peak position
|
||||
// dest2: peak width (sigma)
|
||||
string ¶m // parameters in a key1=value1;key2=value2;... list
|
||||
// branch=-1 or +1: select negative (positive) angles for the fit interval, respectively
|
||||
|
||||
variable nx = dimsize(source, 0)
|
||||
variable ny = dimsize(source, 1)
|
||||
|
||||
// read parameters
|
||||
variable branch = NumberByKey("branch", param, "=", ";")
|
||||
|
||||
// validate parameters
|
||||
if (numtype(branch) != 0)
|
||||
branch = +1
|
||||
endif
|
||||
|
||||
// prepare output
|
||||
adh5_setup_profile(source, dest1, 0)
|
||||
adh5_setup_profile(source, dest2, 0)
|
||||
dest1 = nan
|
||||
dest2 = nan
|
||||
|
||||
// select angle range
|
||||
// hard-coded for a particular measurement series
|
||||
variable y0
|
||||
variable y1
|
||||
if (branch < 0)
|
||||
y0 = -5
|
||||
y1 = 0
|
||||
else
|
||||
y0 = 0
|
||||
y1 = 5
|
||||
endif
|
||||
|
||||
// select energy range
|
||||
// start at the point of highest intensity and go up 0.45 eV
|
||||
variable p0
|
||||
variable p1
|
||||
variable q0
|
||||
variable q1
|
||||
duplicate /free dest1, center
|
||||
q0 = round((y0 - dimoffset(source, 1)) / dimdelta(source, 1))
|
||||
q1 = round((y1 - dimoffset(source, 1)) / dimdelta(source, 1))
|
||||
ad_profile_x_w(source, q0, q1, center)
|
||||
wavestats /q/m=1 center
|
||||
p0 = round((v_maxloc - dimoffset(source, 0)) / dimdelta(source, 0))
|
||||
p1 = round((v_maxloc + 0.4 - dimoffset(source, 0)) / dimdelta(source, 0))
|
||||
|
||||
// prepare intermediate data buffer
|
||||
make /n=(ny)/d/free profile
|
||||
setscale /p x dimoffset(source,1), dimdelta(source,1), waveunits(source,1), profile
|
||||
|
||||
variable pp
|
||||
for (pp = p0; pp <= p1; pp += 1)
|
||||
profile = source[pp][p]
|
||||
curvefit /Q /NTHR=1 /W=2 gauss profile(y0,y1)
|
||||
wave w_coef
|
||||
dest1[pp] = w_coef[2]
|
||||
dest2[pp] = w_coef[3]
|
||||
endfor
|
||||
return 0 // return zero if successful, non-zero if an error occurs
|
||||
end
|
||||
|
||||
function prompt_int_quadbg_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 "int_quadbg_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
|
||||
|
||||
function test_int_quadbg(image)
|
||||
// useful for testing or manual processing
|
||||
// since the int_quadbg_reduction function cannot be called from the command line directly.
|
||||
wave image
|
||||
|
||||
string param = ""
|
||||
prompt_int_quadbg_reduction(param)
|
||||
|
||||
string data1_name = "test_data1"
|
||||
string data2_name = "test_data2"
|
||||
duplicate /o image, $data1_name, $data2_name
|
||||
wave w_data1 = $data1_name
|
||||
wave w_data2 = $data2_name
|
||||
|
||||
int_quadbg_reduction(image, w_data1, w_data2, param)
|
||||
end
|
||||
|
||||
threadsafe function int_quadbg_reduction(source, dest1, dest2, param)
|
||||
// data reduction function for adh5_load_reduced_detector
|
||||
// integrates peak area minus a quadratic backgrouind
|
||||
wave source // source wave
|
||||
// Scienta detector image, energy axis along X, angle axis along Y
|
||||
wave dest1, dest2 // destination waves
|
||||
string ¶m // parameters in a key1=value1;key2=value2;... list
|
||||
// all region parameters are relative to the image size (0...1)
|
||||
// Lcrop = size of the lower cropping region
|
||||
// Hcrop = size of the upper cropping region
|
||||
// Lsize = size of the lower background integration region
|
||||
// Hsize = size of the upper background integration region
|
||||
// Cpos = center position of the of the peak integration region
|
||||
// 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
|
||||
|
||||
variable nx = dimsize(source, 0)
|
||||
variable ny = dimsize(source, 1)
|
||||
|
||||
// read parameters
|
||||
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, "=", ";")
|
||||
|
||||
// validate parameters
|
||||
// background parameters are optional, center parameter is required.
|
||||
if (numtype(lcrop) != 0)
|
||||
lcrop = 0
|
||||
endif
|
||||
if (numtype(lsize) != 0)
|
||||
lsize = 0
|
||||
endif
|
||||
if (numtype(hcrop) != 0)
|
||||
hcrop = 0
|
||||
endif
|
||||
if (numtype(hsize) != 0)
|
||||
hsize = 0
|
||||
endif
|
||||
if (numtype(Cpos) != 0)
|
||||
return 1 // Cpos parameter missing
|
||||
endif
|
||||
if (numtype(Csize) != 0)
|
||||
return 2 // Csize parameter missing
|
||||
endif
|
||||
|
||||
// crop boundaries
|
||||
variable pcl = round(lcrop * nx)
|
||||
variable pch = round((1 - hcrop) * nx)
|
||||
// fit boundaries
|
||||
variable pfl = round((lcrop + lsize) * nx)
|
||||
variable pfh = round((1 - hcrop - hsize) * nx)
|
||||
// integration boundaries
|
||||
variable pil = round((cpos - csize/2) * nx)
|
||||
variable pih = round((cpos + csize/2) * nx)
|
||||
|
||||
adh5_setup_profile(source, dest1, 0)
|
||||
adh5_setup_profile(source, dest2, 0)
|
||||
|
||||
// prepare intermediate data buffer
|
||||
make /n=(nx) /d /free profile, mask, fit
|
||||
setscale /p x dimoffset(source,0), dimdelta(source,0), waveunits(source,0), profile, mask, fit
|
||||
mask = ((p >= pcl) && (p < pfl)) || ((p >= pfh) && (p < pch))
|
||||
|
||||
variable qq
|
||||
variable sp, sf
|
||||
variable xil = x2pnt(profile, pil)
|
||||
variable xih = x2pnt(profile, pih)
|
||||
|
||||
make /n=3 /free /d w_coef
|
||||
for (qq = 0; qq < ny; qq += 1)
|
||||
profile = source[p][qq]
|
||||
curvefit /Q /NTHR=1 /W=2 poly 3, kwCWave=w_coef, profile /M=mask
|
||||
fit = poly(w_coef, x)
|
||||
sp = sum(profile, xil, xih)
|
||||
sf = sum(fit, xil, xih)
|
||||
dest1[qq] = sp - sf
|
||||
dest2[qq] = sqrt(sp)
|
||||
endfor
|
||||
|
||||
return 0 // return zero if successful, non-zero if an error occurs
|
||||
end
|
||||
|
||||
function scienta_norm(w, x): fitfunc
|
||||
wave w
|
||||
variable x
|
||||
|
||||
return w[0] * (x^2 - w[1]^2)
|
||||
end
|
||||
|
||||
function /wave fit_scienta_ang_transm(data, params)
|
||||
wave data // measured angular distribution (1D)
|
||||
wave /z params
|
||||
|
||||
if (!waveexists(params))
|
||||
make /n=12 /o params
|
||||
endif
|
||||
redimension /n=12/d params
|
||||
|
||||
variable h = wavemax(data) - wavemin(data)
|
||||
params[0] = h / 2
|
||||
params[1] = 0
|
||||
params[2] = 7
|
||||
params[3] = h / 4
|
||||
params[4] = -23
|
||||
params[5] = 4
|
||||
params[6] = h / 4
|
||||
params[7] = +23
|
||||
params[8] = 4
|
||||
params[9] = h / 2
|
||||
params[10] = 0
|
||||
params[11] = -0.001
|
||||
FuncFit /NTHR=0 /q scienta_ang_transm params data
|
||||
|
||||
return params
|
||||
end
|
||||
|
||||
threadsafe function scienta_ang_transm(w, x): fitfunc
|
||||
// parameterized angular transmission function of the analyser
|
||||
wave w // coefficients
|
||||
// w[0] = amplitude gauss 1
|
||||
// w[1] = position gauss 1
|
||||
// w[2] = width gauss 1
|
||||
// w[3] = amplitude gauss 2
|
||||
// w[4] = position gauss 2
|
||||
// w[5] = width gauss 2
|
||||
// w[6] = amplitude gauss 3
|
||||
// w[7] = position gauss 3
|
||||
// w[8] = width gauss 3
|
||||
// w[9] = constant background
|
||||
// w[10] = linear background
|
||||
// w[11] = quadratic background
|
||||
variable x
|
||||
|
||||
make /free /n=4 /d w_int
|
||||
w_int[0] = 0
|
||||
w_int[1,] = w[p - 1]
|
||||
variable pk1 = gauss1d(w_int, x)
|
||||
w_int[1,] = w[p + 2]
|
||||
variable pk2 = gauss1d(w_int, x)
|
||||
w_int[1,] = w[p + 5]
|
||||
variable pk3 = gauss1d(w_int, x)
|
||||
w_int[0,2] = w[9 + p]
|
||||
w_int[3] = 0
|
||||
variable bg = poly(w_int, x)
|
||||
|
||||
return bg + pk1 + pk2 + pk3
|
||||
end
|
||||
|
||||
function /wave fit_scienta_poly_bg(data, params, bgterms)
|
||||
wave data // measured distribution (2D)
|
||||
wave /z params // wave, will be redimensioned for the correct size
|
||||
variable bgterms // number of terms in the polynomial background: 2, 3, or 4
|
||||
|
||||
if (!waveexists(params))
|
||||
make /n=15 /o params
|
||||
endif
|
||||
redimension /n=15 /d params
|
||||
|
||||
variable wmax = wavemax(data)
|
||||
variable wmin = wavemin(data)
|
||||
params[0] = 0
|
||||
params[1] = 7
|
||||
params[2] = 1 / 2
|
||||
params[3] = -23
|
||||
params[4] = 4
|
||||
params[5] = 1 / 2
|
||||
params[6] = +23
|
||||
params[7] = 4
|
||||
params[8] = 1
|
||||
params[9] = 0
|
||||
params[10] = -0.001
|
||||
params[11] = wmin
|
||||
params[12] = (wmax - wmin) / dimdelta(data,1) / dimsize(data,1)
|
||||
params[13] = 0
|
||||
params[14] = 0
|
||||
|
||||
string h = "0000000000000"
|
||||
if (bgterms < 3)
|
||||
h = h + "1"
|
||||
else
|
||||
h = h + "0"
|
||||
endif
|
||||
if (bgterms < 4)
|
||||
h = h + "1"
|
||||
else
|
||||
h = h + "0"
|
||||
endif
|
||||
FuncFitMD /NTHR=1 /q /h=h scienta_poly_bg params data
|
||||
|
||||
return params
|
||||
end
|
||||
|
||||
function scienta_poly_bg(w, e, a): fitfunc
|
||||
// polynomial background with
|
||||
// parameterized angular transmission function of the analyser
|
||||
wave w // coefficients
|
||||
// angular transmission, varies with a
|
||||
// amplitude of gauss 1 = 1 constant
|
||||
// other peak amplitudes and linear terms are relative to gauss 1
|
||||
// w[0] = position gauss 1
|
||||
// w[1] = width gauss 1
|
||||
// w[2] = amplitude gauss 2, relative to gauss 1
|
||||
// w[3] = position gauss 2
|
||||
// w[4] = width gauss 2
|
||||
// w[5] = amplitude gauss 3, relative to gauss 1
|
||||
// w[6] = position gauss 3
|
||||
// w[7] = width gauss 3
|
||||
// w[8] = constant term
|
||||
// w[9] = linear term
|
||||
// w[10] = quadratic term
|
||||
// spectral background, varies with e
|
||||
// w[11] = constant term
|
||||
// w[12] = linear term
|
||||
// w[13] = quadratic term
|
||||
// w[14] = cubic term
|
||||
variable a // detection angle
|
||||
variable e // electron energy
|
||||
|
||||
make /free /n=4 /d w_int
|
||||
variable p0 = 0
|
||||
|
||||
w_int[0] = 0
|
||||
w_int[1] = 1
|
||||
w_int[2,] = w[p0 + p - 2]
|
||||
variable pk1 = gauss1d(w_int, a)
|
||||
p0 += 2
|
||||
|
||||
w_int[1,] = w[p0 + p - 1]
|
||||
variable pk2 = gauss1d(w_int, a)
|
||||
p0 += 3
|
||||
|
||||
w_int[1,] = w[p0 + p - 1]
|
||||
variable pk3 = gauss1d(w_int, a)
|
||||
p0 += 3
|
||||
|
||||
w_int[0,2] = w[p0 + p]
|
||||
w_int[3] = 0
|
||||
variable base = poly(w_int, a)
|
||||
p0 += 3
|
||||
|
||||
w_int[0,3] = w[p0 + p]
|
||||
variable bg = poly(w_int, e)
|
||||
|
||||
return bg * (base + pk1 + pk2 + pk3)
|
||||
end
|
135
pearl/pearl-tools.ipf
Normal file
135
pearl/pearl-tools.ipf
Normal file
@ -0,0 +1,135 @@
|
||||
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
|
||||
#pragma version = 1.00
|
||||
#pragma IgorVersion = 6.2
|
||||
#pragma ModuleName = PearlTools
|
||||
#include "pearl-gui-tools"
|
||||
|
||||
// general programming tools for Igor
|
||||
|
||||
// $Id$
|
||||
// author: matthias.muntwiler@psi.ch
|
||||
// Copyright (c) 2009-14 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
|
||||
|
||||
function DefaultWaveIterator(w, sdata)
|
||||
// function prototype for IterateWaves
|
||||
wave w // wave which the iterator is supposed to work on
|
||||
string &sdata // string with additional data, shared between calls
|
||||
// this is a pass-by-reference argument,
|
||||
// the function may modify the string
|
||||
end
|
||||
|
||||
function AppendToGraphIterator(w, sdata)
|
||||
// append iterated waves to the current graph
|
||||
wave w // wave to be displayed
|
||||
string &sdata // not used
|
||||
|
||||
appendtograph w
|
||||
end
|
||||
|
||||
function SumWavesIterator(w, sdata)
|
||||
// sum waves into one result wave
|
||||
wave w // wave which the iterator is supposed to work on
|
||||
string &sdata // name of the result wave, can include absolute path
|
||||
// the wave must exist and compatible with the summands
|
||||
// the caller is responsible for initialization of the wave
|
||||
|
||||
wave result = $sdata
|
||||
result += w
|
||||
end
|
||||
|
||||
function/s IterateWaves(matchStr, iterator, sdata)
|
||||
// iterate over all waves matching a specified pattern (see built-in WaveList function),
|
||||
// passing each wave to a user-defined iterator function
|
||||
string matchStr // matchStr as for WaveList
|
||||
funcref DefaultWaveIterator iterator // iterator function
|
||||
// use the DefaultWaveIterator function as a template
|
||||
string sdata // data string passed to iterator function
|
||||
// the iterator may modify the string
|
||||
// the function returns the string at the end
|
||||
|
||||
string wlist = WaveList(matchStr, ";", "")
|
||||
variable n = ItemsInList(wlist, ";")
|
||||
variable i
|
||||
for (i = 0; i < n; i += 1)
|
||||
wave w = $(StringFromList(i, wlist, ";"))
|
||||
iterator(w, sdata)
|
||||
endfor
|
||||
return sdata
|
||||
end
|
||||
|
||||
function DefaultFolderIterator(df, sdata)
|
||||
// function prototype for IterateWaves
|
||||
dfref df // data folder reference which the iterator is supposed to work on
|
||||
string &sdata // string with additional data, shared between calls
|
||||
// this is a pass-by-reference argument,
|
||||
// the function may modify the string
|
||||
|
||||
// switch to requested data folder
|
||||
setdatafolder df
|
||||
// for testing
|
||||
print getdatafolder(1)
|
||||
// no need to switch back to original folder
|
||||
end
|
||||
|
||||
function/s IterateDataFolders(matchStr, iterator, sdata, [progress_title])
|
||||
// iterate over all data folders matching a specified pattern in the current data folder,
|
||||
// passing each folder to a user-defined iterator function
|
||||
string matchStr // matchStr as for the built-in stringmatch function
|
||||
funcref DefaultFolderIterator iterator // iterator function
|
||||
// use the DefaultFolderIterator function as a template
|
||||
string sdata // data string passed to iterator function
|
||||
// the iterator may modify the string
|
||||
// the function returns the string at the end
|
||||
string progress_title // title of the progress window (optional)
|
||||
// if not specified or empty, the progress window will not be shown.
|
||||
// if the progress window is show, the user can abort the iteration.
|
||||
// the function result does not indicate whether the iteration was completed or aborted.
|
||||
// the iterator and caller must take care of leaving the data in a consistent state.
|
||||
|
||||
if (ParamIsDefault(progress_title))
|
||||
progress_title = ""
|
||||
endif
|
||||
variable show_progress = strlen(progress_title) > 0
|
||||
|
||||
dfref origdf = GetDataFolderDFR()
|
||||
dfref curdf
|
||||
variable index = 0
|
||||
variable abort_req = 0
|
||||
string objName
|
||||
|
||||
variable ndf = CountObjectsDFR(origdf, 4)
|
||||
if (show_progress)
|
||||
display_progress_panel(progress_title, "", ndf)
|
||||
endif
|
||||
|
||||
do
|
||||
objName = GetIndexedObjNameDFR(origdf, 4, index)
|
||||
if (strlen(objName) == 0)
|
||||
break
|
||||
endif
|
||||
if (stringmatch(objname, matchstr))
|
||||
if (show_progress)
|
||||
abort_req = update_progress_panel(index, message=objName)
|
||||
if (abort_req)
|
||||
break
|
||||
endif
|
||||
endif
|
||||
setdatafolder origdf
|
||||
curdf = $(":" + objname)
|
||||
iterator(curdf, sdata)
|
||||
endif
|
||||
index += 1
|
||||
while(1)
|
||||
|
||||
if (show_progress)
|
||||
kill_progress_panel()
|
||||
endif
|
||||
|
||||
setdatafolder origdf
|
||||
return sdata
|
||||
end
|
135
pearl/pearl-vector-operations.ipf
Normal file
135
pearl/pearl-vector-operations.ipf
Normal file
@ -0,0 +1,135 @@
|
||||
#pragma rtGlobals=3
|
||||
#pragma version = 2.0
|
||||
#pragma IgorVersion = 6.1
|
||||
#pragma ModuleName = PearlVectorOperations
|
||||
|
||||
// author: matthias.muntwiler@psi.ch
|
||||
// Copyright (c) 2011-13 Paul Scherrer Institut
|
||||
// $Id$
|
||||
|
||||
function rotate2d_x(xx, yy, angle)
|
||||
// rotates a 2D cartesian vector and returns its x component
|
||||
variable xx, yy
|
||||
variable angle // rotation angle in degrees
|
||||
|
||||
return xx * cos(angle * pi / 180) - yy * sin(angle * pi / 180)
|
||||
end
|
||||
|
||||
function rotate2d_y(xx, yy, angle)
|
||||
// rotates a 2D cartesian vector and returns its y component
|
||||
variable xx, yy
|
||||
variable angle // rotation angle in degrees
|
||||
|
||||
return xx * sin(angle * pi / 180) + yy * cos(angle * pi / 180)
|
||||
end
|
||||
|
||||
function /wave create_rotation_matrix_free()
|
||||
// creates a matrix which represents a 3-vector rotation
|
||||
// the matrix is initialized as identity
|
||||
|
||||
make /n=(3,3)/free matrix
|
||||
matrix = p == q // identity
|
||||
return matrix
|
||||
end
|
||||
|
||||
function /wave set_rotation_x(matrix, angle)
|
||||
// calculates a matrix representing a 3-vector rotation around the x axis
|
||||
wave matrix // rotation matrix
|
||||
variable angle // rotation angle in degrees
|
||||
|
||||
variable si = sin(angle * pi / 180)
|
||||
variable co = cos(angle * pi / 180)
|
||||
|
||||
matrix[1][1] = co
|
||||
matrix[2][2] = co
|
||||
matrix[2][1] = si
|
||||
matrix[1][2] = -si
|
||||
|
||||
return matrix
|
||||
end
|
||||
|
||||
function /wave set_rotation_y(matrix, angle)
|
||||
// calculates a matrix representing a 3-vector rotation around the y axis
|
||||
wave matrix // rotation matrix
|
||||
variable angle // rotation angle in degrees
|
||||
|
||||
variable si = sin(angle * pi / 180)
|
||||
variable co = cos(angle * pi / 180)
|
||||
|
||||
matrix[0][0] = co
|
||||
matrix[2][2] = co
|
||||
matrix[0][2] = si
|
||||
matrix[2][0] = -si
|
||||
|
||||
return matrix
|
||||
end
|
||||
|
||||
function /wave set_rotation_z(matrix, angle)
|
||||
// calculates a matrix representing a 3-vector rotation around the z axis
|
||||
wave matrix // rotation matrix
|
||||
variable angle // rotation angle in degrees
|
||||
|
||||
variable si = sin(angle * pi / 180)
|
||||
variable co = cos(angle * pi / 180)
|
||||
|
||||
matrix[0][0] = co
|
||||
matrix[1][1] = co
|
||||
matrix[1][0] = si
|
||||
matrix[0][1] = -si
|
||||
|
||||
return matrix
|
||||
end
|
||||
|
||||
function rotate_x_wave(inout, angle)
|
||||
// rotates a wave of 3-vectors about the x axis
|
||||
wave inout // wave with dimensions (3, N), N >= 1, (x, y, z)
|
||||
// result will be in same wave
|
||||
variable angle // rotation angle in degrees
|
||||
|
||||
wave m_rotation_x = create_rotation_matrix_free()
|
||||
make /n=3/d/free w_temp_rotate_x
|
||||
variable ivec, nvec
|
||||
nvec = max(DimSize(inout, 1), 1)
|
||||
for (ivec = 0; ivec < nvec; ivec += 1)
|
||||
set_rotation_x(m_rotation_x, angle)
|
||||
w_temp_rotate_x = inout[p][ivec]
|
||||
matrixop /free w_temp_rotate_x_result = m_rotation_x x w_temp_rotate_x
|
||||
inout[][ivec] = w_temp_rotate_x_result[p]
|
||||
endfor
|
||||
end
|
||||
|
||||
function rotate_y_wave(inout, angle)
|
||||
// rotates a wave of 3-vectors about the y axis
|
||||
wave inout // wave with dimensions (3, N), N >= 1, (x, y, z)
|
||||
// result will be in same wave
|
||||
variable angle // rotation angle in degrees
|
||||
|
||||
wave m_rotation_y = create_rotation_matrix_free()
|
||||
make /n=3/d/free w_temp_rotate_y
|
||||
variable ivec, nvec
|
||||
nvec = max(DimSize(inout, 1), 1)
|
||||
for (ivec = 0; ivec < nvec; ivec += 1)
|
||||
set_rotation_y(m_rotation_y, angle)
|
||||
w_temp_rotate_y = inout[p][ivec]
|
||||
matrixop /free w_temp_rotate_y_result = m_rotation_y x w_temp_rotate_y
|
||||
inout[][ivec] = w_temp_rotate_y_result[p]
|
||||
endfor
|
||||
end
|
||||
|
||||
function rotate_z_wave(inout, angle)
|
||||
// rotates a wave of 3-vectors about the z axis
|
||||
wave inout // wave with dimensions (3, N), N >= 1, (x, y, z)
|
||||
// result will be in same wave
|
||||
variable angle // rotation angle in degrees
|
||||
|
||||
wave m_rotation_z = create_rotation_matrix_free()
|
||||
make /n=3/d/free w_temp_rotate_z
|
||||
variable ivec, nvec
|
||||
nvec = max(DimSize(inout, 1), 1)
|
||||
for (ivec = 0; ivec < nvec; ivec += 1)
|
||||
set_rotation_z(m_rotation_z, angle)
|
||||
w_temp_rotate_z = inout[p][ivec]
|
||||
matrixop /free w_temp_rotate_z_result = m_rotation_z x w_temp_rotate_z
|
||||
inout[][ivec] = w_temp_rotate_z_result[p]
|
||||
endfor
|
||||
end
|
BIN
pearl/preferences/pearl_anglescan_tracker/preferences.pxp
Normal file
BIN
pearl/preferences/pearl_anglescan_tracker/preferences.pxp
Normal file
Binary file not shown.
BIN
pearl/preferences/pearl_elog/preferences.pxp
Normal file
BIN
pearl/preferences/pearl_elog/preferences.pxp
Normal file
Binary file not shown.
BIN
pearl/preferences/pearl_explorer/preferences.pxp
Normal file
BIN
pearl/preferences/pearl_explorer/preferences.pxp
Normal file
Binary file not shown.
2
pearl/preferences/readme.txt
Normal file
2
pearl/preferences/readme.txt
Normal file
@ -0,0 +1,2 @@
|
||||
default configuration and preferences for pearl procedures.
|
||||
copy the contents of this folder to "c:\users\{your_username}\AppData\Roaming\WaveMetrics\Igor Pro 6\Packages\".
|
BIN
pearl/tracker-sample-picture.png
Normal file
BIN
pearl/tracker-sample-picture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
Reference in New Issue
Block a user