new user distribution of PEARL procedures
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
*~
|
||||
~*
|
||||
*.bak
|
||||
*.ipfT*
|
||||
doc/html/*
|
||||
doc/latex/*
|
||||
+2381
File diff suppressed because it is too large
Load Diff
@@ -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>
|
||||
@@ -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
|
||||
}
|
||||
@@ -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/*
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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/).
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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\".
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
Reference in New Issue
Block a user