This commit is contained in:
2019-03-20 13:52:00 +01:00
parent 3084fe0510
commit 5db0f78aee
910 changed files with 191152 additions and 322 deletions

View File

@@ -0,0 +1,24 @@
I would like to acknowledge the people who have made a direct impact on the
Diffcalc project, knowingly or not, in terms of encouragement, suggestions,
criticism, bug reports, code contributions, and related projects.
Names are ordered alphabetically by surname.
.. If you add new entries, keep the list sorted by surname!
.. acks::
* Allesandro Bombardi
* Mark Booth
* W. R. Busing
* Steve Collins
* H. A. Levy
* Martin Lohmier
* Chris Nicklin
* Elias Vlieg --- writer of DIF software used as a model for Diffcalc
* Robert Walton
* H. You
Thank you!
Rob Walton

View File

@@ -0,0 +1,193 @@
# Makefile for documentation
# This makefile is a modified version of the makefile generated by the sphinx-quickstart command
# set environment for Diamond Light Source
ifeq ($(CONTEXT),diamond)
@echo "Environment variable CONTEXT=diamond, so setting build environment suitable for Diamond Light Source"
# get the location of a Python that has Sphinx installed
SPHINXBUILD?=$(shell module load python/2.7.2;which sphinx-build)
# set http proxy
export http_proxy?=http://wwwcache.rl.ac.uk:8080
export https_proxy?=https://wwwcache.rl.ac.uk:8080
endif
# optionally use Sphinx's "-W" options, which converts warnings into errors
ifeq ($(HALTONWARNING),y)
SPHINXEXTRAOPT=-W
else ifeq ($(HALTONWARNING),Y)
SPHINXEXTRAOPT=-W
else
SPHINXEXTRAOPT=
endif
### <-- start of Makefile contents generated by sphinx-quickstart --> ###
# You can set these variables from the command line.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
PAPER ?=
BUILDDIR ?= build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXEXTRAOPT) $(SPHINXOPTS) source
.PHONY: help helpfull pwd clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest pdfa4 pdfletter pdf all
help:
@echo
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " pdf to create pdf files for both A4- and Letter-sized paper"
@echo " pdfa4 to create pdf files for A4-sized paper"
@echo " pdfletter to create pdf files for Letter-sized paper"
@echo " all to build html and pdf"
@echo " clean to wipe the build directory"
@echo
@echo "You can use \`make helpfull' to get a full list of targets (not all have been tested)"
helpfull:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
pwd:
@echo
@echo "*******************************************************************************************************"
@echo "Current directory = "`pwd`
@echo "*******************************************************************************************************"
clean: pwd
-rm -rf $(BUILDDIR)/*
html: pwd
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/GDA.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/GDA.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/GDA"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/GDA"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex: pwd
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf: pwd
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
make -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
### <-- end of Makefile contents generated by sphinx-quickstart --> ###
pdfa4: pwd
rm -rf $(BUILDDIR)/latex
rm -rf $(BUILDDIR)/pdf-a4
make latexpdf PAPER=a4
mkdir $(BUILDDIR)/pdf-a4/
cp $(BUILDDIR)/latex/*.pdf $(BUILDDIR)/pdf-a4/.
@echo
@echo "Build finished for A4-sized PDFs. The PDF files are in $(BUILDDIR)/pdf-a4."
pdfletter: pwd
rm -rf $(BUILDDIR)/latex
rm -rf $(BUILDDIR)/pdf-letter
make latexpdf PAPER=letter
mkdir $(BUILDDIR)/pdf-letter/
cp $(BUILDDIR)/latex/*.pdf $(BUILDDIR)/pdf-letter/.
@echo
@echo "Build finished for Letter-sized PDFs. The PDF files are in $(BUILDDIR)/pdf-letter."
pdf: pwd pdfa4 pdfletter
all: pwd html pdf

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LAUNCH_CONFIGURATION_BUILD_SCOPE" value="${none}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="/usr/bin/make"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="${string_prompt:the target(s), which can be one or more of &quot;clean html pdfa4 pdfletter pdf all&quot; (all means &quot;html pdf&quot;).:clean all} HALTONWARNING=${string_prompt:treat warnings as errors (and halt the build):y} CONTEXT=${string_prompt:a keyword (typically the name of your organization) which identifies any setup required (can be omitted).:diamond}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc:diffcalc}/doc"/>
</launchConfiguration>

View File

@@ -0,0 +1,22 @@
.. [You1999] H. You. *Angle calculations for a '4S+2D' six-circle diffractometer.*
J. Appl. Cryst. (1999). **32**, 614-623. `(pdf link)
<http://journals.iucr.org/j/issues/1999/04/00/hn0093/hn0093.pdf>`__.
.. [Busing1967] W. R. Busing and H. A. Levy. *Angle calculations for 3- and 4-circle X-ray
and neutron diffractometers.* Acta Cryst. (1967). **22**, 457-464. `(pdf link)
<http://journals.iucr.org/q/issues/1967/04/00/a05492/a05492.pdf>`__.
.. [Vlieg1993] Martin Lohmeier and Elias Vlieg. *Angle calculations for a six-circle
surface x-ray diffractometer.* J. Appl. Cryst. (1993). **26**, 706-716. `(pdf link)
<http://journals.iucr.org/j/issues/1993/05/00/la0044/la0044.pdf>`__.
.. [Vlieg1998] Elias Vlieg. *A (2+3)-type surface diffractometer: mergence of the z-axis and
(2+2)-type geometries.* J. Appl. Cryst. (1998). **31**, 198-203. `(pdf link)
<http://journals.iucr.org/j/issues/1998/02/00/pe0028/pe0028.pdf>`__.
.. [Willmott2011] C. M. Schlepütz, S. O. Mariager, S. A. Pauli, R. Feidenhans'l and
P. R. Willmott. *Angle calculations for a (2+3)-type diffractometer: focus
on area detectors.* J. Appl. Cryst. (2011). **44**, 73-83. `(pdf link)
<http://journals.iucr.org/j/issues/2011/01/00/db5088/db5088.pdf>`__.

View File

@@ -0,0 +1,243 @@
# -*- coding: utf-8 -*-
#
# documentation build configuration file, created by
# sphinx-quickstart on Fri Apr 15 10:03:07 2011.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os, time
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.extlinks', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.pngmath', 'sphinx.ext.ifconfig']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Diffcalc'
copyright = u'2017-%s, Diamond Light Source' % time.strftime('%Y')
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '2.0'
# The full version, including alpha/beta/rc tags.
release = '2.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = []
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# html_theme_options = {
# 'sidebarbgcolor' : '#f2f2f2',
# 'sidebartextcolor': '#444a95',
# 'sidebarlinkcolor': '#0b0f40',
# }
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
import sphinx_rtd_theme
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
html_logo = 'diffcalc_web.png'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
#html_static_path = ['_static']
html_static_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
html_show_sourcelink = False
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
html_show_sphinx = False
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
latex_paper_size = 'a4'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('youmanual', 'diffcalc_user_guide.tex', u'Diffcalc User Guide',
u'Diamond Light Source', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page
latex_logo = 'diffcalc_pdf.png'
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
#man_pages = []
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {}
"""
Additional options for Diffcalc
"""
todo_include_todos = True
extlinks = {
'opengda_url' :('http://www.opengda.org/%s', None),
}
rst_prolog = """
.. |DLS| replace:: :abbr:`DLS (Diamond Light Source)`
"""

View File

@@ -0,0 +1,7 @@
********
Thanks
********
.. Do not add the names of contributors here. Instead, add them to the common list, so that they can be included in separate documents.
.. include:: ../../ACKS_diffcalc.rst

View File

@@ -0,0 +1,26 @@
########################
Diffcalc Developer Guide
########################
:Author: Rob Walton
:Contact: rob.walton (at) diamond (dot) ac (dot) uk
:Website: http://www.opengda.org/
.. rubric:: Diffcalc: A diffraction condition calculator for diffractometer control
.. toctree::
:maxdepth: 2
:numbered:
intro
package
quickstart_api
development
ACKS
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@@ -0,0 +1,24 @@
Development
===========
The files are kept here_ on github_. See bootcamp for an introduction to
using github. To contribute please fork the project. Otherwise you can make
a read-only clone or export.
Code format should follow pep8 guidelines. PyDev has a good pep8 checker.
To run the tests install nose_, change directory into the test folder and run::
$ nosetests
.......... ...
----------------------------------------------------------------------
Ran 3914 tests in 9.584s
OK (SKIP=15)
.. _here: https://github.com/DiamondLightSource/diffcalc
.. _github: https://github.com
.. _nose: http://nose.readthedocs.org/en/latest/
.. _pep8: http://www.python.org/dev/peps/pep-0008/

View File

@@ -0,0 +1,55 @@
Introduction
============
Diffcalc is a diffraction condition calculator used for controlling
diffractometers within reciprocal lattice space. It performs the same
task as the ``fourc``, ``sixc``, ``twoc``, ``kappa``, ``psic`` and
``surf`` macros from SPEC_.
Diffcalc's standard calculation engine is an implementation of
[You1999]_ . The first versions of Diffcalc were based on
[Vlieg1993]_ and [Vlieg1998]_ and a 'Vlieg' engine is still
available. The 'You' engine is more generic and the plan is to remove
the old 'Vlieg' engine once beamlines have been migrated. New users
should use the 'You' engine.
The foundations for this type of calculation were laid by by Busing &
Levi in their classic paper [Busing1967]_. Diffcalc's orientation
algorithm is taken from this paper. Busing & Levi also provided the
original definition of the coordinate frames and of the U and B
matrices used to describe a crystal's orientation and to convert between
Cartesian and reciprical lattice space.
Geometry plugins are used to adapt the six circle model used
internally by Diffcalc to apply to other diffractometers. These
contain a dictionary of the 'missing' angles which Diffcalc uses to
constrain these angles internally, and a methods to map from external
angles to Diffcalc angles and visa versa.
Options to use Diffcalc:
- **The User manual next to this developer manual or README file on github.**
- The :ref:`quickstart-api` section describes how to run up only
the core in Python_. This provides a base option for system integration.
Diffcalc will work with Python 2.7 or higher with numpy_, or with
Jython 2.7 of higher with Jama_.
.. [*] The very small 'Willmott' engine currently handles the case for
surface diffraction where the surface normal is held vertical
[Willmott2011]_. The 'You' engine handles this case fine, but
currently spins nu into an unhelpful quadrant. We hope to
remove the need for this engine soon.
.. _SPEC: http://www.certif.com/
.. _Python: http://python.org
.. _IPython: http://http://ipython.org/
.. _Jython: http://jython.org
.. _OpenGDA: http://opengda.org
.. _numpy: http://numpy.scipy.org/
.. _Jama: http://math.nist.gov/javanumerics/jama/
.. include:: ../../references

View File

@@ -0,0 +1,30 @@
Project Files & Directories
===========================
diffcalc
The main source package.
test
Diffcalcs unit-test package (use Nose_ to run them).
diffcmd
A spec-like openGDA emulator.
numjy
A *very* minimal implentation of numpy for jython. It supports only what
Diffcalc needs.
doc
The documentation is written in reStructuredText and can be compiled into
html and pdf using Python's `Sphinx <http://sphinx.pocoo.org>`_. With Sphinx
installed use ``make clean all`` from within the user and developer guide
folders to build the documentation.
startup
Starup scripts called by diffcmd or openGDA to startup diffcalc
model
Vrml models of diffractometers and a hokey script for animating then and
controlling them from diffcalc.
.. _Nose: http://readthedocs.org/docs/nose/en/latest/

View File

@@ -0,0 +1,266 @@
.. _quickstart-api:
.. warning:: This documentation is out of date. The README and the user doc has been updated recently. For now if you need help with API, please contact me at Diamond. -- Rob Walton
Quick-Start: Python API
=======================
This section describes how to run up only the core in Python or
IPython. This provides an API which could be used to integrate Diffcalc into an
existing data acquisition system; although the interface described in
the README would normally provide a better starting point.
For a full description of what Diffcalc does and how to use it please
see the 'Diffcalc user manual'.
Setup environment
-----------------
.. include:: quickstart_setup_environment
Start
-----
With Python start the sixcircle_api.py example startup script (notice
the -i and -m) and call `demo_all()`::
$ python -i -m startup.api.sixcircle
>>> demo_all()
IPython requires::
$ ipython -i startup/api/sixcircle.py
>>> demo_all()
Alternatively start Python or IPython and cut and paste lines from the rest of
this tutorial.
Configure a diffraction calculator
----------------------------------
By default some exceptions are handled in a way to make user interaction
friendlier. Switch this off with::
>>> import diffcalc.util
>>> diffcalc.util.DEBUG = True
To setup a Diffcalc calculator, first configure `diffcalc.settings` module::
>>> from diffcalc import settings
>>> from diffcalc.hkl.you.geometry import SixCircle
>>> from diffcalc.hardware import DummyHardwareAdapter
>>> settings.hardware = DummyHardwareAdapter(('mu', 'delta', 'gam', 'eta', 'chi', 'phi'))
>>> settings.geometry = SixCircle() # @UndefinedVariable
The hardware adapter is used by Diffcalc to read up the current angle
settings, wavelength and axes limits. It is primarily used to simplify
commands for end users. It could be dropped for this API use, but it
is also used for the important job of checking axes limits while
choosing solutions.
Geometry plugins are used to adapt the six circle model used
internally by Diffcalc to apply to other diffractometers. These
contain a dictionary of the 'missing' angles which Diffcalc internally
uses to constrain these angles, and a methods to map from
external angles to Diffcalc angles and visa versa.
Calling the API
---------------
The ``diffcalc.dc.dcyou`` module (and others) read the ``diffcalc.settings`` module when first
imported. Note that this means that changes to the settings will most likely
have no effect unless ``diffcalc.dc.dcyou`` is reloaded::
>>> import diffcalc.dc.dcyou as dc
This includes the two critical functions::
def hkl_to_angles(h, k, l, energy=None):
"""Convert a given hkl vector to a set of diffractometer angles
return angle tuple and virtual angles dictionary
"""
def angles_to_hkl(angle_tuple, energy=None):
"""Converts a set of diffractometer angles to an hkl position
Return hkl tuple and virtual angles dictionary
"""
``diffcalc.dc.dcyou`` also brings in all the commands from ``diffcalc.ub.ub``,
``diffcalc.hardware`` and ``diffcalc.hkl.you.hkl``. That is it includes all the
commands exposed in the top level namespace when diffcalc is used interactively::
>>> dir(dc)
['__builtins__', '__doc__', '__file__', '__name__', '__package__',
'_hardware','_hkl', '_ub', 'addref', 'allhkl', 'angles_to_hkl', 'c2th',
'calcub', 'checkub', 'clearref', 'con', 'constraint_manager', 'delref',
'diffcalc', 'editref', 'energy_to_wavelength', 'hardware', 'hkl_to_angles',
'hklcalc', 'lastub', 'listub', 'loadub', 'newub', 'rmub', 'saveubas', 'setcut',
'setlat', 'setmax', 'setmin', 'settings', 'setu', 'setub', 'showref',
'swapref', 'trialub', 'ub', 'ub_commands_for_help', 'ubcalc', 'uncon']
This doesn't form the best API to program against though, so it is best to
use the four modules more directly. The example below assumes you have
also imported::
>>> from diffcalc.ub import ub
>>> from diffcalc import hardware
>>> from diffcalc.hkl.you import hkl
Getting help
------------
To get help for the diffcalc angle calculations, the orientation phase, the
angle calculation phase, and the dummy hardware adapter commands::
>>> help(dc)
>>> help(ub)
>>> help(hkl)
>>> help(hardware)
Orientation
-----------
To orient the crystal for example (see the user manual for a fuller
tutorial) first find some reflections::
# Create a new ub calculation and set lattice parameters
ub.newub('test')
ub.setlat('cubic', 1, 1, 1, 90, 90, 90)
# Add 1st reflection (demonstrating the hardware adapter)
hardware.settings.hardware.wavelength = 1
ub.c2th([1, 0, 0]) # energy from hardware
settings.hardware.position = 0, 60, 0, 30, 0, 0 # mu del nu eta chi ph
ub.addref([1, 0, 0]) # energy & pos from hardware
# Add 2nd reflection (this time without the hardware adapter)
ub.c2th([0, 1, 0], 12.39842)
ub.addref([0, 1, 0], [0, 60, 0, 30, 0, 90], 12.39842)
To check the state of the current UB calculation::
>>> ub.ub()
UBCALC
name: test
n_phi: 0.00000 0.00000 1.00000 <- set
n_hkl: -0.00000 0.00000 1.00000
miscut: None
CRYSTAL
name: cubic
a, b, c: 1.00000 1.00000 1.00000
90.00000 90.00000 90.00000
B matrix: 6.28319 0.00000 0.00000
0.00000 6.28319 0.00000
0.00000 0.00000 6.28319
UB MATRIX
U matrix: 1.00000 0.00000 0.00000
0.00000 1.00000 0.00000
0.00000 0.00000 1.00000
U angle: 0
UB matrix: 6.28319 0.00000 0.00000
0.00000 6.28319 0.00000
0.00000 0.00000 6.28319
REFLECTIONS
ENERGY H K L MU DELTA GAM ETA CHI PHI TAG
1 12.398 1.00 0.00 0.00 0.0000 60.0000 0.0000 30.0000 0.0000 0.0000
2 12.398 0.00 1.00 0.00 0.0000 60.0000 0.0000 30.0000 0.0000 90.0000
And finally to check the reflections were specified acurately::
>>> dc.checkub()
ENERGY H K L H_COMP K_COMP L_COMP TAG
1 12.3984 1.00 0.00 0.00 1.0000 0.0000 0.0000
2 12.3984 0.00 1.00 0.00 -0.0000 1.0000 0.0000
Motion
------
Hkl positions and virtual angles can now be read up from angle
settings (the easy direction!)::
>>> dc.angles_to_hkl((0., 60., 0., 30., 0., 0.)) # energy from hardware
((1.0, 5.5511151231257827e-17, 0.0),
{'alpha': -0.0,
'beta': 3.5083546492674376e-15,
'naz': 0.0,
'psi': 90.0,
'qaz': 90.0,
'tau': 90.0,
'theta': 29.999999999999996})
Before calculating the settings to reach an hkl position (the trickier
direction) hardware limits must be set and combination of constraints
chosen. The constraints here result in a four circle like mode with a
vertical scattering plane and incident angle 'alpha' equal to the exit
angle 'beta'::
>>> hkl.con('qaz', 90)
! 2 more constraints required
qaz: 90.0000
>>> hkl.con('a_eq_b')
! 1 more constraint required
qaz: 90.0000
a_eq_b
>>> hkl.con('mu', 0)
qaz: 90.0000
a_eq_b
mu: 0.0000
To check the constraints::
>>> hkl.con()
DET REF SAMP
====== ====== ======
delta --> a_eq_b --> mu
alpha eta
--> qaz beta chi
naz psi phi
mu_is_nu
qaz: 90.0000
a_eq_b
mu: 0.0000
Type 'help con' for instructions
Limits can be set to help Diffcalc choose a solution::
>>> hardware.setmin('delta', 0) # used when choosing solution
Angles and virtual angles are then easily determined for a given hkl reflection::
>>> dc.hkl_to_angles(1, 0, 0) # energy from hardware
((0.0, 60.0, 0.0, 30.0, 0.0, 0.0),
{'alpha': -0.0,
'beta': 0.0,
'naz': 0.0,
'psi': 90.0,
'qaz': 90.0,
'tau': 90.0,
'theta': 30.0}
)

View File

@@ -0,0 +1,25 @@
Change directory to the diffcalc project (python adds the current
working directory to the path)::
$ cd diffcalc
$ ls
COPYING diffcalc doc example mock.py mock.pyc model numjy test
If using Python make sure numpy and diffcalc can be imported::
$ python
Python 2.7.2+ (default, Oct 4 2011, 20:06:09)
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy
>>> import diffcalc
If using Jython make sure Jama and diffcalc can be imported::
$ jython -Dpython.path=<diffcalc_root>:<path_to_Jama>/Jama-1.0.1.jar
Jython 2.2.1 on java1.5.0_11
Type "copyright", "credits" or "license" for more information.
>>> import Jama
>>> import diffcalc

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,26 @@
###################################
Diffcalc User and Developer Guide
###################################
:Author: Rob Walton
:Contact: rob.walton (at) diamond.ac.uk
:Web site: https://github.com/DiamondLightSource/diffcalc
.. rubric:: Diffcalc: A Diffraction Condition Calculator for Diffractometer Control
See also the `quickstart guide at github <https://github.com/DiamondLightSource/diffcalc/blob/master/README.rst>`_.
.. toctree::
:maxdepth: 2
:numbered:
youmanual
vliegmanual/contents
developer/contents
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@@ -0,0 +1,7 @@
********
Thanks
********
.. Do not add the names of contributors here. Instead, add them to the common list, so that they can be included in separate documents.
.. include:: ../../ACKS_diffcalc.rst

View File

@@ -0,0 +1,22 @@
#############################################
Diffcalc User Guide (Deprecated Vlieg Engine)
#############################################
:Author: Rob Walton
:Contact: rob.walton (at) diamond (dot) ac (dot) uk
:Website: http://www.opengda.org/
.. rubric:: Diffcalc: A diffraction condition calculator for diffractometer control
.. toctree::
:maxdepth: 2
:numbered:
vliegmanual
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,827 @@
Introduction
============
.. warning::
This manual refers to the 'Vlieg' calculation available in Diffcalc I. By
default Diffcalc II now uses its 'You' engine. This manual will be updated
soon. For now the developer guide shows how the new constraint system works.
This manual assumes that you are running Diffcalc within the external
framework of the GDA or Minigda and that Diffcalc has been configured
for the six circle diffractometer pictured here:
.. figure:: images/sixcircle_gamma_on_arm.*
:scale: 50
:align: center
Gamma-on-delta six-circle diffractometer, modified from Elias Vlieg
& Martin Lohmeier (1993)
Your Diffcalc configuration will have been customised for the geometry
of your diffractometer and possibly the types of experiment you
perform. For example: a five-circle diffractometer might be missing
the Gamma circle above, some six-circle modes and the option to fix
gamma that would otherwise exist in some modes.
The laboratory, crystal and reciprocal-lattice coordinate frames are
defined with respect to the beam and to gravity to be (for a cubic crystal):
.. figure:: images/fix.png
:align: center
Laboratory and illustratrive crystal coordinate frames for a cubic crystal
The crystal lattice basis vectors are defined within the Cartesian
crystal coordinate frame to be:
.. figure:: images/unit_cell.*
:align: center
:scale: 100
Unit cell defined in crystal coordinate frame
.. _overview:
Overview
========
The following assumes that the diffractometer has been properly levelled, aligned with
the beam and zeroed. See the `SPEC fourc manual <http://www.certif.com/spec_manual/fourc_4_2.html>`__.
Before moving in hkl space you must calculate a UB matrix by
specifying the crystal's lattice parameters (which define the B
matrix) and finding two reflections (from which the
U matrix can be inferred); and, optionally for surface-diffraction
experiments, determine how the surface of the crystal is oriented with
respect to the phi axis.
Once a UB matrix has been calculated, the diffractometer may be driven
in hkl coordinates. A valid diffractometer setting maps easily into a
single hkl value. However for a diffractometer with more than three circles
there are excess degrees of freedom when calculating a diffractometer
setting from an hkl value. Diffcalc provides modes for using up
the excess degrees of freedom.
Diffcalc does not perform scans directly. Instead, scannables that use
diffcalc to map between reciprocal lattice space and real
diffractometer settings are scanned using the Gda's (or minigda's)
generic scan mechanism.
Theory
------
Thanks to Elias Vlieg for sharing his dos based ``DIF`` software that
Diffcalc has borrowed heavily from. (See also the THANKS.txt file).
See the papers (included in ``docs/ref``):
* Busing & Levi (1966), "Angle Calculations for 3- and 4- Circle X-ray
and Neutron Diffractometers", Acta Cryst. 22, 457
* Elias Vlieg & Martin Lohmeier (1993), "Angle Calculations for a Six-Circle
Surface X-ray Diffractometer", J. Appl. Cryst. 26, 706-716
Getting Help
============
There are few commands to remember. If a command is called without
arguments, Diffcalc will prompt for arguments and provide sensible
defaults which can be chosen by pressing enter.
The ``helpub`` and ``helphkl`` commands provide help with the crystal
orientation and hkl movement phases of an experiment respectively::
>>> helpub
Diffcalc
--------
helpub ['command'] - lists all ub commands, or one if command is given
helphkl ['command'] - lists all hkl commands, or one if command is given
UB State
--------
newub 'name' - starts a new ub calculation with no lattice or
reflection list
loadub 'name' - loads an existing ub calculation: lattice and
reflection list
saveubas 'name' - saves the ubcalculation with a new name (other
changes autosaved)
ub - shows the complete state of the ub calculation
UB lattice
----------
setlat - prompts user to enter lattice parameters (in
Angstroms and Deg.)
setlat 'name' a - assumes cubic
setlat 'name' a b - assumes tetragonal
setlat 'name' a b c - assumes ortho
setlat 'name' a b c gam - assumes mon/hex with gam not equal to 90
setlat 'name' a b c alpha beta gamma - arbitrary
UB surface
----------
sigtau [sigma tau] - sets sigma and tau
UB reflections
--------------
showref - shows full reflection list
addref - add reflection
addref h k l ['tag'] - add reflection with hardware position and energy
addref h k l (p1,p2...pN) energy ['tag']- add reflection with specified position
and energy
delref num - deletes a reflection (numbered from 1)
swapref - swaps first two reflections used for calculating U
swapref num1 num2 - swaps two reflections (numbered from 1)
UB calculation
--------------
setu [((,,),(,,),(,,))] - manually set u matrix
setub ((,,),(,,),(,,)) - manually set ub matrix
calcub - (re)calculate u matrix from ref1 and ref2
checkub - show calculated and entered hkl values for reflections
>>> helphkl
Diffcalc
--------
helphkl [command] - lists all hkl commands, or one if command is given
helpub [command] - lists all ub commands, or one if command is given
Settings
--------
hklmode [num] - changes mode or shows current and available modes
and all settings
setalpha [num] - fixes alpha, or shows all settings if no num given
setgamma [num] - fixes gamma, or shows all settings if no num given
setbetain [num] - fixes betain, or shows all settings if no num given
setbetaout [num] - fixes betaout, or shows all settings if no num given
trackalpha [boolean] - determines wether alpha parameter will track alpha axis
trackgamma [boolean] - determines wether gamma parameter will track gamma axis
trackphi [boolean] - determines wether phi parameter will track phi axis
setsectorlim [omega_high omega_low phi_high phi_low]- sets sector limits
Motion
------
pos hkl [h k l] - move diffractometer to hkl, or read hkl position.
Use None to hold a value still
sim hkl [h k l] - simulates moving hkl
hkl - shows loads of info about current hkl position
pos sixc [alpha, delta, gamma, omega, chi, phi,]- move diffractometer to Eularian
position. Use None to hold a
value still
sim sixc [alpha, delta, gamma, omega, chi, phi,]- simulates moving sixc
sixc - shows loads of info about current sixc position
Diffcalc's Scannables
=====================
Please see :ref:`moving-in-hkl-space` and :ref:`scanning-in-hkl-space` for some relevant examples.
To list and show the current positions of your beamline's scannables
use ``pos`` with no arguments::
>>> pos
Results in:
**Energy and wavelength scannables**::
energy 12.3984
wl: 1.0000
**Diffractometer scannables**, as a group and in component axes (in
the real GDA these have limits)::
sixc: alpha: 0.0000 delta: 0.0000 gamma: 0.0000 omega: 0.0000 chi: 0.0000 phi: 0.0000
alpha: 0.0000
chi: 0.0000
delta: 0.0000
gamma: 0.0000
omega: 0.0000
phi: 0.0000
**Dummy counter**, which in this example simply counts at 1hit/s::
cnt: 0.0000
**Hkl scannable**, as a group and in component::
hkl: Error: No UB matrix
h: Error: No UB matrix
k: Error: No UB matrix
l: Error: No UB matrix
**Parameter scannables**, used in some modes, these provide a
scannable alternative to the series of ``fix`` commands described in
:ref:`moving-in-hkl-space`.::
alpha_par:0.00000
azimuth: ---
betain: ---
betaout: ---
gamma_par:0.00000
phi_par: ---
Note that where a parameter corresponds with a physical
diffractometer axis, it can also be set to track that axis
directly. See `Tracking axis`_ below.
Crystal orientation
===================
Before moving in hkl space you must calculate a UB matrix by
specifying the crystal's lattice parameters (which define the B
matrix) and finding two reflections (from which the
U matrix can be inferred); and, optionally for surface-diffraction
experiments, determine how the surface of the crystal is oriented with
respect to the phi axis (see :ref:`overview`).
Starting a UB calculation
-------------------------
A *UB-calculation* contains the description of the crystal-under-test,
any saved reflections, sigma & tau (both default to 0), and a B & UB
matrix pair if they have been calculated or manually specified.
Starting a new UB calculation will clear all of these.
Before starting a UB-calculation, the ``ub`` command used to summarise
the state of the current UB-calculation, will reflect that no
UB-calculation has been started::
>>> ub
No UB calculation started.
Wavelength: 1.239842
Energy: 10.000000
A new UB-calculation calculation may be started and lattice specified
explicitly::
>>> newub 'b16_270608'
>>> setlat 'xtal' 3.8401 3.8401 5.43072 90 90 90
or interactively::
>>> newub
calculation name: b16_270608
crystal name: xtal
a [1]: 3.8401
b [3.8401]: 3.8401
c [3.8401]: 5.43072
alpha [90]: 90
beta [90]: 90
gamma [90]: 90
where a,b and c are the lengths of the three unit cell basis vectors
in Angstroms, and alpha, beta and gamma the typically used angles
(defined in the figure above) in Degrees.
The ``ub`` command will show the state of the current UB-calculation
(and the current energy for reference)::
UBCalc: b16_270608
======
Crystal
-------
name: xtal
lattice: a ,b ,c = 3.84010, 3.84010, 5.43072
alpha, beta , gamma = 90.00000, 90.00000, 90.00000
reciprocal: b1, b2, b3 = 1.63620, 1.63620, 1.15697
beta1, beta2, beta3 = 1.57080, 1.57080, 1.57080
B matrix: 1.6362035642769 -0.0000000000000 -0.000000000000
0.0000000000000 1.6362035642769 -0.000000000000
0.0000000000000 0.0000000000000 1.156970955450
Reflections
-----------
energy h k l alpha delta gamma omega chi phi tag
UB matrix
---------
none calculated
Sigma: 0.000000
Tau: 0.000000
Wavelength: 1.000000
Energy: 12.398420
Specifying Sigma and Tau for surface diffraction experiments
------------------------------------------------------------
Sigma and Tau are used in modes that fix either the beam exit or entry angle with
respect to the crystal surface, or that keep the surface normal in the horizontal
laboratory plane. For non surface-diffraction experiments these can
safely be left at zero.
For surface diffraction experiments, where not only the crystal's
lattice planes must be oriented appropriately but so must the crystal's
optical surface, two angles _Tau_ and _Sigma_ define the orientation of
the surface with respect to the phi axis. Sigma is (minus) the amount of chi axis
rotation and Tau (minus) the amount of phi axis rotation needed to
move the surface normal parallel to the omega circle
axis. These angles are often determined by reflecting a laser from the
surface of the Crystal onto some thing and moving chi and tau until
the reflected spot remains stationary with movements of omega.
Use ``sigtau`` with no args to set interactively::
>>> pos chi -3.1
chi: -3.1000
>>> pos phi 10.0
phi: 10.0000
>>> sigtau
sigma, tau = 0.000000, 0.000000
chi, phi = -3.100000, 10.000000
sigma[ 3.1]: 3.1
tau[-10.0]: 10.0
Sigma and Tau can also be set explicitly::
>>>sigtau 0 0
Managing reflections
--------------------
The normal way to calculate a UB matrix is to find the position of **two**
reflections with known hkl values. Diffcalc allows many
reflections to be recorded but currently only uses the first two when
calculating a UB matrix.
Add reflection at current location
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is normal to first move to a reflection::
>>> pos en 10
en: 10.0000
>>> pos sixc [5.000, 22.790, 0.000, 1.552, 22.400, 14.255]
sixc: alpha: 5.0000 delta: 22.7900 gamma: 0.0000 omega: 1.5520 chi: 22.4000 phi: 14.2550
and then use the ``addref`` command either explicitly::
addref 1 0 1.0628 'optional_tag'
or interactively::
>>> addref
h: 1
k: 0
l: 1.0628
current pos[y]: y
tag: 'tag_string'
to add a reflection.
Add a reflection manually
~~~~~~~~~~~~~~~~~~~~~~~~~
If a reflection cannot be reached but its position is known (or if its
position has been previously determined), a reflection may be added
without first moving to it either explicitly::
>>> addref 0 1 1.0628 [5.000, 22.790, 0.000,4.575, 24.275, 101.320] 'optional_tag'
or interactively::
>>> addref
h: 0
k: 1
l: 1.0628
current pos[y]: n
alpha[5.000]:
delta[22.79]:
gamma[0.000]:
omega[1.552]: 4.575
chi[22.40]: 24.275
phi[14.25]: 101.320
en[9.998]:
tag: optional_tag2
Edit reflection list
~~~~~~~~~~~~~~~~~~~~
Use ``showref`` to show the reflection list::
>>> showref
energy h k l alpha delta gamma omega chi phi tag
1 9.999 1.00 0.00 1.06 5.0000 22.7900 0.0000 1.5520 22.4000 14.2550 1st
2 9.999 0.00 1.00 1.06 5.0000 22.7900 0.0000 4.5750 24.2750 101.32000 2nd
Use ``swapref`` to swap reflections::
>>> swapref 1 2
Recalculating UB matrix.
>>> showref
energy h k l alpha delta gamma omega chi phi tag
1 9.999 0.00 1.00 1.06 5.0000 22.7900 0.0000 4.5750 24.2750 101.3200 2nd
2 9.999 1.00 0.00 1.06 5.0000 22.7900 0.0000 1.5520 22.4000 14.2550 1st
Use ``delref`` to delete a reflection::
>>> delref 1
>>> showref
energy h k l alpha delta gamma omega chi phi tag
1 9.999 1.00 0.00 1.06 5.0000 22.7900 0.0000 1.5520 22.4000 14.2550 1st
Calculating a UB matrix
-----------------------
Unless a U or UB matrix has been manually specified, a new UB matrix
will be calculated after the second reflection has been found, or
whenever one of the first two reflections is changed.
Use the command ``calcub`` to force the UB matrix to be calculated
from the first two reflections.
If you have misidentified a reflection used for the orientation the
resulting UB matrix will be incorrect. Always use the ``checkub``
command to check that the computed values agree with the estimated values::
>>>checkub
energy h k l h_comp k_comp l_comp tag
1 9.9987 1.00 0.00 1.06 1.0000 0.0000 1.0628 1st
2 9.9987 0.00 1.00 1.06 -0.0329 1.0114 1.0400 2nd
Notice that the first reflection will always match, but that the
second will not match exactly. (The system of equations used to
calculate the U matrix is overdetermined and some information from the
second reflection is thrown away.)
Manually setting U and UB
-------------------------
*To help find the initial reflections* it may be useful to set the U
matrix manually---to the identity matrix for example. Use the ``setu``
command to do this. Once set the diffractometer may be driven to the
ideal location of a reflection and then the actual reflection
sought. Normally this would be done in the default mode, four-circle-bisecting, (see
:ref:`moving-in-hkl-space`). In the following example this has been done
by setting the alpha to 5 and leaving gamma at 0 (it would be normal
to leave alpha at 0)::
>>> hklmode 1
1) fourc bisecting
alpha: 0.0
gamma: 0.0
>>> setalpha 5
alpha: 0 --> 5.000000
>>> setu
row1[1 0 0]:
row2[0 1 0]:
row3[0 0 1]:
>>> sim hkl [1,0,1.0628] # Check it all makes sense
sixc would move to:
alpha : 5.00000 deg
delta : 22.79026 deg
gamma : 0.00000 deg
omega : 5.82845 deg
chi : 24.57658 deg
phi : 6.14137 deg
theta : 70702.991919
2theta : 23.303705
Bin : 6.969151
Bout : 6.969151
azimuth : 7.262472
>>> pos hkl [1,0,1.0628]
hkl: h: 1.00000 k: 0.00000 l: 1.06280
>>> # scan about to find actual reflection
>>> addref
h[0.0]: 1
k[0.0]: 0
l[0.0]: 1.0628
current pos[y]: y
tag: 'ref1'
>>>
There is currently no way to refine a manually specified U matrix by
inferring as much as possible from just one found reflection.
.. _moving-in-hkl-space:
Moving in hkl space
===================
Once a UB matrix has been calculated, the diffractometer may be driven
in hkl coordinates. A given diffractometer setting maps easily into a
single hkl value. However for a diffractometer with more than three circles
there are excess degrees of freedom when calculating a diffractometer
setting from an hkl value. Diffcalc provides many for using up
the excess degrees of freedom.
By default Diffcalc selects four-circle bisecting mode (see below).
Note that to play along with the following ``run`` the file in
``example/session/sixc_example.py`` to configure the UB-calculation.
Modes
-----
Use the command ``hklmode`` to summarise the state of Diffcalc's angle
calculator. It shows a list the available modes for your
diffractometer and the parameters that must be fixed for each, the
current mode and the current parameter settings::
>>> hklmode
Available modes:
0) fourc fixed-bandlw (alpha, gamma, blw) (Not impl.)
1) fourc bisecting (alpha, gamma)
2) fourc incoming (alpha, gamma, betain)
3) fourc outgoing (alpha, gamma, betaout)
4) fourc azimuth (alpha, gamma, azimuth) (Not impl.)
5) fourc fixed-phi (alpha, gamma, phi) (Not impl.)
10) fivec bisecting (gamma)
11) fivec incoming (gamma, betain)
12) fivec outgoing (gamma, betaout)
13) fivec bisecting (alpha)
14) fivec incoming (alpha, betain)
15) fivec outgoing (alpha, betaout)
20) zaxis bisecting ()
21) zaxis incoming (betain)
22) zaxiz outgoing (betaout)
Current mode:
1) fourc bisecting
Parameters:
alpha: 0.0
gamma: 0.0
betain: --- (not relevant in this mode)
betaout: --- (not relevant in this mode)
azimuth: --- (not relevant in this mode)
phi: --- (not relevant in this mode)
blw: --- (not relevant in this mode)
Note that 'Not impl.' is short for 'not implemented'. Standby.
Your output may differ. For example:
- When listed with a typical five-circle diffractometer with no gamma
circle: the fourc modes will have no gamma parameter to fix
(actually it will have been fixed under the covers to 0), there
will be no gamma or alpha parameters to fix in the five circle
modes (again, under the covers gamma will have been fixed) and
there will be no zaxis modes (as these require six circles, or an
actual z-axis diffractometer).
- When listed with a typical four-circle diffractometer with no alpha
or gamma circle, the four-circle modes will appear with no alpha or
gamma parameters (again, they are fixed under the covers), and
there will be no five circle or zaxis modes.
To change the current mode, call ``hklmode`` with an argument::
>>> hklmode 2
2) fourc incoming
alpha: 0.0
gamma: 0.0
betain: ---
(The dashes next to the betain parameter indicate that a parameter
has not yet been set.)
Mode parameters
---------------
A parameter can be set using either one of the series of {{{set}}}
commands, by moving one of the scannables associated with each
parameter or, where appropriate, by asking that a parameter track an
axis.
Set commands
~~~~~~~~~~~~
Use the series of commands ``set<param_name>`` to set a parameter::
>>> setalpha 3
alpha: 0 --> 3.000000
>>> setbetain 5
WARNING: The parameter betain is not used in mode 1
betain: --- --> 5.000000
>>> setalpha # With no args, the current value is displayed
alpha: 3
>>> setbetain
betain: ---
Parameter Scannables
~~~~~~~~~~~~~~~~~~~~
In most installations there will be a scannable for each parameter. In
this example installation, the parameters which correspond to physical
axes have had '_par' appended to their names to prevent clashes. These
may be used to change a parameter either with the ``pos`` command or
by using them within a scan (see :ref:`scanning-in-hkl-space`).::
>>> pos betain
betain: 0.00000
>>> pos betain 5
betain: 5.00000
>>> setbetain
betain: 5
>>> pos alpha_par
alpha_par:3.00000
>>> setalpha
alpha: 3
Tracking Axis
~~~~~~~~~~~~~
Where a parameter matches an axis name, that parameter may be set to
track that axis::
>>> pos alpha
alpha: 5.0000
>>> hklmode 1
1) fourc bisecting
alpha: 0.0
gamma: 0.0
>>> trackalpha
alpha: 5
>>> pos alpha
alpha: 6.0000
>>> hklmode 1
1) fourc bisecting
alpha: 6.0 (tracking physical axis)
gamma: 0.0
Although convenient, there is a danger with this method that in
geometries where the axes are built from other axes (such as in a
kappa geometry), the position of an axis may drift slightly during a
scan.
Sectors
-------
When mapping from reciprocal lattice space to a set of diffractometer
settings, there is normally a choice of solutions for the sample
orientation. The selected sector mode will determine which solution is
used. There is currently only one sector mode:
Sector mode: Find first solution within sector limits
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In this sector mode, taken from 'DIF', the first solution found within
the 'sector limits' is chosen. These are different from the physical
or software limits on the axes and can be checked/modified using
``setsectorlim``::
>>> setsectorlim
omega_high[270]:
omega_low[-90]:
phi_high[180]:
phi_low[-180]:
The hkl scannable
-----------------
Once a UB matrix has been calculated, a mode chosen and parmeters set,
use the hkl scannable to move to a point in reciprocal lattice space::
>>> pos hkl [1,0,0]
hkl: h: 1.00000 k: -0.00000 l: -0.00000
>>> pos sixc
sixc: alpha: 3.0000 delta: 17.2252 gamma: 4.0000 omega: 7.5046 chi: -24.6257 phi: 4.8026
>>> pos hkl
hkl: h: 1.00000 k: -0.00000 l: -0.00000
>>> hkl
hkl:
h : 1.000000
k : -0.000000
l : -0.000000
2theta : 18.582618
Bin : -0.387976
Bout : -0.387976
azimuth : 1.646099
Notice that typing ``hkl`` will also display some virtual angles (such
as twotheta and Bin), that checking the position with ``pos hkl`` will
not.
To get this extra information into a scan use the scannable hklverbose
instead of hkl::
>>> pos hklverbose [1,0,0]
hklverbose: h: 1.00000 k: -0.00000 l: -0.00000 2theta : 18.582618 Bin : -0.387976
Bout :-0.387976 azimuth : 1.646099
The ``sim`` command will report, without moving the diffractometer,
where an hkl position would be found::
>>> sim hkl [1,0,0]
sixc would move to:
alpha : 3.00000 deg
delta : 17.22516 deg
gamma : 4.00000 deg
omega : 7.50461 deg
chi : -24.62568 deg
phi : 4.80260 deg
theta : 70702.991919
2theta : 18.582618
Bin : -0.387976
Bout : -0.387976
azimuth : 1.646099
Moving out of range
~~~~~~~~~~~~~~~~~~~
Not every hkl position can be reached::
>>> pos hkl [10,10,10]
Exception: Could not compute delta for this hkl position
The diffractometer scannable (sixc)
-----------------------------------
We've seen this before, but it also works with sim::
gda>>>sim sixc [3, 17.22516, 4, 7.50461, -24.62568, 4.80260]
hkl would move to:
h : 1.000000
k : 0.000000
l : -0.000000
.. _scanning-in-hkl-space:
Scanning in hkl space
=====================
All scans described below use the same generic scanning mechanism
provided by the GDA system or by minigda. Here are some examples.
Fixed hkl scans
---------------
In a 'fixed hkl scan' something (such as energy or Bin) is scanned,
and at each step hkl is 'moved' to keep the sample and detector
aligned. Also plonk the diffractometer scannable (sixc) on there with no
destination to monitor what is actually happening and then
throw on a detector (cnt) with an exposure time if appropriate::
>>> #scan scannable_name start stop step [scannable_name [pos or time]]..
>>> scan en 9 11 .5 hkl [1,0,0] sixc cnt 1
>>> scan en 9 11 .5 hklverbose [1,0,0] sixc cnt 1
>>> scan betain 4 5 .2 hkl [1,0,0] sixc cnt 1
>>> scan alpha_par 0 10 2 hkl [1,0,0] sixc cnt 1
>>> trackalpha
>>> scan alpha 0 10 2 hkl [1,0,0] sixc cnt 1 # Equivalent to last scan
Scanning hkl
------------
Hkl, or one component, may also be scanned directly::
>>> scan h .8 1.2 .1 hklverbose sixc cnt 1
At each step, this will read the current hkl position, modify the h
component and then move to the resulting vector. There is a danger
that with this method k and l may drift. To get around this the start,
stop and step values may also be specified as vectors. So for example::
>>> scan hkl [1,0,0] [1,.3,0] [1,0.1,0] cnt1
is equivilant to::
>>> pos hkl [1,0,0]
>>> scan k 0 .3 .1 cnt1
but will not suffer from drifting. This method also allows scans along
any direction in hkl space to be performed.
Multidimension scans
--------------------
Two and three dimensional scans::
>>> scan en 9 11 .5 h .9 1.1 .2 hklverbose sixc cnt 1
>>> scan h 1 3 1 k 1 3 1 l 1 3 1 hkl cnt 1
Good luck --- RobW

View File

@@ -0,0 +1,786 @@
################################
Diffcalc User Guide (You Engine)
################################
.. rubric:: Diffcalc: A diffraction condition calculator for diffractometer control
:Author: Rob Walton
:Contact: rob.walton (at) diamond (dot) ac (dot) uk
:Website: https://github.com/DiamondLightSource/diffcalc
.. toctree::
:maxdepth: 2
:numbered:
See also the `quickstart guide at github <https://github.com/DiamondLightSource/diffcalc/blob/master/README.rst>`_
Introduction
============
This manual assumes that you are running Diffcalc within OpenGDA or have started
it using IPython. It assumes that Diffcalc has been configured for the six
circle diffractometer pictured here:
.. figure:: youmanual_images/4s_2d_diffractometer.png
:scale: 100
:align: center
4s + 2d six-circle diffractometer, from H.You (1999)
Your Diffcalc configuration may have been customised for the geometry of your
diffractometer and possibly the types of experiment you perform. For example, a
five-circle diffractometer might be missing the nu circle above.
The laboratory frame is shown above. With all settings at zero as shown the
crystal cartesian frame aligns with the laboratory frame. Therefor a cubic
crystal mounted squarely in a way that the U matrix (defined below) is unitary
will have h||a||x, k||b||y & l||c||z, crystal and reciprocal-lattice coordinate
frames are defined with respect to the beam and to gravity to be (for a cubic
crystal):
Overview
========
The following assumes that the diffractometer has been properly leveled, aligned
with the beam and zeroed. See the `SPEC fourc manual
<http://www.certif.com/spec_manual/fourc_4_2.html>`__.
Before moving in hkl space you must calculate a UB matrix by specifying the
crystal's lattice parameters (which define the B matrix) and finding two
reflections (from which the U matrix defining any mismount can be inferred);
and, optionally for surface-diffraction experiments, determine how the surface
of the crystal is oriented with respect to the phi axis.
Once a UB matrix has been calculated, the diffractometer may be driven in hkl
coordinates. A valid diffractometer setting maps easily into a single hkl value.
However for a diffractometer with more than three circles there are excess
degrees of freedom when calculating a diffractometer setting from an hkl value.
Diffcalc provides modes for using up the excess degrees of freedom.
Diffcalc does not perform scans directly. Instead, Scannables that use diffcalc
to map between reciprocal lattice space and real diffractometer settings are
scanned using the Gda's (or minigda's) generic scan mechanism.
Theory
------
Thanks to Elias Vlieg for sharing his dos based ``DIF`` software that Diffcalc
has borrowed heavily from. The version of Diffcalc described here is based on papers by
pHH. You. [You1999]_ and Busing & Levy [Busing1967]_. (See also the THANKS.txt file.)
Getting Help
============
There are few commands to remember. If a command is called without
arguments in some cases Diffcalc will prompt for arguments and provide sensible
defaults which can be chosen by pressing enter.
**Orientation**. The ``helpub`` command lists all commands related with crystal
orientation and the reference vector (often used with surfaces). See the
`Orientation Commands`_ section at the end of this manual::
>>> help ub
...
**HKL movement**. The ``help hkl`` list all commands related to moving in reciprocal-lattice
space. See the `Motion Commands`_ section at the end of this manual::
>>> help hkl
...
Call help on any command. e.g.::
>>> help loadub
loadub (diffcalc command):
loadub 'name' | num -- load an existing ub calculation
Diffcalc's Scannables
=====================
To list and show the current positions of your beamline's scannables
use ``pos`` with no arguments::
>>> pos
Results in:
**Energy and wavelength scannables**::
energy 12.3984
wl: 1.0000
**Diffractometer scannables**, as a group and in component axes (in
the real GDA these have limits)::
sixc: mu: 0.0000 delta: 0.0000 gamma: 0.0000 omega: 0.0000 chi: 0.0000 phi: 0.0000
mu: 0.0000
chi: 0.0000
delta: 0.0000
gamma: 0.0000
omega: 0.0000
phi: 0.0000
**Dummy counter**, which in this example simply counts at 1hit/s::
ct: 0.0000
**Hkl scannable**, as a group and in component::
hkl: Error: No UB matrix
h: Error: No UB matrix
k: Error: No UB matrix
l: Error: No UB matrix
**Parameter scannables**, used in some modes, these provide a
scannable alternative to the `Motion`_ section. Some constrain of
these constrain virtual angles::
alpha: ---
beta: ---
naz: ---
psi: ---
qaz: ---
and some constrain physical angles::
phi_con: ---
chi_con: ---
delta_con:---
eta_con: ---
gam_con: ---
mu_con: ---
Crystal orientation
===================
Before moving in hkl space you must calculate a UB matrix by specifying the
crystal's lattice parameters (which define the B matrix) and finding two
reflections (from which the U matrix can be inferred); and, optionally for
surface-diffraction experiments, determine how the surface of the crystal is
oriented with respect to the phi axis.
Start a new UB calculation
--------------------------
A *UB calculation* contains the description of the crystal-under-test,
any saved reflections, reference angle direction, and a B & UB
matrix pair if they have been calculated or manually specified.
Starting a new UB calculation will clear all of these.
Before starting a UB-calculation, the ``ub`` command used to summarise
the state of the current UB-calculation, will reflect that no
UB-calculation has been started::
>>> ub
<<< No UB calculation started >>>
A new UB-calculation calculation may be started and lattice specified
explicitly::
>>> newub 'example'
>>> setlat '1Acube' 1 1 1 90 90 90
or interactively::
>>> newub
calculation name: example
crystal name: 1Acube
a [1]: 1
b [1]: 1
c [1]: 1
alpha [90]: 90
beta [90]: 90
gamma [90]: 90
where a,b and c are the lengths of the three unit cell basis vectors
in Angstroms, and alpha, beta and gamma are angles in Degrees.
The ``ub`` command will show the state of the current UB-calculation
(and the current energy for reference)::
>>> ub
UBCALC
name: example
n_phi: 0.00000 0.00000 1.00000 <- set
CRYSTAL
name: 1Acube
a, b, c: 1.00000 1.00000 1.00000
90.00000 90.00000 90.00000
B matrix: 6.28319 0.00000 0.00000
0.00000 6.28319 0.00000
0.00000 0.00000 6.28319
UB MATRIX
<<< none calculated >>>
REFLECTIONS
<<< none specified >>>
Load a UB calculation
---------------------
To load the last used UB-calculation::
>>> lastub
Loading ub calculation: 'mono-Si'
To load a previous UB-calculation::
>>> listub
UB calculations in: /Users/walton/.diffcalc/i16
0) mono-Si 15 Feb 2017 (22:32)
1) i16-32 13 Feb 2017 (18:32)
>>> loadub 0
Generate a U matrix from two reflections
----------------------------------------
The normal way to calculate a U matrix is to find the position of **two**
reflections with known hkl values. Diffcalc allows many reflections to be
recorded but currently only uses the first two when calculating a UB matrix.
Find U matrix from two reflections::
>>> pos wl 1
wl: 1.0000
>>> c2th [0 0 1]
59.99999999999999
>>> pos sixc [0 60 0 30 90 0]
sixc: mu: 0.0000 delta: 60.0000 gam: 0.0000 eta: 30.0000 chi: 90.0000 phi: 0.0000
>>> addref [0 0 1]
>>> pos sixc [0 90 0 45 45 90]
sixc: mu: 0.0000 delta: 90.0000 gam: 0.0000 eta: 45.0000 chi: 45.0000 phi: 90.0000
>>> addref [0 1 1]
Calculating UB matrix.
Check that it looks good::
>>> checkub
ENERGY H K L H_COMP K_COMP L_COMP TAG
1 12.3984 0.00 0.00 1.00 0.0000 0.0000 1.0000
2 12.3984 0.00 1.00 1.00 0.0000 1.0000 1.0000
Generate a U matrix from one reflection
---------------------------------------
To estimate based on first reflection only::
>>> trialub
resulting U angle: 0.00000 deg
resulting U axis direction: [-1.00000, 0.00000, 0.00000]
Recalculating UB matrix from the first reflection only.
NOTE: A new UB matrix will not be automatically calculated when the orientation reflections are modified.
Manually specify U matrix
-------------------------
Set U matrix manually (pretending sample is squarely mounted)::
>>> setu [[1 0 0] [0 1 0] [0 0 1]]
Recalculating UB matrix.
NOTE: A new UB matrix will not be automatically calculated when the orientation reflections are modified.
Edit reflection list
--------------------
Use ``showref`` to show the reflection list::
>>> showref
ENERGY H K L MU DELTA GAM ETA CHI PHI TAG
1 12.398 0.00 0.00 1.00 0.0000 60.0000 0.0000 30.0000 90.0000 0.0000
2 12.398 0.00 1.00 1.00 0.0000 90.0000 0.0000 45.0000 45.0000 90.0000
Use ``swapref`` to swap reflections::
>>> swapref 1 2
Not calculating UB matrix as it has been manually set. Use 'calcub' to explicitly recalculate it.
Recalculating UB matrix.
Use ``delref`` to delete a reflection::
>>> delref 1
Calculate a UB matrix
---------------------
Unless a U or UB matrix has been manually specified, a new UB matrix will be
calculated after the second reflection has been found, or whenever one of the
first two reflections is changed.
Use the command ``calcub`` to force the UB matrix to be calculated from the
first two reflections.
If you have misidentified a reflection used for the orientation the
resulting UB matrix will be incorrect. Always use the ``checkub``
command to check that the computed values agree with the estimated values::
>>> checkub
ENERGY H K L H_COMP K_COMP L_COMP TAG
1 12.3984 0.00 1.00 1.00 0.0000 1.0000 1.0000
2 12.3984 0.00 0.00 1.00 0.0000 0.0000 1.0000
Set the reference vector
-------------------------
When performing surface experiments the reference vector should be set normal
to the surface. It can also be used to define other directions within the crystal
with which we want to orient the incident or diffracted beam.
By default the reference vector is set parallel to the phi axis. That is,
along the z-axis of the phi coordinate frame.
The `ub` command shows the current reference vector, along with any inferred
miscut, at the top its report (or it can be shown by calling ``setnphi`` or
``setnhkl'`` with no args)::
>>> ub
...
n_phi: 0.00000 0.00000 1.00000 <- set
n_hkl: -0.00000 0.00000 1.00000
miscut: None
...
The ``<- set`` label here indicates that the reference vector is set in the phi
coordinate frame. In this case, therefor, its direction in the crystal's
reciprocal lattice space is inferred from the UB matrix.
To set the reference vector in the phi coordinate frame use::
>>> setnphi [0 0 1]
...
This is useful if the surface normal has be found with a laser or by x-ray
occlusion. This vector must currently be manually calculated from the sample
angle settings required to level the surface (sigma and tau commands on the
way).
To set the reference vector in the crystal's reciprocal lattice space use (this
is a quick way to determine the surface orientation if the surface is known to
be cleaved cleanly along a known axis)::
>>> setnhkl [0 0 1] ...
Motion
======
Once a UB matrix has been calculated, the diffractometer may be driven
in hkl coordinates. A given diffractometer setting maps easily into a
single hkl value. However for a diffractometer with more than three circles
there are excess degrees of freedom when calculating a diffractometer
setting from an hkl value. Diffcalc provides many for using up
the excess degrees of freedom.
By default Diffcalc selects no mode.
Constraining solutions for moving in hkl space
----------------------------------------------
To get help and see current constraints::
>>> help con
...
>>> con
DET REF SAMP
------ ------ ------
delta a_eq_b mu
gam alpha eta
qaz beta chi
naz psi phi
mu_is_gam
! 3 more constraints required
Type 'help con' for instructions
Three constraints can be given: zero or one from the DET and REF columns and the
remainder from the SAMP column. Not all combinations are currently available.
Use ``help con`` to see a summary if you run into troubles.
To configure four-circle vertical scattering::
>>> con gam 0 mu 0 a_eq_b
gam : 0.0000
a_eq_b
mu : 0.0000
In the following the *scattering plane* is defined as the plane including the
scattering vector, or momentum transfer vector, and the incident beam.
**DETECTOR COLUMN:**
- **delta** - physical delta setting (vertical detector motion) *del=0 is equivalent to qaz=0*
- **gam** - physical gamma setting (horizontal detector motion) *gam=0 is equivalent to qaz=90*
- **qaz** - azimuthal rotation of scattering vector (about the beam, from horizontal)
- **naz** - azimuthal rotation of reference vector (about the beam, from horizontal)
**REFERENCE COLUMN:**
- **alpha** - incident angle to surface (if reference is normal to surface)
- **beta** - exit angle from surface (if reference is normal to surface)
- **psi** - azimuthal rotation about scattering vector of reference vector (from scattering plane)
- **a_eq_b** - bisecting mode with alpha=beta. *Equivalent to psi=90*
**SAMPLE COLUMN:**
- **mu, eta, chi & phi** - physical settings
- **mu_is_gam** - force mu to follow gamma (results in a 5-circle geometry)
Diffcalc will report two other (un-constrainable) virtual angles:
- **theta** - half of 2theta, the angle through the diffracted beam bends
- **tau** - longitude of reference vector from scattering vector (in scattering plane)
Example constraint modes
------------------------
There is sometimes more than one way to get the same effect.
**Vertical four-circle mode**::
>>> con gam 0 mu 0 a_eq_b # or equivalently:
>>> con qaz 90 mu 0 a_eq_b
>>> con alpha 1 # replaces a_eq_b
**Horizontal four-circle mode**::
>>> con del 0 eta 0 alpha 1 # or equivalently:
>>> con qaz 0 mu 0 alpha 1
**Surface vertical mode**::
>>> con naz 90 mu 0 alpha 1
**Surface horizontal mode**::
>>> con naz 0 eta 0 alpha 1
**Z-axis mode (surface horizontal)**::
>>> con chi (-sigma) phi (-tau) alpha 1
where sigma and tau are the offsets required in chi and phi to bring the surface
normal parallel to eta. Alpha will determine mu directly leaving eta to orient
the planes. Or::
>>> con naz 0 phi 0 alpha 1 # or any another sample angle
**Z-axis mode (surface vertical)**::
>>> con naz 0 phi 0 alpha 1 # or any another sample angle
Changing constrained values
---------------------------
Once constraints are chosen constrained values may be changed directly::
>>> con mu 10
gam : 0.0000
a_eq_b
mu : 10.0000
or via the associated scannable::
>>> pos mu_con 10
mu_con: 10.00000
Configuring limits and cuts
---------------------------
Diffcalc maintains its own limits on axes. These limits will be used when
choosing solutions. If more than one detector solution is exists Diffcalc will
ask you to reduce the the limits until there is only one. However if more than
one solution for the sample settings is available it will choose one base on
heuristics.
Use the ``hardware`` command to see the current limits and cuts::
>>> hardware
mu (cut: -180.0)
delta (cut: -180.0)
gam (cut: -180.0)
eta (cut: -180.0)
chi (cut: -180.0)
phi (cut: 0.0)
Note: When auto sector/transforms are used,
cuts are applied before checking limits.
To set the limits::
>>> setmin delta -1
>>> setmax delta 145
To set a cut::
>>> setcut phi -180
This causes requests to move phi to be between the configured -180 and +360
degress above this. i.e. it might dive to -10 degrees rather than 350.
Moving in hkl space
-------------------
Configure a mode, e.g. four-circle vertical::
>>> con gam 0 mu 0 a_eq_b
gam : 0.0000
a_eq_b
mu : 0.0000
Simulate moving to a reflection::
>>> sim hkl [0 1 1]
sixc would move to:
mu : 0.0000
delta : 90.0000
gam : 0.0000
eta : 45.0000
chi : 45.0000
phi : 90.0000
alpha : 30.0000
beta : 30.0000
naz : 35.2644
psi : 90.0000
qaz : 90.0000
tau : 45.0000
theta : 45.0000
Move to reflection::
>>> pos hkl [0 1 1]
hkl: h: 0.00000 k: 1.00000 l: 1.00000
>>> pos sixc
sixc: mu: 0.0000 delta: 90.0000 gam: 0.0000 eta: 45.0000 chi: 45.0000 phi: 90.0000
Simulate moving to a location::
>>> pos sixc [0 60 0 30 90 0]
sixc: mu: 0.0000 delta: 60.0000 gam: 0.0000 eta: 30.0000 chi: 90.0000 phi: 0.0000
Scanning in hkl space
=====================
All scans described below use the same generic scanning mechanism
provided by the GDA system or by minigda. Here are some examples.
Fixed hkl scans
---------------
In a 'fixed hkl scan' something (such as energy or Bin) is scanned,
and at each step hkl is 'moved' to keep the sample and detector
aligned. Also plonk the diffractometer scannable (sixc) on there with no
destination to monitor what is actually happening and then
throw on a detector (ct) with an exposure time if appropriate::
>>> #scan scannable_name start stop step [scannable_name [pos or time]]..
>>> scan en 9 11 .5 hkl [1 0 0] sixc ct 1
>>> scan en 9 11 .5 hklverbose [1 0 0] sixc ct 1
>>> scan betain 4 5 .2 hkl [1 0 0] sixc ct 1
>>> scan alpha_par 0 10 2 hkl [1 0 0] sixc ct 1
Scanning hkl
------------
Hkl, or one component, may also be scanned directly::
>>> scan h .8 1.2 .1 hklverbose sixc ct 1
At each step, this will read the current hkl position, modify the h
component and then move to the resulting vector. There is a danger
that with this method k and l may drift. To get around this the start,
stop and step values may also be specified as vectors. So for example::
>>> scan hkl [1 0 0] [1 .3 0] [1 0.1 0] ct1
is equivilant to::
>>> pos hkl [1 0 0]
>>> scan k 0 .3 .1 ct1
but will not suffer from drifting. This method also allows scans along
any direction in hkl space to be performed.
Multidimension scans
--------------------
Two and three dimensional scans::
>>> scan en 9 11 .5 h .9 1.1 .2 hklverbose sixc ct 1
>>> scan h 1 3 1 k 1 3 1 l 1 3 1 hkl ct 1
Commands
========
Orientation Commands
--------------------
+-----------------------------+---------------------------------------------------+
| **STATE** |
+-----------------------------+---------------------------------------------------+
| **-- newub** {'name'} | start a new ub calculation name |
+-----------------------------+---------------------------------------------------+
| **-- loadub** 'name' | num | load an existing ub calculation |
+-----------------------------+---------------------------------------------------+
| **-- lastub** | load the last used ub calculation |
+-----------------------------+---------------------------------------------------+
| **-- listub** | list the ub calculations available to load |
+-----------------------------+---------------------------------------------------+
| **-- rmub** 'name'|num | remove existing ub calculation |
+-----------------------------+---------------------------------------------------+
| **-- saveubas** 'name' | save the ub calculation with a new name |
+-----------------------------+---------------------------------------------------+
| **LATTICE** |
+-----------------------------+---------------------------------------------------+
| **-- setlat** | interactively enter lattice parameters (Angstroms |
| | and Deg) |
+-----------------------------+---------------------------------------------------+
| **-- setlat** name a | assumes cubic |
+-----------------------------+---------------------------------------------------+
| **-- setlat** name a b | assumes tetragonal |
+-----------------------------+---------------------------------------------------+
| **-- setlat** name a b c | assumes ortho |
+-----------------------------+---------------------------------------------------+
| **-- setlat** name a b c | assumes mon/hex with gam not equal to 90 |
| gamma | |
+-----------------------------+---------------------------------------------------+
| **-- setlat** name a b c | arbitrary |
| alpha beta gamma | |
+-----------------------------+---------------------------------------------------+
| **-- c2th** [h k l] | calculate two-theta angle for reflection |
+-----------------------------+---------------------------------------------------+
| **REFERENCE (SURFACE)** |
+-----------------------------+---------------------------------------------------+
| **-- setnphi** {[x y z]} | sets or displays n_phi reference |
+-----------------------------+---------------------------------------------------+
| **-- setnhkl** {[h k l]} | sets or displays n_hkl reference |
+-----------------------------+---------------------------------------------------+
| **REFLECTIONS** |
+-----------------------------+---------------------------------------------------+
| **-- showref** | shows full reflection list |
+-----------------------------+---------------------------------------------------+
| **-- addref** | add reflection interactively |
+-----------------------------+---------------------------------------------------+
| **-- addref** [h k l] | add reflection with current position and energy |
| {'tag'} | |
+-----------------------------+---------------------------------------------------+
| **-- addref** [h k l] (p1, | add arbitrary reflection |
| .., pN) energy {'tag'} | |
+-----------------------------+---------------------------------------------------+
| **-- editref** num | interactively edit a reflection |
+-----------------------------+---------------------------------------------------+
| **-- delref** num | deletes a reflection (numbered from 1) |
+-----------------------------+---------------------------------------------------+
| **-- clearref** | deletes all the reflections |
+-----------------------------+---------------------------------------------------+
| **-- swapref** | swaps first two reflections used for calulating U |
| | matrix |
+-----------------------------+---------------------------------------------------+
| **-- swapref** num1 num2 | swaps two reflections (numbered from 1) |
+-----------------------------+---------------------------------------------------+
| **UB MATRIX** |
+-----------------------------+---------------------------------------------------+
| **-- checkub** | show calculated and entered hkl values for |
| | reflections |
+-----------------------------+---------------------------------------------------+
| **-- setu** | manually set u matrix |
| {[[..][..][..]]} | |
+-----------------------------+---------------------------------------------------+
| **-- setub** | manually set ub matrix |
| {[[..][..][..]]} | |
+-----------------------------+---------------------------------------------------+
| **-- calcub** | (re)calculate u matrix from ref1 and ref2 |
+-----------------------------+---------------------------------------------------+
| **-- trialub** | (re)calculate u matrix from ref1 only (check |
| | carefully) |
+-----------------------------+---------------------------------------------------+
Motion commands
---------------
+-----------------------------+---------------------------------------------------+
| **CONSTRAINTS** |
+-----------------------------+---------------------------------------------------+
| **-- con** | list available constraints and values |
+-----------------------------+---------------------------------------------------+
| **-- con** <name> {val} | constrains and optionally sets one constraint |
+-----------------------------+---------------------------------------------------+
| **-- con** <name> {val} | clears and then fully constrains |
| <name> {val} <name> {val} | |
+-----------------------------+---------------------------------------------------+
| **-- uncon** <name> | remove constraint |
+-----------------------------+---------------------------------------------------+
| **HKL** |
+-----------------------------+---------------------------------------------------+
| **-- allhkl** [h k l] | print all hkl solutions ignoring limits |
+-----------------------------+---------------------------------------------------+
| **HARDWARE** |
+-----------------------------+---------------------------------------------------+
| **-- hardware** | show diffcalc limits and cuts |
+-----------------------------+---------------------------------------------------+
| **-- setcut** {name {val}} | sets cut angle |
+-----------------------------+---------------------------------------------------+
| **-- setmin** {axis {val}} | set lower limits used by auto sector code (None |
| | to clear) |
+-----------------------------+---------------------------------------------------+
| **-- setmax** {name {val}} | sets upper limits used by auto sector code (None |
| | to clear) |
+-----------------------------+---------------------------------------------------+
| **MOTION** |
+-----------------------------+---------------------------------------------------+
| **-- sim** hkl scn | simulates moving scannable (not all) |
+-----------------------------+---------------------------------------------------+
| **-- sixc** | show Eularian position |
+-----------------------------+---------------------------------------------------+
| **-- pos** sixc [mu, delta, | move to Eularian position(None holds an axis |
| gam, eta, chi, phi] | still) |
+-----------------------------+---------------------------------------------------+
| **-- sim** sixc [mu, delta, | simulate move to Eulerian positionsixc |
| gam, eta, chi, phi] | |
+-----------------------------+---------------------------------------------------+
| **-- hkl** | show hkl position |
+-----------------------------+---------------------------------------------------+
| **-- pos** hkl [h k l] | move to hkl position |
+-----------------------------+---------------------------------------------------+
| **-- pos** {h | k | l} val | move h, k or l to val |
+-----------------------------+---------------------------------------------------+
| **-- sim** hkl [h k l] | simulate move to hkl position |
+-----------------------------+---------------------------------------------------+
Good luck --- RobW
References
==========
.. [You1999] H. You. *Angle calculations for a '4S+2D' six-circle diffractometer.*
J. Appl. Cryst. (1999). **32**, 614-623. `(pdf link)
<http://journals.iucr.org/j/issues/1999/04/00/hn0093/hn0093.pdf>`__.
.. [Busing1967] W. R. Busing and H. A. Levy. *Angle calculations for 3- and 4-circle X-ray
and neutron diffractometers.* Acta Cryst. (1967). **22**, 457-464. `(pdf link)
<http://journals.iucr.org/q/issues/1967/04/00/a05492/a05492.pdf>`__.

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 KiB

View File

@@ -0,0 +1,565 @@
################################
Diffcalc User Guide (You Engine)
################################
.. rubric:: Diffcalc: A diffraction condition calculator for diffractometer control
:Author: Rob Walton
:Contact: rob.walton (at) diamond (dot) ac (dot) uk
:Website: https://github.com/DiamondLightSource/diffcalc
.. toctree::
:maxdepth: 2
:numbered:
See also the `quickstart guide at github <https://github.com/DiamondLightSource/diffcalc/blob/master/README.rst>`_
Introduction
============
This manual assumes that you are running Diffcalc within OpenGDA or have started
it using IPython. It assumes that Diffcalc has been configured for the six
circle diffractometer pictured here:
.. figure:: youmanual_images/4s_2d_diffractometer.png
:scale: 100
:align: center
4s + 2d six-circle diffractometer, from H.You (1999)
Your Diffcalc configuration may have been customised for the geometry of your
diffractometer and possibly the types of experiment you perform. For example, a
five-circle diffractometer might be missing the nu circle above.
The laboratory frame is shown above. With all settings at zero as shown the
crystal cartesian frame aligns with the laboratory frame. Therefor a cubic
crystal mounted squarely in a way that the U matrix (defined below) is unitary
will have h||a||x, k||b||y & l||c||z, crystal and reciprocal-lattice coordinate
frames are defined with respect to the beam and to gravity to be (for a cubic
crystal):
Overview
========
The following assumes that the diffractometer has been properly leveled, aligned
with the beam and zeroed. See the `SPEC fourc manual
<http://www.certif.com/spec_manual/fourc_4_2.html>`__.
Before moving in hkl space you must calculate a UB matrix by specifying the
crystal's lattice parameters (which define the B matrix) and finding two
reflections (from which the U matrix defining any mismount can be inferred);
and, optionally for surface-diffraction experiments, determine how the surface
of the crystal is oriented with respect to the phi axis.
Once a UB matrix has been calculated, the diffractometer may be driven in hkl
coordinates. A valid diffractometer setting maps easily into a single hkl value.
However for a diffractometer with more than three circles there are excess
degrees of freedom when calculating a diffractometer setting from an hkl value.
Diffcalc provides modes for using up the excess degrees of freedom.
Diffcalc does not perform scans directly. Instead, Scannables that use diffcalc
to map between reciprocal lattice space and real diffractometer settings are
scanned using the Gda's (or minigda's) generic scan mechanism.
Theory
------
Thanks to Elias Vlieg for sharing his dos based ``DIF`` software that Diffcalc
has borrowed heavily from. The version of Diffcalc described here is based on papers by
pHH. You. [You1999]_ and Busing & Levy [Busing1967]_. (See also the THANKS.txt file.)
Getting Help
============
There are few commands to remember. If a command is called without
arguments in some cases Diffcalc will prompt for arguments and provide sensible
defaults which can be chosen by pressing enter.
**Orientation**. The ``helpub`` command lists all commands related with crystal
orientation and the reference vector (often used with surfaces). See the
`Orientation Commands`_ section at the end of this manual::
>>> help ub
...
**HKL movement**. The ``help hkl`` list all commands related to moving in reciprocal-lattice
space. See the `Motion Commands`_ section at the end of this manual::
>>> help hkl
...
Call help on any command. e.g.::
==> help loadub
Diffcalc's Scannables
=====================
To list and show the current positions of your beamline's scannables
use ``pos`` with no arguments::
>>> pos
Results in:
**Energy and wavelength scannables**::
energy 12.3984
wl: 1.0000
**Diffractometer scannables**, as a group and in component axes (in
the real GDA these have limits)::
sixc: mu: 0.0000 delta: 0.0000 gamma: 0.0000 omega: 0.0000 chi: 0.0000 phi: 0.0000
mu: 0.0000
chi: 0.0000
delta: 0.0000
gamma: 0.0000
omega: 0.0000
phi: 0.0000
**Dummy counter**, which in this example simply counts at 1hit/s::
ct: 0.0000
**Hkl scannable**, as a group and in component::
hkl: Error: No UB matrix
h: Error: No UB matrix
k: Error: No UB matrix
l: Error: No UB matrix
**Parameter scannables**, used in some modes, these provide a
scannable alternative to the `Motion`_ section. Some constrain of
these constrain virtual angles::
alpha: ---
beta: ---
naz: ---
psi: ---
qaz: ---
and some constrain physical angles::
phi_con: ---
chi_con: ---
delta_con:---
eta_con: ---
gam_con: ---
mu_con: ---
Crystal orientation
===================
Before moving in hkl space you must calculate a UB matrix by specifying the
crystal's lattice parameters (which define the B matrix) and finding two
reflections (from which the U matrix can be inferred); and, optionally for
surface-diffraction experiments, determine how the surface of the crystal is
oriented with respect to the phi axis.
Start a new UB calculation
--------------------------
A *UB calculation* contains the description of the crystal-under-test,
any saved reflections, reference angle direction, and a B & UB
matrix pair if they have been calculated or manually specified.
Starting a new UB calculation will clear all of these.
Before starting a UB-calculation, the ``ub`` command used to summarise
the state of the current UB-calculation, will reflect that no
UB-calculation has been started::
==> ub
A new UB-calculation calculation may be started and lattice specified
explicitly::
==> newub 'example'
==> setlat '1Acube' 1 1 1 90 90 90
or interactively::
>>> newub
calculation name: example
crystal name: 1Acube
a [1]: 1
b [1]: 1
c [1]: 1
alpha [90]: 90
beta [90]: 90
gamma [90]: 90
where a,b and c are the lengths of the three unit cell basis vectors
in Angstroms, and alpha, beta and gamma are angles in Degrees.
The ``ub`` command will show the state of the current UB-calculation
(and the current energy for reference)::
==> ub
Load a UB calculation
---------------------
To load the last used UB-calculation::
>>> lastub
Loading ub calculation: 'mono-Si'
To load a previous UB-calculation::
>>> listub
UB calculations in: /Users/walton/.diffcalc/i16
0) mono-Si 15 Feb 2017 (22:32)
1) i16-32 13 Feb 2017 (18:32)
>>> loadub 0
Generate a U matrix from two reflections
----------------------------------------
The normal way to calculate a U matrix is to find the position of **two**
reflections with known hkl values. Diffcalc allows many reflections to be
recorded but currently only uses the first two when calculating a UB matrix.
Find U matrix from two reflections::
==> pos wl 1
==> c2th [0 0 1]
59.99999999999999
==> pos sixc [0 60 0 30 90 0]
==> addref [0 0 1]
==> pos sixc [0 90 0 45 45 90]
==> addref [0 1 1]
Check that it looks good::
==> checkub
Generate a U matrix from one reflection
---------------------------------------
To estimate based on first reflection only::
==> trialub
Manually specify U matrix
-------------------------
Set U matrix manually (pretending sample is squarely mounted)::
==> setu [[1 0 0] [0 1 0] [0 0 1]]
Edit reflection list
--------------------
Use ``showref`` to show the reflection list::
==> showref
Use ``swapref`` to swap reflections::
==> swapref 1 2
Recalculating UB matrix.
Use ``delref`` to delete a reflection::
>>> delref 1
Calculate a UB matrix
---------------------
Unless a U or UB matrix has been manually specified, a new UB matrix will be
calculated after the second reflection has been found, or whenever one of the
first two reflections is changed.
Use the command ``calcub`` to force the UB matrix to be calculated from the
first two reflections.
If you have misidentified a reflection used for the orientation the
resulting UB matrix will be incorrect. Always use the ``checkub``
command to check that the computed values agree with the estimated values::
==> checkub
Set the reference vector
-------------------------
When performing surface experiments the reference vector should be set normal
to the surface. It can also be used to define other directions within the crystal
with which we want to orient the incident or diffracted beam.
By default the reference vector is set parallel to the phi axis. That is,
along the z-axis of the phi coordinate frame.
The `ub` command shows the current reference vector, along with any inferred
miscut, at the top its report (or it can be shown by calling ``setnphi`` or
``setnhkl'`` with no args)::
>>> ub
...
n_phi: 0.00000 0.00000 1.00000 <- set
n_hkl: -0.00000 0.00000 1.00000
miscut: None
...
The ``<- set`` label here indicates that the reference vector is set in the phi
coordinate frame. In this case, therefor, its direction in the crystal's
reciprocal lattice space is inferred from the UB matrix.
To set the reference vector in the phi coordinate frame use::
>>> setnphi [0 0 1]
...
This is useful if the surface normal has be found with a laser or by x-ray
occlusion. This vector must currently be manually calculated from the sample
angle settings required to level the surface (sigma and tau commands on the
way).
To set the reference vector in the crystal's reciprocal lattice space use (this
is a quick way to determine the surface orientation if the surface is known to
be cleaved cleanly along a known axis)::
>>> setnhkl [0 0 1] ...
Motion
======
Once a UB matrix has been calculated, the diffractometer may be driven
in hkl coordinates. A given diffractometer setting maps easily into a
single hkl value. However for a diffractometer with more than three circles
there are excess degrees of freedom when calculating a diffractometer
setting from an hkl value. Diffcalc provides many for using up
the excess degrees of freedom.
By default Diffcalc selects no mode.
Constraining solutions for moving in hkl space
----------------------------------------------
To get help and see current constraints::
>>> help con
...
==> con
Three constraints can be given: zero or one from the DET and REF columns and the
remainder from the SAMP column. Not all combinations are currently available.
Use ``help con`` to see a summary if you run into troubles.
To configure four-circle vertical scattering::
==> con gam 0 mu 0 a_eq_b
In the following the *scattering plane* is defined as the plane including the
scattering vector, or momentum transfer vector, and the incident beam.
**DETECTOR COLUMN:**
- **delta** - physical delta setting (vertical detector motion) *del=0 is equivalent to qaz=0*
- **gam** - physical gamma setting (horizontal detector motion) *gam=0 is equivalent to qaz=90*
- **qaz** - azimuthal rotation of scattering vector (about the beam, from horizontal)
- **naz** - azimuthal rotation of reference vector (about the beam, from horizontal)
**REFERENCE COLUMN:**
- **alpha** - incident angle to surface (if reference is normal to surface)
- **beta** - exit angle from surface (if reference is normal to surface)
- **psi** - azimuthal rotation about scattering vector of reference vector (from scattering plane)
- **a_eq_b** - bisecting mode with alpha=beta. *Equivalent to psi=90*
**SAMPLE COLUMN:**
- **mu, eta, chi & phi** - physical settings
- **mu_is_gam** - force mu to follow gamma (results in a 5-circle geometry)
Diffcalc will report two other (un-constrainable) virtual angles:
- **theta** - half of 2theta, the angle through the diffracted beam bends
- **tau** - longitude of reference vector from scattering vector (in scattering plane)
Example constraint modes
------------------------
There is sometimes more than one way to get the same effect.
**Vertical four-circle mode**::
>>> con gam 0 mu 0 a_eq_b # or equivalently:
>>> con qaz 90 mu 0 a_eq_b
>>> con alpha 1 # replaces a_eq_b
**Horizontal four-circle mode**::
>>> con del 0 eta 0 alpha 1 # or equivalently:
>>> con qaz 0 mu 0 alpha 1
**Surface vertical mode**::
>>> con naz 90 mu 0 alpha 1
**Surface horizontal mode**::
>>> con naz 0 eta 0 alpha 1
**Z-axis mode (surface horizontal)**::
>>> con chi (-sigma) phi (-tau) alpha 1
where sigma and tau are the offsets required in chi and phi to bring the surface
normal parallel to eta. Alpha will determine mu directly leaving eta to orient
the planes. Or::
>>> con naz 0 phi 0 alpha 1 # or any another sample angle
**Z-axis mode (surface vertical)**::
>>> con naz 0 phi 0 alpha 1 # or any another sample angle
Changing constrained values
---------------------------
Once constraints are chosen constrained values may be changed directly::
==> con mu 10
or via the associated scannable::
==> pos mu_con 10
Configuring limits and cuts
---------------------------
Diffcalc maintains its own limits on axes. These limits will be used when
choosing solutions. If more than one detector solution is exists Diffcalc will
ask you to reduce the the limits until there is only one. However if more than
one solution for the sample settings is available it will choose one base on
heuristics.
Use the ``hardware`` command to see the current limits and cuts::
==> hardware
To set the limits::
==> setmin delta -1
==> setmax delta 145
To set a cut::
==> setcut phi -180
This causes requests to move phi to be between the configured -180 and +360
degress above this. i.e. it might dive to -10 degrees rather than 350.
Moving in hkl space
-------------------
Configure a mode, e.g. four-circle vertical::
==> con gam 0 mu 0 a_eq_b
Simulate moving to a reflection::
==> sim hkl [0 1 1]
Move to reflection::
==> pos hkl [0 1 1]
==> pos sixc
Simulate moving to a location::
==> pos sixc [0 60 0 30 90 0]
Scanning in hkl space
=====================
All scans described below use the same generic scanning mechanism
provided by the GDA system or by minigda. Here are some examples.
Fixed hkl scans
---------------
In a 'fixed hkl scan' something (such as energy or Bin) is scanned,
and at each step hkl is 'moved' to keep the sample and detector
aligned. Also plonk the diffractometer scannable (sixc) on there with no
destination to monitor what is actually happening and then
throw on a detector (ct) with an exposure time if appropriate::
>>> #scan scannable_name start stop step [scannable_name [pos or time]]..
>>> scan en 9 11 .5 hkl [1 0 0] sixc ct 1
>>> scan en 9 11 .5 hklverbose [1 0 0] sixc ct 1
>>> scan betain 4 5 .2 hkl [1 0 0] sixc ct 1
>>> scan alpha_par 0 10 2 hkl [1 0 0] sixc ct 1
Scanning hkl
------------
Hkl, or one component, may also be scanned directly::
>>> scan h .8 1.2 .1 hklverbose sixc ct 1
At each step, this will read the current hkl position, modify the h
component and then move to the resulting vector. There is a danger
that with this method k and l may drift. To get around this the start,
stop and step values may also be specified as vectors. So for example::
>>> scan hkl [1 0 0] [1 .3 0] [1 0.1 0] ct1
is equivilant to::
>>> pos hkl [1 0 0]
>>> scan k 0 .3 .1 ct1
but will not suffer from drifting. This method also allows scans along
any direction in hkl space to be performed.
Multidimension scans
--------------------
Two and three dimensional scans::
>>> scan en 9 11 .5 h .9 1.1 .2 hklverbose sixc ct 1
>>> scan h 1 3 1 k 1 3 1 l 1 3 1 hkl ct 1
Commands
========
Orientation Commands
--------------------
==> UB_HELP_TABLE
Motion commands
---------------
==> HKL_HELP_TABLE
Good luck --- RobW
References
==========
.. [You1999] H. You. *Angle calculations for a '4S+2D' six-circle diffractometer.*
J. Appl. Cryst. (1999). **32**, 614-623. `(pdf link)
<http://journals.iucr.org/j/issues/1999/04/00/hn0093/hn0093.pdf>`__.
.. [Busing1967] W. R. Busing and H. A. Levy. *Angle calculations for 3- and 4-circle X-ray
and neutron diffractometers.* Acta Cryst. (1967). **22**, 457-464. `(pdf link)
<http://journals.iucr.org/q/issues/1967/04/00/a05492/a05492.pdf>`__.

View File

@@ -0,0 +1,47 @@
Take a six circle diffractometer with angles:
delta, nu, mu, eta, chi, phi
and virtual angles:
qaz, naz, psi, alpha, beta.
Many combinations of these can be constrained:
constrain
>>> con nu
>>> con psi
>>> con mu
>>> con nu mu a_eq_b
real angles are always constrained to there last set position. If they are too far from here
an error will result.
>>> pos nu 0 (moves, parameter tracks last set value (actually checks it when hkl moved))
>>> pos psi 90 (does not move, sets parameter in diffcalc)
>>> pos mu 0 (moves)
>>> pos hkl [1 0 0] (moves based on last set nu, psi, mu)
>>> pos betain --> Exception, not constrained
moving a virtual angle simply sets it to efftec the next hkl move
Here we need onlu con, uncon and pos.
......
However it would be nice to be able to pos betain for example and have it change
betain while staying on the same reflection. This might be enabled by locking the
the current hkl position. It would be trick to make this work with the physical angles though.
>>> lock hkl
>>> pos psi 90 (moves immediately)
>>> scan psi 0 90 1 (scans, moving immediately)
>>> pos mu 0 (does not move immediately) (could work by listening to target positions, and triggering move when complete)
>>> pos c(mu) moves
>>> pos mu_c moves
Only one thing would be varyable at a time unless they are put in a CoordinatedMotionGroup,
which would be hard for the real motors)

View File

@@ -0,0 +1,525 @@
/* [wxMaxima batch file version 1] [ DO NOT EDIT BY HAND! ]*/
/* [ Created with wxMaxima version 11.08.0 ] */
/* [wxMaxima: input start ] */
Rx:matrix([1,0,0],[0, cos(theta), -sin(theta)],[0, sin(theta), cos(theta)])$
Ry:matrix([cos(theta), 0, sin(theta)], [0, 1, 0], [-sin(theta), 0, cos(theta)])$
Rz:matrix([cos(theta), -sin(theta), 0], [sin(theta), cos(theta), 0], [0, 0, 1])$
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
Equation 5:
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
PHI:subst(-phi, theta, Rz);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
CHI:subst(chi, theta, Ry);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
ETA:subst(-eta, theta, Rz);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
MU:subst(mu, theta, Rx);
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
Generic V:
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
V:matrix([v11, v12, v13], [v21, v22, v23], [v31, v32, v33]);
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
[wxMaxima: comment end ] */
/* [wxMaxima: section start ]
When one sample-orienting angle is given
[wxMaxima: section end ] */
/* [wxMaxima: subsect start ]
For mu fixed
[wxMaxima: subsect end ] */
/* [wxMaxima: input start ] */
eq34:ETA.CHI.PHI;
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
eq34_chi0:subst(0, chi, eq34);
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
*phi* with chi <> 0
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
trigreduce(trigsimp((eq34[3,2]=V[3,2])/(eq34[3,1]=V[3,1])));
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
show that with phi with v31 == 0 and v12 <> 0, no special case is needed when using atan2
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
solve(cos(phi)=0, phi);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
atan2(1234,0);
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
show that with phi with v32 == 0 and v31 <> 0, no special case is needed when using atan2
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
solve(sin(phi)=0, phi);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
atan2(0,1234);
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
*eta* with chi <> 0
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
trigreduce(trigsimp((-eq34[2,3]=V[2,3]) / (eq34[1, 3]=V[1,3])));
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
eta with v23 == 0 and v13 == 0 (phi||eta degeneracy because chi == 0)
Then see equation for phi+eta above
[wxMaxima: comment end ] */
/* [wxMaxima: comment start ]
*chi*
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
trigsimp(sqrt((eq34[3,1]=V[3,1])^2+(eq34[3,2]=V[3,2])^2)/(eq34[3,3]=V[3,3]));
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
*phi + eta* with chi == 0
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
trigreduce(trigrat((eq34_chi0[1,2]=V[1,2])/(eq1:eq34_chi0[1,1]=V[1,1])));
/* [wxMaxima: input end ] */
/* [wxMaxima: subsect start ]
For phi fixed
[wxMaxima: subsect end ] */
/* [wxMaxima: input start ] */
eq36:MU.ETA.CHI;
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
eq36_eta90:subst(%pi/2, eta, eq36);
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
*eta*
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
trigsimp((eq36[1,2]=V[1,2])/sqrt((eq36[2,2]=V[2,2])^2+(eq36[3,2]=V[3,2])^2));
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
*mu* with eta <> +-90
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
trigreduce(trigsimp((eq36[3,2]=V[3,2])/(eq36[2,2]=V[2,2])));
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
*chi* with eta <> +-90
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
trigreduce(trigsimp((eq36[1,3]=V[1,3])/(eq36[1,1]=V[1,1])));
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
*chi + mu* with eta == +-90
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
trigreduce(trigrat((eq36_eta90[2,3]=V[2,3])/(eq36_eta90[2,1]=V[2,1])));
/* [wxMaxima: input end ] */
/* [wxMaxima: subsect start ]
For eta or chi fixed
[wxMaxima: subsect end ] */
/* [wxMaxima: input start ] */
eq38:MU.ETA.CHI.PHI;
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
*chi* (eq. 39) given eta, and eta <> +-90 (with eta == +-90 chi||mu)
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
(eq38[1,3]=V[1,3])/cos(eta);
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
[wxMaxima: comment end ] */
/* [wxMaxima: comment start ]
*eta* given chi, and chi <> 0 (with chi == 0 phi||eta)
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
(eq38[1,3]=V[1,3])/sin(chi);
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
*mu* given that chi and eta have been given or calclulated respecitively
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
top:(eq38[3,3]=V[3,3])*sin(eta)*sin(chi) + (eq38[2,3]=V[2,3])*cos(chi);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
bot:-(eq38[3,3]=V[3,3])*cos(chi)+(eq38[2,3]=V[2,3])*sin(eta)*sin(chi);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
factor(top);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
factor(bot);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
trigsimp(top/bot);
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
*phi - mu* when phi || mu because chi == +-90, eta == 0 or eta == 180
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
phi_mu_parallel:subst(0, eta, subst(%pi/2, chi, eq38));
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
trigreduce(trigrat((phi_mu_parallel[2,1]=V[2,1])/(phi_mu_parallel[2,2]=V[2,2])));
/* [wxMaxima: input end ] */
/* [wxMaxima: section start ]
Two sample angles given
[wxMaxima: section end ] */
/* [wxMaxima: input start ] */
THETA:subst(-theta, theta, Rz);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
PSI:subst(psi, theta, Rx);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
F:subst(xi, theta, Ry);
/* [wxMaxima: input end ] */
/* [wxMaxima: section start ]
psi, mu, eta given
[wxMaxima: section end ] */
/* [wxMaxima: input start ] */
eq49:transpose(PHI).transpose(CHI).transpose(ETA).transpose(MU).F;
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
*chi*
[wxMaxima: comment end ] */
/* [wxMaxima: comment start ]
using the linear combination identity
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
comb_idenity:sqrt(A^2+B^2)*sin(x+omega);
omega:atan(B/A);
A*sin(x)+B*cos(x)=comb_idenity;
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
a:-sin(eta)*cos(mu)$
b:-sin(mu)$
V32=a*sin(chi)+b*cos(chi);
V32=subst(b, B, subst(a, A, comb_idenity));
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
asin(%/(sqrt(sin(mu)^2+sin(eta)^2*cos(mu)^2))), triginverses=all;
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
*xi and phi*
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
top:factor(eq49[3,1]*cos(xi)+eq49[3,3]*sin(xi));
bot:factor(eq49[3,1]*sin(xi)-eq49[3,3]*cos(xi));
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
factor(top/bot);
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
When mu=-90 and eta = 0, used to for a surface normal vertical mode
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
eq49_vert:subst(-%pi/2, mu, subst(0, eta, eq49));
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
(eq49_vert[2,2]=V[2,2]) / (eq49_vert[1,2]=V[1,2]);
/* [wxMaxima: input end ] */
/* [wxMaxima: subsect start ]
mu, phi, qaz (for three circle on i10 and i06, not in paper )
[wxMaxima: subsect end ] */
/* [wxMaxima: input start ] */
thisV:transpose(MU).F.THETA;
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
Nphi:matrix([n11, n12, n13], [n21, n22, n23], [n31, n32, n33]);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
eq:ETA.CHI.PHI.Nphi.transpose(PSI);
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
*chi*
[wxMaxima: comment end ] */
/* [wxMaxima: comment start ]
using the linear combination identity
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
comb_idenity:sqrt(A^2+B^2)*sin(x+omega);
omega:atan(B/A);
A*sin(x)+B*cos(x)=comb_idenity;
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
on V31:
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
a:-1*(n21*sin(phi)+n11*cos(phi))$
b:n31$
V31=a*sin(chi)+b*cos(chi);
V31=subst(b, B, subst(a, A, comb_idenity));
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
asin(%/sqrt((-n21*sin(phi)-n11*cos(phi))^2+n31^2)), triginverses=all;
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
*xi and phi*
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
top:factor(eq49[3,1]*cos(xi)+eq49[3,3]*sin(xi));
bot:factor(eq49[3,1]*sin(xi)-eq49[3,3]*cos(xi));
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
factor(top/bot);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
solve();
/* [wxMaxima: input end ] */
/* [wxMaxima: section start ]
Fixed mu, chi, psi (probably with mu=chi=0) (not in paper)
[wxMaxima: section end ] */
/* [wxMaxima: input start ] */
Vcalulated:Nphi.transpose(PSI).transpose(THETA);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
thisV:transpose(PHI).transpose(CHI).transpose(ETA).transpose(MU).F;
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
v:thisVvert:subst(0, chi, subst(0, mu, thisV));
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
acos(thisVvert[3,3]=V[3,3]), triginverses=all;
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
top:(v[1,2]=V[1,2])*cos(phi) + (v[2,2]=V[2,2])*sin(phi);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
bot:(v[1,2]=V[1,2])*sin(phi) - (v[2,2]=V[2,2])*cos(phi);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
factor(top);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
factor(bot);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
trigsimp(top/bot);
/* [wxMaxima: input end ] */
/* [wxMaxima: title start ]
5.5 subset with eta=chi=0 & phi set
[wxMaxima: title end ] */
/* [wxMaxima: input start ] */
matrix([cos(theta)*sin(qaz)], [-sin(theta)], [cos(theta)*cos(qaz)]);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
h_phi:matrix([h1], [h2], [h3]);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
Z:MU.ETA.CHI.PHI;
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
eq68yterm:-sin(theta) = ((Z.h_phi))[2][1];
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
expands(%);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
eq68_chi_eta_0:subst(0, chi, subst(0, eta, Z.h_phi));
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
eq68_chi_eta_0_yterm:-sin(theta)=eq68_chi_eta_0[2];
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
subst(0, chi, subst(0, eta, eq68yterm));
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
a;
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
ratsubst(a, -h3, eq68_chi_eta_0_yterm);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
a:-h3;
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
b:-h1*sin(phi) +h2*cos(phi);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
c:-sin(theta);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
ratsubst(cc, c, ratsubst(bb, b, ratsubst(aa, a, eq68_chi_eta_0_yterm)));
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
arcsin(c/sqrt(a^2+b^2)) - arctan(b, a);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
eq68_chi_eta_0[1] /eq68_chi_eta_0[2];
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
without chi=eta=0
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
eq68yterm:-sin(theta) = ((Z.h_phi))[2][1];
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
expand(eq68yterm);
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
solve for mu unknown
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
c:-sin(theta);
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
a:sin(chi)*h2*sin(phi) + sin(chi)*h1*cos(phi) - cos(chi)*h3;
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
b: -cos(chi)*sin(eta)*h2*sin(phi) -cos(eta)*h1*sin(phi) +cos(eta)*h2*cos(phi) -cos(chi)*sin(eta)*h1*cos(phi) - sin(chi)*sin(eta)*h3;
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
expand(subst(a, aa, subst(b, bb, -sin(theta)=aa*sin(mu) + bb*cos(mu))));
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
Check a and b expand to produce original (Okay)
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
expand(eq68yterm);
/* [wxMaxima: input end ] */
/* [wxMaxima: comment start ]
Check against special case above (Okay)
[wxMaxima: comment end ] */
/* [wxMaxima: input start ] */
subst(0, chi, subst(0, eta, a));
/* [wxMaxima: input end ] */
/* [wxMaxima: input start ] */
subst(0, chi, subst(0, eta, b));
/* [wxMaxima: input end ] */
/* Maxima can't load/batch files which end with a comment! */
"Created with wxMaxima"$

View File

@@ -0,0 +1,71 @@
Creating a UB Matrix
There are three euler modes:
=bisecting: eta and delta are fixed, phi and chi are not fixed.
=fixed phi: phi and 2theta are fixed, eta and chi are not fixed.
=fixed psi: Not used for creating a UB matrix .
First creat a reflection file to store the reflections data using:
reffile('name')
Set the crystal lattice:
latt([a]) assumes cubic
latt([a,b]) assumes tetragonal
latt([a,b,c]) assumes orthorhombic
latt([a,b,c,gam]) assumes monclinic/hexagonal gam different from 90.
latt([a,b,c,alp,bet,gam])
Use:
c2th([h k l])
to calculate the 2 theta position for the hkl for example:
c2th([0 0 2])
Then use the following to move the diffractometer to the correct positions:
pos delta c2th([0 0 2]) eta c2th([0 0 2])/2
You can now scan eta, chi, and delta to optomise the peak intensity using the following scans for example:
scancn eta 0.01 40 w 0.2 t 1
scancn chi 0.01 40 w 0.2 t 1
scancn delta 0.01 40 w 0.2 t 1
A few iterations may be required.
Now that you have the first reflection it can be stored using the following command:
saveref('reflable',[h k l])
saveref('Ti1',[0 0 2]) for the above example.
Then create a dummy UB matrix using a dummy non-parallel hkl plane eg:
ubm('Ti1',[2 0 0])
Useing the following command to calculate the direction of the second reflection:
hkl_calc([0 2 2])
If the calculated positions can be safely achieved then type:
pos hkl [0 2 2]
Find the second reflection by scanning phi, once the reflection is found save the second reflection using:
saveref('Ti2',[0 2 2]) for example.
Now create a real UB-Matrix using:
ubm('Ti1','Ti2')
You can now drive in recriprocal space.
To change the lattice parameters according the found Bragg peaks
latt([latt()[0]*2/l()]) (cubic only)