├── .cache └── v │ └── cache │ └── lastfailed ├── .github └── workflows │ └── main.yml ├── .gitignore ├── .project ├── .settings ├── com.wdev91.eclipse.copyright.xml ├── org.eclipse.core.resources.prefs └── org.eclipse.core.runtime.prefs ├── COPYING ├── Makefile ├── README.rst ├── README_template.rst ├── buckminster.cspec ├── component.def ├── diffcalc.py ├── diffcalc ├── __init__.py ├── dc │ ├── __init__.py │ ├── common.py │ ├── dcvlieg.py │ ├── dcwillmot.py │ ├── dcyou.py │ └── help.py ├── gdasupport │ ├── __init__.py │ ├── minigda │ │ ├── __init__.py │ │ ├── command.py │ │ └── scannable.py │ ├── scannable │ │ ├── __init__.py │ │ ├── base.py │ │ ├── diffractometer.py │ │ ├── hkl.py │ │ ├── hkloffset.py │ │ ├── mock.py │ │ ├── parameter.py │ │ ├── parametrised_hkl.py │ │ ├── qtrans.py │ │ ├── setref2.py │ │ ├── sim.py │ │ ├── simulation.py │ │ ├── slave_driver.py │ │ ├── sr2.py │ │ ├── vrmlanimator.py │ │ └── wavelength.py │ └── you.py ├── hardware.py ├── hkl │ ├── __init__.py │ ├── calcbase.py │ ├── common.py │ ├── vlieg │ │ ├── __init__.py │ │ ├── calc.py │ │ ├── constraints.py │ │ ├── geometry.py │ │ ├── hkl.py │ │ └── transform.py │ ├── willmott │ │ ├── __init__.py │ │ ├── calc.py │ │ ├── commands.py │ │ └── constraints.py │ └── you │ │ ├── __init__.py │ │ ├── calc.py │ │ ├── constraints.py │ │ ├── geometry.py │ │ ├── hkl.py │ │ └── persistence.py ├── log.py ├── settings.py ├── tests │ ├── __init__.py │ ├── dc │ │ ├── __init__.py │ │ ├── test_dcvlieg.py │ │ └── you │ │ │ ├── __init__.py │ │ │ ├── test_fourcircle.py │ │ │ └── test_sixcircle.py │ ├── gdasupport │ │ ├── __init__.py │ │ ├── minigda │ │ │ ├── __init__.py │ │ │ ├── test_command.py │ │ │ └── test_scannable.py │ │ ├── scannable │ │ │ ├── __init__.py │ │ │ ├── mockdiffcalc.py │ │ │ ├── test_diffractometer.py │ │ │ ├── test_hkl.py │ │ │ ├── test_parameter.py │ │ │ ├── test_simulation.py │ │ │ └── test_wavelength.py │ │ └── test_you.py │ ├── hkl │ │ ├── __init__.py │ │ ├── vlieg │ │ │ ├── __init__.py │ │ │ ├── test_calc.py │ │ │ ├── test_constraints.py │ │ │ ├── test_geometry.py │ │ │ ├── test_hkl.py │ │ │ └── test_transform.py │ │ ├── willmot │ │ │ ├── __init__.py │ │ │ └── test_calcwill.py │ │ └── you │ │ │ ├── __init__.py │ │ │ ├── test_calc.py │ │ │ ├── test_calc_methods.py │ │ │ ├── test_calc_surface.py │ │ │ ├── test_constraints.py │ │ │ └── test_hkl.py │ ├── ref │ │ ├── b16_dif_270608_printout_for_SixCircleGammaOnArmTestAgainstDif.txt │ │ ├── i16_reference_results.txt │ │ └── output_from_spec.txt │ ├── scenarios.py │ ├── test_hardware.py │ ├── test_numjy.py │ ├── test_tools.py │ ├── test_utils.py │ ├── tools.py │ └── ub │ │ ├── __init__.py │ │ ├── test_calculation.py │ │ ├── test_calculation_vlieg.py │ │ ├── test_calculation_you.py │ │ ├── test_crystal.py │ │ ├── test_orientations.py │ │ ├── test_persistence.py │ │ ├── test_reference.py │ │ ├── test_reflections.py │ │ └── test_ub.py ├── ub │ ├── __init__.py │ ├── calc.py │ ├── calcstate.py │ ├── crystal.py │ ├── fitting.py │ ├── orientations.py │ ├── persistence.py │ ├── reference.py │ ├── reflections.py │ └── ub.py └── util.py ├── diffcmd ├── __init__.py ├── diffcalc_launcher.py ├── diffcmd_utils.py ├── ipython.py ├── ipythonmagic.py ├── make_manual.py ├── start.py └── tests │ ├── __init__.py │ └── test_ipython.py ├── doc ├── Makefile ├── docs-build-diffcalc_doc-linux.launch ├── references ├── source │ ├── ACKS.rst │ ├── conf.py │ ├── developer │ │ ├── contents.rst │ │ ├── development.rst │ │ ├── intro.rst │ │ ├── package.rst │ │ ├── quickstart_api.rst │ │ └── quickstart_setup_environment │ ├── diffcalc_pdf.png │ ├── diffcalc_web.png │ ├── index.rst │ ├── vliegmanual │ │ ├── contents.rst │ │ ├── images │ │ │ ├── fix.png │ │ │ ├── sixcircle_gamma_on_arm.pdf │ │ │ ├── sixcircle_gamma_on_arm.png │ │ │ ├── sixcircle_gamma_on_arm.ppt │ │ │ ├── unit_cell.pdf │ │ │ └── unit_cell.png │ │ └── vliegmanual.rst │ ├── youmanual.rst │ ├── youmanual_images │ │ └── 4s_2d_diffractometer.png │ └── youmanual_template.rst └── tmp │ ├── constraints.txt │ ├── extensions_to_yous_paper.wxm │ └── i16_non_diffcalc_manual.txt ├── install-jython-environment.sh ├── integration_checks.py ├── model ├── README.txt ├── fivec.fxw ├── fivec.wcfg ├── fivec.wrl ├── sixc.fxw ├── sixc.wcfg ├── sixc.wrl ├── sixc_horizontal.fxw ├── sixc_horizontal.wrl └── vrml_animator.py ├── numjy ├── __init__.py ├── jama_matrix_wrapper.py └── linalg.py ├── setup.py ├── simplejson ├── __init__.py ├── _speedups.c ├── decoder.py ├── encoder.py ├── ordered_dict.py ├── scanner.py └── tool.py ├── startup ├── __init__.py ├── _common_imports.py ├── _demo.py ├── _make_sixcircle_manual.py ├── api │ ├── __init__.py │ └── sixcircle.py ├── b16.py ├── beamlinespecific │ ├── __init__.py │ ├── azihkl.py │ ├── conic_scannables.py │ └── i21.py ├── fivecircle.py ├── fourcircle.py ├── i06.py ├── i07EH1h.py ├── i07EH1v.py ├── i07EH2v.py ├── i10.py ├── i13.py ├── i16.py ├── i16robot.py ├── i21.py └── sixcircle.py ├── todo.txt └── tox.ini /.cache/v/cache/lastfailed: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Diffcalc build 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | test: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | flavour: ['python', 'jython'] 13 | python-version: [2.7] 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Set up Python ${{ matrix.python-version }} 18 | uses: actions/setup-python@v2 19 | with: 20 | python-version: ${{ matrix.python-version }} 21 | if: matrix.flavour == 'python' 22 | 23 | - name: Install Python packages 24 | run: | 25 | pip install pytest==3.10.1; pip install pytest-xdist==1.26.1; pip install scipy==1.2.1; pip install nose==1.3.7; pip install mock==3.0.5 26 | echo "PYTEST=pytest -W ignore::PendingDeprecationWarning" >> $GITHUB_ENV 27 | if: matrix.flavour == 'python' 28 | 29 | - name: Install Jython 30 | run: | 31 | source install-jython-environment.sh 32 | echo "PYTEST=$HOME/jython/bin/jython -m pytest" >> $GITHUB_ENV 33 | echo "CLASSPATH=$PWD/jama-1.0.3.jar:$PWD/commons-math3-3.6.1.jar" >> $GITHUB_ENV 34 | if: matrix.flavour == 'jython' 35 | 36 | - name: Tests 37 | run: | 38 | echo Running $PYTEST 39 | $PYTEST 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *~ 3 | *.pyc 4 | doc/build/ 5 | .pydevproject 6 | .project 7 | .tox 8 | .DS_Store 9 | .idea 10 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | diffcalc 4 | 5 | 6 | 7 | 8 | 9 | org.python.pydev.PyDevBuilder 10 | 11 | 12 | 13 | 14 | 15 | org.python.pydev.pythonNature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.settings/com.wdev91.eclipse.copyright.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Diamond Light Source Ltd. 4 | .]]> 19 |
20 | 21 | 22 | 23 |
24 |
25 | 26 | 27 | 28 |
29 |
30 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//doc/source/conf.py=utf-8 3 | encoding/=UTF-8 4 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.runtime.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | line.separator=\n 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | test-all: test-python test-jython test-integration test-launcher 3 | 4 | test-python: 5 | py.test 6 | 7 | test-jython: 8 | export CLASSPATH=$(HOME)/lib/Jama-1.0.3.jar:$(CLASSPATH); echo $$CLASSPATH; $(HOME)/jython/bin/py.test 9 | 10 | test-integration: 11 | py.test --boxed integration_checks.py 12 | 13 | test-launcher: 14 | ./diffcalc.py --help 15 | ./diffcalc.py --modules 16 | ./diffcalc.py --non-interactive --python sixcircle 17 | 18 | install-jython: 19 | ./install-jython-environment.sh 20 | 21 | doc-source: 22 | ./diffcalc.py --non-interactive --make-manuals-source 23 | 24 | doc-html: 25 | cd doc; make html 26 | 27 | doc-pdf: 28 | cd doc; make pdf 29 | 30 | doc-all: 31 | cd doc; make all 32 | 33 | doc-clean: 34 | cd doc; make clean 35 | 36 | help: 37 | @echo 38 | @echo "Please use \`make ' where is one of" 39 | @echo 40 | @echo " test-all" 41 | @echo " test-python" 42 | @echo " test-jython" 43 | @echo " test-integration" 44 | @echo " test-launcher" 45 | @echo " install-jython" 46 | @echo 47 | @echo " doc-source : to expand *_template.rst to *.rst" 48 | @echo " doc-html" 49 | @echo " doc-pdf" 50 | @echo " doc-all" 51 | @echo " doc-clean" 52 | @echo 53 | -------------------------------------------------------------------------------- /buckminster.cspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /component.def: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | -------------------------------------------------------------------------------- /diffcalc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | 5 | from diffcmd.diffcalc_launcher import main 6 | 7 | 8 | if __name__ == '__main__': 9 | sys.exit(main()) -------------------------------------------------------------------------------- /diffcalc/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/__init__.py -------------------------------------------------------------------------------- /diffcalc/dc/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/dc/__init__.py -------------------------------------------------------------------------------- /diffcalc/dc/common.py: -------------------------------------------------------------------------------- 1 | from diffcalc.util import allnum, command, DiffcalcException 2 | 3 | 4 | def sim(scn, hkl): 5 | """sim hkl scn -- simulates moving scannable (not all) 6 | """ 7 | if not isinstance(hkl, (tuple, list)): 8 | raise TypeError() 9 | 10 | if not allnum(hkl): 11 | raise TypeError() 12 | 13 | try: 14 | print scn.simulateMoveTo(hkl) 15 | except AttributeError: 16 | raise TypeError( 17 | "The first argument does not support simulated moves") 18 | 19 | def energy_to_wavelength(energy): 20 | try: 21 | return 12.39842 / energy 22 | except ZeroDivisionError: 23 | raise DiffcalcException( 24 | "Cannot calculate hkl position as Energy is set to 0") -------------------------------------------------------------------------------- /diffcalc/dc/dcvlieg.py: -------------------------------------------------------------------------------- 1 | from diffcalc.dc.common import energy_to_wavelength 2 | 3 | from diffcalc import settings 4 | from diffcalc.hkl.vlieg.transform import VliegTransformSelector,\ 5 | TransformCommands, VliegPositionTransformer 6 | from diffcalc.dc.help import compile_extra_motion_commands_for_help 7 | import diffcalc.hkl.vlieg.calc 8 | 9 | 10 | # reload to aid testing only 11 | import diffcalc.ub.ub as _ub 12 | reload(_ub) 13 | from diffcalc import hardware as _hardware 14 | #reload(_hardware) 15 | import diffcalc.hkl.vlieg.hkl as _hkl 16 | reload(_hkl) 17 | 18 | from diffcalc.ub.ub import * # @UnusedWildImport 19 | from diffcalc.hardware import * # @UnusedWildImport 20 | from diffcalc.hkl.vlieg.hkl import * # @UnusedWildImport 21 | from diffcalc.gdasupport.scannable.sim import sim 22 | 23 | _transform_selector = VliegTransformSelector() 24 | _transform_commands = TransformCommands(_transform_selector) 25 | _transformer = VliegPositionTransformer(settings.geometry, settings.hardware, 26 | _transform_selector) 27 | 28 | transform = _transform_commands.transform 29 | transforma = _transform_commands.transforma 30 | transformb = _transform_commands.transformb 31 | transformc = _transform_commands.transformc 32 | 33 | 34 | on = 'on' 35 | off = 'off' 36 | auto = 'auto' 37 | manual = 'manual' 38 | 39 | def hkl_to_angles(h, k, l, energy=None): 40 | """Convert a given hkl vector to a set of diffractometer angles""" 41 | if energy is None: 42 | energy = settings.hardware.get_energy() # @UndefinedVariable 43 | 44 | position, params = hklcalc.hklToAngles(h, k, l, energy_to_wavelength(energy)) 45 | position = _transformer.transform(position) 46 | angle_tuple = settings.geometry.internal_position_to_physical_angles(position) # @UndefinedVariable 47 | angle_tuple = settings.hardware.cut_angles(angle_tuple) # @UndefinedVariable 48 | 49 | return angle_tuple, params 50 | 51 | 52 | def angles_to_hkl(angleTuple, energy=None): 53 | """Converts a set of diffractometer angles to an hkl position 54 | ((h, k, l), paramDict)=angles_to_hkl(self, (a1, a2,aN), energy=None)""" 55 | if energy is None: 56 | energy = settings.hardware.get_energy() # @UndefinedVariable 57 | 58 | i_pos = settings.geometry.physical_angles_to_internal_position(angleTuple) # @UndefinedVariable 59 | return hklcalc.anglesToHkl(i_pos, energy_to_wavelength(energy)) 60 | 61 | 62 | settings.ubcalc_strategy = diffcalc.hkl.vlieg.calc.VliegUbCalcStrategy() 63 | settings.angles_to_hkl_function = diffcalc.hkl.vlieg.calc.vliegAnglesToHkl 64 | settings.include_sigtau = True 65 | 66 | ub_commands_for_help = _ub.commands_for_help 67 | 68 | hkl_commands_for_help = (_hkl.commands_for_help + 69 | _hardware.commands_for_help + 70 | ['Transform', 71 | transform, 72 | transforma, 73 | transformb, 74 | transformc] + 75 | compile_extra_motion_commands_for_help()) 76 | 77 | -------------------------------------------------------------------------------- /diffcalc/dc/dcwillmot.py: -------------------------------------------------------------------------------- 1 | # This file differs from dcyou in only two places 2 | 3 | from diffcalc import settings 4 | from diffcalc.dc.common import energy_to_wavelength 5 | from diffcalc.dc.help import compile_extra_motion_commands_for_help 6 | import diffcalc.hkl.willmott.calc 7 | 8 | 9 | # reload to aid testing only 10 | from diffcalc.ub import ub as _ub 11 | reload(_ub) 12 | from diffcalc import hardware as _hardware 13 | #reload(_hardware) 14 | from diffcalc.hkl.you import hkl as _hkl 15 | reload(_hkl) 16 | 17 | from diffcalc.ub.ub import * # @UnusedWildImport 18 | from diffcalc.hardware import * # @UnusedWildImport 19 | from diffcalc.hkl.willmot.hkl import * # @UnusedWildImport 20 | from diffcalc.gdasupport.scannable.sim import sim 21 | 22 | def hkl_to_angles(h, k, l, energy=None): 23 | """Convert a given hkl vector to a set of diffractometer angles""" 24 | if energy is None: 25 | energy = settings.hardware.get_energy() # @UndefinedVariable 26 | 27 | (pos, params) = hklcalc.hklToAngles(h, k, l, energy_to_wavelength(energy)) 28 | angle_tuple = settings.geometry.internal_position_to_physical_angles(pos) # @UndefinedVariable 29 | angle_tuple = settings.hardware.cut_angles(angle_tuple) # @UndefinedVariable 30 | 31 | return angle_tuple, params 32 | 33 | def angles_to_hkl(angleTuple, energy=None): 34 | """Converts a set of diffractometer angles to an hkl position 35 | ((h, k, l), paramDict)=angles_to_hkl(self, (a1, a2,aN), energy=None)""" 36 | if energy is None: 37 | energy = settings.hardware.get_energy() # @UndefinedVariable 38 | i_pos = settings.geometry.physical_angles_to_internal_position(angleTuple) # @UndefinedVariable 39 | return hklcalc.anglesToHkl(i_pos, energy_to_wavelength(energy)) 40 | 41 | settings.ubcalc_strategy = diffcalc.hkl.willmott.calc.WillmottHorizontalUbCalcStrategy() 42 | settings.angles_to_hkl_function = diffcalc.hkl.willmott.calc.angles_to_hkl 43 | 44 | 45 | ub_commands_for_help = _ub.commands_for_help 46 | 47 | hkl_commands_for_help = _hkl.commands_for_help + _hardware.commands_for_help + compile_extra_motion_commands_for_help() 48 | -------------------------------------------------------------------------------- /diffcalc/dc/dcyou.py: -------------------------------------------------------------------------------- 1 | from diffcalc import settings 2 | from diffcalc.dc.common import energy_to_wavelength 3 | from diffcalc.dc.help import compile_extra_motion_commands_for_help 4 | 5 | import diffcalc.hkl.you.calc 6 | settings.ubcalc_strategy = diffcalc.hkl.you.calc.YouUbCalcStrategy() 7 | settings.angles_to_hkl_function = diffcalc.hkl.you.calc.youAnglesToHkl 8 | 9 | # reload to aid testing only 10 | from diffcalc.ub import ub as _ub 11 | 12 | reload(_ub) 13 | from diffcalc import hardware as _hardware 14 | #reload(_hardware) 15 | from diffcalc.hkl.you import hkl as _hkl 16 | reload(_hkl) 17 | 18 | from diffcalc.ub.ub import * # @UnusedWildImport 19 | from diffcalc.hardware import * # @UnusedWildImport 20 | from diffcalc.hkl.you.hkl import * # @UnusedWildImport 21 | 22 | 23 | class DiffractometerYouCalculator(object): 24 | 25 | def __init__(self, diffractometerObject, diffcalcObject): 26 | self.diffhw = diffractometerObject 27 | self.geometry = diffcalcObject 28 | 29 | 30 | def hkl_to_angles(self, h, k, l, energy=None): 31 | """Convert a given hkl vector to a set of diffractometer angles 32 | 33 | return angle tuple and params dictionary 34 | 35 | """ 36 | if energy is None: 37 | energy = self.diffhw.get_energy() # @UndefinedVariable 38 | 39 | (pos, params) = hklcalc.hklToAngles(h, k, l, energy_to_wavelength(energy)) 40 | angle_tuple = self.geometry.internal_position_to_physical_angles(pos) # @UndefinedVariable 41 | angle_tuple = self.diffhw.cut_angles(angle_tuple) # @UndefinedVariable 42 | 43 | return angle_tuple, params 44 | 45 | 46 | def hkl_list_to_angles(self, hkl_list, energy=None): 47 | """Convert a given hkl vector to a set of diffractometer angles 48 | 49 | return angle tuple and params dictionary 50 | 51 | """ 52 | if energy is None: 53 | energy = self.diffhw.get_energy() # @UndefinedVariable 54 | 55 | (pos, params) = hklcalc.hklListToAngles(hkl_list, energy_to_wavelength(energy)) 56 | angle_tuple = self.geometry.internal_position_to_physical_angles(pos) # @UndefinedVariable 57 | angle_tuple = self.diffhw.cut_angles(angle_tuple) # @UndefinedVariable 58 | 59 | return angle_tuple, params 60 | 61 | 62 | def angles_to_hkl(self, angleTuple, energy=None): 63 | """Converts a set of diffractometer angles to an hkl position 64 | 65 | Return hkl tuple and params dictionary 66 | 67 | """ 68 | if energy is None: 69 | energy = self.diffhw.get_energy() # @UndefinedVariable 70 | i_pos = self.geometry.physical_angles_to_internal_position(angleTuple) # @UndefinedVariable 71 | return hklcalc.anglesToHkl(i_pos, energy_to_wavelength(energy)) 72 | 73 | 74 | def hkl_to_angles(h, k, l, energy=None): 75 | _dcyou = DiffractometerYouCalculator(settings.hardware, settings.geometry) 76 | return _dcyou.hkl_to_angles(h, k, l, energy) 77 | 78 | def hkl_list_to_angles(hkl, energy=None): 79 | _dcyou = DiffractometerYouCalculator(settings.hardware, settings.geometry) 80 | return _dcyou.hkl_list_to_angles(hkl, energy) 81 | 82 | def angles_to_hkl(angleTuple, energy=None): 83 | _dcyou = DiffractometerYouCalculator(settings.hardware, settings.geometry) 84 | return _dcyou.angles_to_hkl(angleTuple, energy) 85 | 86 | 87 | 88 | ub_commands_for_help = _ub.commands_for_help 89 | hkl_commands_for_help = _hkl.commands_for_help + _hardware.commands_for_help + compile_extra_motion_commands_for_help() 90 | -------------------------------------------------------------------------------- /diffcalc/gdasupport/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/gdasupport/__init__.py -------------------------------------------------------------------------------- /diffcalc/gdasupport/minigda/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/gdasupport/minigda/__init__.py -------------------------------------------------------------------------------- /diffcalc/gdasupport/scannable/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/gdasupport/scannable/__init__.py -------------------------------------------------------------------------------- /diffcalc/gdasupport/scannable/base.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | try: 20 | from gda.device.scannable import ScannableMotionBase \ 21 | as PseudoDevice 22 | except ImportError: 23 | from diffcalc.gdasupport.minigda.scannable import \ 24 | ScannableBase as PseudoDevice 25 | 26 | 27 | class ScannableGroup(PseudoDevice): 28 | 29 | def __init__(self, name, motorList): 30 | 31 | self.setName(name) 32 | # Set input format 33 | motorNames = [] 34 | for scn in motorList: 35 | motorNames.append(scn.getName()) 36 | self.setInputNames(motorNames) 37 | # Set output format 38 | format = [] 39 | for motor in motorList: 40 | format.append(motor.getOutputFormat()[0]) 41 | self.setOutputFormat(format) 42 | self.__motors = motorList 43 | 44 | def asynchronousMoveTo(self, position): 45 | # if input has any Nones, then replace these with the current positions 46 | if None in position: 47 | position = list(position) 48 | current = self.getPosition() 49 | for idx, val in enumerate(position): 50 | if val is None: 51 | position[idx] = current[idx] 52 | 53 | for scn, pos in zip(self.__motors, position): 54 | scn.asynchronousMoveTo(pos) 55 | 56 | def getPosition(self): 57 | return [scn.getPosition() for scn in self.__motors] 58 | 59 | def isBusy(self): 60 | for scn in self.__motors: 61 | if scn.isBusy(): 62 | return True 63 | return False 64 | -------------------------------------------------------------------------------- /diffcalc/gdasupport/scannable/mock.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | try: 20 | from gda.device.scannable import ScannableMotionBase 21 | except ImportError: 22 | from diffcalc.gdasupport.minigda.scannable import \ 23 | ScannableBase as ScannableMotionBase 24 | 25 | 26 | class MockMotor(ScannableMotionBase): 27 | 28 | def __init__(self, name='mock'): 29 | self.pos = 0.0 30 | self._busy = False 31 | self.name = name 32 | 33 | def asynchronousMoveTo(self, pos): 34 | self._busy = True 35 | self.pos = float(pos) 36 | 37 | def getPosition(self): 38 | return self.pos 39 | 40 | def isBusy(self): 41 | return self._busy 42 | 43 | def makeNotBusy(self): 44 | self._busy = False 45 | 46 | def getOutputFormat(self): 47 | return ['%f'] 48 | -------------------------------------------------------------------------------- /diffcalc/gdasupport/scannable/parameter.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | from diffcalc import settings 19 | 20 | try: 21 | from gda.device.scannable import ScannableMotionBase 22 | except ImportError: 23 | from diffcalc.gdasupport.minigda.scannable import \ 24 | ScannableBase as ScannableMotionBase 25 | 26 | 27 | class DiffractionCalculatorParameter(ScannableMotionBase): 28 | 29 | def __init__(self, name, parameterName, parameter_manager): 30 | 31 | self.parameter_manager = parameter_manager 32 | self.parameterName = parameterName 33 | self._ext_name = settings.geometry.map_to_external_name(parameterName) 34 | 35 | self.setName(name) 36 | self.setInputNames([parameterName,]) 37 | self.setOutputFormat(['%5.5f',]) 38 | self.setLevel(3) 39 | 40 | def asynchronousMoveTo(self, value): 41 | _, cons_value = settings.geometry.map_to_internal_position(self._ext_name, value) 42 | self.parameter_manager.set_constraint(self.parameterName, cons_value) 43 | 44 | def getPosition(self): 45 | value = self.parameter_manager.get_constraint(self.parameterName) 46 | _, cons_value = settings.geometry.map_to_internal_position(self.parameterName, value) 47 | return [cons_value,] 48 | 49 | def isBusy(self): 50 | return False 51 | -------------------------------------------------------------------------------- /diffcalc/gdasupport/scannable/parametrised_hkl.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2019 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | from diffcalc.gdasupport.scannable.hkl import Hkl 19 | from diffcalc import settings 20 | from diffcalc.util import getMessageFromException 21 | from pprint import pformat 22 | 23 | 24 | class ParametrisedHKLScannable(Hkl): 25 | 26 | def __init__(self, name, inputNames, num_cached_params=0, idx_cached_pos=[], tol=1e-4): 27 | 28 | from diffcalc.dc import dcyou as _dc 29 | Hkl.__init__(self, name, settings.axes_scannable_group, _dc, None) 30 | 31 | self.setName(name) 32 | self.setInputNames(inputNames) 33 | self.setOutputFormat(['%7.5f'] * len(inputNames)) 34 | 35 | self.parameter_to_hkl = self._diffcalc.angles_to_hkl 36 | self.hkl_to_parameter = self._diffcalc.hkl_to_angles 37 | self.num_cached_params = num_cached_params 38 | self.cached_params = None 39 | self.idx_cached_pos = idx_cached_pos 40 | self.tol = tol 41 | 42 | self.completeInstantiation() 43 | self.setAutoCompletePartialMoveToTargets(True) 44 | self.dynamic_class_doc = 'Parametrised HKL Scannable' 45 | 46 | 47 | def rawAsynchronousMoveTo(self, params): 48 | self.cached_params = params[-self.num_cached_params:] 49 | tmp_pos = self.diffhw.getPosition() # a tuple 50 | cached_pos = {idx: tmp_pos[idx] for idx in self.idx_cached_pos} 51 | hkl = self.parameter_to_hkl(params) 52 | if isinstance(hkl[0], (int, float)): 53 | (calc_pos, _) = self._diffcalc.hkl_to_angles(*hkl) 54 | elif isinstance(hkl[0], (tuple, list)): 55 | (calc_pos, _) = self._diffcalc.hkl_list_to_angles(hkl) 56 | final_pos = tuple(cached_pos[idx] if idx in cached_pos else val for idx, val in enumerate(calc_pos)) 57 | calc_hkl, _ = self._diffcalc.angles_to_hkl(calc_pos) 58 | final_hkl, _ = self._diffcalc.angles_to_hkl(final_pos) 59 | if max([abs(i - j) for i,j in zip(calc_hkl, final_hkl)]) > self.tol: 60 | print("Warning: Final hkl position %s exceeds tolerance %f compared to calculated hkl %s" 61 | % (pformat(final_hkl), self.tol, pformat(calc_hkl))) 62 | self.diffhw.asynchronousMoveTo(final_pos) 63 | 64 | 65 | def rawGetPosition(self): 66 | pos = self.diffhw.getPosition() # a tuple 67 | hkl, _ = self._diffcalc.angles_to_hkl(pos) 68 | pos = self.hkl_to_parameter(list(hkl)) 69 | return pos 70 | 71 | 72 | def simulateMoveTo(self, pos): 73 | lines = ['%s:' % self.name] 74 | hkl = self.parameter_to_hkl(pos) 75 | if isinstance(hkl[0], (tuple, list)): 76 | (angles, _) = self._diffcalc.hkl_list_to_angles(hkl) 77 | hkl, _ = self._diffcalc.angles_to_hkl(angles) 78 | #fmt_scn_params = ' '.join([' : %9.4f'] + ['%.4f'] * (len(pos) - 1)) 79 | #lines.append(' ' + self.name + fmt_scn_params % tuple(pos)) 80 | width = max(len(k) for k in self.inputNames) 81 | fmt = ' %' + str(width) + 's : % 9.4f' 82 | for idx, k in enumerate(self.inputNames): 83 | lines.append(fmt % (k, pos[idx])) 84 | lines.append('\n ' + 'hkl'.rjust(width) + ' : %9.4f %.4f %.4f' % (hkl[0], hkl[1], hkl[2])) 85 | res = Hkl.simulateMoveTo(self, hkl) 86 | lines.append(res) 87 | return '\n'.join(lines) 88 | 89 | 90 | def __repr__(self): 91 | lines = ['%s:' % self.name] 92 | pos = self.diffhw.getPosition() 93 | try: 94 | (hkl, params) = self._diffcalc.angles_to_hkl(pos) 95 | scn_params = self.hkl_to_parameter(list(hkl)) 96 | except Exception, e: 97 | return "<%s: %s>" % (self.name, getMessageFromException(e)) 98 | 99 | width = max(len(k) for k in params) 100 | fmt_scn_params = ' '.join([' : %9.4f'] + ['%.4f'] * (len(scn_params) - 1)) 101 | lines.append(' ' + self.name.rjust(width) + fmt_scn_params % scn_params) 102 | lines.append(' ' + 'hkl'.rjust(width) + ' : %9.4f %.4f %.4f' % (hkl[0], hkl[1], hkl[2])) 103 | lines[-1] = lines[-1] + '\n' 104 | fmt = ' %' + str(width) + 's : % 9.4f' 105 | for k in sorted(params): 106 | lines.append(fmt % (k, params[k])) 107 | return '\n'.join(lines) 108 | -------------------------------------------------------------------------------- /diffcalc/gdasupport/scannable/setref2.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on 1 Nov 2018 3 | 4 | @author: voo82357 5 | ''' 6 | from diffcalc.util import allnum, DiffcalcException, TODEG 7 | from diffcalc.gdasupport.scannable.sim import sim 8 | from diffcalc.util import getInputWithDefault 9 | 10 | def setref2(scn, hkl): 11 | """setref2 scn [h k l] -- setup hkloffset scannable to scan for second reflection [hkl]""" 12 | 13 | if not isinstance(hkl, (tuple, list)): 14 | raise DiffcalcException("Please specify hkl values for a second reference reflection to search.") 15 | 16 | if not allnum(hkl): 17 | raise DiffcalcException("Please specify numeric values for hkl.") 18 | 19 | try: 20 | hkl_ref = scn._diffcalc._ub.ubcalc.get_reflection(0)[0] 21 | except IndexError: 22 | raise DiffcalcException("Please add one reference reflection into the reflection list.") 23 | pol, az, sc = scn._diffcalc._ub.ubcalc.calc_offset_for_hkl(hkl, hkl_ref) 24 | hkl_rot = [sc * val for val in hkl_ref] 25 | hkl_sc = hkl_rot[:] 26 | hkl_rot.extend([pol * TODEG, az * TODEG]) 27 | hkl_sc.extend([0, 0]) 28 | 29 | print ('\nRescaled hkl reference for second reflection : %9.4f %.4f %.4f' % (hkl_sc[0], hkl_sc[1], hkl_sc[2])) 30 | print (' polar and azimuthal rotation angles : %9.4f %.4f\n' % (pol * TODEG, az * TODEG)) 31 | 32 | sim(scn, hkl_sc) 33 | print ('IMPORTANT: Applying subsequent polar and azimuthal rotations might fail. In this case, please manually\n' 34 | ' find accessible azimuthal rotation range to scan for second reference reflection.') 35 | reply = getInputWithDefault('Move to rescaled hkl position', 'y') 36 | if reply in ('y', 'Y', 'yes'): 37 | scn.asynchronousMoveTo(hkl_sc) 38 | else: 39 | print 'Aborting' 40 | return 41 | 42 | sim(scn, hkl_rot) 43 | reply = getInputWithDefault('Apply polar and azimuthal rotations', 'y') 44 | if reply in ('y', 'Y', 'yes'): 45 | scn.asynchronousMoveTo(hkl_rot) 46 | else: 47 | print 'Aborting' 48 | return -------------------------------------------------------------------------------- /diffcalc/gdasupport/scannable/sim.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on 7 May 2016 3 | 4 | @author: walton 5 | ''' 6 | 7 | def sim(scn, hkl): 8 | """sim hkl scn -- simulates moving scannable (not all) 9 | """ 10 | try: 11 | print scn.simulateMoveTo(hkl) 12 | except AttributeError: 13 | raise TypeError( 14 | "The first argument does not support simulated moves") -------------------------------------------------------------------------------- /diffcalc/gdasupport/scannable/simulation.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | import time 20 | from math import sqrt, pi, exp 21 | 22 | try: 23 | from gda.device.scannable import ScannableMotionBase \ 24 | as PseudoDevice 25 | except ImportError: 26 | from diffcalc.gdasupport.minigda.scannable import \ 27 | ScannableBase as PseudoDevice 28 | 29 | from diffcalc.ub.crystal import CrystalUnderTest 30 | from diffcalc.hkl.you.calc import youAnglesToHkl 31 | from diffcalc.hkl.vlieg.calc import vliegAnglesToHkl 32 | from diffcalc.hkl.you.geometry import calcCHI, calcPHI 33 | 34 | TORAD = pi / 180 35 | TODEG = 180 / pi 36 | 37 | 38 | class Equation(object): 39 | 40 | def __call__(self, dh, dk, dl): 41 | raise Exception('Abstract') 42 | 43 | def __str__(self): 44 | "Abstract equation" 45 | 46 | 47 | class Gaussian(Equation): 48 | 49 | def __init__(self, variance): 50 | self.variance = float(variance) 51 | 52 | def __call__(self, dh, dk, dl): 53 | dr_squared = dh * dh + dk * dk + dl * dl 54 | return (1 / sqrt(2 * pi * self.variance) * 55 | exp(-dr_squared / (2 * self.variance))) 56 | 57 | 58 | class SimulatedCrystalCounter(PseudoDevice): 59 | 60 | def __init__(self, name, diffractometerScannable, geometryPlugin, 61 | wavelengthScannable, equation=Gaussian(.01), engine='you'): 62 | self.setName(name) 63 | self.setInputNames([name + '_count']) 64 | self.setOutputFormat(['%7.5f']) 65 | self.exposureTime = 1 66 | self.pause = True 67 | self.diffractometerScannable = diffractometerScannable 68 | self.geometry = geometryPlugin 69 | self.wavelengthScannable = wavelengthScannable 70 | self.equation = equation 71 | self.engine = engine 72 | 73 | self.cut = None 74 | self.UB = None 75 | self.chiMissmount = 0. 76 | self.phiMissmount = 0. 77 | self.setCrystal('cubic', 1, 1, 1, 90, 90, 90) 78 | 79 | def setCrystal(self, name, a, b, c, alpha, beta, gamma): 80 | self.cut = CrystalUnderTest(name, a, b, c, alpha, beta, gamma) 81 | self.calcUB() 82 | 83 | def setChiMissmount(self, chi): 84 | self.chiMissmount = chi 85 | self.calcUB() 86 | 87 | def setPhiMissmount(self, phi): 88 | self.phiMissmount = phi 89 | self.calcUB() 90 | 91 | def calcUB(self): 92 | CHI = calcCHI(self.chiMissmount * TORAD) 93 | PHI = calcPHI(self.phiMissmount * TORAD) 94 | self.UB = CHI * PHI * self.cut.B 95 | 96 | def asynchronousMoveTo(self, exposureTime): 97 | self.exposureTime = exposureTime 98 | if self.pause: 99 | time.sleep(exposureTime) # Should not technically block! 100 | 101 | def getPosition(self): 102 | h, k, l = self.getHkl() 103 | dh, dk, dl = h - round(h), k - round(k), l - round(l) 104 | count = self.equation(dh, dk, dl) 105 | #return self.exposureTime, count*self.exposureTime 106 | return count * self.exposureTime 107 | 108 | def getHkl(self): 109 | pos = self.geometry.physical_angles_to_internal_position( 110 | self.diffractometerScannable.getPosition()) 111 | pos.changeToRadians() 112 | wavelength = self.wavelengthScannable.getPosition() 113 | if self.engine.lower() == 'vlieg': 114 | return vliegAnglesToHkl(pos, wavelength, self.UB) 115 | elif self.engine.lower() == 'you': 116 | return youAnglesToHkl(pos, wavelength, self.UB) 117 | else: 118 | raise ValueError(self.engine) 119 | 120 | def isBusy(self): 121 | return False 122 | 123 | def __str__(self): 124 | return self.__repr__() 125 | 126 | def __repr__(self): 127 | s = 'simulated crystal detector: %s\n' % self.getName() 128 | h, k, l = self.getHkl() 129 | s += ' h : %f\n' % h 130 | s += ' k : %f\n' % k 131 | s += ' l : %f\n' % l 132 | s += self.cut.__str__() + '\n' 133 | s += "chi orientation: %s\n" % self.chiMissmount 134 | s += "phi orientation: %s\n" % self.phiMissmount 135 | ub = self.UB.tolist() 136 | s += "UB:\n" 137 | s += " % 18.13f% 18.13f% 18.12f\n" % (ub[0][0], ub[0][1], ub[0][2]) 138 | s += " % 18.13f% 18.13f% 18.12f\n" % (ub[1][0], ub[1][1], ub[1][2]) 139 | s += " % 18.13f% 18.13f% 18.12f\n" % (ub[2][0], ub[2][1], ub[2][2]) 140 | return s 141 | -------------------------------------------------------------------------------- /diffcalc/gdasupport/scannable/slave_driver.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | from math import pi, tan, sin, atan, cos, atan2 20 | 21 | TORAD = pi / 180 22 | TODEG = 180 / pi 23 | 24 | 25 | class SlaveScannableDriver(object): 26 | 27 | def __init__(self, scannables): 28 | self.scannables = scannables 29 | 30 | def isBusy(self): 31 | for scn in self.scannables: 32 | if scn.isBusy(): 33 | return True 34 | return False 35 | 36 | def waitWhileBusy(self): 37 | for scn in self.scannables: 38 | scn.waitWhileBusy() 39 | 40 | def triggerAsynchronousMove(self, triggerPos): 41 | nu = self.slaveFromTriggerPos(triggerPos) 42 | for scn in self.scannables: 43 | scn.asynchronousMoveTo(nu) 44 | 45 | def getPosition(self): 46 | return self.scannables[0].getPosition() 47 | 48 | def slaveFromTriggerPos(self, triggerPos): 49 | raise Exception("Abstract") 50 | 51 | def getScannableNames(self): 52 | return [scn.name for scn in self.scannables] 53 | 54 | def getScannable(self, name): 55 | for scn in self.scannables: 56 | if scn.getName() == name: 57 | return scn 58 | return None 59 | 60 | def getOutputFormat(self): 61 | return [list(scn.outputFormat)[0] for scn in self.scannables] 62 | 63 | def getPositions(self): 64 | return [float(scn.getPosition()) for scn in self.scannables] 65 | 66 | 67 | """ 68 | Based on: Elias Vlieg, "A (2+3)-Type Surface Diffractometer: Mergence of the 69 | z-axis and (2+2)-Type Geometries", J. Appl. Cryst. (1998). 31. 198-203 70 | """ 71 | 72 | 73 | class NuDriverForSixCirclePlugin(SlaveScannableDriver): 74 | 75 | def slaveFromTriggerPos(self, triggerPos): 76 | 77 | alpha, delta, gamma, _, _, _ = triggerPos 78 | alpha = alpha * TORAD 79 | delta = delta * TORAD 80 | gamma = gamma * TORAD 81 | 82 | ### Equation16 RHS ### 83 | rhs = -1 * tan(gamma - alpha) * sin(delta) 84 | nu = atan(rhs) # -pi/2 <= nu <= pi/2 85 | return nu * TODEG 86 | 87 | 88 | class NuDriverForWillmottHorizontalGeometry(SlaveScannableDriver): 89 | 90 | """ 91 | Based on: Phillip Willmott, "Angle calculations for a (2+3)-type 92 | diffractometer: focus on area detectors", J. Appl. Cryst. (2011). 44. 93 | 73-83 94 | """ 95 | 96 | def __init__(self, scannables, area_detector=False): 97 | SlaveScannableDriver.__init__(self, scannables) 98 | self.area_detector = area_detector 99 | 100 | def slaveFromTriggerPos(self, triggerPos): 101 | 102 | delta, gamma, omegah, _ = triggerPos 103 | delta *= TORAD 104 | gamma *= TORAD 105 | omegah *= TORAD 106 | if self.area_detector: 107 | nu = atan2(sin(delta - omegah), tan(gamma)) # (66) 108 | else: 109 | top = -sin(gamma) * sin(omegah) 110 | bot = (sin(omegah) * cos(gamma) * sin(delta) + 111 | cos(omegah) * cos(delta)) 112 | nu = atan2(top, bot) # (61) 113 | 114 | print 'nu:', nu * TODEG 115 | return nu * TODEG 116 | -------------------------------------------------------------------------------- /diffcalc/gdasupport/scannable/wavelength.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | try: 20 | from gdascripts.pd.dummy_pds import DummyPD 21 | except ImportError: 22 | from diffcalc.gdasupport.minigda.scannable import DummyPD 23 | 24 | 25 | class Wavelength(DummyPD): 26 | 27 | def __init__(self, name, energyScannable, 28 | energyScannableMultiplierToGetKeV=1): 29 | self.energyScannable = energyScannable 30 | self.energyScannableMultiplierToGetKeV = \ 31 | energyScannableMultiplierToGetKeV 32 | 33 | DummyPD.__init__(self, name) 34 | 35 | def asynchronousMoveTo(self, pos): 36 | self.energyScannable.asynchronousMoveTo( 37 | (12.39842 / pos) / self.energyScannableMultiplierToGetKeV) 38 | 39 | def getPosition(self): 40 | energy = self.energyScannable.getPosition() 41 | if energy == 0: 42 | raise Exception( 43 | "The energy is 0, so no wavelength could be calculated.run_All()") 44 | return 12.39842 / (energy * self.energyScannableMultiplierToGetKeV) 45 | 46 | def isBusy(self): 47 | return self.energyScannable.isBusy() 48 | 49 | def waitWhileBusy(self): 50 | return self.energyScannable.waitWhileBusy() 51 | -------------------------------------------------------------------------------- /diffcalc/gdasupport/you.py: -------------------------------------------------------------------------------- 1 | from diffcalc.gdasupport.scannable.diffractometer import DiffractometerScannableGroup 2 | from diffcalc.gdasupport.scannable.hkl import Hkl 3 | from diffcalc.gdasupport.scannable.hkloffset import HklOffset 4 | from diffcalc.gdasupport.scannable.simulation import SimulatedCrystalCounter 5 | from diffcalc.gdasupport.scannable.wavelength import Wavelength 6 | from diffcalc.gdasupport.scannable.parameter import DiffractionCalculatorParameter 7 | 8 | 9 | from diffcalc.dc import dcyou as _dc 10 | from diffcalc.dc.help import format_command_help 11 | from diffcalc.gdasupport.scannable.sr2 import Sr2 12 | from diffcalc.gdasupport.scannable.qtrans import Qtrans 13 | reload(_dc) 14 | from diffcalc.dc.dcyou import * # @UnusedWildImport 15 | from diffcalc import settings 16 | 17 | try: 18 | import gda # @UnusedImport @UnresolvedImport 19 | GDA = True 20 | except: 21 | GDA = False 22 | 23 | if not GDA: 24 | from diffcalc.gdasupport.minigda import command 25 | _pos = command.Pos() 26 | _scan = command.Scan(command.ScanDataPrinter()) 27 | 28 | def pos(*args): 29 | """ 30 | pos show position of all Scannables 31 | pos scn show position of scn 32 | pos scn targetmove scn to target (a number) 33 | """ 34 | return _pos(*args) 35 | 36 | def scan(*args): 37 | """ 38 | scan scn start stop step {scn {target}} {det t} 39 | """ 40 | return _scan(*args) 41 | 42 | 43 | from diffcalc.gdasupport.scannable.sim import sim # @UnusedImport 44 | 45 | _scn_group = settings.axes_scannable_group 46 | _diff_scn_name = settings.geometry.name # @UndefinedVariable 47 | _energy_scannable = settings.energy_scannable 48 | 49 | 50 | # Create diffractometer scannable 51 | _diff_scn = DiffractometerScannableGroup(_diff_scn_name, _dc, _scn_group) 52 | globals()[_diff_scn_name] = _diff_scn 53 | 54 | # Create hkl scannables 55 | hkl = Hkl('hkl', _scn_group, _dc) 56 | h = hkl.h 57 | k = hkl.k 58 | l = hkl.l 59 | 60 | hkloffset = HklOffset('hkloffset', _scn_group, _dc) 61 | h_offset = hkloffset.h 62 | k_offset = hkloffset.k 63 | l_offset = hkloffset.l 64 | pol_offset = hkloffset.polar 65 | az_offset = hkloffset.azimuthal 66 | 67 | sr2 = Sr2('sr2', _scn_group, _dc) 68 | 69 | qtrans = Qtrans('qtrans', _scn_group, _dc) 70 | 71 | Hkl.dynamic_docstring = format_command_help(hkl_commands_for_help) # must be on the class 72 | ub.__doc__ = format_command_help(ub_commands_for_help) 73 | 74 | if settings.include_reference: 75 | _virtual_angles = ('theta', 'ttheta', 'qaz', 'alpha', 'naz', 'tau', 'psi', 'beta', 'betain', 'betaout') 76 | else: 77 | _virtual_angles = ('theta', 'ttheta', 'qaz', 'betain', 'betaout') 78 | hklverbose = Hkl('hklverbose', _scn_group, _dc, _virtual_angles) 79 | 80 | 81 | # Create wavelength scannable 82 | wl = Wavelength( 83 | 'wl', _energy_scannable, settings.energy_scannable_multiplier_to_get_KeV) 84 | if not GDA: 85 | wl.asynchronousMoveTo(1) # Angstrom 86 | _energy_scannable.level = 3 87 | wl.level = 3 88 | 89 | 90 | # Create simulated counter timer 91 | ct = SimulatedCrystalCounter('ct', _scn_group, settings.geometry, wl) 92 | ct.level = 10 93 | 94 | 95 | # Create constraint scannables 96 | def _create_constraint_scannable(con_name, scn_name=None): 97 | if not scn_name: 98 | scn_name = con_name 99 | return DiffractionCalculatorParameter( 100 | scn_name, con_name, _dc.constraint_manager) 101 | 102 | # Detector constraints 103 | def isconstrainable(name): 104 | return not constraint_manager.is_constraint_fixed(name) 105 | 106 | if isconstrainable('delta'): delta_con = _create_constraint_scannable('delta', 'delta_con') 107 | if isconstrainable('gam'): gam_con = _create_constraint_scannable('gam', 'gam_con') 108 | if isconstrainable('qaz'): qaz = _create_constraint_scannable('qaz') 109 | if isconstrainable('naz'): naz = _create_constraint_scannable('naz') 110 | 111 | # Reference constraints 112 | if settings.include_reference: 113 | alpha = _create_constraint_scannable('alpha') 114 | beta = _create_constraint_scannable('beta') 115 | psi = _create_constraint_scannable('psi') 116 | a_eq_b = 'a_eq_b' 117 | betain = _create_constraint_scannable('betain') 118 | betaout = _create_constraint_scannable('betaout') 119 | bin_eq_bout = 'bin_eq_bout' 120 | 121 | # Sample constraints 122 | if isconstrainable('mu'): mu_con = _create_constraint_scannable('mu', 'mu_con') 123 | if isconstrainable('eta'): eta_con = _create_constraint_scannable('eta', 'eta_con') 124 | if isconstrainable('chi'): chi_con = _create_constraint_scannable('chi', 'chi_con') 125 | if isconstrainable('phi'): phi_con = _create_constraint_scannable('phi', 'phi_con') 126 | if isconstrainable('mu') and isconstrainable('gam'): mu_is_gam = 'mu_is_gam' 127 | omega = _create_constraint_scannable('omega') 128 | bisect = 'bisect' 129 | 130 | 131 | # Cleanup other cruft 132 | del format_command_help 133 | -------------------------------------------------------------------------------- /diffcalc/hkl/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/hkl/__init__.py -------------------------------------------------------------------------------- /diffcalc/hkl/common.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | from diffcalc.util import allnum 19 | 20 | def getNameFromScannableOrString(o): 21 | try: # it may be a scannable 22 | return o.getName() 23 | except AttributeError: 24 | return str(o) 25 | raise TypeError() 26 | 27 | 28 | class DummyParameterManager(object): 29 | 30 | def getParameterDict(self): 31 | return {} 32 | 33 | def _setParameter(self, name, value): 34 | raise KeyError(name) 35 | 36 | def _getParameter(self, name): 37 | raise KeyError(name) 38 | 39 | def update_tracked(self): 40 | pass 41 | 42 | 43 | def sim(self, scn, hkl): 44 | """sim hkl scn -- simulates moving scannable (not all) 45 | """ 46 | if not isinstance(hkl, (tuple, list)): 47 | raise TypeError 48 | 49 | if not allnum(hkl): 50 | raise TypeError() 51 | 52 | try: 53 | print scn.simulateMoveTo(hkl) 54 | except AttributeError: 55 | raise TypeError("The first argument does not support simulated moves") 56 | -------------------------------------------------------------------------------- /diffcalc/hkl/vlieg/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/hkl/vlieg/__init__.py -------------------------------------------------------------------------------- /diffcalc/hkl/vlieg/hkl.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | from diffcalc.hkl.common import getNameFromScannableOrString 20 | from diffcalc.util import command 21 | from diffcalc import settings 22 | 23 | 24 | from diffcalc.ub import ub 25 | from diffcalc.hkl.vlieg.calc import VliegHklCalculator 26 | 27 | 28 | __all__ = ['hklmode', 'setpar', 'trackalpha', 'trackgamma', 'trackphi', 29 | 'parameter_manager', 'hklcalc'] 30 | 31 | 32 | hklcalc = VliegHklCalculator(ub.ubcalc) 33 | 34 | parameter_manager = hklcalc.parameter_manager 35 | 36 | def __str__(self): 37 | return hklcalc.__str__() 38 | 39 | @command 40 | def hklmode(num=None): 41 | """hklmode {num} -- changes mode or shows current and available modes and all settings""" #@IgnorePep8 42 | 43 | if num is None: 44 | print hklcalc.__str__() 45 | else: 46 | hklcalc.mode_selector.setModeByIndex(int(num)) 47 | pm = hklcalc.parameter_manager 48 | print (hklcalc.mode_selector.reportCurrentMode() + "\n" + 49 | pm.reportParametersUsedInCurrentMode()) 50 | 51 | def _setParameter(name, value): 52 | hklcalc.parameter_manager.set_constraint(name, value) 53 | 54 | def _getParameter(name): 55 | return hklcalc.parameter_manager.get_constraint(name) 56 | 57 | @command 58 | def setpar(scannable_or_string=None, val=None): 59 | """setpar {parameter_scannable {{val}} -- sets or shows a parameter' 60 | setpar {parameter_name {val}} -- sets or shows a parameter' 61 | """ 62 | 63 | if scannable_or_string is None: 64 | #show all 65 | parameterDict = hklcalc.parameter_manager.getParameterDict() 66 | names = parameterDict.keys() 67 | names.sort() 68 | for name in names: 69 | print _representParameter(name) 70 | else: 71 | name = getNameFromScannableOrString(scannable_or_string) 72 | if val is None: 73 | _representParameter(name) 74 | else: 75 | oldval = _getParameter(name) 76 | _setParameter(name, float(val)) 77 | print _representParameter(name, oldval, float(val)) 78 | 79 | def _representParameter(name, oldval=None, newval=None): 80 | flags = '' 81 | if hklcalc.parameter_manager.isParameterTracked(name): 82 | flags += '(tracking hardware) ' 83 | if settings.geometry.parameter_fixed(name): # @UndefinedVariable 84 | flags += '(fixed by geometry) ' 85 | pm = hklcalc.parameter_manager 86 | if not pm.isParameterUsedInSelectedMode(name): 87 | flags += '(not relevant in this mode) ' 88 | if oldval is None: 89 | val = _getParameter(name) 90 | if val is None: 91 | val = "---" 92 | else: 93 | val = str(val) 94 | return "%s: %s %s" % (name, val, flags) 95 | else: 96 | return "%s: %s --> %f %s" % (name, oldval, newval, flags) 97 | 98 | def _checkInputAndSetOrShowParameterTracking(name, b=None): 99 | """ 100 | for track-parameter commands: If no args displays parameter settings, 101 | otherwise sets the tracking switch for the given parameter and displays 102 | settings. 103 | """ 104 | # set if arg given 105 | if b is not None: 106 | hklcalc.parameter_manager.setTrackParameter(name, b) 107 | # Display: 108 | lastValue = _getParameter(name) 109 | if lastValue is None: 110 | lastValue = "---" 111 | else: 112 | lastValue = str(lastValue) 113 | flags = '' 114 | if hklcalc.parameter_manager.isParameterTracked(name): 115 | flags += '(tracking hardware)' 116 | print "%s: %s %s" % (name, lastValue, flags) 117 | 118 | @command 119 | def trackalpha(b=None): 120 | """trackalpha {boolean} -- determines wether alpha parameter will track alpha axis""" #@IgnorePep8 121 | _checkInputAndSetOrShowParameterTracking('alpha', b) 122 | 123 | @command 124 | def trackgamma(b=None): 125 | """trackgamma {boolean} -- determines wether gamma parameter will track alpha axis""" #@IgnorePep8 126 | _checkInputAndSetOrShowParameterTracking('gamma', b) 127 | 128 | @command 129 | def trackphi(b=None): 130 | """trackphi {boolean} -- determines wether phi parameter will track phi axis""" #@IgnorePep8 131 | _checkInputAndSetOrShowParameterTracking('phi', b) 132 | 133 | 134 | commands_for_help = ['Mode', 135 | hklmode, 136 | setpar, 137 | trackalpha, 138 | trackgamma, 139 | trackphi] 140 | -------------------------------------------------------------------------------- /diffcalc/hkl/willmott/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/hkl/willmott/__init__.py -------------------------------------------------------------------------------- /diffcalc/hkl/willmott/commands.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | from diffcalc.hkl.common import getNameFromScannableOrString 20 | from diffcalc.util import command 21 | 22 | 23 | class WillmottHklCommands(object): 24 | 25 | def __init__(self, hklcalc): 26 | self._hklcalc = hklcalc 27 | self.commands = [self.con, 28 | self.uncon, 29 | self.cons] 30 | 31 | def __str__(self): 32 | return self._hklcalc.__str__() 33 | 34 | @command 35 | def con(self, scn_or_string): 36 | """con -- constrains constraint 37 | """ 38 | name = getNameFromScannableOrString(scn_or_string) 39 | self._hklcalc.constraints.constrain(name) 40 | print self._report_constraints() 41 | 42 | @command 43 | def uncon(self, scn_or_string): 44 | """uncon -- unconstrains constraint 45 | """ 46 | name = getNameFromScannableOrString(scn_or_string) 47 | self._hklcalc.constraints.unconstrain(name) 48 | print self._report_constraints() 49 | 50 | @command 51 | def cons(self): 52 | """cons -- list available constraints and values 53 | """ 54 | print self._report_constraints() 55 | 56 | def _report_constraints(self): 57 | return (self._hklcalc.constraints.build_display_table_lines() + '\n\n' + 58 | self._hklcalc.constraints._report_constraints()) 59 | -------------------------------------------------------------------------------- /diffcalc/hkl/you/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/hkl/you/__init__.py -------------------------------------------------------------------------------- /diffcalc/hkl/you/persistence.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2018 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | from diffcalc.ub.calcstate import UBCalcStateEncoder, UBCalcState 19 | from diffcalc.util import DiffcalcException, TODEG 20 | 21 | 22 | class YouStateEncoder(UBCalcStateEncoder): 23 | 24 | def default(self, obj): 25 | 26 | if isinstance(obj, UBCalcState): 27 | d = UBCalcStateEncoder.default(self, obj) 28 | 29 | from diffcalc.hkl.you.hkl import constraint_manager 30 | d['constraints'] = constraint_manager.all 31 | return d 32 | 33 | return UBCalcStateEncoder.default(self, obj) 34 | 35 | @staticmethod 36 | def decode_ubcalcstate(state, geometry, diffractometer_axes_names, multiplier): 37 | 38 | # Backwards compatibility code 39 | try: 40 | cons_dict = state['constraints'] 41 | from diffcalc.hkl.you.hkl import constraint_manager 42 | for cons_name, val in cons_dict.iteritems(): 43 | try: 44 | constraint_manager.constrain(cons_name) 45 | if val is not None: 46 | constraint_manager.set_constraint(cons_name, val * TODEG) 47 | except DiffcalcException: 48 | print 'WARNING: Ignoring constraint %s' % cons_name 49 | except KeyError: 50 | pass 51 | 52 | return UBCalcStateEncoder.decode_ubcalcstate(state, geometry, diffractometer_axes_names, multiplier) 53 | -------------------------------------------------------------------------------- /diffcalc/log.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | from __future__ import absolute_import 20 | 21 | import logging 22 | 23 | try: 24 | import gda 25 | GDA = True 26 | except ImportError: 27 | GDA = False 28 | 29 | if not GDA: 30 | import getpass 31 | logging.basicConfig(format="%(asctime)s %(levelname)s:%(name)s:%(message)s", 32 | datefmt='%m/%d/%Y %I:%M:%S', 33 | filename='/tmp/diffcalc_%s.log' % getpass.getuser(), 34 | level=logging.DEBUG) 35 | -------------------------------------------------------------------------------- /diffcalc/settings.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Aug 5, 2013 3 | 4 | @author: walton 5 | ''' 6 | from diffcalc.ub.persistence import UbCalculationNonPersister 7 | 8 | try: 9 | from numpy import matrix 10 | except ImportError: 11 | from numjy import matrix 12 | 13 | # These should be by the user *before* importing other modules 14 | geometry = None 15 | hardware = None 16 | ubcalc_persister = UbCalculationNonPersister() 17 | 18 | axes_scannable_group = None 19 | energy_scannable = None 20 | energy_scannable_multiplier_to_get_KeV=1 21 | 22 | 23 | # These will be set by dcyou, dcvlieg or dcwillmot 24 | ubcalc_strategy = None 25 | angles_to_hkl_function = None # Used by checkub to avoid coupling it to an hkl module 26 | include_sigtau=False 27 | include_reference=True 28 | 29 | reference_vector = matrix('1; 0; 0') 30 | surface_vector = matrix('0; 0; 1') 31 | 32 | NUNAME = 'gam' 33 | -------------------------------------------------------------------------------- /diffcalc/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/tests/__init__.py -------------------------------------------------------------------------------- /diffcalc/tests/dc/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/tests/dc/__init__.py -------------------------------------------------------------------------------- /diffcalc/tests/dc/you/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/tests/dc/you/__init__.py -------------------------------------------------------------------------------- /diffcalc/tests/dc/you/test_fourcircle.py: -------------------------------------------------------------------------------- 1 | from math import pi 2 | 3 | try: 4 | from numpy import matrix 5 | except ImportError: 6 | from numjy import matrix 7 | from diffcalc.tests.tools import mneq_, aneq_, assert_dict_almost_equal 8 | 9 | import diffcalc.util # @UnusedImport 10 | from diffcalc.hardware import DummyHardwareAdapter 11 | from diffcalc.hkl.you.geometry import FourCircle 12 | from diffcalc.ub.persistence import UbCalculationNonPersister 13 | from diffcalc import settings 14 | 15 | 16 | diffcalc.util.DEBUG = True 17 | wl = 1 18 | en = 12.39842 / wl 19 | 20 | angles = [60, 30, 0, 0] 21 | param = {'tau': 90, 'psi': 90, 'beta': 0, 'alpha': 0, 'naz': 0, 'qaz': 90, 'theta': 30, 'ttheta': 60, 'betain': 0, 'betaout': 0} 22 | 23 | 24 | dc = None 25 | def setup_module(): 26 | global dc 27 | axes = 'delta', 'eta', 'chi', 'phi' 28 | settings.hardware = DummyHardwareAdapter(axes) 29 | settings.geometry = FourCircle() 30 | settings.ubcalc_persister = UbCalculationNonPersister() 31 | settings.reference_vector = matrix('0; 0; 1') 32 | 33 | from diffcalc.dc import dcyou as dc 34 | reload(dc) 35 | dc.newub('test') 36 | dc.setlat('cubic', 1, 1, 1, 90, 90, 90) 37 | dc.addref([1, 0, 0], [60, 30, 0, 0], en, 'ref1') 38 | dc.addref([0, 1, 0], [60, 30, 0, 90], en, 'ref2') 39 | 40 | def test_orientation_phase(): 41 | # assumes reflections added were ideal (with no mis-mount) 42 | dc.ub() 43 | dc.checkub() 44 | dc.showref() 45 | 46 | U = matrix('1 0 0; 0 1 0; 0 0 1') 47 | UB = U * 2 * pi 48 | mneq_(dc._ub.ubcalc.U, U) 49 | mneq_(dc._ub.ubcalc.UB, UB) 50 | 51 | def test_angles_to_hkl_bypassing_hardware_plugin(): 52 | hkl_calc, param_calc = dc.angles_to_hkl(angles, en) 53 | aneq_(hkl_calc, [1, 0, 0]) 54 | assert_dict_almost_equal(param_calc, param) 55 | 56 | def test_hkl_to_angles_bypassing_hardware_plugin(): 57 | dc.con('a_eq_b') 58 | h, k, l = [1, 0, 0] 59 | angles_calc, param_calc = dc.hkl_to_angles(h, k, l, en) 60 | aneq_(angles_calc, angles) 61 | assert_dict_almost_equal(param_calc, param) 62 | 63 | def test_angles_to_hkl(): 64 | hkl_calc, param_calc = dc.angles_to_hkl(angles, en) 65 | aneq_(hkl_calc, [1, 0, 0]) 66 | assert_dict_almost_equal(param_calc, param) 67 | 68 | def test_hkl_to_angles(): 69 | dc.con('a_eq_b') 70 | h, k, l = [1, 0, 0] 71 | angles_calc, param_calc = dc.hkl_to_angles(h, k, l, en) 72 | aneq_(angles_calc, angles) 73 | assert_dict_almost_equal(param_calc, param) -------------------------------------------------------------------------------- /diffcalc/tests/dc/you/test_sixcircle.py: -------------------------------------------------------------------------------- 1 | 2 | from math import pi 3 | 4 | try: 5 | from numpy import matrix 6 | except ImportError: 7 | from numjy import matrix 8 | from diffcalc.tests.tools import mneq_, aneq_, dneq_ 9 | 10 | import diffcalc.util # @UnusedImport 11 | from diffcalc.hardware import DummyHardwareAdapter 12 | from diffcalc.hkl.you.geometry import SixCircle 13 | from diffcalc.ub.persistence import UbCalculationNonPersister 14 | from diffcalc.settings import NUNAME 15 | from diffcalc import settings 16 | 17 | 18 | diffcalc.util.DEBUG = True 19 | wl = 1 20 | en = 12.39842 / wl 21 | 22 | angles = [0, 60, 0, 30, 0, 0] 23 | param = {'tau': 90, 'psi': 90, 'beta': 0, 'alpha': 0, 'naz': 0, 'qaz': 90, 'theta': 30, 'ttheta': 60, 'betain': 0, 'betaout': 0} 24 | 25 | 26 | dc=None 27 | def setup_module(): 28 | global dc 29 | axes = 'mu', 'delta', NUNAME, 'eta', 'chi', 'phi' 30 | settings.hardware = DummyHardwareAdapter(axes) 31 | settings.geometry = SixCircle() 32 | settings.ubcalc_persister = UbCalculationNonPersister() 33 | 34 | from diffcalc.dc import dcyou as dc 35 | reload(dc) 36 | 37 | dc.newub('test') 38 | dc.setlat('cubic', 1, 1, 1, 90, 90, 90) 39 | dc.addref([1, 0, 0], [0, 60, 0, 30, 0, 0], en, 'ref1') 40 | dc.addref([0, 1, 0], [0, 60, 0, 30, 0, 90], en, 'ref2') 41 | 42 | def test_orientation_phase(): 43 | # assumes reflections added were ideal (with no mis-mount) 44 | dc.ub() 45 | dc.checkub() 46 | dc.showref() 47 | 48 | U = matrix('1 0 0; 0 1 0; 0 0 1') 49 | UB = U * 2 * pi 50 | mneq_(dc._ub.ubcalc.U, U) 51 | mneq_(dc._ub.ubcalc.UB, UB) 52 | 53 | def test_angles_to_hkl_bypassing_hardware_plugin(): 54 | hkl_calc, param_calc = dc.angles_to_hkl(angles, en) 55 | aneq_(hkl_calc, [1, 0, 0]) 56 | dneq_(param_calc, param) 57 | 58 | def test_hkl_to_angles_bypassing_hardware_plugin(): 59 | dc.con('a_eq_b') 60 | dc.con('mu', 0) 61 | dc.con(NUNAME, 0) 62 | 63 | h, k, l = [1, 0, 0] 64 | angles_calc, param_calc = dc.hkl_to_angles(h, k, l, en) 65 | aneq_(angles_calc, angles) 66 | dneq_(param_calc, param) 67 | 68 | def test_angles_to_hkl(): 69 | hkl_calc, param_calc = dc.angles_to_hkl(angles) 70 | aneq_(hkl_calc, [1, 0, 0]) 71 | dneq_(param_calc, param) 72 | 73 | def test_hkl_to_angles(): 74 | dc.con('a_eq_b') 75 | dc.con('mu', 0) 76 | dc.con(NUNAME, 0) 77 | 78 | h, k, l = [1, 0, 0] 79 | angles_calc, param_calc = dc.hkl_to_angles(h, k, l) 80 | aneq_(angles_calc, angles) 81 | dneq_(param_calc, param) 82 | 83 | def test_allhkl(): 84 | diffcalc.util.DEBUG = True 85 | dc.con('eta', 0, 'chi', 0, 'phi', 0) 86 | dc.allhkl([.1, 0, .01], 1) 87 | 88 | 89 | # def test_ub_help_visually(self): 90 | # print "-" * 80 + "\nub:" 91 | # print format_command_help(self.dc.ub.commands) 92 | # 93 | # def test_hkl_help_visually(self): 94 | # print "-" * 80 + "\nhkl:" 95 | # print format_command_help(self.dc.hkl.commands) -------------------------------------------------------------------------------- /diffcalc/tests/gdasupport/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/tests/gdasupport/__init__.py -------------------------------------------------------------------------------- /diffcalc/tests/gdasupport/minigda/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/tests/gdasupport/minigda/__init__.py -------------------------------------------------------------------------------- /diffcalc/tests/gdasupport/minigda/test_scannable.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | import unittest 20 | 21 | try: 22 | from gdascripts.pd.dummy_pds import DummyPD # @UnusedImport 23 | except ImportError: 24 | from diffcalc.gdasupport.minigda.scannable import DummyPD 25 | 26 | from diffcalc.gdasupport.scannable.mock import MockMotor 27 | from diffcalc.gdasupport.minigda.scannable import \ 28 | SingleFieldDummyScannable 29 | from diffcalc.gdasupport.minigda.scannable import Scannable 30 | from diffcalc.gdasupport.minigda.scannable import ScannableGroup 31 | 32 | 33 | class TestScannable(object): 34 | 35 | def setup_method(self): 36 | self.scannable = Scannable() 37 | 38 | def testSomethingUnrelated(self): 39 | a = SingleFieldDummyScannable('a') 40 | print isinstance(a, Scannable) 41 | 42 | 43 | def createDummyAxes(names): 44 | result = [] 45 | for name in names: 46 | result.append(DummyPD(name)) 47 | return result 48 | 49 | 50 | class TestScannableGroup(object): 51 | 52 | def setup_method(self): 53 | self.a = MockMotor('a') 54 | self.b = MockMotor('bbb') 55 | self.c = MockMotor('c') 56 | self.sg = ScannableGroup('abc', (self.a, self.b, self.c)) 57 | 58 | def testInit(self): 59 | assert list(self.sg.getInputNames()) == ['a', 'bbb', 'c'] 60 | assert self.sg.getPosition() == [0.0, 0.0, 0.0] 61 | 62 | def testAsynchronousMoveTo(self): 63 | self.sg.asynchronousMoveTo([1, 2.0, 3]) 64 | assert self.sg.getPosition() == [1.0, 2.0, 3.0] 65 | 66 | def testAsynchronousMoveToWithNones(self): 67 | self.sg.asynchronousMoveTo([1.0, 2.0, 3.0]) 68 | self.sg.asynchronousMoveTo([None, None, 3.2]) 69 | assert self.sg.getPosition() == [1.0, 2.0, 3.2] 70 | 71 | def testGetPosition(self): 72 | # implicitely tested above 73 | pass 74 | 75 | def testIsBusy(self): 76 | assert not self.sg.isBusy() 77 | self.sg.asynchronousMoveTo([1.0, 2.0, 3.0]) 78 | assert self.sg.isBusy() 79 | self.b.makeNotBusy() 80 | assert self.sg.isBusy() 81 | self.a.makeNotBusy() 82 | self.c.makeNotBusy() 83 | assert not self.sg.isBusy() 84 | -------------------------------------------------------------------------------- /diffcalc/tests/gdasupport/scannable/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/tests/gdasupport/scannable/__init__.py -------------------------------------------------------------------------------- /diffcalc/tests/gdasupport/scannable/mockdiffcalc.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | class MockParameterManager: 20 | 21 | def __init__(self): 22 | self.params = {} 23 | 24 | def set_constraint(self, name, value): 25 | self.params[name] = value 26 | 27 | def get_constraint(self, name): 28 | return self.params[name] 29 | 30 | 31 | class MockDiffcalc: 32 | 33 | def __init__(self, numberAngles): 34 | self.numberAngles = numberAngles 35 | self.parameter_manager = MockParameterManager() 36 | 37 | def hkl_to_angles(self, h, k, l): 38 | params = {} 39 | params['theta'] = 1. 40 | params['2theta'] = 12. 41 | params['Bin'] = 123. 42 | params['Bout'] = 1234. 43 | params['azimuth'] = 12345. 44 | return ([h] * self.numberAngles, params) 45 | 46 | def angles_to_hkl(self, pos): 47 | if len(pos) != self.numberAngles: raise ValueError 48 | params = {} 49 | params['theta'] = 1. 50 | params['2theta'] = 12. 51 | params['Bin'] = 123. 52 | params['Bout'] = 1234. 53 | params['azimuth'] = 12345. 54 | return ([pos[0]] * 3, params) 55 | 56 | -------------------------------------------------------------------------------- /diffcalc/tests/gdasupport/scannable/test_parameter.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | import unittest 20 | 21 | from diffcalc.gdasupport.scannable.parameter import \ 22 | DiffractionCalculatorParameter 23 | from diffcalc.tests.gdasupport.scannable.mockdiffcalc import \ 24 | MockParameterManager 25 | 26 | 27 | class TestDiffractionCalculatorParameter(object): 28 | 29 | def setup_method(self): 30 | self.dcp = DiffractionCalculatorParameter('dcp', 'betain', 31 | MockParameterManager()) 32 | 33 | def testAsynchronousMoveToAndGetPosition(self): 34 | self.dcp.asynchronousMoveTo(12.3) 35 | assert self.dcp.getPosition() == [12.3,] 36 | 37 | def testIsBusy(self): 38 | assert not self.dcp.isBusy() 39 | -------------------------------------------------------------------------------- /diffcalc/tests/gdasupport/scannable/test_simulation.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | from math import pi 20 | import unittest 21 | from pytest import approx 22 | 23 | try: 24 | from numpy import matrix 25 | except ImportError: 26 | from numjy import matrix 27 | 28 | from diffcalc.gdasupport.scannable.simulation import SimulatedCrystalCounter, \ 29 | Gaussian 30 | from diffcalc.hkl.vlieg.geometry import Fourc 31 | from diffcalc.util import nearlyEqual 32 | from diffcalc.tests.tools import mneq_ 33 | 34 | 35 | class MockScannable(object): 36 | def __init__(self): 37 | self.pos = None 38 | 39 | def getPosition(self): 40 | return self.pos 41 | 42 | 43 | class MockEquation(object): 44 | 45 | def __call__(self, dh, dk, dl): 46 | self.dHkl = dh, dk, dl 47 | return 1 48 | 49 | 50 | class TestSimulatedCrystalCounter(object): 51 | 52 | def setup_method(self): 53 | self.diff = MockScannable() 54 | self.wl = MockScannable() 55 | self.wl.pos = 1. 56 | self.eq = MockEquation() 57 | self.scc = SimulatedCrystalCounter('det', self.diff, Fourc(), self.wl, 58 | self.eq) 59 | 60 | def testInit(self): 61 | assert list(self.scc.getInputNames()) == ['det_count'] 62 | assert list(self.scc.getExtraNames()) == [] 63 | assert self.scc.chiMissmount == 0. 64 | assert self.scc.phiMissmount == 0. 65 | 66 | def testCalcUB(self): 67 | UB = matrix([[2 * pi, 0, 0], [0, 2 * pi, 0], [0, 0, 2 * pi]]) 68 | mneq_(self.scc.UB, UB) 69 | 70 | def testGetHkl(self): 71 | self.diff.pos = [60, 30, 0, 0] 72 | hkl = self.scc.getHkl() 73 | assert hkl == approx((1, 0, 0)) 74 | 75 | self.diff.pos = [60, 31, 0, 0] 76 | hkl = self.scc.getHkl() 77 | assert hkl == approx((0.999847695156391, 0.017452406437283574, 0)) 78 | 79 | def testGetPosition(self): 80 | self.diff.pos = [60, 30, 0, 0] 81 | self.scc.asynchronousMoveTo(2) 82 | count = self.scc.getPosition() 83 | assert self.eq.dHkl == approx((0, 0, 0)) 84 | assert count == 2 85 | 86 | self.diff.pos = [60, 31, 0, 0] 87 | count = self.scc.getPosition() 88 | dHkl = (0.999847695156391 - 1, .017452406437283574, 0) 89 | assert self.eq.dHkl == approx(dHkl) 90 | assert count == 2 91 | 92 | def test__repr__(self): 93 | self.diff.pos = [60, 30, 0, 0] 94 | print self.scc.__repr__() 95 | 96 | 97 | class TestGaussianEquation(object): 98 | def setup_method(self): 99 | self.eq = Gaussian(1.) 100 | 101 | def test__call__(self): 102 | assert self.eq(0, 0, 0) == 0.3989422804014327 103 | -------------------------------------------------------------------------------- /diffcalc/tests/gdasupport/scannable/test_wavelength.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | import unittest 20 | 21 | from diffcalc.gdasupport.scannable.wavelength import Wavelength 22 | try: 23 | from gdascripts.pd.dummy_pds import DummyPD 24 | except ImportError: 25 | from diffcalc.gdasupport.minigda.scannable import DummyPD 26 | 27 | 28 | class TestWavelength(object): 29 | 30 | def setup_method(self): 31 | self.en = DummyPD('en') 32 | self.wl = Wavelength('wl', self.en) 33 | 34 | def testIt(self): 35 | self.en.asynchronousMoveTo(12.39842) 36 | assert self.wl.getPosition() == 1 37 | 38 | self.wl.asynchronousMoveTo(1.) 39 | assert self.wl.getPosition() == 1. 40 | assert self.en.getPosition() == 12.39842 41 | -------------------------------------------------------------------------------- /diffcalc/tests/hkl/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/tests/hkl/__init__.py -------------------------------------------------------------------------------- /diffcalc/tests/hkl/vlieg/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/tests/hkl/vlieg/__init__.py -------------------------------------------------------------------------------- /diffcalc/tests/hkl/vlieg/test_constraints.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | import unittest 20 | 21 | from diffcalc.hkl.vlieg.constraints import ModeSelector, VliegParameterManager 22 | from diffcalc.util import DiffcalcException 23 | from diffcalc.tests.hkl.vlieg.test_calc import \ 24 | createMockHardwareMonitor, createMockDiffractometerGeometry 25 | import pytest 26 | 27 | 28 | class TestModeSelector(object): 29 | 30 | def setup_method(self): 31 | 32 | self.ms = ModeSelector(createMockDiffractometerGeometry(), 33 | parameterManager=None) 34 | self.pm = VliegParameterManager(createMockDiffractometerGeometry(), 35 | None, self.ms) 36 | self.ms.setParameterManager(self.pm) 37 | 38 | def testSetModeByIndex(self): 39 | self.ms.setModeByIndex(0) 40 | assert self.ms.getMode().name == '4cFixedw' 41 | self.ms.setModeByIndex(1) 42 | assert self.ms.getMode().name == '4cBeq' 43 | 44 | def testGetMode(self): 45 | # tested implicetely by testSetmode 46 | pass 47 | 48 | def testShowAvailableModes(self): 49 | print self.ms.reportAvailableModes() 50 | 51 | 52 | class TestParameterManager(object): 53 | 54 | def setup_method(self): 55 | self.hw = createMockHardwareMonitor() 56 | self.ms = ModeSelector(createMockDiffractometerGeometry()) 57 | self.pm = VliegParameterManager(createMockDiffractometerGeometry(), 58 | self.hw, self.ms) 59 | 60 | def testDefaultParameterValues(self): 61 | assert self.pm.get_constraint('alpha') == 0 62 | assert self.pm.get_constraint('gamma') == 0 63 | with pytest.raises(DiffcalcException): 64 | self.pm.get_constraint('not-a-parameter-name') 65 | 66 | def testSetParameter(self): 67 | self.pm.set_constraint('alpha', 10.1) 68 | assert self.pm.get_constraint('alpha') == 10.1 69 | 70 | def testSetTrackParameter_isParameterChecked(self): 71 | assert not self.pm.isParameterTracked('alpha') 72 | self.pm.set_constraint('alpha', 9) 73 | 74 | self.pm.setTrackParameter('alpha', True) 75 | assert self.pm.isParameterTracked('alpha') == True 76 | with pytest.raises(DiffcalcException): 77 | self.pm.set_constraint('alpha', 10) 78 | self.hw.get_position.return_value = 888, 11, 999 79 | assert self.pm.get_constraint('alpha') == 11 80 | 81 | print self.pm.reportAllParameters() 82 | print "**" 83 | print self.ms.reportCurrentMode() 84 | print self.pm.reportParametersUsedInCurrentMode() 85 | 86 | self.pm.setTrackParameter('alpha', False) 87 | assert not self.pm.isParameterTracked('alpha') 88 | assert self.pm.get_constraint('alpha') == 11 89 | self.hw.get_position.return_value = 888, 12, 999 90 | assert self.pm.get_constraint('alpha') == 11 91 | self.pm.set_constraint('alpha', 13) 92 | assert self.pm.get_constraint('alpha') == 13 93 | -------------------------------------------------------------------------------- /diffcalc/tests/hkl/vlieg/test_hkl.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | import unittest 20 | 21 | from mock import Mock 22 | 23 | import diffcalc.util # @UnusedImport to overide raw_input 24 | from diffcalc.hkl.vlieg.geometry import SixCircleGammaOnArmGeometry 25 | from diffcalc.hardware import DummyHardwareAdapter 26 | from diffcalc.util import MockRawInput 27 | from diffcalc.hkl.vlieg.calc import VliegHklCalculator 28 | from diffcalc.ub.calc import UBCalculation 29 | from diffcalc.ub.persistence import UbCalculationNonPersister 30 | import pytest 31 | 32 | try: 33 | from gdascripts.pd.dummy_pds import DummyPD # @UnusedImport 34 | except ImportError: 35 | from diffcalc.gdasupport.minigda.scannable import DummyPD 36 | 37 | 38 | def prepareRawInput(listOfStrings): 39 | diffcalc.util.raw_input = MockRawInput(listOfStrings) 40 | 41 | prepareRawInput([]) 42 | 43 | 44 | class TestHklCommands(object): 45 | 46 | def setup_method(self): 47 | from diffcalc import settings 48 | settings.geometry = SixCircleGammaOnArmGeometry() 49 | dummy = 'alpha', 'delta', 'gamma', 'omega', 'chi', 'phi' 50 | settings.hardware = DummyHardwareAdapter(dummy) 51 | self.mock_ubcalc = Mock(spec=UBCalculation) 52 | self.hklcalc = VliegHklCalculator(self.mock_ubcalc, True) 53 | settings.ubcalc_persister = UbCalculationNonPersister() 54 | 55 | from diffcalc.hkl.vlieg import hkl 56 | reload(hkl) 57 | hkl.hklcalc = self.hklcalc 58 | self.hkl = hkl 59 | prepareRawInput([]) 60 | 61 | def testHklmode(self): 62 | with pytest.raises(TypeError): 63 | self.hkl.hklmode(1, 2) 64 | with pytest.raises(ValueError): 65 | self.hkl.hklmode('unwanted_string') 66 | print self.hkl.hklmode() 67 | print self.hkl.hklmode(1) 68 | 69 | def testSetWithString(self): 70 | self.hkl.setpar() 71 | self.hkl.setpar('alpha') 72 | self.hkl.setpar('alpha', 1) 73 | self.hkl.setpar('alpha', 1.1) 74 | pm = self.hkl.hklcalc.parameter_manager 75 | assert pm.get_constraint('alpha') == 1.1 76 | 77 | def testSetWithScannable(self): 78 | alpha = DummyPD('alpha') 79 | self.hkl.setpar(alpha, 1.1) 80 | pm = self.hkl.hklcalc.parameter_manager 81 | assert pm.get_constraint('alpha') == 1.1 82 | -------------------------------------------------------------------------------- /diffcalc/tests/hkl/willmot/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/tests/hkl/willmot/__init__.py -------------------------------------------------------------------------------- /diffcalc/tests/hkl/you/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/tests/hkl/you/__init__.py -------------------------------------------------------------------------------- /diffcalc/tests/hkl/you/test_hkl.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | 20 | from mock import Mock, call 21 | from diffcalc import settings 22 | 23 | import diffcalc 24 | from diffcalc.tests.test_hardware import SimpleHardwareAdapter 25 | from diffcalc.hkl.you.geometry import SixCircle 26 | diffcalc.util.DEBUG = True 27 | 28 | 29 | hkl = None 30 | def setup_module(): 31 | global hkl 32 | settings.hardware=SimpleHardwareAdapter([]) 33 | settings.geometry=SixCircle() 34 | settings.angles_to_hkl_function=Mock() 35 | settings.ubcalc_strategy=Mock() 36 | settings.geometry.fixed_constraints = {} 37 | 38 | from diffcalc.hkl.you import hkl 39 | reload(hkl) 40 | 41 | hkl.hklcalc = Mock() 42 | hkl.hklcalc.constraints.report_constraints_lines.return_value = ['report1', 'report2'] 43 | 44 | 45 | def test_con_with_1_constraint(): 46 | hkl.con('cona') 47 | hkl.hklcalc.constraints.constrain.assert_called_with('cona') 48 | 49 | def test_con_with_1_constraint_with_value(): 50 | hkl.con('cona', 123) 51 | hkl.hklcalc.constraints.constrain.assert_called_with('cona') 52 | hkl.hklcalc.constraints.set_constraint.assert_called_with('cona', 123) 53 | 54 | def test_con_with_3_constraints(): 55 | hkl.con('cona', 'conb', 'conc') 56 | hkl.hklcalc.constraints.clear_constraints.assert_called() 57 | calls = [call('cona'), call('conb'), call('conc')] 58 | hkl.hklcalc.constraints.constrain.assert_has_calls(calls) 59 | 60 | def test_con_with_3_constraints_first_val(): 61 | hkl.con('cona', 1, 'conb', 'conc') 62 | hkl.hklcalc.constraints.clear_constraints.assert_called() 63 | calls = [call('cona'), call('conb'), call('conc')] 64 | hkl.hklcalc.constraints.constrain.assert_has_calls(calls) 65 | hkl.hklcalc.constraints.set_constraint.assert_called_with('cona', 1) 66 | 67 | def test_con_with_3_constraints_second_val(): 68 | hkl.con('cona', 'conb', 2, 'conc') 69 | hkl.hklcalc.constraints.clear_constraints.assert_called() 70 | calls = [call('cona'), call('conb'), call('conc')] 71 | hkl.hklcalc.constraints.constrain.assert_has_calls(calls) 72 | hkl.hklcalc.constraints.set_constraint.assert_called_with('conb', 2) 73 | 74 | def test_con_with_3_constraints_third_val(): 75 | hkl.con('cona', 'conb', 'conc', 3) 76 | hkl.hklcalc.constraints.clear_constraints.assert_called() 77 | calls = [call('cona'), call('conb'), call('conc')] 78 | hkl.hklcalc.constraints.constrain.assert_has_calls(calls) 79 | hkl.hklcalc.constraints.set_constraint.assert_called_with('conc', 3) 80 | 81 | def test_con_with_3_constraints_all_vals(): 82 | hkl.con('cona', 1, 'conb', 2, 'conc', 3) 83 | hkl.hklcalc.constraints.clear_constraints.assert_called() 84 | calls = [call('cona'), call('conb'), call('conc')] 85 | hkl.hklcalc.constraints.constrain.assert_has_calls(calls) 86 | calls = [call('cona', 1), call('conb', 2), call('conc', 3)] 87 | hkl.hklcalc.constraints.set_constraint.assert_has_calls(calls) 88 | 89 | def test_con_messages_and_help_visually(): 90 | hkl.con() 91 | print "**" 92 | print hkl.con.__doc__ 93 | 94 | def test_con_message_display_whenn_selecting_an_unimplmented_mode(): 95 | hkl.hklcalc.constraints.is_fully_constrained.return_value = True 96 | hkl.hklcalc.constraints.is_current_mode_implemented.return_value = False 97 | hkl.con('phi', 'chi', 'eta') 98 | -------------------------------------------------------------------------------- /diffcalc/tests/ub/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/tests/ub/__init__.py -------------------------------------------------------------------------------- /diffcalc/tests/ub/test_calculation_you.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | from math import pi 20 | from mock import Mock 21 | from diffcalc import settings 22 | 23 | try: 24 | from numpy import matrix 25 | except ImportError: 26 | from numjy import matrix 27 | 28 | from diffcalc.hkl.you.geometry import SixCircle 29 | from diffcalc.hkl.you.geometry import YouPosition 30 | from diffcalc.hkl.you.calc import YouUbCalcStrategy 31 | from diffcalc.tests.tools import matrixeq_ 32 | from diffcalc.ub.calc import UBCalculation 33 | from diffcalc.ub.persistence import UbCalculationNonPersister 34 | 35 | #newub 'cubic' <--> reffile('cubic) 36 | #setlat 'cubic' 1 1 1 90 90 90 <--> latt([1,1,1,90,90,90]) 37 | #pos wl 1 <--> BLi.setWavelength(1) 38 | # <--> c2th([0,0,1]) --> 60 39 | #pos sixc [0 60 0 30 1 1] <--> pos euler [1 1 30 0 60 0] 40 | #addref 1 0 0 <--> saveref('100',[1, 0, 0]) 41 | #pos chi 91 <--> 42 | #addref 0 0 1 <--> saveref('100',[1, 0, 0]) ; showref() 43 | # ubm('100','001') 44 | # ubm() -> 45 | #array('d', [0.9996954135095477, -0.01745240643728364, -0.017449748351250637, 46 | #0.01744974835125045, 0.9998476951563913, -0.0003045864904520898, 47 | #0.017452406437283505, -1.1135499981271473e-16, 0.9998476951563912]) 48 | 49 | 50 | def posFromI16sEuler(phi, chi, eta, mu, delta, gamma): 51 | return YouPosition(mu, delta, gamma, eta, chi, phi, unit='DEG') 52 | 53 | UB1 = matrix( 54 | ((0.9996954135095477, -0.01745240643728364, -0.017449748351250637), 55 | (0.01744974835125045, 0.9998476951563913, -0.0003045864904520898), 56 | (0.017452406437283505, -1.1135499981271473e-16, 0.9998476951563912)) 57 | ) * (2 * pi) 58 | 59 | EN1 = 12.39842 60 | REF1a = posFromI16sEuler(1, 1, 30, 0, 60, 0) 61 | REF1b = posFromI16sEuler(1, 91, 30, 0, 60, 0) 62 | 63 | 64 | class TestUBCalculationWithYouStrategy(): 65 | """Testing the math only here. 66 | """ 67 | 68 | def setup_method(self): 69 | geometry = SixCircle() # pass through 70 | hardware = Mock() 71 | names = 'm', 'd', 'n', 'e', 'c', 'p' 72 | hardware.get_axes_names.return_value = names 73 | settings.hardware = hardware 74 | settings.geometry = geometry 75 | self.ubcalc = UBCalculation(UbCalculationNonPersister(), 76 | YouUbCalcStrategy()) 77 | 78 | def testAgainstI16Results(self): 79 | self.ubcalc.start_new('cubcalc') 80 | self.ubcalc.set_lattice('latt', 1, 1, 1, 90, 90, 90) 81 | self.ubcalc.add_reflection(1, 0, 0, REF1a, EN1, '100', None) 82 | self.ubcalc.add_reflection(0, 0, 1, REF1b, EN1, '001', None) 83 | self.ubcalc.calculate_UB() 84 | matrixeq_(self.ubcalc.UB, UB1) 85 | -------------------------------------------------------------------------------- /diffcalc/tests/ub/test_crystal.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | import unittest 20 | 21 | try: 22 | from numpy import matrix 23 | except ImportError: 24 | from numjy import matrix 25 | 26 | from diffcalc.tests.tools import assert_dict_almost_equal, mneq_ 27 | from diffcalc.ub.crystal import CrystalUnderTest 28 | from diffcalc.tests import scenarios 29 | 30 | 31 | class TestCrystalUnderTest(object): 32 | 33 | def setup_method(self): 34 | self.tclatt = [] 35 | self.tcbmat = [] 36 | 37 | # From the dif_init.mat next to dif_dos.exe on Vlieg's cd 38 | #self.tclatt.append([4.0004, 4.0004, 2.270000, 90, 90, 90]) 39 | #self.tcbmat.append([[1.570639, 0, 0] ,[0.0, 1.570639, 0] , 40 | # [0.0, 0.0, 2.767923]]) 41 | 42 | # From b16 on 27June2008 (From Chris Nicklin) 43 | # self.tclatt.append([3.8401, 3.8401, 5.43072, 90, 90, 90]) 44 | # self.tcbmat.append([[1.636204, 0, 0],[0, 1.636204, 0], 45 | # [0, 0, 1.156971]]) 46 | 47 | def testGetBMatrix(self): 48 | # Check the calculated B Matrix 49 | for sess in scenarios.sessions(): 50 | if sess.bmatrix is None: 51 | continue 52 | cut = CrystalUnderTest('tc', *sess.lattice) 53 | desired = matrix(sess.bmatrix) 54 | print desired.tolist() 55 | answer = cut.B 56 | print answer.tolist() 57 | note = "Incorrect B matrix calculation for scenario " + sess.name 58 | mneq_(answer, desired, 4, note=note) 59 | 60 | def test__str__(self): 61 | cut = CrystalUnderTest("HCl", 1, 2, 3, 4, 5, 6) 62 | print cut.__str__() -------------------------------------------------------------------------------- /diffcalc/tests/ub/test_orientations.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2019 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | from datetime import datetime 20 | from diffcalc.ub.orientations import OrientationList 21 | from diffcalc.hkl.you.geometry import YouPosition as Pos, SixCircle 22 | from diffcalc.util import DiffcalcException 23 | import pytest 24 | 25 | 26 | class TestOrientationList(object): 27 | 28 | def setup_method(self): 29 | self._geometry = SixCircle() 30 | self.orientlist = OrientationList(self._geometry, 31 | ['a', 'd', 'g', 'o', 'c', 'p']) 32 | self.time = datetime.now() 33 | pos = Pos(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 'DEG') 34 | self.orientlist.add_orientation(1, 2, 3, 0.1, 0.2, 0.3, pos, "orient1", self.time) 35 | pos = Pos(0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 'DEG') 36 | self.orientlist.add_orientation(1.1, 2.2, 3.3, 0.11, 0.12, 0.13, pos, "orient2", self.time) 37 | 38 | def test_add_orientation(self): 39 | assert len(self.orientlist) == 2 40 | pos = Pos(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 'DEG') 41 | self.orientlist.add_orientation(10, 20, 30, 0.1, 0.2, 0.3, pos, "orient1", self.time) 42 | 43 | def testGetOrientation(self): 44 | pos = Pos(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 'DEG') 45 | answered = self.orientlist.getOrientation(1) 46 | desired = ([1, 2, 3], [0.1, 0.2, 0.3], pos, "orient1", self.time) 47 | assert answered == desired 48 | answered = self.orientlist.getOrientation("orient1") 49 | assert answered == desired 50 | 51 | def testRemoveOrientation(self): 52 | self.orientlist.removeOrientation(1) 53 | pos = Pos(0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 'DEG') 54 | answered = self.orientlist.getOrientation(1) 55 | desired = ([1.1, 2.2, 3.3], [0.11, 0.12, 0.13], pos, "orient2", self.time) 56 | assert answered == desired 57 | self.orientlist.removeOrientation("orient2") 58 | assert self.orientlist._orientlist == [] 59 | 60 | def testedit_orientation(self): 61 | ps = Pos(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 'DEG') 62 | self.orientlist.edit_orientation(1, 10, 20, 30, 1, 2, 3, ps, "new1", self.time) 63 | assert (self.orientlist.getOrientation(1) 64 | == ([10, 20, 30], [1, 2, 3], ps, "new1", self.time)) 65 | pos = Pos(0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 'DEG') 66 | assert (self.orientlist.getOrientation(2) 67 | == ([1.1, 2.2, 3.3], [0.11, 0.12, 0.13], pos, "orient2", self.time)) 68 | self.orientlist.edit_orientation("orient2", 1.1, 2.2, 3.3, 1.11, 1.12, 1.13, pos, "new2", self.time) 69 | assert (self.orientlist.getOrientation("new2") 70 | == ([1.1, 2.2, 3.3], [1.11, 1.12, 1.13], pos, "new2", self.time)) 71 | self.orientlist.edit_orientation("new2", 1.1, 2.2, 3.3, 1.11, 1.12, 1.13, pos, "new1", self.time) 72 | assert (self.orientlist.getOrientation("new1") 73 | == ([10, 20, 30], [1, 2, 3], ps, "new1", self.time)) 74 | 75 | def testSwapOrientation(self): 76 | self.orientlist.swap_orientations(1, 2) 77 | pos = Pos(0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 'DEG') 78 | assert (self.orientlist.getOrientation(1) 79 | == ([1.1, 2.2, 3.3], [0.11, 0.12, 0.13], pos, "orient2", self.time)) 80 | pos = Pos(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 'DEG') 81 | assert (self.orientlist.getOrientation(2) 82 | == ([1, 2, 3], [0.1, 0.2, 0.3], pos, "orient1", self.time)) 83 | self.orientlist.swap_orientations("orient1", "orient2") 84 | pos = Pos(0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 'DEG') 85 | assert (self.orientlist.getOrientation(2) 86 | == ([1.1, 2.2, 3.3], [0.11, 0.12, 0.13], pos, "orient2", self.time)) 87 | pos = Pos(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 'DEG') 88 | assert (self.orientlist.getOrientation(1) 89 | == ([1, 2, 3], [0.1, 0.2, 0.3], pos, "orient1", self.time)) 90 | -------------------------------------------------------------------------------- /diffcalc/tests/ub/test_persistence.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | import os 20 | import shutil 21 | import unittest 22 | import tempfile 23 | import time 24 | from nose.tools import eq_ # @UnresolvedImport 25 | 26 | try: 27 | from gda.configuration.properties import LocalProperties 28 | except ImportError: 29 | print "Could not import LocalProperties to configure database locations." 30 | 31 | from diffcalc.ub.persistence import UbCalculationNonPersister, UBCalculationJSONPersister 32 | from diffcalc.ub.calcstate import UBCalcStateEncoder 33 | 34 | 35 | def prepareEmptyGdaVarFolder(): 36 | vartest_dir = os.path.join(os.getcwd(), 'var_test') 37 | LocalProperties.set('gda.var', vartest_dir) 38 | if os.path.exists(vartest_dir): 39 | print "Removing existing gda.var: ", vartest_dir 40 | shutil.rmtree(vartest_dir) 41 | print "Creating gda.var: ", vartest_dir 42 | os.mkdir(vartest_dir) 43 | 44 | 45 | class TestUBCalculationNonPersister(object): 46 | 47 | def setup_method(self): 48 | self.persister = UbCalculationNonPersister() 49 | 50 | def testSaveAndLoad(self): 51 | self.persister.save('string1', 'ub1') 52 | 53 | 54 | class TestUBCalculationJSONPersister(object): 55 | 56 | def setup_method(self): 57 | self.tmpdir = tempfile.mkdtemp() 58 | print self.tmpdir 59 | self.persister = UBCalculationJSONPersister(self.tmpdir, UBCalcStateEncoder) 60 | f = open(os.path.join(self.tmpdir, 'unexpected_file'), 'w') 61 | f.close() 62 | 63 | def test_list_with_empty_dir(self): 64 | eq_(self.persister.list(), []) 65 | 66 | def test_save_load(self): 67 | d = {'a' : 1, 'b': 2} 68 | self.persister.save(d, 'first') 69 | eq_(self.persister.load('first'), d) 70 | 71 | def test_save_overwites(self): 72 | d1 = {'a' : 1, 'b': 2} 73 | self.persister.save(d1, 'first') 74 | eq_(self.persister.load('first'), d1) 75 | 76 | d2 = {'a' : 3, 'b': 4, 'c' : 5} 77 | self.persister.save(d2, 'first') 78 | eq_(self.persister.load('first'), d2) 79 | 80 | def test_list(self): 81 | d = {'a' : 1, 'b': 2} 82 | self.persister.save(d, 'first') 83 | eq_(self.persister.list(), ['first']) 84 | 85 | def test_multiple_list(self): 86 | d = {'a' : 1, 'b': 2} 87 | self.persister.save(d, 'first_written') 88 | time.sleep(1.) 89 | eq_(self.persister.list(), ['first_written']) 90 | self.persister.save(d, 'second_written') 91 | time.sleep(1.) 92 | eq_(self.persister.list(), ['second_written', 'first_written']) 93 | self.persister.save(d, 'third_written') 94 | time.sleep(1.) 95 | eq_(self.persister.list(), ['third_written', 'second_written', 'first_written']) 96 | 97 | def test_remove_list(self): 98 | d = {'a' : 1, 'b': 2} 99 | self.persister.save(d, 'first') 100 | self.persister.remove('first') 101 | eq_(self.persister.list(), []) 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /diffcalc/tests/ub/test_reference.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | from mock import Mock 20 | from diffcalc.ub.reference import YouReference 21 | from diffcalc.tests.tools import assert_array_almost_equal, assert_2darray_almost_equal 22 | 23 | try: 24 | from numpy import matrix, hstack 25 | from numpy.linalg import norm 26 | except ImportError: 27 | from numjy import matrix, hstack 28 | from numjy.linalg import norm 29 | 30 | 31 | class TestYouReference(): 32 | 33 | def setup_method(self): 34 | self.get_UB = Mock() 35 | self.reference = YouReference(self.get_UB) 36 | self.reference._set_n_phi_configured(matrix('0; 0; 1')) 37 | self.get_UB.return_value = matrix('1 0 0; 0 1 0; 0 0 1') 38 | 39 | def test_default_n_phi(self): 40 | assert_2darray_almost_equal(self.reference.n_phi.tolist(), matrix('0; 0; 1').tolist()) 41 | 42 | def test__str__with_phi_configured(self): 43 | print self.reference 44 | 45 | def test__str__with_hkl_configured(self): 46 | self.reference.n_hkl_configured = matrix('0; 1; 1') 47 | print self.reference 48 | 49 | def test_n_phi_from_hkl_with_unity_matrix_001(self): 50 | self.get_UB.return_value = matrix('1 0 0; 0 1 0; 0 0 1') 51 | self.reference.n_hkl_configured = matrix('0; 0; 1') 52 | assert_2darray_almost_equal(self.reference.n_phi.tolist(), matrix('0; 0; 1').tolist()) 53 | 54 | def test_n_phi_from_hkl_with_unity_matrix_010(self): 55 | self.get_UB.return_value = matrix('1 0 0; 0 1 0; 0 0 1') 56 | self.reference.n_hkl_configured = matrix('0; 1; 0') 57 | assert_2darray_almost_equal(self.reference.n_phi.tolist(), matrix('0; 1; 0').tolist()) 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /diffcalc/tests/ub/test_reflections.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | from datetime import datetime 20 | from diffcalc.ub.reflections import ReflectionList 21 | from diffcalc.hkl.you.geometry import YouPosition as Pos, SixCircle 22 | from diffcalc.util import DiffcalcException 23 | import pytest 24 | 25 | 26 | class TestReflectionList(object): 27 | 28 | def setup_method(self): 29 | self._geometry = SixCircle() 30 | self.reflist = ReflectionList(self._geometry, 31 | ['a', 'd', 'g', 'o', 'c', 'p']) 32 | self.time = datetime.now() 33 | pos = Pos(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 'DEG') 34 | self.reflist.add_reflection(1, 2, 3, pos, 1000, "ref1", self.time) 35 | pos = Pos(0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 'DEG') 36 | self.reflist.add_reflection(1.1, 2.2, 3.3, pos, 1100, "ref2", self.time) 37 | 38 | def test_add_reflection(self): 39 | assert len(self.reflist) == 2 40 | pos = Pos(0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 'DEG') 41 | self.reflist.add_reflection(11.1, 12.2, 13.3, pos, 1100, "ref2", self.time) 42 | 43 | def testGetReflection(self): 44 | answered = self.reflist.getReflection(1) 45 | pos = Pos(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 'DEG') 46 | desired = ([1, 2, 3], pos, 1000, "ref1", self.time) 47 | assert answered == desired 48 | answered = self.reflist.getReflection('ref1') 49 | assert answered == desired 50 | 51 | def testRemoveReflection(self): 52 | self.reflist.removeReflection(1) 53 | answered = self.reflist.getReflection(1) 54 | pos = Pos(0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 'DEG') 55 | desired = ([1.1, 2.2, 3.3], pos, 1100, "ref2", self.time) 56 | assert answered == desired 57 | self.reflist.removeReflection("ref2") 58 | assert self.reflist._reflist == [] 59 | 60 | def testedit_reflection(self): 61 | ps = Pos(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 'DEG') 62 | self.reflist.edit_reflection(1, 10, 20, 30, ps, 1000, "new1", self.time) 63 | assert (self.reflist.getReflection(1) 64 | == ([10, 20, 30], ps, 1000, "new1", self.time)) 65 | pos = Pos(0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 'DEG') 66 | assert (self.reflist.getReflection(2) 67 | == ([1.1, 2.2, 3.3], pos, 1100, "ref2", self.time)) 68 | self.reflist.edit_reflection("ref2", 1.1, 2.2, 3.3, pos, 1100, "new2", self.time) 69 | assert (self.reflist.getReflection("new2") 70 | == ([1.1, 2.2, 3.3], pos, 1100, "new2", self.time)) 71 | self.reflist.edit_reflection("new2", 10, 20, 30, pos, 1100, "new1", self.time) 72 | assert (self.reflist.getReflection("new1") 73 | == ([10, 20, 30], ps, 1000, "new1", self.time)) 74 | 75 | def testSwapReflection(self): 76 | self.reflist.swap_reflections(1, 2) 77 | pos = Pos(0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 'DEG') 78 | assert (self.reflist.getReflection(1) 79 | == ([1.1, 2.2, 3.3], pos, 1100, "ref2", self.time)) 80 | pos = Pos(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 'DEG') 81 | assert (self.reflist.getReflection(2) 82 | == ([1, 2, 3], pos, 1000, "ref1", self.time)) 83 | self.reflist.swap_reflections("ref1", "ref2") 84 | pos = Pos(0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 'DEG') 85 | assert (self.reflist.getReflection(2) 86 | == ([1.1, 2.2, 3.3], pos, 1100, "ref2", self.time)) 87 | pos = Pos(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 'DEG') 88 | assert (self.reflist.getReflection(1) 89 | == ([1, 2, 3], pos, 1000, "ref1", self.time)) 90 | 91 | def createRefStateDicts(self): 92 | ref_0 = { 93 | 'h': 1, 94 | 'k': 2, 95 | 'l': 3, 96 | 'position': (0.1, 0.2, 0.3, 0.4, 0.5, 0.6), 97 | 'energy': 1000, 98 | 'tag': "ref1", 99 | 'time': repr(self.time) 100 | } 101 | ref_1 = { 102 | 'h': 1.1, 103 | 'k': 2.2, 104 | 'l': 3.3, 105 | 'position': (0.11, 0.22, 0.33, 0.44, 0.55, 0.66), 106 | 'energy': 1100, 107 | 'tag': "ref2", 108 | 'time': repr(self.time) 109 | } 110 | return ref_0, ref_1 -------------------------------------------------------------------------------- /diffcalc/ub/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcalc/ub/__init__.py -------------------------------------------------------------------------------- /diffcalc/ub/reference.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2019 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | try: 20 | from numpy.linalg import norm 21 | except ImportError: 22 | from numjy.linalg import norm 23 | 24 | 25 | class YouReference(object): 26 | 27 | def __init__(self, get_UB): 28 | self.get_UB = get_UB # callable 29 | self._n_phi_configured = None 30 | self._n_hkl_configured = None 31 | 32 | def _set_n_phi_configured(self, n_phi): 33 | self._n_phi_configured = n_phi 34 | self._n_hkl_configured = None 35 | 36 | def _get_n_phi_configured(self): 37 | return self._n_phi_configured 38 | 39 | n_phi_configured = property(_get_n_phi_configured, _set_n_phi_configured) 40 | 41 | def _set_n_hkl_configured(self, n_hkl): 42 | self._n_phi_configured = None 43 | self._n_hkl_configured = n_hkl 44 | 45 | def _get_n_hkl_configured(self): 46 | return self._n_hkl_configured 47 | 48 | n_hkl_configured = property(_get_n_hkl_configured, _set_n_hkl_configured) 49 | 50 | @property 51 | def n_phi(self): 52 | if self._n_phi_configured is None: 53 | n_phi = self.get_UB() * self._n_hkl_configured 54 | n_phi = n_phi / norm(n_phi) 55 | else: 56 | n_phi = self._n_phi_configured 57 | return n_phi 58 | 59 | @property 60 | def n_hkl(self): 61 | if self._n_hkl_configured is None: 62 | n_hkl = self.get_UB().I * self._n_phi_configured 63 | n_hkl = n_hkl / norm(n_hkl) 64 | else: 65 | n_hkl = self._n_hkl_configured 66 | return n_hkl 67 | 68 | def _pretty_vector(self, m): 69 | return ' '.join([('% 9.5f' % e).rjust(9) for e in m.T.tolist()[0]]) 70 | 71 | def repr_lines(self, ub_calculated, WIDTH, conv): 72 | SET_LABEL = ' <- set' 73 | lines = [] 74 | if self._n_phi_configured is not None: 75 | nphi_label = SET_LABEL 76 | nhkl_label = '' 77 | elif self._n_hkl_configured is not None: 78 | nphi_label = '' 79 | nhkl_label = SET_LABEL 80 | else: 81 | raise AssertionError("Neither a manual n_phi nor n_hkl is configured") 82 | 83 | if ub_calculated: 84 | lines.append(" n_phi:".ljust(WIDTH) + self._pretty_vector(conv.transform(self.n_phi, True)) + nphi_label) 85 | lines.append(" n_hkl:".ljust(WIDTH) + self._pretty_vector(self.n_hkl) + nhkl_label) 86 | else: # no ub calculated 87 | if self._n_phi_configured is not None: 88 | lines.append(" n_phi:".ljust(WIDTH) + self._pretty_vector(conv.transform(self._n_phi_configured, True)) + SET_LABEL) 89 | elif self._n_hkl_configured is not None: 90 | lines.append(" n_hkl:".ljust(WIDTH) + self._pretty_vector(self._n_hkl_configured) + SET_LABEL) 91 | 92 | return lines 93 | -------------------------------------------------------------------------------- /diffcmd/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcmd/__init__.py -------------------------------------------------------------------------------- /diffcmd/diffcalc_launcher.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import argparse 4 | import subprocess 5 | import os 6 | import getpass 7 | 8 | DIFFCALC_BIN = os.path.split(os.path.realpath(__file__))[0] 9 | DIFFCALC_ROOT = os.path.abspath(os.path.join(DIFFCALC_BIN, os.pardir)) 10 | 11 | MODULE_FOR_MANUALS = '_make_sixcircle_manual' 12 | 13 | def main(): 14 | parser = argparse.ArgumentParser(description='Diffcalc: A diffraction condition calculator of x-ray and neutron crystalography') 15 | parser.add_argument('--modules', dest='show_modules', action='store_true', 16 | help='list available modules') 17 | parser.add_argument('--python', dest='use_python', action='store_true', 18 | help='run within python rather than ipython') 19 | parser.add_argument('--debug', dest='debug', action='store_true', 20 | help='run in debug mode') 21 | parser.add_argument('--make-manuals-source', dest='make_manuals', action='store_true', 22 | help='make .rst manual files by running template through sixcircle') 23 | parser.add_argument('--non-interactive', dest='non_interactive', action='store_true', 24 | help='do not enter interactive mode after startup') 25 | parser.add_argument('module', type=str, nargs='?', 26 | help='the module to startup with') 27 | args = parser.parse_args() 28 | 29 | # Create list of available modules 30 | module_names = [] 31 | for module_path in os.listdir(os.path.join(DIFFCALC_ROOT, 'startup')): 32 | if not module_path.startswith('_') and module_path.endswith('.py'): 33 | module_names.append(module_path.split('.')[0]) 34 | module_names.sort() 35 | 36 | if args.show_modules: 37 | print_available_modules(module_names) 38 | exit(0) 39 | 40 | if not args.make_manuals and not args.module: 41 | print "A module name should be provided. Choose one of:" 42 | print_available_modules(module_names) 43 | exit(0) 44 | 45 | if args.make_manuals: 46 | if args.module: 47 | print "When building the manuals no module should be given" 48 | exit(1) 49 | args.module = MODULE_FOR_MANUALS 50 | 51 | if not args.make_manuals and args.module not in module_names: 52 | print "The provided argument '%s' is not one of:" % args.module 53 | print_available_modules(module_names) 54 | exit(1) 55 | 56 | env = os.environ.copy() 57 | 58 | if 'PYTHONPATH' not in env: 59 | env['PYTHONPATH'] = '' 60 | env['PYTHONPATH'] = DIFFCALC_ROOT + ':' + env['PYTHONPATH'] 61 | 62 | diffcmd_start_path = os.path.join(DIFFCALC_ROOT, 'diffcmd', 'start.py') 63 | 64 | if args.use_python: 65 | cmd = 'python' 66 | else: # ipython 67 | cmd = 'ipython --no-banner --HistoryManager.hist_file=/tmp/ipython_hist_%s.sqlite' % getpass.getuser() 68 | 69 | iflag = '' if args.non_interactive else '-i' 70 | cmd = cmd + ' ' + ' '.join([iflag, diffcmd_start_path, args.module, str(args.debug)]) 71 | 72 | print 'Running: ' + cmd 73 | rc = subprocess.call(cmd, env=env, shell=True) 74 | exit(rc) 75 | 76 | 77 | def print_available_modules(module_names): 78 | lines = [] 79 | for m in sorted(module_names): 80 | lines.append(' ' + m) 81 | print '\n'.join(lines) 82 | 83 | 84 | if __name__ == '__main__': 85 | main() 86 | # 87 | -------------------------------------------------------------------------------- /diffcmd/diffcmd_utils.py: -------------------------------------------------------------------------------- 1 | # 2 | # General utility functions to handle Diffcalc commands 3 | # 4 | 5 | from gda.jython.commands.GeneralCommands import alias 6 | 7 | try: 8 | import gda 9 | GDA = True 10 | except ImportError: 11 | GDA = False 12 | 13 | 14 | 15 | def alias_commands(global_namespace_dict): 16 | """Alias commands left in global_namespace_dict by previous import from 17 | diffcalc. 18 | 19 | This is the equivalent of diffcmd/ipython/magic_commands() for use 20 | when IPython is not available 21 | """ 22 | gnd = global_namespace_dict 23 | global GLOBAL_NAMESPACE_DICT 24 | GLOBAL_NAMESPACE_DICT = gnd 25 | print "Aliasing commands" 26 | 27 | ### Alias commands in namespace ### 28 | commands = gnd['hkl_commands_for_help'] 29 | commands += gnd['ub_commands_for_help'] 30 | if not GDA: # TODO: encapsulation issue: this should be done outside this function! 31 | commands.append(gnd['pos']) 32 | commands.append(gnd['scan']) 33 | aliased_names = [] 34 | 35 | for f in commands: 36 | # Skip section headers like 'Motion' 37 | if not hasattr(f, '__call__'): 38 | continue 39 | 40 | alias(f.__name__) 41 | aliased_names.append(f.__name__) 42 | 43 | print "Aliased commands: " + ' '.join(aliased_names) 44 | -------------------------------------------------------------------------------- /diffcmd/ipythonmagic.py: -------------------------------------------------------------------------------- 1 | 2 | import diffcmd.ipython 3 | from IPython.core.magic import register_line_magic 4 | from diffcmd.ipython import parse_line 5 | 6 | command_map = {} 7 | 8 | _DEFAULT_HELP = """ 9 | For help with diffcalc's orientation phase try: 10 | 11 | >>> help ub 12 | 13 | For help with moving in reciprocal lattice space try: 14 | 15 | >>> help hkl 16 | 17 | For more detailed help try for example: 18 | 19 | >>> help newub 20 | 21 | For help with driving axes or scanning: 22 | 23 | >>> help pos 24 | >>> help scan 25 | 26 | For help with regular python try for example: 27 | 28 | >>> help list 29 | 30 | For more detailed help with diffcalc go to: 31 | 32 | https://diffcalc.readthedocs.io 33 | 34 | """ 35 | 36 | # This function should be called with parameter globals() 37 | def define_commands(dictionary): 38 | print "Ipython detected - magicing commands" 39 | magiced_names = [] 40 | commands = hkl_commands_for_help + ub_commands_for_help # @UndefinedVariable 41 | commands += [pos, scan] # @UndefinedVariable 42 | ipython.GLOBAL_NAMESPACE_DICT = dictionary 43 | for f in commands: 44 | # Skip section headers like 'Motion' 45 | if not hasattr(f, '__call__'): 46 | continue 47 | 48 | # magic the function and remove from namespace (otherwise it would 49 | # shadow the magiced command) 50 | register_line_magic(parse_line(f)) 51 | del dictionary[f.__name__] 52 | command_map[f.__name__] = f 53 | magiced_names.append(f.__name__) 54 | 55 | print "Magiced commands: " + ' '.join(magiced_names) 56 | 57 | # because the functions have gone from namespace we need to override 58 | pythons_help = __builtins__.help 59 | del __builtins__.help 60 | 61 | register_line_magic(help) 62 | del help 63 | 64 | def help(s): 65 | """Diffcalc help for iPython 66 | """ 67 | if s == '': 68 | print _DEFAULT_HELP 69 | elif s == 'hkl': 70 | # Use help injected into hkl object 71 | print hkl.__doc__ 72 | elif s == 'ub': 73 | # Use help injected into ub command 74 | print command_map['ub'].__doc__ 75 | elif s in command_map: 76 | print "%s (diffcalc command):" %s 77 | print command_map[s].__doc__ 78 | else: 79 | exec('pythons_help(%s)' %s) 80 | -------------------------------------------------------------------------------- /diffcmd/make_manual.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from StringIO import StringIO 4 | from IPython import get_ipython 5 | import sys 6 | from diffcalc.dc.help import format_commands_for_rst_table 7 | 8 | 9 | TEST_INPUT=""" 10 | Diffcalc's Scannables 11 | ===================== 12 | 13 | Please see :ref:`moving-in-hkl-space` and :ref:`scanning-in-hkl-space` for some relevant examples. 14 | 15 | To list and show the current positions of your beamline's scannables 16 | use ``pos`` with no arguments:: 17 | 18 | >>> pos wl 19 | 20 | should do nought, but this should be replaced:: 21 | 22 | ==> pos wl 2 23 | 24 | should do the thing 25 | 26 | ==> abcd 27 | """ 28 | 29 | 30 | 31 | def echorun(magic_cmd): 32 | print "\n>>> " + str(magic_cmd) 33 | 34 | 35 | 36 | def make_manual(input_file_path, 37 | output_file_path, 38 | ub_commands_for_help, 39 | hkl_commands_for_help): 40 | 41 | # Read input file (should be .rst file) 42 | with open(input_file_path, 'r') as f: 43 | input_string = f.read() 44 | 45 | # Parse input string 46 | output_lines = [] 47 | for lineno, line in enumerate(input_string.split('\n')): 48 | process = '==>' in line 49 | 50 | if process and 'STOP' in line: 51 | print "'==> STOP' found on line. STOPPING", lineno + 1 52 | return 53 | 54 | elif process and 'UB_HELP_TABLE' in line: 55 | print 'Creating UB help table' 56 | output_lines_from_line = format_commands_for_rst_table( 57 | '', ub_commands_for_help) 58 | 59 | elif process and 'HKL_HELP_TABLE' in line: 60 | print 'Creating HKL help table' 61 | output_lines_from_line = format_commands_for_rst_table( 62 | '', hkl_commands_for_help) 63 | 64 | else: 65 | output_lines_from_line = parse_line( 66 | line, lineno + 1, input_file_path) 67 | 68 | # print '\n'.join(output_lines_from_line) 69 | output_lines.extend(output_lines_from_line) 70 | 71 | # Write output file 72 | if output_file_path: 73 | with open(output_file_path, 'w') as f: 74 | f.write('\n'.join(output_lines)) 75 | print "Wrote file:", output_file_path 76 | # try: 77 | # if output_file_path: 78 | # orig_stdout = sys.stdout 79 | # f = file(output_file_path, 'w') 80 | # sys.stdout = f 81 | # 82 | # 83 | # 84 | # finally: 85 | # if output_file_path: 86 | # sys.stdout = orig_stdout 87 | # f.close() 88 | 89 | 90 | def parse_line(linein, lineno, filepath): 91 | output_lines = [] 92 | if '==>' in linein: 93 | pre, cmd = linein.split('==>') 94 | _check_spaces_only(pre, lineno, filepath) 95 | cmd = cmd.strip() # strip whitespace 96 | output_lines.append(pre + ">>> " + cmd) 97 | result_lines = _capture_magic_command_output(cmd, lineno, filepath) 98 | 99 | 100 | # append to output 101 | for line in result_lines: 102 | output_lines.append(pre + line) 103 | else: 104 | output_lines.append(linein) 105 | return output_lines 106 | 107 | 108 | def _check_spaces_only(s, lineno, filepath): 109 | for c in s: 110 | if c != ' ': 111 | raise Exception('Error on line %i of %s :\n text proceeding --> must be ' 112 | 'spaces only' % (lineno, filepath)) 113 | 114 | def _capture_magic_command_output(magic_cmd, lineno, filepath): 115 | orig_stdout = sys.stdout 116 | result = StringIO() 117 | sys.stdout = result 118 | 119 | def log_error(): 120 | msg = "Error on line %i of %s evaluating '%s'" % (lineno, filepath, magic_cmd) 121 | sys.stderr.write('\n' + '=' * 79 + '\n' + msg + '\n' +'v' * 79 + '\n') 122 | return msg 123 | 124 | try: 125 | line_magics = get_ipython().magics_manager.magics['line'] 126 | magic = magic_cmd.split(' ')[0] 127 | if magic not in line_magics: 128 | msg = log_error() 129 | raise Exception(msg + " ('%s' is not a magic command)" % magic) 130 | get_ipython().magic(magic_cmd) 131 | except: 132 | log_error() 133 | raise 134 | finally: 135 | sys.stdout = orig_stdout 136 | 137 | result_lines = result.getvalue().split('\n') 138 | 139 | # trim trailing lines which are whitespace only 140 | while result_lines and (result_lines[-1].isspace() or not result_lines[-1]): 141 | result_lines.pop() 142 | 143 | return result_lines 144 | 145 | 146 | -------------------------------------------------------------------------------- /diffcmd/start.py: -------------------------------------------------------------------------------- 1 | """ 2 | start the diffcmd environemt using a script from startup. 3 | This should normally be run by the main diffcalc.py program. 4 | 5 | with diffcalc on PYTHONPATH 6 | $ ipython -i -m diffcm.diffcmd module_name_string debug_bool 7 | """ 8 | from __future__ import absolute_import 9 | 10 | import diffcalc 11 | import diffcalc.settings 12 | import os 13 | import sys 14 | from diffcalc.ub.persistence import UBCalculationJSONPersister 15 | from diffcalc.ub.calcstate import UBCalcStateEncoder 16 | from diffcalc.util import bold 17 | import diffcalc.util 18 | import diffcalc.gdasupport.minigda.command 19 | DIFFCALC_ROOT = os.path.realpath(diffcalc.__file__).split('diffcalc/__init__.py')[0] 20 | 21 | try: 22 | __IPYTHON__ # @UndefinedVariable 23 | IPYTHON = True 24 | except NameError: 25 | IPYTHON = False 26 | 27 | 28 | module_name = sys.argv[1] #3 if IPYTHON else 1] 29 | debug = sys.argv[2] == 'True' #4 if IPYTHON else 2]) 30 | 31 | print 32 | print bold('-' * 34 + ' DIFFCALC ' + '-' * 35) 33 | 34 | # configure persisentence 35 | DIFFCALC_VAR = os.path.join(os.path.expanduser('~'), '.diffcalc', module_name) 36 | if not os.path.exists(DIFFCALC_VAR): 37 | print "Making diffcalc var folder:'%s'" % DIFFCALC_VAR 38 | os.makedirs(DIFFCALC_VAR) 39 | diffcalc.settings.ubcalc_persister = UBCalculationJSONPersister(DIFFCALC_VAR, UBCalcStateEncoder) 40 | 41 | # configure debug 42 | diffcalc.util.DEBUG = debug 43 | if debug: 44 | print "WARNING: debug mode on; help for command syntax errors disabled." 45 | 46 | # import script 47 | script = os.path.join(DIFFCALC_ROOT, 'startup', module_name) + '.py' 48 | 49 | print "Startup script: '%s'" % script 50 | namespace = {} 51 | execfile(script, namespace) 52 | globals().update(namespace) 53 | diffcalc.gdasupport.minigda.command.ROOT_NAMESPACE_DICT = dict(namespace) 54 | print bold('-' * 36 + ' Help ' + '-' * 37) 55 | print HELP_STRING # @UndefinedVariable 56 | if 'LOCAL_MANUAL' in locals(): 57 | print "Local: " + LOCAL_MANUAL # @UndefinedVariable 58 | print bold('-' * 79) 59 | print 60 | 61 | 62 | # magic commands if IPython 63 | if IPYTHON: 64 | from diffcmd.ipython import magic_commands 65 | magic_commands(globals()) 66 | 67 | 68 | if 'MANUALS_TO_MAKE' in locals(): 69 | summary_lines = ['Made manuals:'] 70 | from diffcmd.make_manual import make_manual 71 | for source_path in MANUALS_TO_MAKE: # @UndefinedVariable 72 | import diffcalc.ub.ub 73 | try: 74 | diffcalc.ub.ub.rmub('example') 75 | except KeyError: 76 | pass 77 | target_path = source_path.replace('_template', '') 78 | print '@' * 79 79 | print "Making manual" 80 | print " Source:", source_path 81 | print " Target:", target_path 82 | 83 | make_manual(source_path, target_path, 84 | ub_commands_for_help, # @UndefinedVariable 85 | hkl_commands_for_help) # @UndefinedVariable 86 | summary_lines.append(' - ' + source_path + ' -- > ' + target_path) 87 | print '\n'.join(summary_lines) 88 | -------------------------------------------------------------------------------- /diffcmd/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/diffcmd/tests/__init__.py -------------------------------------------------------------------------------- /doc/docs-build-diffcalc_doc-linux.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /doc/references: -------------------------------------------------------------------------------- 1 | 2 | .. [You1999] H. You. *Angle calculations for a '4S+2D' six-circle diffractometer.* 3 | J. Appl. Cryst. (1999). **32**, 614-623. `(pdf link) 4 | `__. 5 | 6 | .. [Busing1967] W. R. Busing and H. A. Levy. *Angle calculations for 3- and 4-circle X-ray 7 | and neutron diffractometers.* Acta Cryst. (1967). **22**, 457-464. `(pdf link) 8 | `__. 9 | 10 | .. [Vlieg1993] Martin Lohmeier and Elias Vlieg. *Angle calculations for a six-circle 11 | surface x-ray diffractometer.* J. Appl. Cryst. (1993). **26**, 706-716. `(pdf link) 12 | `__. 13 | 14 | .. [Vlieg1998] Elias Vlieg. *A (2+3)-type surface diffractometer: mergence of the z-axis and 15 | (2+2)-type geometries.* J. Appl. Cryst. (1998). **31**, 198-203. `(pdf link) 16 | `__. 17 | 18 | .. [Willmott2011] C. M. Schlepütz, S. O. Mariager, S. A. Pauli, R. Feidenhans'l and 19 | P. R. Willmott. *Angle calculations for a (2+3)-type diffractometer: focus 20 | on area detectors.* J. Appl. Cryst. (2011). **44**, 73-83. `(pdf link) 21 | `__. 22 | 23 | -------------------------------------------------------------------------------- /doc/source/ACKS.rst: -------------------------------------------------------------------------------- 1 | ################ 2 | Acknowledgements 3 | ################ 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :numbered: 8 | 9 | We would like to acknowledge the people who have made a direct impact on the 10 | Diffcalc project, knowingly or not, in terms of encouragement, suggestions, 11 | criticism, bug reports, code contributions, and related projects. 12 | 13 | Names are ordered alphabetically by surname. 14 | 15 | .. If you add new entries, keep the list sorted by surname! 16 | 17 | .. acks:: 18 | 19 | * Allesandro Bombardi 20 | * Mark Booth 21 | * W. R. Busing 22 | * Steve Collins 23 | * Mirian Garcia-Fernandez 24 | * H. A. Levy 25 | * Martin Lohmier 26 | * Chris Nicklin 27 | * Elias Vlieg --- writer of DIF software used as a model for Diffcalc 28 | * Robert Walton 29 | * H. You 30 | * Fajin Yuan 31 | 32 | Thank you! 33 | 34 | Rob Walton & Irakli Sikharulidze -------------------------------------------------------------------------------- /doc/source/developer/contents.rst: -------------------------------------------------------------------------------- 1 | ######################## 2 | Diffcalc Developer Guide 3 | ######################## 4 | 5 | :Author: Rob Walton 6 | :Contact: rob.walton (at) diamond (dot) ac (dot) uk 7 | :Website: http://www.opengda.org/ 8 | 9 | .. rubric:: Diffcalc: A diffraction condition calculator for diffractometer control 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | :numbered: 14 | 15 | intro 16 | package 17 | quickstart_api 18 | development 19 | 20 | Indices and tables 21 | ================== 22 | 23 | * :ref:`genindex` 24 | * :ref:`modindex` 25 | * :ref:`search` -------------------------------------------------------------------------------- /doc/source/developer/development.rst: -------------------------------------------------------------------------------- 1 | Development 2 | =========== 3 | 4 | The files are kept here_ on github_. See bootcamp for an introduction to 5 | using github. To contribute please fork the project. Otherwise you can make 6 | a read-only clone or export. 7 | 8 | Code format should follow pep8 guidelines. PyDev has a good pep8 checker. 9 | 10 | To run the tests install nose_, change directory into the test folder and run:: 11 | 12 | $ nosetests 13 | .......... ... 14 | ---------------------------------------------------------------------- 15 | Ran 3914 tests in 9.584s 16 | 17 | OK (SKIP=15) 18 | 19 | 20 | 21 | .. _here: https://github.com/DiamondLightSource/diffcalc 22 | .. _github: https://github.com 23 | .. _nose: http://nose.readthedocs.org/en/latest/ 24 | .. _pep8: http://www.python.org/dev/peps/pep-0008/ 25 | -------------------------------------------------------------------------------- /doc/source/developer/intro.rst: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | Diffcalc is a diffraction condition calculator used for controlling 5 | diffractometers within reciprocal lattice space. It performs the same 6 | task as the ``fourc``, ``sixc``, ``twoc``, ``kappa``, ``psic`` and 7 | ``surf`` macros from SPEC_. 8 | 9 | Diffcalc's standard calculation engine is an implementation of 10 | [You1999]_ . The first versions of Diffcalc were based on 11 | [Vlieg1993]_ and [Vlieg1998]_ and a 'Vlieg' engine is still 12 | available. The 'You' engine is more generic and the plan is to remove 13 | the old 'Vlieg' engine once beamlines have been migrated. New users 14 | should use the 'You' engine. 15 | 16 | The foundations for this type of calculation were laid by by Busing & 17 | Levi in their classic paper [Busing1967]_. Diffcalc's orientation 18 | algorithm is taken from this paper. Busing & Levi also provided the 19 | original definition of the coordinate frames and of the U and B 20 | matrices used to describe a crystal's orientation and to convert between 21 | Cartesian and reciprical lattice space. 22 | 23 | Geometry plugins are used to adapt the six circle model used 24 | internally by Diffcalc to apply to other diffractometers. These 25 | contain a dictionary of the 'missing' angles which Diffcalc uses to 26 | constrain these angles internally, and a methods to map from external 27 | angles to Diffcalc angles and visa versa. 28 | 29 | Options to use Diffcalc: 30 | 31 | - **The User manual next to this developer manual or README file on github.** 32 | - The :ref:`quickstart-api` section describes how to run up only 33 | the core in Python_. This provides a base option for system integration. 34 | 35 | Diffcalc will work with Python 2.7 or higher with numpy_, or with 36 | Jython 2.7 of higher with Jama_. 37 | 38 | 39 | .. [*] The very small 'Willmott' engine currently handles the case for 40 | surface diffraction where the surface normal is held vertical 41 | [Willmott2011]_. The 'You' engine handles this case fine, but 42 | currently spins nu into an unhelpful quadrant. We hope to 43 | remove the need for this engine soon. 44 | 45 | 46 | .. _SPEC: http://www.certif.com/ 47 | .. _Python: http://python.org 48 | .. _IPython: http://http://ipython.org/ 49 | .. _Jython: http://jython.org 50 | .. _OpenGDA: http://opengda.org 51 | .. _numpy: http://numpy.scipy.org/ 52 | .. _Jama: http://math.nist.gov/javanumerics/jama/ 53 | 54 | 55 | .. include:: ../../references 56 | -------------------------------------------------------------------------------- /doc/source/developer/package.rst: -------------------------------------------------------------------------------- 1 | Project Files & Directories 2 | =========================== 3 | 4 | diffcalc 5 | The main source package. 6 | 7 | test 8 | Diffcalcs unit-test package (use Nose_ to run them). 9 | 10 | diffcmd 11 | A spec-like openGDA emulator. 12 | 13 | numjy 14 | A *very* minimal implentation of numpy for jython. It supports only what 15 | Diffcalc needs. 16 | 17 | doc 18 | The documentation is written in reStructuredText and can be compiled into 19 | html and pdf using Python's `Sphinx `_. With Sphinx 20 | installed use ``make clean all`` from within the user and developer guide 21 | folders to build the documentation. 22 | 23 | startup 24 | Starup scripts called by diffcmd or openGDA to startup diffcalc 25 | 26 | model 27 | Vrml models of diffractometers and a hokey script for animating then and 28 | controlling them from diffcalc. 29 | 30 | .. _Nose: http://readthedocs.org/docs/nose/en/latest/ -------------------------------------------------------------------------------- /doc/source/developer/quickstart_setup_environment: -------------------------------------------------------------------------------- 1 | 2 | Change directory to the diffcalc project (python adds the current 3 | working directory to the path):: 4 | 5 | $ cd diffcalc 6 | $ ls 7 | COPYING diffcalc doc example mock.py mock.pyc model numjy test 8 | 9 | If using Python make sure numpy and diffcalc can be imported:: 10 | 11 | $ python 12 | Python 2.7.2+ (default, Oct 4 2011, 20:06:09) 13 | [GCC 4.6.1] on linux2 14 | Type "help", "copyright", "credits" or "license" for more information. 15 | >>> import numpy 16 | >>> import diffcalc 17 | 18 | If using Jython make sure Jama and diffcalc can be imported:: 19 | 20 | $ jython -Dpython.path=:/Jama-1.0.1.jar 21 | 22 | Jython 2.2.1 on java1.5.0_11 23 | Type "copyright", "credits" or "license" for more information. 24 | >>> import Jama 25 | >>> import diffcalc 26 | -------------------------------------------------------------------------------- /doc/source/diffcalc_pdf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/doc/source/diffcalc_pdf.png -------------------------------------------------------------------------------- /doc/source/diffcalc_web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/doc/source/diffcalc_web.png -------------------------------------------------------------------------------- /doc/source/index.rst: -------------------------------------------------------------------------------- 1 | ################################### 2 | Diffcalc User and Developer Guide 3 | ################################### 4 | 5 | :Author: Rob Walton 6 | :Contact: rob.walton (at) diamond.ac.uk 7 | :Web site: https://github.com/DiamondLightSource/diffcalc 8 | 9 | .. rubric:: Diffcalc: A Diffraction Condition Calculator for Diffractometer Control 10 | 11 | See also the `quickstart guide at github `_. 12 | 13 | .. toctree:: 14 | :maxdepth: 2 15 | 16 | youmanual 17 | vliegmanual/contents 18 | developer/contents 19 | ACKS 20 | 21 | Indices and tables 22 | ================== 23 | 24 | * :ref:`genindex` 25 | * :ref:`modindex` 26 | * :ref:`search` 27 | -------------------------------------------------------------------------------- /doc/source/vliegmanual/contents.rst: -------------------------------------------------------------------------------- 1 | ############################################# 2 | Diffcalc User Guide (Deprecated Vlieg Engine) 3 | ############################################# 4 | 5 | :Author: Rob Walton 6 | :Contact: rob.walton (at) diamond (dot) ac (dot) uk 7 | :Website: http://www.opengda.org/ 8 | 9 | .. rubric:: Diffcalc: A diffraction condition calculator for diffractometer control 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | :numbered: 14 | 15 | vliegmanual 16 | 17 | Indices and tables 18 | ================== 19 | 20 | * :ref:`genindex` 21 | * :ref:`modindex` 22 | * :ref:`search` -------------------------------------------------------------------------------- /doc/source/vliegmanual/images/fix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/doc/source/vliegmanual/images/fix.png -------------------------------------------------------------------------------- /doc/source/vliegmanual/images/sixcircle_gamma_on_arm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/doc/source/vliegmanual/images/sixcircle_gamma_on_arm.pdf -------------------------------------------------------------------------------- /doc/source/vliegmanual/images/sixcircle_gamma_on_arm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/doc/source/vliegmanual/images/sixcircle_gamma_on_arm.png -------------------------------------------------------------------------------- /doc/source/vliegmanual/images/sixcircle_gamma_on_arm.ppt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/doc/source/vliegmanual/images/sixcircle_gamma_on_arm.ppt -------------------------------------------------------------------------------- /doc/source/vliegmanual/images/unit_cell.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/doc/source/vliegmanual/images/unit_cell.pdf -------------------------------------------------------------------------------- /doc/source/vliegmanual/images/unit_cell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/doc/source/vliegmanual/images/unit_cell.png -------------------------------------------------------------------------------- /doc/source/youmanual_images/4s_2d_diffractometer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/doc/source/youmanual_images/4s_2d_diffractometer.png -------------------------------------------------------------------------------- /doc/tmp/constraints.txt: -------------------------------------------------------------------------------- 1 | Take a six circle diffractometer with angles: 2 | 3 | delta, nu, mu, eta, chi, phi 4 | 5 | and virtual angles: 6 | 7 | qaz, naz, psi, alpha, beta. 8 | 9 | Many combinations of these can be constrained: 10 | 11 | 12 | constrain 13 | >>> con nu 14 | >>> con psi 15 | >>> con mu 16 | >>> con nu mu a_eq_b 17 | 18 | real angles are always constrained to there last set position. If they are too far from here 19 | an error will result. 20 | 21 | >>> pos nu 0 (moves, parameter tracks last set value (actually checks it when hkl moved)) 22 | >>> pos psi 90 (does not move, sets parameter in diffcalc) 23 | >>> pos mu 0 (moves) 24 | >>> pos hkl [1 0 0] (moves based on last set nu, psi, mu) 25 | >>> pos betain --> Exception, not constrained 26 | 27 | moving a virtual angle simply sets it to efftec the next hkl move 28 | 29 | Here we need onlu con, uncon and pos. 30 | 31 | ...... 32 | 33 | However it would be nice to be able to pos betain for example and have it change 34 | betain while staying on the same reflection. This might be enabled by locking the 35 | the current hkl position. It would be trick to make this work with the physical angles though. 36 | 37 | >>> lock hkl 38 | >>> pos psi 90 (moves immediately) 39 | >>> scan psi 0 90 1 (scans, moving immediately) 40 | >>> pos mu 0 (does not move immediately) (could work by listening to target positions, and triggering move when complete) 41 | >>> pos c(mu) moves 42 | >>> pos mu_c moves 43 | 44 | Only one thing would be varyable at a time unless they are put in a CoordinatedMotionGroup, 45 | which would be hard for the real motors) 46 | 47 | 48 | -------------------------------------------------------------------------------- /doc/tmp/i16_non_diffcalc_manual.txt: -------------------------------------------------------------------------------- 1 | Creating a UB Matrix 2 | There are three euler modes: 3 | 4 | =bisecting: eta and delta are fixed, phi and chi are not fixed. 5 | =fixed phi: phi and 2theta are fixed, eta and chi are not fixed. 6 | =fixed psi: Not used for creating a UB matrix . 7 | First creat a reflection file to store the reflections data using: 8 | 9 | reffile('name') 10 | 11 | Set the crystal lattice: 12 | 13 | latt([a]) assumes cubic 14 | latt([a,b]) assumes tetragonal 15 | latt([a,b,c]) assumes orthorhombic 16 | latt([a,b,c,gam]) assumes monclinic/hexagonal gam different from 90. 17 | latt([a,b,c,alp,bet,gam]) 18 | 19 | Use: 20 | 21 | c2th([h k l]) 22 | 23 | to calculate the 2 theta position for the hkl for example: 24 | 25 | c2th([0 0 2]) 26 | 27 | Then use the following to move the diffractometer to the correct positions: 28 | 29 | pos delta c2th([0 0 2]) eta c2th([0 0 2])/2 30 | 31 | You can now scan eta, chi, and delta to optomise the peak intensity using the following scans for example: 32 | 33 | scancn eta 0.01 40 w 0.2 t 1 34 | 35 | scancn chi 0.01 40 w 0.2 t 1 36 | 37 | scancn delta 0.01 40 w 0.2 t 1 38 | 39 | A few iterations may be required. 40 | 41 | Now that you have the first reflection it can be stored using the following command: 42 | 43 | saveref('reflable',[h k l]) 44 | 45 | saveref('Ti1',[0 0 2]) for the above example. 46 | 47 | Then create a dummy UB matrix using a dummy non-parallel hkl plane eg: 48 | 49 | ubm('Ti1',[2 0 0]) 50 | 51 | Useing the following command to calculate the direction of the second reflection: 52 | 53 | hkl_calc([0 2 2]) 54 | 55 | If the calculated positions can be safely achieved then type: 56 | 57 | pos hkl [0 2 2] 58 | 59 | Find the second reflection by scanning phi, once the reflection is found save the second reflection using: 60 | 61 | saveref('Ti2',[0 2 2]) for example. 62 | 63 | Now create a real UB-Matrix using: 64 | 65 | ubm('Ti1','Ti2') 66 | 67 | You can now drive in recriprocal space. 68 | 69 | To change the lattice parameters according the found Bragg peaks 70 | 71 | latt([latt()[0]*2/l()]) (cubic only) -------------------------------------------------------------------------------- /install-jython-environment.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | JYTHON_URL='https://repo1.maven.org/maven2/org/python/jython-installer/2.7.1/jython-installer-2.7.1.jar' 4 | JAMA_JAR_URL='https://repo1.maven.org/maven2/gov/nist/math/jama/1.0.3/jama-1.0.3.jar' 5 | COMMONS_MATH_URL='https://repo1.maven.org/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar' 6 | 7 | # Install jars 8 | wget $JAMA_JAR_URL 9 | wget $COMMONS_MATH_URL 10 | export CLASSPATH=$PWD/jama-1.0.3.jar:$PWD/commons-math3-3.6.1.jar:$CLASSPATH 11 | 12 | # Install Jython 13 | wget $JYTHON_URL -O jython_installer.jar 14 | java -jar jython_installer.jar -s -d $HOME/jython 15 | 16 | # Install nose for Jython 17 | # TODO: move to a setup.py 18 | #$HOME/jython/bin/pip install nose==1.3.7 19 | #$HOME/jython/bin/pip install pytest==3.10.1 20 | #$HOME/jython/bin/pip install pytest-xdist==1.26.1 21 | 22 | 23 | # Download dependencies directly from Pypi 24 | # as pip is currently broken (https://github.com/jython/jython/issues/97) 25 | 26 | 27 | wget https://files.pythonhosted.org/packages/02/ee/b6e02dc6529e82b75bb06823ff7d005b141037cb1416b10c6f00fc419dca/Pygments-2.2.0-py2.py3-none-any.whl 28 | wget https://files.pythonhosted.org/packages/a1/4e/c42167ba5c3192bed633726d39d7896cc55d4fa3ec4a1fb60cd3a53fc4c7/decorator-4.1.2-py2.py3-none-any.whl 29 | wget https://files.pythonhosted.org/packages/70/c7/e8cb4a537ee4fc497ac80a606a667fd1832f28ad3ddbfa25bf30473eae13/pytest-4.6.11-py2.py3-none-any.whl 30 | wget https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl 31 | wget https://files.pythonhosted.org/packages/2c/a0/da5f49008ec6e9a658dbf5d7310a4debd397bce0b4db03cf8a410066bb87/atomicwrites-1.4.0-py2.py3-none-any.whl 32 | wget https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl 33 | wget https://files.pythonhosted.org/packages/be/be/7abce643bfdf8ca01c48afa2ddf8308c2308b0c3b239a44e57d020afa0ef/attrs-21.4.0-py2.py3-none-any.whl 34 | wget https://files.pythonhosted.org/packages/a0/28/85c7aa31b80d150b772fbe4a229487bc6644da9ccb7e427dd8cc60cb8a62/pluggy-0.13.1-py2.py3-none-any.whl 35 | wget https://files.pythonhosted.org/packages/c1/f9/9058661f6b4bb017dfe17ef84b461e4b11130c7bbee1b35cc0883ec8533b/importlib_metadata-2.1.2-py2.py3-none-any.whl 36 | wget https://files.pythonhosted.org/packages/96/0a/67556e9b7782df7118c1f49bdc494da5e5e429c93aa77965f33e81287c8c/zipp-1.2.0-py2.py3-none-any.whl 37 | wget https://files.pythonhosted.org/packages/cf/e5/989798d38831a8505d62687c94b0f2954ff0a40782e25f9add8ed675dc1f/contextlib2-0.6.0-py2.py3-none-any.whl 38 | wget https://files.pythonhosted.org/packages/7a/2a/95ed0501cf5d8709490b1d3a3f9b5cf340da6c433f896bbe9ce08dbe6785/configparser-4.0.2-py2.py3-none-any.whl 39 | wget https://files.pythonhosted.org/packages/76/67/dc02c72177ec79f0176e5bf9921e9c1745a381ed556afb3b3ecc2bb8ba2e/pathlib2-2.3.6-py2.py3-none-any.whl 40 | wget https://files.pythonhosted.org/packages/f9/d0/6b7b38eaf9964510f5c32aa5aaf9f419864d2e0ebe34274e6cba5689a0c5/scandir-1.10.0-cp27-cp27m-win_amd64.whl 41 | wget https://files.pythonhosted.org/packages/3e/89/7ea760b4daa42653ece2380531c90f64788d979110a2ab51049d92f408af/packaging-20.9-py2.py3-none-any.whl 42 | wget https://files.pythonhosted.org/packages/69/cb/f5be453359271714c01b9bd06126eaf2e368f1fddfff30818754b5ac2328/funcsigs-1.0.2-py2.py3-none-any.whl 43 | wget https://files.pythonhosted.org/packages/a4/a6/42f17d065bda1fac255db13afc94c93dbfb64393eae37c749b4cb0752fc7/more_itertools-5.0.0-py3-none-any.whl 44 | wget https://files.pythonhosted.org/packages/99/4f/13fb671119e65c4dce97c60e67d3fd9e6f7f809f2b307e2611f4701205cb/nose-1.3.7-py2-none-any.whl 45 | wget https://files.pythonhosted.org/packages/59/83/8fcdcf4babcc55290e50cbd54fcc9fcdd81c2e62eff27c1e6a2f23d79381/mock-3.0.0-py2.py3-none-any.whl 46 | 47 | unzip -d $HOME/jython/Lib/site-packages Pygments-2.2.0-py2.py3-none-any.whl 48 | unzip -d $HOME/jython/Lib/site-packages decorator-4.1.2-py2.py3-none-any.whl 49 | unzip -d $HOME/jython/Lib/site-packages pytest-4.6.11-py2.py3-none-any.whl 50 | unzip -d $HOME/jython/Lib/site-packages six-1.16.0-py2.py3-none-any.whl 51 | unzip -d $HOME/jython/Lib/site-packages atomicwrites-1.4.0-py2.py3-none-any.whl 52 | unzip -d $HOME/jython/Lib/site-packages py-1.11.0-py2.py3-none-any.whl 53 | unzip -d $HOME/jython/Lib/site-packages attrs-21.4.0-py2.py3-none-any.whl 54 | unzip -d $HOME/jython/Lib/site-packages pluggy-0.13.1-py2.py3-none-any.whl 55 | unzip -d $HOME/jython/Lib/site-packages importlib_metadata-2.1.2-py2.py3-none-any.whl 56 | unzip -d $HOME/jython/Lib/site-packages zipp-1.2.0-py2.py3-none-any.whl 57 | unzip -d $HOME/jython/Lib/site-packages contextlib2-0.6.0-py2.py3-none-any.whl 58 | unzip -d $HOME/jython/Lib/site-packages configparser-4.0.2-py2.py3-none-any.whl 59 | unzip -d $HOME/jython/Lib/site-packages pathlib2-2.3.6-py2.py3-none-any.whl 60 | unzip -d $HOME/jython/Lib/site-packages scandir-1.10.0-cp27-cp27m-win_amd64.whl 61 | unzip -d $HOME/jython/Lib/site-packages packaging-20.9-py2.py3-none-any.whl 62 | unzip -d $HOME/jython/Lib/site-packages funcsigs-1.0.2-py2.py3-none-any.whl 63 | unzip -d $HOME/jython/Lib/site-packages more_itertools-5.0.0-py3-none-any.whl 64 | unzip -d $HOME/jython/Lib/site-packages nose-1.3.7-py2-none-any.whl 65 | unzip -d $HOME/jython/Lib/site-packages mock-3.0.0-py2.py3-none-any.whl 66 | 67 | -------------------------------------------------------------------------------- /integration_checks.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on 9 Mar 2017 3 | 4 | @author: zrb13439 5 | 6 | ''' 7 | 8 | ''' 9 | Integration tests for startup scripts (named so that nosetests will *not* pick 10 | up by default. 11 | 12 | This is because these must be run with: 13 | 14 | $ nosetests --with-process-isolation integration_checks.py 15 | 16 | This is not a standard nose option. Install it with: 17 | 18 | $ pip install nosepipe 19 | 20 | nosepipe is described at https://github.com/dmccombs/nosepipe/ 21 | ''' 22 | 23 | from nose import SkipTest 24 | 25 | 26 | def test_sixcircle_startup(): 27 | import startup.sixcircle 28 | startup.sixcircle.ct.pause = False 29 | startup.sixcircle.demo.all() 30 | 31 | 32 | def test_fivecircle_startup(): 33 | import startup.fivecircle 34 | startup.fivecircle.ct.pause = False 35 | startup.fivecircle.demo.all() 36 | 37 | 38 | def test_fourcircle_startup(): 39 | import startup.fourcircle 40 | startup.fourcircle.ct.pause = False 41 | startup.fourcircle.demo.all() 42 | 43 | 44 | def test_i13_startup(): 45 | raise SkipTest('Still need to work out to use i13s very tight limits') 46 | import startup.i13 47 | startup.i13.ct.pause = False 48 | startup.i13.demo.all() 49 | 50 | 51 | def test_i16_startup(): 52 | import startup.i16 53 | startup.i16.ct.pause = False 54 | startup.i16.demo.all() 55 | 56 | 57 | def test_i21_startup_standard(): 58 | import startup.i21 59 | startup.i21.ct.pause = False 60 | startup.i21.demo.all() 61 | 62 | 63 | def test_i21_startup_bespoke(): 64 | import startup.i21 65 | startup.i21.ct.pause = False 66 | startup.i21.demo.i21() 67 | 68 | 69 | def test_sixcirle_api(): 70 | import startup.api.sixcircle 71 | startup.api.sixcircle.demo_all() 72 | 73 | -------------------------------------------------------------------------------- /model/README.txt: -------------------------------------------------------------------------------- 1 | Setting up the sixc vrml model to work via Epics pv's from b16's simulation running on the office network. 2 | 3 | 4 | 1. Synoptic 5 | $ launcher --port 6064 6 | 7 | 2. Shell 8 | export EPICS_CA_REPEATER_PORT=6065 9 | export EPICS_CA_SERVER_PORT=6064 10 | 11 | 3. Vrml viewer 12 | export EPICS_CA_SERVER_PORT=6064 13 | dls-vrml-epics-viewer.py fivec.wrl fivec.wcfg 14 | -------------------------------------------------------------------------------- /model/fivec.fxw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/model/fivec.fxw -------------------------------------------------------------------------------- /model/fivec.wcfg: -------------------------------------------------------------------------------- 1 | dad_alpha_frame rotation pv["DIFFSIM:FIVEC:ALPHA.RBV"] 2 | dad_delta_frame rotation pv["DIFFSIM:FIVEC:DELTA.RBV"] 3 | dad_omega_frame rotation pv["DIFFSIM:FIVEC:OMEGA.RBV"] 4 | dad_chi_frame rotation pv["DIFFSIM:FIVEC:CHI.RBV"] 5 | dad_phi_frame rotation pv["DIFFSIM:FIVEC:PHI.RBV"] -------------------------------------------------------------------------------- /model/sixc.fxw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/model/sixc.fxw -------------------------------------------------------------------------------- /model/sixc.wcfg: -------------------------------------------------------------------------------- 1 | dad_alpha_frame rotation pv["DIFFSIM:SIXC:ALPHA.RBV"] 2 | dad_delta_frame rotation pv["DIFFSIM:SIXC:DELTA.RBV"] 3 | dad_gamma_frame rotation pv["DIFFSIM:SIXC:GAMMA.RBV"] 4 | dad_omega_frame rotation pv["DIFFSIM:SIXC:OMEGA.RBV"] 5 | dad_chi_frame rotation pv["DIFFSIM:SIXC:CHI.RBV"] 6 | dad_phi_frame rotation pv["DIFFSIM:SIXC:PHI.RBV"] 7 | -------------------------------------------------------------------------------- /model/sixc_horizontal.fxw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/model/sixc_horizontal.fxw -------------------------------------------------------------------------------- /model/vrml_animator.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | import sys 20 | import time 21 | import threading 22 | from math import pi 23 | import socket 24 | 25 | from pivy.coin import * 26 | from pivy.sogui import * 27 | 28 | 29 | PORT = 4567 30 | TORAD = pi / 180 31 | 32 | 33 | def connect_to_socket(host, port): 34 | print "Connecting to %s on port %d" % (host, port) 35 | connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 36 | print "Connected" 37 | connection.connect((host, port)) 38 | socketfile = connection.makefile('rw', 0) 39 | return socketfile 40 | 41 | 42 | def serve_socket_connection(port): 43 | print ("Serving connection on all interfaces on %s port %d" % 44 | (socket.gethostname(), port)) 45 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 46 | sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 47 | sock.bind((socket.gethostname(), port)) 48 | sock.listen(1) 49 | time.sleep(1) 50 | (connection, addr) = sock.accept() 51 | print 'Connected from ', addr, ' accepted' 52 | socket_file = connection.makefile('rw', 0) # no buffering 53 | return socket_file 54 | 55 | 56 | def node_name(anglename): 57 | return 'dad_' + anglename + '_frame' 58 | 59 | 60 | class SceneUpdatingThread(threading.Thread): 61 | 62 | def __init__(self, scene, axisnames): 63 | threading.Thread.__init__(self) 64 | self.scene = scene 65 | 66 | # Infer rotation axes based on initial orientation 67 | self.rotation_axes = {} 68 | self.axies_nodes = {} 69 | for axisname in axisnames: 70 | node = self.scene.getByName(node_name(axisname)) 71 | self.axies_nodes[axisname] = node 72 | value = node.rotation.getValue() 73 | self.rotation_axes[axisname] = value.getAxisAngle()[0] 74 | 75 | def run(self): 76 | socket_file = serve_socket_connection(PORT) 77 | 78 | while True: 79 | msg = socket_file.readline() 80 | if msg == '': 81 | print '***Socket closed' 82 | socket_file = serve_socket_connection(PORT) 83 | continue 84 | print msg.strip() 85 | d = eval(msg.strip()) # msg should be a dictionary representation 86 | for axisname in d: 87 | self.set_axis_rotation(axisname, d[axisname]) 88 | 89 | def set_axis_rotation(self, anglename, degrees): 90 | nodename = node_name(anglename) 91 | angle = degrees * TORAD 92 | while angle < 0: 93 | angle = 2 * pi + angle 94 | node = self.scene.getByName(nodename) 95 | getattr(node, 'rotation').setValue( 96 | self.rotation_axes[anglename], angle) 97 | 98 | 99 | class Animator(object): 100 | 101 | def __init__(self, filename, axisnames): 102 | print "filename : " + filename 103 | print " axes : " + ' '.join(axisnames) 104 | # Create viewer 105 | self.myWindow = SoGui.init(sys.argv[0]) # @UndefinedVariable 106 | if self.myWindow is None: sys.exit(1) 107 | viewer = SoGuiExaminerViewer(self.myWindow) # @UndefinedVariable 108 | # load file into scene 109 | so_input = SoInput() # @UndefinedVariable 110 | so_input.openFile(filename) 111 | self.scene = SoDB.readAll(so_input) # @UndefinedVariable 112 | # Add scene to viewer 113 | viewer.setSceneGraph(self.scene) 114 | viewer.setTitle(' '.join(axisnames)) 115 | viewer.show() 116 | 117 | self.start_update_scene_thread(axisnames) 118 | 119 | def start_update_scene_thread(self, axisnames): 120 | t = SceneUpdatingThread(self.scene, axisnames) 121 | t.setDaemon(True) 122 | t.start() 123 | 124 | def show(self): 125 | SoGui.show(self.myWindow) # @UndefinedVariable 126 | SoGui.mainLoop() # @UndefinedVariable 127 | 128 | def main(): 129 | animator = Animator(sys.argv[1], sys.argv[2:]) 130 | animator.show() 131 | 132 | if __name__ == "__main__": 133 | main() 134 | 135 | -------------------------------------------------------------------------------- /numjy/__init__.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | try: 20 | import Jama 21 | from numjy import linalg 22 | from numjy.jama_matrix_wrapper import matrix 23 | JAMA = True 24 | except ImportError: 25 | JAMA = False 26 | 27 | 28 | def hstack(list_of_column_matrices): 29 | if not Jama: 30 | raise Exception('Jama not available, use numpy directly') 31 | ncol = len(list_of_column_matrices) 32 | nrow = list_of_column_matrices[0].shape[0] 33 | m = Jama.Matrix(nrow, ncol) 34 | for c, column_matrix in enumerate(list_of_column_matrices): 35 | m.setMatrix(0, nrow - 1, c, c, column_matrix.m) 36 | return matrix(m) 37 | -------------------------------------------------------------------------------- /numjy/jama_matrix_wrapper.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | import Jama 20 | 21 | 22 | class matrix(object): 23 | 24 | def __init__(self, a): 25 | if isinstance(a, Jama.Matrix): 26 | self.m = a 27 | elif isinstance(a, basestring): 28 | l = [] 29 | for row in a.strip().split(';'): 30 | l.append([float(element) 31 | for element in row.replace(',', ' ').split()]) 32 | self.m = Jama.Matrix(l) 33 | elif isinstance(a, matrix): 34 | self.m = Jama.Matrix(a.tolist()) 35 | elif isinstance(a, (list, tuple)): 36 | if isinstance(a[0], (list, tuple)): 37 | # a is a list of lists (not rigorous test!) 38 | self.m = Jama.Matrix(a) 39 | else: 40 | # a is a row vector 41 | self.m = Jama.Matrix([a]) 42 | else: 43 | # give it a go 44 | self.m = Jama.Matrix(a) 45 | 46 | def __eq__(self, other): 47 | nrow, ncol = self.shape 48 | b = matrix(Jama.Matrix(nrow, ncol)) 49 | for i in range(nrow): 50 | for j in range(ncol): 51 | b[i, j] = self[i, j] == other[i, j] 52 | return b 53 | 54 | @property 55 | def shape(self): 56 | return self.m.getRowDimension(), self.m.getColumnDimension() 57 | 58 | def __len__(self): 59 | return self.m.getRowDimension() 60 | 61 | def all(self): # @ReservedAssignment 62 | for row in self.m.array: 63 | if not all(row): 64 | return False 65 | return True 66 | 67 | def tolist(self): 68 | l = [] 69 | nrow, ncol = self.shape 70 | for i in range(nrow): 71 | row = [] 72 | for j in range(ncol): 73 | row.append(self[i, j]) 74 | l.append(row) 75 | return l 76 | 77 | def sum(self): # @ReservedAssignment 78 | return sum(sum(row) for row in self.m.array) 79 | 80 | @property 81 | def I(self): 82 | return matrix(self.m.inverse()) 83 | 84 | @property 85 | def T(self): 86 | return matrix(self.m.transpose()) 87 | 88 | def _scaler(self, scaler): 89 | return Jama.Matrix(self.shape[0], self.shape[1], scaler) 90 | 91 | def __add__(self, other): 92 | v = other.m if isinstance(other, matrix) else self._scaler(other) 93 | return matrix(self.m.plus(v)) 94 | 95 | def __sub__(self, other): 96 | v = other.m if isinstance(other, matrix) else self._scaler(other) 97 | return matrix(self.m.minus(v)) 98 | 99 | def __mul__(self, other): 100 | return matrix(self.m.times(other.m if isinstance(other, matrix) else 101 | other)) 102 | 103 | def __div__(self, other): 104 | # dividend = other.I if isinstance(other, matrix) else 1. /float(other) 105 | return self.__mul__(1. / float(other)) 106 | 107 | def __getitem__(self, key): 108 | i, j = key 109 | return self.m.get(i, j) 110 | 111 | def __setitem__(self, key, value): 112 | i, j = key 113 | self.m.set(i, j, value) 114 | 115 | def __str__(self): 116 | insides = [' '.join([str(el) for el in row]) for row in self.tolist()] 117 | return '[[' + ']\n ['.join(insides) + ']]' 118 | 119 | def __repr__(self): 120 | return 'matrix(' + '\n '.join(self.__str__().split('\n')) + ')' 121 | -------------------------------------------------------------------------------- /numjy/linalg.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | def norm(mat): 20 | return mat.m.normF() 21 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | setup( 4 | name='diffcalc', 5 | version='2.1', 6 | 7 | description='A diffraction condition calculator for X-ray or neutron diffractometer control.', 8 | long_description=open('README.rst').read(), 9 | url='https://github.com/DiamondLightSource/diffcalc', 10 | 11 | author='Rob Walton', 12 | author_email='rob.walton@diamond.ac.uk', 13 | 14 | license='GNU', 15 | 16 | packages=find_packages(exclude=['docs']), 17 | 18 | install_requires=[ 19 | 'numpy', 20 | 'ipython', 21 | 'pytest==3.10.1', 22 | 'pytest-xdist', 23 | 'nose', 24 | 'mock' 25 | ], 26 | 27 | entry_points={ 28 | 'console_scripts': [ 29 | 'diffcalc=diffcmd.diffcalc_launcher:main', 30 | ], 31 | }, 32 | ) -------------------------------------------------------------------------------- /simplejson/ordered_dict.py: -------------------------------------------------------------------------------- 1 | """Drop-in replacement for collections.OrderedDict by Raymond Hettinger 2 | 3 | http://code.activestate.com/recipes/576693/ 4 | 5 | """ 6 | from UserDict import DictMixin 7 | 8 | # Modified from original to support Python 2.4, see 9 | # http://code.google.com/p/simplejson/issues/detail?id=53 10 | try: 11 | all 12 | except NameError: 13 | def all(seq): 14 | for elem in seq: 15 | if not elem: 16 | return False 17 | return True 18 | 19 | class OrderedDict(dict, DictMixin): 20 | 21 | def __init__(self, *args, **kwds): 22 | if len(args) > 1: 23 | raise TypeError('expected at most 1 arguments, got %d' % len(args)) 24 | try: 25 | self.__end 26 | except AttributeError: 27 | self.clear() 28 | self.update(*args, **kwds) 29 | 30 | def clear(self): 31 | self.__end = end = [] 32 | end += [None, end, end] # sentinel node for doubly linked list 33 | self.__map = {} # key --> [key, prev, next] 34 | dict.clear(self) 35 | 36 | def __setitem__(self, key, value): 37 | if key not in self: 38 | end = self.__end 39 | curr = end[1] 40 | curr[2] = end[1] = self.__map[key] = [key, curr, end] 41 | dict.__setitem__(self, key, value) 42 | 43 | def __delitem__(self, key): 44 | dict.__delitem__(self, key) 45 | key, prev, next = self.__map.pop(key) 46 | prev[2] = next 47 | next[1] = prev 48 | 49 | def __iter__(self): 50 | end = self.__end 51 | curr = end[2] 52 | while curr is not end: 53 | yield curr[0] 54 | curr = curr[2] 55 | 56 | def __reversed__(self): 57 | end = self.__end 58 | curr = end[1] 59 | while curr is not end: 60 | yield curr[0] 61 | curr = curr[1] 62 | 63 | def popitem(self, last=True): 64 | if not self: 65 | raise KeyError('dictionary is empty') 66 | # Modified from original to support Python 2.4, see 67 | # http://code.google.com/p/simplejson/issues/detail?id=53 68 | if last: 69 | key = reversed(self).next() 70 | else: 71 | key = iter(self).next() 72 | value = self.pop(key) 73 | return key, value 74 | 75 | def __reduce__(self): 76 | items = [[k, self[k]] for k in self] 77 | tmp = self.__map, self.__end 78 | del self.__map, self.__end 79 | inst_dict = vars(self).copy() 80 | self.__map, self.__end = tmp 81 | if inst_dict: 82 | return (self.__class__, (items,), inst_dict) 83 | return self.__class__, (items,) 84 | 85 | def keys(self): 86 | return list(self) 87 | 88 | setdefault = DictMixin.setdefault 89 | update = DictMixin.update 90 | pop = DictMixin.pop 91 | values = DictMixin.values 92 | items = DictMixin.items 93 | iterkeys = DictMixin.iterkeys 94 | itervalues = DictMixin.itervalues 95 | iteritems = DictMixin.iteritems 96 | 97 | def __repr__(self): 98 | if not self: 99 | return '%s()' % (self.__class__.__name__,) 100 | return '%s(%r)' % (self.__class__.__name__, self.items()) 101 | 102 | def copy(self): 103 | return self.__class__(self) 104 | 105 | @classmethod 106 | def fromkeys(cls, iterable, value=None): 107 | d = cls() 108 | for key in iterable: 109 | d[key] = value 110 | return d 111 | 112 | def __eq__(self, other): 113 | if isinstance(other, OrderedDict): 114 | return len(self)==len(other) and \ 115 | all(p==q for p, q in zip(self.items(), other.items())) 116 | return dict.__eq__(self, other) 117 | 118 | def __ne__(self, other): 119 | return not self == other 120 | -------------------------------------------------------------------------------- /simplejson/scanner.py: -------------------------------------------------------------------------------- 1 | """JSON token scanner 2 | """ 3 | import re 4 | def _import_c_make_scanner(): 5 | try: 6 | from simplejson._speedups import make_scanner 7 | return make_scanner 8 | except ImportError: 9 | return None 10 | c_make_scanner = _import_c_make_scanner() 11 | 12 | __all__ = ['make_scanner'] 13 | 14 | NUMBER_RE = re.compile( 15 | r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?', 16 | (re.VERBOSE | re.MULTILINE | re.DOTALL)) 17 | 18 | def py_make_scanner(context): 19 | parse_object = context.parse_object 20 | parse_array = context.parse_array 21 | parse_string = context.parse_string 22 | match_number = NUMBER_RE.match 23 | encoding = context.encoding 24 | strict = context.strict 25 | parse_float = context.parse_float 26 | parse_int = context.parse_int 27 | parse_constant = context.parse_constant 28 | object_hook = context.object_hook 29 | object_pairs_hook = context.object_pairs_hook 30 | memo = context.memo 31 | 32 | def _scan_once(string, idx): 33 | try: 34 | nextchar = string[idx] 35 | except IndexError: 36 | raise StopIteration 37 | 38 | if nextchar == '"': 39 | return parse_string(string, idx + 1, encoding, strict) 40 | elif nextchar == '{': 41 | return parse_object((string, idx + 1), encoding, strict, 42 | _scan_once, object_hook, object_pairs_hook, memo) 43 | elif nextchar == '[': 44 | return parse_array((string, idx + 1), _scan_once) 45 | elif nextchar == 'n' and string[idx:idx + 4] == 'null': 46 | return None, idx + 4 47 | elif nextchar == 't' and string[idx:idx + 4] == 'true': 48 | return True, idx + 4 49 | elif nextchar == 'f' and string[idx:idx + 5] == 'false': 50 | return False, idx + 5 51 | 52 | m = match_number(string, idx) 53 | if m is not None: 54 | integer, frac, exp = m.groups() 55 | if frac or exp: 56 | res = parse_float(integer + (frac or '') + (exp or '')) 57 | else: 58 | res = parse_int(integer) 59 | return res, m.end() 60 | elif nextchar == 'N' and string[idx:idx + 3] == 'NaN': 61 | return parse_constant('NaN'), idx + 3 62 | elif nextchar == 'I' and string[idx:idx + 8] == 'Infinity': 63 | return parse_constant('Infinity'), idx + 8 64 | elif nextchar == '-' and string[idx:idx + 9] == '-Infinity': 65 | return parse_constant('-Infinity'), idx + 9 66 | else: 67 | raise StopIteration 68 | 69 | def scan_once(string, idx): 70 | try: 71 | return _scan_once(string, idx) 72 | finally: 73 | memo.clear() 74 | 75 | return scan_once 76 | 77 | make_scanner = c_make_scanner or py_make_scanner 78 | -------------------------------------------------------------------------------- /simplejson/tool.py: -------------------------------------------------------------------------------- 1 | r"""Command-line tool to validate and pretty-print JSON 2 | 3 | Usage:: 4 | 5 | $ echo '{"json":"obj"}' | python -m simplejson.tool 6 | { 7 | "json": "obj" 8 | } 9 | $ echo '{ 1.2:3.4}' | python -m simplejson.tool 10 | Expecting property name: line 1 column 2 (char 2) 11 | 12 | """ 13 | import sys 14 | import simplejson as json 15 | 16 | def main(): 17 | if len(sys.argv) == 1: 18 | infile = sys.stdin 19 | outfile = sys.stdout 20 | elif len(sys.argv) == 2: 21 | infile = open(sys.argv[1], 'rb') 22 | outfile = sys.stdout 23 | elif len(sys.argv) == 3: 24 | infile = open(sys.argv[1], 'rb') 25 | outfile = open(sys.argv[2], 'wb') 26 | else: 27 | raise SystemExit(sys.argv[0] + " [infile [outfile]]") 28 | try: 29 | obj = json.load(infile, 30 | object_pairs_hook=json.OrderedDict, 31 | use_decimal=True) 32 | except ValueError, e: 33 | raise SystemExit(e) 34 | json.dump(obj, outfile, sort_keys=True, indent=' ', use_decimal=True) 35 | outfile.write('\n') 36 | 37 | 38 | if __name__ == '__main__': 39 | main() 40 | -------------------------------------------------------------------------------- /startup/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/startup/__init__.py -------------------------------------------------------------------------------- /startup/_common_imports.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2011 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | 20 | from __future__ import absolute_import 21 | 22 | import os, sys 23 | 24 | from diffcalc.hardware import ScannableHardwareAdapter 25 | import diffcalc.hkl.you.geometry 26 | from diffcalc.ub.persistence import UBCalculationJSONPersister 27 | from diffcalc.hkl.you.persistence import YouStateEncoder 28 | from diffcalc import settings 29 | import diffcalc.util 30 | 31 | try: 32 | __IPYTHON__ # @UndefinedVariable 33 | IPYTHON = True 34 | except NameError: 35 | IPYTHON = False 36 | 37 | try: 38 | from gda.device.scannable.scannablegroup import ScannableGroup 39 | from gdascripts.scannable.dummy import SingleInputDummy as Dummy 40 | from diffcmd.diffcmd_utils import alias_commands 41 | GDA = True 42 | except ImportError: 43 | # Not running in gda environment so fall back to minigda emulation 44 | from diffcalc.gdasupport.minigda.scannable import ScannableGroup 45 | from diffcalc.gdasupport.minigda.scannable import SingleFieldDummyScannable as Dummy 46 | GDA = False 47 | 48 | 49 | HELP_STRING = \ 50 | """Quick: https://github.com/DiamondLightSource/diffcalc/blob/master/README.rst 51 | Manual: http://diffcalc.readthedocs.io/en/latest/youmanual.html 52 | Type: > help ub 53 | > help hkl""" 54 | 55 | 56 | if GDA: 57 | from gda.configuration.properties import LocalProperties # @UnresolvedImport 58 | var_folder = LocalProperties.get("gda.var") 59 | diffcalc_persistance_path = os.path.join(var_folder, 'diffcalc') 60 | if not os.path.exists(diffcalc_persistance_path): 61 | print "Making diffcalc var folder:'%s'" % diffcalc_persistance_path 62 | os.makedirs(diffcalc_persistance_path) 63 | settings.ubcalc_persister = UBCalculationJSONPersister(diffcalc_persistance_path, YouStateEncoder) 64 | # else: should have been set if outside GDA 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /startup/_make_sixcircle_manual.py: -------------------------------------------------------------------------------- 1 | from startup._common_imports import * 2 | 3 | 4 | diffcalc.util.COLOURISE_TERMINAL_OUTPUT = False 5 | 6 | ### Create dummy scannables ### 7 | print "Dummy scannables: sixc(mu, delta, gam, eta, chi, phi) and en" 8 | mu = Dummy('mu') 9 | delta = Dummy('delta') 10 | gam = Dummy('gam') 11 | eta = Dummy('eta') 12 | chi = Dummy('chi') 13 | phi = Dummy('phi') 14 | _sixc = ScannableGroup('sixc', (mu, delta, gam, eta, chi, phi)) 15 | en = Dummy('en') 16 | en.level = 3 17 | 18 | 19 | ### Configure and import diffcalc objects ### 20 | ESMTGKeV = 1 21 | settings.hardware = ScannableHardwareAdapter(_sixc, en, ESMTGKeV) 22 | settings.geometry = diffcalc.hkl.you.geometry.SixCircle() # @UndefinedVariable 23 | settings.energy_scannable = en 24 | settings.axes_scannable_group= _sixc 25 | settings.energy_scannable_multiplier_to_get_KeV = ESMTGKeV 26 | 27 | 28 | # For manual! 29 | from diffcalc.ub.persistence import UbCalculationNonPersister 30 | settings.ubcalc_persister = UbCalculationNonPersister() 31 | 32 | from diffcalc.gdasupport.you import * # @UnusedWildImport 33 | 34 | 35 | DIFFCALC_ROOT = os.sep.join( 36 | os.path.realpath(diffcalc.__file__).split(os.sep)[:-2]) 37 | 38 | MANUALS_TO_MAKE = [ 39 | os.path.join( 40 | DIFFCALC_ROOT, 'doc', 'source', 'youmanual_template.rst'), 41 | os.path.join( 42 | DIFFCALC_ROOT, 'README_template.rst')] 43 | 44 | print 'MANUALS_TO_MAKE: ', MANUALS_TO_MAKE 45 | -------------------------------------------------------------------------------- /startup/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/startup/api/__init__.py -------------------------------------------------------------------------------- /startup/api/sixcircle.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import absolute_import 3 | 4 | 5 | from diffcalc import settings 6 | from diffcalc.hkl.you.geometry import SixCircle 7 | from diffcalc.hardware import DummyHardwareAdapter 8 | import diffcalc.util # @UnusedImport 9 | 10 | 11 | # Disable error handling designed for interactive use 12 | diffcalc.util.DEBUG = True 13 | 14 | 15 | # Configure and import diffcalc objects 16 | settings.hardware = DummyHardwareAdapter(('mu', 'delta', 'gam', 'eta', 'chi', 'phi')) 17 | settings.geometry = SixCircle() # @UndefinedVariable 18 | 19 | 20 | # These must be imported AFTER the settings have been configured 21 | from diffcalc.dc import dcyou as dc 22 | from diffcalc.ub import ub 23 | from diffcalc import hardware 24 | from diffcalc.hkl.you import hkl 25 | 26 | # Set some limits 27 | hardware.setmin('gam', -179) 28 | hardware.setmax('gam', 179) 29 | 30 | # These demos reproduce the outline in the developer guide 31 | def demo_all(): 32 | demo_orient() 33 | demo_motion() 34 | 35 | 36 | def demo_orient(): 37 | 38 | ub.listub() 39 | 40 | # Create a new ub calculation and set lattice parameters 41 | ub.newub('test') 42 | ub.setlat('cubic', 1, 1, 1, 90, 90, 90) 43 | 44 | # Add 1st reflection (demonstrating the hardware adapter) 45 | settings.hardware.wavelength = 1 46 | ub.c2th([1, 0, 0]) # energy from hardware 47 | settings.hardware.position = 0, 60, 0, 30, 0, 0 48 | ub.addref([1, 0, 0])# energy and position from hardware 49 | 50 | # Add 2nd reflection (this time without the harware adapter) 51 | ub.c2th([0, 1, 0], 12.39842) 52 | ub.addref([0, 1, 0], [0, 60, 0, 30, 0, 90], 12.39842) 53 | 54 | # check the state 55 | ub.ub() 56 | ub.checkub() 57 | 58 | 59 | def demo_motion(): 60 | dc.angles_to_hkl((0., 60., 0., 30., 0., 0.)) 61 | hkl.con('qaz', 90) 62 | hkl.con('a_eq_b') 63 | hkl.con('mu', 0) 64 | 65 | hardware.setmin('delta', 0) 66 | dc.hkl_to_angles(1, 0, 0) 67 | 68 | 69 | demo_all() 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /startup/b16.py: -------------------------------------------------------------------------------- 1 | from startup._common_imports import * 2 | from diffcalc.hkl.you.geometry import YouPosition 3 | import diffcalc.hkl.you.geometry 4 | 5 | if GDA: 6 | from __main__ import delta, theta, chi, phi 7 | 8 | from diffcalc.hkl.you.geometry import YouRemappedGeometry 9 | 10 | class FourCircleB16(YouRemappedGeometry): 11 | """For a diffractometer with angles: 12 | delta, theta, chi, phi 13 | """ 14 | def __init__(self, beamline_axes_transform=None): 15 | YouRemappedGeometry.__init__(self, 'fourc', {"gam": 0, "mu": 0}, beamline_axes_transform) 16 | 17 | # Order should match scannable order in _fourc group for mapping to work correctly 18 | self._scn_mapping_to_int = (('delta', lambda x: x), 19 | ('eta', lambda x: x), 20 | ('chi', lambda x: x + 90.0), 21 | ('phi', lambda x: x)) 22 | self._scn_mapping_to_ext = (('delta', lambda x: x), 23 | ('eta', lambda x: x), 24 | ('chi', lambda x: x - 90.0), 25 | ('phi', lambda x: x)) 26 | 27 | if GDA: 28 | from scannable.extraNameHider import ExtraNameHider 29 | dummy_energy = Dummy('dummy_energy') 30 | simple_energy = ExtraNameHider('energy', dummy_energy) # @UndefinedVariable 31 | 32 | else: # Assume running in dummy mode outside GDA 33 | delta = Dummy('delta') 34 | theta = Dummy('theta') 35 | chi = Dummy('chi') 36 | phi = Dummy('phi') 37 | energy = simple_energy = Dummy('energy') 38 | energy.level = 3 39 | 40 | ### Configure and import diffcalc objects ### 41 | 42 | ESMTGKeV = 0.001 43 | euler = ScannableGroup('euler', (delta, theta, chi, phi)) 44 | 45 | settings.hardware = ScannableHardwareAdapter(euler, simple_energy, ESMTGKeV) 46 | settings.geometry = FourCircleB16() 47 | settings.energy_scannable = simple_energy 48 | settings.axes_scannable_group= euler 49 | settings.energy_scannable_multiplier_to_get_KeV = ESMTGKeV 50 | 51 | from diffcalc.gdasupport.you import * # @UnusedWildImport 52 | 53 | hkl.setLevel(6) 54 | 55 | if GDA: 56 | print "Running in GDA --- aliasing commands" 57 | alias_commands(globals()) 58 | 59 | #lastub() # Load the last ub calculation used 60 | 61 | from startup.beamlinespecific.azihkl import AzihklClass 62 | azihkl=AzihklClass('aziref') 63 | azihkl() 64 | 65 | # iPython removes the actual command from namespace 66 | if not GDA: 67 | diffcalc.hardware.setrange(chi, -96.4, 259.4) 68 | diffcalc.hardware.setrange(phi, -147, 150) 69 | diffcalc.hardware.setrange(theta, -100, 235) 70 | diffcalc.hardware.setrange(delta, -10.4, 101.9) 71 | setcut(phi, -180) 72 | -------------------------------------------------------------------------------- /startup/beamlinespecific/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DiamondLightSource/diffcalc/e72db71307a65fbd2c30c1ab37422297a6cfaa25/startup/beamlinespecific/__init__.py -------------------------------------------------------------------------------- /startup/beamlinespecific/azihkl.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2018 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | import platform 20 | from diffcalc.util import DiffcalcException 21 | 22 | DEBUG = False 23 | 24 | try: 25 | from gda.device.scannable import ScannableBase 26 | except ImportError: 27 | from diffcalc.gdasupport.minigda.scannable import ScannableBase 28 | 29 | from diffcalc.ub.ub import ubcalc, _to_column_vector_triple 30 | 31 | 32 | class _DynamicDocstringMetaclass(type): 33 | 34 | def _get_doc(self): 35 | return AzihklClass.dynamic_docstring 36 | 37 | __doc__ = property(_get_doc) # @ReservedAssignment 38 | 39 | 40 | class AzihklClass(ScannableBase): 41 | 'Azimuthal reference reciprocal lattice vector' 42 | 43 | if platform.system() != 'Java': 44 | __metaclass__ = _DynamicDocstringMetaclass # TODO: Removed to fix Jython 45 | 46 | dynamic_docstring = 'Azimuthal reference reciprocal lattice vector' 47 | 48 | def _get_doc(self): 49 | return AzihklClass.dynamic_docstring 50 | 51 | __doc__ = property(_get_doc) # @ReservedAssignment 52 | 53 | def __init__(self,name): 54 | self.setName(name) 55 | self.setLevel(3) 56 | self.setInputNames(['azih','azik','azil']) 57 | self.setOutputFormat(['%4.4f', '%4.4f','%4.4f']) 58 | 59 | def asynchronousMoveTo(self,new_position): 60 | ref_matrix = _to_column_vector_triple(new_position) 61 | ubcalc.set_n_hkl_configured(ref_matrix) 62 | 63 | def isBusy(self): 64 | return 0 65 | 66 | def getPosition(self): 67 | try: 68 | ref_matrix = ubcalc.n_hkl 69 | return ref_matrix.T.tolist()[0] 70 | except DiffcalcException, e: 71 | print e 72 | -------------------------------------------------------------------------------- /startup/beamlinespecific/i21.py: -------------------------------------------------------------------------------- 1 | ### 2 | # Copyright 2008-2019 Diamond Light Source Ltd. 3 | # This file is part of Diffcalc. 4 | # 5 | # Diffcalc is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Diffcalc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Diffcalc. If not, see . 17 | ### 18 | 19 | try: 20 | from gda.device.scannable.scannablegroup import ScannableGroup 21 | except ImportError: 22 | from diffcalc.gdasupport.minigda.scannable import ScannableGroup 23 | 24 | from diffcalc.gdasupport.scannable.diffractometer import DiffractometerScannableGroup 25 | from diffcalc.settings import NUNAME 26 | from diffcalc.hkl.you.geometry import YouRemappedGeometry 27 | 28 | 29 | TP_TOLL = 1e-4 30 | 31 | class FourCircleI21(YouRemappedGeometry): 32 | """For a diffractometer with angles: 33 | delta, eta, chi, phi 34 | """ 35 | def __init__(self, beamline_axes_transform=None, delta_offset=0): 36 | self._delta_offset = delta_offset 37 | YouRemappedGeometry.__init__(self, 'fourc', {'eta': 0, 'delta': 0}, beamline_axes_transform) 38 | 39 | # Order should match scannable order in _fourc group for mapping to work correctly 40 | self._scn_mapping_to_int = ((NUNAME, lambda x: x + self._delta_offset), 41 | ('mu', lambda x: x), 42 | ('chi', lambda x: x), 43 | ('phi', lambda x: -x)) 44 | self._scn_mapping_to_ext = ((NUNAME, lambda x: x - self._delta_offset), 45 | ('mu', lambda x: x), 46 | ('chi', lambda x: x), 47 | ('phi', lambda x: -x)) 48 | 49 | class TPScannableGroup(ScannableGroup): 50 | 51 | def asynchronousMoveTo(self, position): 52 | # if input has any Nones, then replace these with the current positions 53 | current = self.getPosition() 54 | if None in position: 55 | position = list(position) 56 | for idx, val in enumerate(position): 57 | if val is None: 58 | position[idx] = current[idx] 59 | 60 | for scn, pos, cur in zip(self.getGroupMembers(), position, current): 61 | if abs(pos - cur) < TP_TOLL: 62 | continue 63 | scn.asynchronousMoveTo(pos) 64 | scn.waitWhileBusy() 65 | 66 | class DiffractometerTPScannableGroup(DiffractometerScannableGroup): 67 | 68 | def asynchronousMoveTo(self, position): 69 | # if input has any Nones, then replace these with the current positions 70 | current = self.getPosition() 71 | if None in position: 72 | position = list(position) 73 | for idx, val in enumerate(position): 74 | if val is None: 75 | position[idx] = current[idx] 76 | 77 | for scn, pos, cur in zip(self.__motors, position, current): 78 | if abs(pos - cur) < TP_TOLL: 79 | continue 80 | scn.asynchronousMoveTo(pos) 81 | scn.waitWhileBusy() 82 | 83 | 84 | -------------------------------------------------------------------------------- /startup/fivecircle.py: -------------------------------------------------------------------------------- 1 | from startup._common_imports import * 2 | import startup._demo 3 | 4 | ### Create dummy scannables ### 5 | print "Diffcalc creating dummy Scannables as _fivec and en were not found" 6 | delta = Dummy('delta') 7 | gam = Dummy('gam') 8 | eta = Dummy('eta') 9 | chi = Dummy('chi') 10 | phi = Dummy('phi') 11 | _fivec = ScannableGroup('_fivec', (delta, gam, eta, chi, phi)) 12 | en = Dummy('en') 13 | en.level = 3 14 | 15 | 16 | ### Configure and import diffcalc objects ### 17 | ESMTGKeV = 1 18 | settings.hardware = ScannableHardwareAdapter(_fivec, en, ESMTGKeV) 19 | settings.geometry = diffcalc.hkl.you.geometry.FiveCircle() # @UndefinedVariable 20 | settings.energy_scannable = en 21 | settings.axes_scannable_group = _fivec 22 | settings.energy_scannable_multiplier_to_get_KeV = ESMTGKeV 23 | 24 | from diffcalc.gdasupport.you import * # @UnusedWildImport 25 | 26 | if GDA: 27 | print "Running in GDA --- aliasing commands" 28 | alias_commands(globals()) 29 | 30 | lastub() # Load the last ub calculation used 31 | 32 | # Set some limits 33 | setmin('gam', -179) 34 | setmax('gam', 179) 35 | 36 | demo = startup._demo.Demo(globals(), 'fivec') -------------------------------------------------------------------------------- /startup/fourcircle.py: -------------------------------------------------------------------------------- 1 | from startup._common_imports import * 2 | import startup._demo 3 | 4 | ### Create dummy scannables ### 5 | delta = Dummy('delta') 6 | eta = Dummy('eta') 7 | chi = Dummy('chi') 8 | phi = Dummy('phi') 9 | _fourc = ScannableGroup('_fourc', (delta, eta, chi, phi)) 10 | en = Dummy('en') 11 | en.level = 3 12 | 13 | 14 | ### Configure and import diffcalc objects ### 15 | ESMTGKeV = 1 16 | settings.hardware = ScannableHardwareAdapter(_fourc, en, ESMTGKeV) 17 | settings.geometry = diffcalc.hkl.you.geometry.FourCircle() # @UndefinedVariable 18 | settings.energy_scannable = en 19 | settings.axes_scannable_group= _fourc 20 | settings.energy_scannable_multiplier_to_get_KeV = ESMTGKeV 21 | 22 | from diffcalc.gdasupport.you import * # @UnusedWildImport 23 | 24 | if GDA: 25 | print "Running in GDA --- aliasing commands" 26 | alias_commands(globals()) 27 | 28 | # Load the last ub calculation used 29 | lastub() 30 | 31 | demo = startup._demo.Demo(globals(), 'fourc') -------------------------------------------------------------------------------- /startup/i06.py: -------------------------------------------------------------------------------- 1 | from startup._common_imports import * # @UnusedWildImport 2 | from diffcalc.gdasupport.minigda.scannable import ScannableMotionWithScannableFieldsBase # @UnusedImport 3 | 4 | from diffcalc.hkl.you.geometry import YouGeometry, YouPosition 5 | from diffcalc.settings import NUNAME 6 | from diffcalc.hardware import setrange 7 | from diffcalc.hkl.you.calc import SMALL 8 | if not GDA: 9 | import startup._demo 10 | else: 11 | # import __main__ # @UnresolvedImport 12 | from __main__ import dd2th,ddth,dummychi,energy # @UnresolvedImport 13 | LOCAL_MANUAL = "http://confluence.diamond.ac.uk/pages/viewpage.action?pageId=31853413" 14 | # Diffcalc i06-1 15 | # ======== === 16 | # delta dd2th 17 | # eta ddth 18 | # chi dummy 19 | # phi 0 20 | 21 | class ThreeCircleI06(YouGeometry): 22 | """For a diffractometer with theta two-theta geometry: 23 | delta, eta 24 | """ 25 | def __init__(self, beamline_axes_transform=None): 26 | YouGeometry.__init__(self, 'threec', {'mu': 0, NUNAME: 0, 'phi': 0}, beamline_axes_transform) 27 | 28 | def physical_angles_to_internal_position(self, physical_angle_tuple): 29 | # mu, delta, nu, eta, chi, phi 30 | delta_phys, eta_phys, chi_phys = physical_angle_tuple 31 | return YouPosition(0, delta_phys, 0, eta_phys, chi_phys, 0, 'DEG') 32 | 33 | def internal_position_to_physical_angles(self, internal_position): 34 | clone_position = internal_position.clone() 35 | clone_position.changeToDegrees() 36 | _, delta_phys, _, eta_phys, chi_phys, _ = clone_position.totuple() 37 | return delta_phys, eta_phys, chi_phys 38 | 39 | 40 | ### Create dummy scannables ### 41 | if GDA: 42 | print "!!! Starting LIVE diffcalc with delta(dd2th), eta(ddth), chi(dummy) and denergy." 43 | _threec = ScannableGroup('_threec', (dd2th, ddth, dummychi)) 44 | delta = _threec.dd2th 45 | eta = _threec.ddth 46 | en=energy 47 | # if float(en.getPosition()) == 0: # no energy value - dummy mode 48 | # en(800) 49 | 50 | else: 51 | delta = Dummy('delta') 52 | eta = Dummy('eta') 53 | chi = Dummy('chi') 54 | _threec = ScannableGroup('_threec', (delta, eta, chi)) 55 | en = Dummy('en') 56 | en(800) 57 | 58 | en.level = 3 59 | 60 | ### Configure and import diffcalc objects ### 61 | ESMTGKeV = 0.001 62 | settings.hardware = ScannableHardwareAdapter(_threec, en, ESMTGKeV) 63 | settings.geometry = ThreeCircleI06() # @UndefinedVariable 64 | settings.energy_scannable = en 65 | settings.axes_scannable_group= _threec 66 | settings.energy_scannable_multiplier_to_get_KeV = ESMTGKeV 67 | 68 | if not GDA: 69 | setrange('chi', 90 - SMALL, 90 + SMALL) 70 | 71 | from diffcalc.gdasupport.you import * # @UnusedWildImport 72 | 73 | if GDA: 74 | print "Running in GDA --- aliasing commands" 75 | alias_commands(globals()) 76 | 77 | # Load the last ub calculation used 78 | lastub() 79 | -------------------------------------------------------------------------------- /startup/i07EH1h.py: -------------------------------------------------------------------------------- 1 | from startup._common_imports import * # @UnusedWildImport 2 | from diffcalc.settings import NUNAME 3 | 4 | if GDA: 5 | from __main__ import diff1delta, diff1chi, diff1gamma, diff1theta, dcm1energy # @UnresolvedImport 6 | 7 | from diffcalc.hkl.you.geometry import YouRemappedGeometry 8 | 9 | try: 10 | from numpy import matrix 11 | except ImportError: 12 | from numjy import matrix 13 | 14 | 15 | class FourCircleI07EH1h(YouRemappedGeometry): 16 | """For a diffractometer with angles: 17 | delta, gam, eta, phi 18 | """ 19 | def __init__(self, beamline_axes_transform=None): 20 | YouRemappedGeometry.__init__(self, 'fourc', {'mu': 0, 'chi': 90}, beamline_axes_transform) 21 | 22 | # Order should match scannable order in _fourc group for mapping to work correctly 23 | omega_to_phi = lambda x: 180. - x 24 | self._scn_mapping_to_int = (('delta', lambda x: x), 25 | ('gam', lambda x: x), 26 | ('eta', lambda x: x), 27 | ('phi', omega_to_phi)) 28 | phi_to_omega = lambda x: ((180. - x) + 180.) % 360 - 180 29 | self._scn_mapping_to_ext = (('delta', lambda x: x), 30 | ('gam', lambda x: x), 31 | ('eta', lambda x: x), 32 | ('phi', phi_to_omega)) 33 | 34 | ### Create dummy scannables ### 35 | if GDA: 36 | ###map GDA scannable to diffcalc axis name### 37 | _fourc = ScannableGroup('_fourc', (diff1delta, diff1gamma, diff1chi, diff1theta)) 38 | delta=_fourc.diff1delta 39 | gamma=_fourc.diff1gamma 40 | chi=_fourc.diff1chi 41 | theta=_fourc.diff1theta 42 | omega = diff1omega 43 | en=dcm1energy 44 | if float(en.getPosition()) == 0: # no energy value - dummy mode 45 | en(800) 46 | else: 47 | #Create dummy axes to run outside GDA in IPython# 48 | delta = Dummy('delta') 49 | gamma = Dummy('gamma') 50 | chi = Dummy('chi') 51 | theta = Dummy('theta') 52 | _fourc = ScannableGroup('_fourc', (delta, gamma, chi, theta)) 53 | en = Dummy('en') 54 | en(800) 55 | 56 | en.level = 3 57 | 58 | ### Configure and import diffcalc objects ### 59 | ESMTGKeV = 1 60 | settings.hardware = ScannableHardwareAdapter(_fourc, en, ESMTGKeV) 61 | settings.geometry = FourCircleI07EH1h() # @UndefinedVariable 62 | settings.energy_scannable = en 63 | settings.axes_scannable_group= _fourc 64 | settings.energy_scannable_multiplier_to_get_KeV = ESMTGKeV 65 | settings.include_reference = False 66 | 67 | from diffcalc.gdasupport.you import * # @UnusedWildImport 68 | 69 | if GDA: 70 | omega = diff1omega 71 | print "Running in GDA --- aliasing commands" 72 | alias_commands(globals()) 73 | 74 | # Load the last ub calculation used 75 | lastub() 76 | # Set reference vector direction returning betain and betaout angles as theta and beta 77 | if ubcalc.name: 78 | surfnphi('0; 0; 1') 79 | 80 | ### Set i07 specific limits 81 | def setLimitsAndCuts(): 82 | ''' set motor limits for diffcalc, these are within the actual motor limits 83 | ''' 84 | setmin(delta, -11.275) 85 | setmax(delta, 100.0) 86 | setmin(gamma, -11.0) 87 | setmax(gamma, 49.934) 88 | setmin(chi, -5.096) 89 | setmax(chi, 5.115) 90 | setcut(omega, -180.0) 91 | print "Current hardware limits set to:" 92 | hardware() 93 | 94 | if not GDA: 95 | setLimitsAndCuts() 96 | 97 | # TODO: make demo code for (2+2) diffractometer geometry 98 | #if not GDA: 99 | # demo = startup._demo.Demo(globals(), 'fourc') 100 | -------------------------------------------------------------------------------- /startup/i07EH1v.py: -------------------------------------------------------------------------------- 1 | from startup._common_imports import * # @UnusedWildImport 2 | from diffcalc.settings import NUNAME 3 | 4 | if GDA: 5 | from __main__ import diff1delta, diff1theta, diff1gamma, diff1omega, dcm1energy # @UnresolvedImport 6 | 7 | from diffcalc.hkl.you.geometry import YouGeometry, YouPosition 8 | 9 | 10 | class FourCircleI07EH1v(YouGeometry): 11 | """For a diffractometer with angles: 12 | delta, gam, mu, phi 13 | """ 14 | def __init__(self, beamline_axes_transform=None): 15 | YouGeometry.__init__(self, 'fourc', {'eta': 0, 'chi': 0}, beamline_axes_transform) 16 | 17 | def physical_angles_to_internal_position(self, physical_angle_tuple): 18 | delta_phys, gam_phys, mu_phys, phi_phys = physical_angle_tuple 19 | return YouPosition(mu_phys, delta_phys, gam_phys, 0, 0, phi_phys, 'DEG') 20 | 21 | def internal_position_to_physical_angles(self, internal_position): 22 | clone_position = internal_position.clone() 23 | clone_position.changeToDegrees() 24 | mu_phys, delta_phys, gam_phys, _, _, phi_phys = clone_position.totuple() 25 | return delta_phys, gam_phys, mu_phys, phi_phys 26 | 27 | 28 | ### Create dummy scannables ### 29 | if GDA: 30 | ###map GDA scannable to diffcalc axis name### 31 | _fourc = ScannableGroup('_fourc', (diff1delta, diff1gamma, diff1theta, diff1omega)) 32 | delta=_fourc.diff1delta 33 | gamma = _fourc.diff1gamma 34 | omega = _fourc.diff1omega 35 | chi = diff1chi 36 | theta = diff1theta 37 | en=dcm1energy 38 | else: 39 | #Create dummy axes to run outside GDA in IPython# 40 | delta = Dummy('delta') 41 | gamma = Dummy('gamma') 42 | theta = Dummy('theta') 43 | omega = Dummy('omega') 44 | _fourc = ScannableGroup('_fourc', (delta, gamma, theta, omega)) 45 | en = Dummy('en') 46 | 47 | en.level = 3 48 | 49 | ### Configure and import diffcalc objects ### 50 | ESMTGKeV = 1 51 | settings.hardware = ScannableHardwareAdapter(_fourc, en, ESMTGKeV) 52 | settings.geometry = FourCircleI07EH1v() # @UndefinedVariable 53 | settings.energy_scannable = en 54 | settings.axes_scannable_group= _fourc 55 | settings.energy_scannable_multiplier_to_get_KeV = ESMTGKeV 56 | settings.include_reference = False 57 | 58 | from diffcalc.gdasupport.you import * # @UnusedWildImport 59 | 60 | if GDA: 61 | omega = _fourc.diff1omega 62 | print "Running in GDA --- aliasing commands" 63 | alias_commands(globals()) 64 | 65 | # Load the last ub calculation used 66 | lastub() 67 | # Set reference vector direction returning betain and betaout angles as theta and beta 68 | if ubcalc.name: 69 | surfnphi('0; 0; 1') 70 | 71 | ### Set i07 specific limits 72 | def setLimitsAndCuts(): 73 | ''' set motor limits for diffcalc, these are within the actual motor limits 74 | ''' 75 | setmin(delta, -11.275) 76 | setmax(delta, 100.0) 77 | setmin(gamma, -11.0) 78 | setmax(gamma, 49.934) 79 | setmin(theta, -6.561) 80 | setmax(theta, 29.163) 81 | setcut(omega, -180.0) 82 | print "Current hardware limits set to:" 83 | hardware() 84 | 85 | if not GDA: 86 | setLimitsAndCuts() 87 | 88 | # TODO: make demo code for (2+2) diffractometer geometry 89 | #if not GDA: 90 | # demo = startup._demo.Demo(globals(), 'fourc') 91 | -------------------------------------------------------------------------------- /startup/i07EH2v.py: -------------------------------------------------------------------------------- 1 | from startup._common_imports import * # @UnusedWildImport 2 | from diffcalc.settings import NUNAME 3 | 4 | if GDA: 5 | from __main__ import diff2delta, diff2alpha, diff2gamma, diff2omega, dcm1energy # @UnresolvedImport 6 | 7 | from diffcalc.hkl.you.geometry import YouGeometry, YouPosition 8 | 9 | 10 | class FourCircleI07EH2v(YouGeometry): 11 | """For a diffractometer with angles: 12 | delta, gam, mu, phi 13 | """ 14 | def __init__(self, beamline_axes_transform=None): 15 | YouGeometry.__init__(self, 'fourc', {'eta': 0, 'chi': 0}, beamline_axes_transform) 16 | 17 | def physical_angles_to_internal_position(self, physical_angle_tuple): 18 | delta_phys, gam_phys, mu_phys, phi_phys = physical_angle_tuple 19 | return YouPosition(mu_phys, delta_phys, gam_phys, 0, 0, phi_phys, 'DEG') 20 | 21 | def internal_position_to_physical_angles(self, internal_position): 22 | clone_position = internal_position.clone() 23 | clone_position.changeToDegrees() 24 | mu_phys, delta_phys, gam_phys, _, _, phi_phys = clone_position.totuple() 25 | return delta_phys, gam_phys, mu_phys, phi_phys 26 | 27 | 28 | ### Create dummy scannables ### 29 | if GDA: 30 | ###map GDA scannable to diffcalc axis name### 31 | _fourc = ScannableGroup('_fourc', (diff2delta, diff2gamma, diff2alpha, diff2omega)) 32 | delta=_fourc.diff2delta 33 | gamma = _fourc.diff2gamma 34 | alpha = _fourc.diff2alpha 35 | omega = _fourc.diff2omega 36 | en=dcm1energy 37 | else: 38 | #Create dummy axes to run outside GDA in IPython# 39 | delta = Dummy('delta') 40 | gamma = Dummy('gamma') 41 | alpha = Dummy('alpha') 42 | omega = Dummy('omega') 43 | _fourc = ScannableGroup('_fourc', (delta, gamma, alpha, omega)) 44 | en = Dummy('en') 45 | 46 | en.level = 3 47 | 48 | ### Configure and import diffcalc objects ### 49 | ESMTGKeV = 1 50 | settings.hardware = ScannableHardwareAdapter(_fourc, en, ESMTGKeV) 51 | settings.geometry = FourCircleI07EH2v() # @UndefinedVariable 52 | settings.energy_scannable = en 53 | settings.axes_scannable_group= _fourc 54 | settings.energy_scannable_multiplier_to_get_KeV = ESMTGKeV 55 | settings.include_reference = False 56 | 57 | from diffcalc.gdasupport.you import * # @UnusedWildImport 58 | 59 | if GDA: 60 | omega = _fourc.diff2omega 61 | print "Running in GDA --- aliasing commands" 62 | alias_commands(globals()) 63 | 64 | # Load the last ub calculation used 65 | lastub() 66 | # Set reference vector direction returning betain and betaout angles as alpha and beta 67 | if ubcalc.name: 68 | surfnphi('0; 0; 1') 69 | 70 | ### Set i07 specific limits 71 | def setLimitsAndCuts(): 72 | ''' set motor limits for diffcalc, these are within the actual motor limits 73 | ''' 74 | setmin(delta, -0.60755) 75 | setmax(delta, 120.0) 76 | setmin(gamma, -1.3913) 77 | setmax(gamma, 48.160) 78 | setmin(alpha, -2.5124) 79 | setmax(alpha, 24.107) 80 | setcut(omega, -180.0) 81 | print "Current hardware limits set to:" 82 | hardware() 83 | 84 | if not GDA: 85 | setLimitsAndCuts() 86 | 87 | # TODO: make demo code for (2+2) diffractometer geometry 88 | #if not GDA: 89 | # demo = startup._demo.Demo(globals(), 'fourc') 90 | -------------------------------------------------------------------------------- /startup/i16robot.py: -------------------------------------------------------------------------------- 1 | from startup._common_imports import * 2 | from diffcalc.hkl.you.geometry import YouPosition 3 | import diffcalc.hkl.you.geometry 4 | 5 | if GDA: 6 | from __main__ import delta, gam, rmu, reta, rchi, rphi # @UnresolvedImport 7 | 8 | if not GDA: 9 | import startup._demo 10 | 11 | LOCAL_MANUAL = 'http://confluence.diamond.ac.uk/display/I16/Diffcalc%20(i16)' 12 | 13 | class SixCircleI16(diffcalc.hkl.you.geometry.YouGeometry): 14 | def __init__(self): 15 | diffcalc.hkl.you.geometry.YouGeometry.__init__(self, 'sixc', {}) 16 | 17 | def physical_angles_to_internal_position(self, physical_angle_tuple): 18 | # i16: phi, chi, eta, mu, delta, gam 19 | # H. You: mu, delta, nu, eta, chi, phi 20 | phi_phys, chi_phys, eta_phys, mu_phys, delta_phys, gam_phys = physical_angle_tuple 21 | return YouPosition(mu_phys, delta_phys, gam_phys, eta_phys, chi_phys, phi_phys, unit='DEG') 22 | 23 | def internal_position_to_physical_angles(self, internal_position): 24 | clone_position = internal_position.clone() 25 | clone_position.changeToDegrees() 26 | mu_phys, delta_phys, nu_phys, eta_phys, chi_phys, phi_phys = clone_position.totuple() 27 | return phi_phys, chi_phys, eta_phys, mu_phys, delta_phys, nu_phys 28 | 29 | 30 | if GDA: 31 | from scannable.extraNameHider import ExtraNameHider 32 | dummy_energy = Dummy('dummy_energy') 33 | simple_energy = ExtraNameHider('energy', dummy_energy) # @UndefinedVariable 34 | reuler = ScannableGroup('reuler', (rphi, rchi, reta, rmu, delta, gam)) 35 | phi = reuler.phi 36 | chi = reluer.chi 37 | eta = reuler.eta 38 | mu = reuler.mu 39 | else: # Assume running in dummy mode outside GDA 40 | mu = Dummy('mu') 41 | delta = Dummy('delta') 42 | gam = Dummy('gam') 43 | eta = Dummy('eta') 44 | chi = Dummy('chi') 45 | phi = Dummy('phi') 46 | euler = ScannableGroup('euler', (phi, chi, eta, mu, delta, gam)) 47 | en = simple_energy = Dummy('energy') 48 | en.level = 3 49 | 50 | 51 | ### Configure and import diffcalc objects ### 52 | ESMTGKeV = 1 53 | settings.hardware = ScannableHardwareAdapter(reuler, simple_energy, ESMTGKeV) 54 | settings.geometry = SixCircleI16() 55 | settings.energy_scannable = simple_energy 56 | settings.axes_scannable_group= reuler 57 | settings.energy_scannable_multiplier_to_get_KeV = ESMTGKeV 58 | 59 | from diffcalc.gdasupport.you import * # @UnusedWildImport 60 | 61 | hkl.setLevel(6) 62 | 63 | if GDA: 64 | print "Running in GDA --- aliasing commands" 65 | alias_commands(globals()) 66 | 67 | lastub() # Load the last ub calculation used 68 | 69 | from startup.beamlinespecific.azihkl import AzihklClass 70 | azihkl=AzihklClass('aziref') 71 | azihkl() 72 | 73 | # iPython removes the actual command from namespace 74 | if not GDA: 75 | diffcalc.hardware.setrange(chi, -2, 100) 76 | diffcalc.hardware.setrange(eta, -2, 92) 77 | diffcalc.hardware.setrange(delta, -2, 145) 78 | diffcalc.hardware.setrange(gam, -2, 145) 79 | setcut(phi, -180) 80 | 81 | demo = startup._demo.Demo(globals(), 'i16') 82 | -------------------------------------------------------------------------------- /startup/sixcircle.py: -------------------------------------------------------------------------------- 1 | from startup._common_imports import * 2 | import startup._demo 3 | 4 | ### Create dummy scannables ### 5 | mu = Dummy('mu') 6 | delta = Dummy('delta') 7 | gam = Dummy('gam') 8 | eta = Dummy('eta') 9 | chi = Dummy('chi') 10 | phi = Dummy('phi') 11 | _sixc = ScannableGroup('_sixc', (mu, delta, gam, eta, chi, phi)) 12 | en = Dummy('en') 13 | en.level = 3 14 | 15 | 16 | ### Configure and import diffcalc objects ### 17 | ESMTGKeV = 1 18 | settings.hardware = ScannableHardwareAdapter(_sixc, en, ESMTGKeV) 19 | settings.geometry = diffcalc.hkl.you.geometry.SixCircle() # @UndefinedVariable 20 | settings.energy_scannable = en 21 | settings.axes_scannable_group= _sixc 22 | settings.energy_scannable_multiplier_to_get_KeV = ESMTGKeV 23 | 24 | from diffcalc.gdasupport.you import * # @UnusedWildImport 25 | 26 | if GDA: 27 | print "Running in GDA --- aliasing commands" 28 | alias_commands(globals()) 29 | 30 | # Load the last ub calculation used 31 | lastub() 32 | 33 | # Set some limits 34 | setmin('gam', -179) 35 | setmax('gam', 179) 36 | 37 | demo = startup._demo.Demo(globals(), 'sixc') -------------------------------------------------------------------------------- /todo.txt: -------------------------------------------------------------------------------- 1 | Complete restructure work: 2 | -------------------------- 3 | 4 | Merge current mast in 5 | 6 | Make sure we can start the willmot engine - also dcwillmot differs from dcyou in only two places 7 | 8 | Fix and sure have tests (or delete startup files): 9 | 10 | append_diffcalc_to_gda_jython_path.py 11 | b16fivecircle.py 12 | b16fourcircle_you_engine.py 13 | i10fourcircle.py 14 | sixcircle_api.py 15 | sixcircle_vrmldummy.py 16 | sixcircle.py 17 | 18 | Check for 3 failing math (at least on OSX): 19 | - 20 | 21 | Remove _diffcalc module: 22 | - comment as you go! 23 | - checkub -> add test to test_you.py 24 | - fix the 'help ub' and 'help hkl' commands 25 | - get hkl scannable working without _diffcalc 26 | 27 | 28 | Tidy: 29 | - move sim logic off: DiffractometerScannableGroup 30 | - move example folder up into diffcalc.gdasupport package 31 | - rewite documentaion to call actual code for tests 32 | 33 | Improve: 34 | - you.py should not skip creating any scannables for fixed constraints (or related ones) 35 | 36 | Compare number of tests again branch point 37 | Decision not to dump vlieg mode 38 | why no integration test for willmott 39 | 40 | 41 | 42 | 43 | 44 | 45 | List needs review. Unordered. RobW. 46 | ---------------------------------- 47 | 48 | - look at all commands together (showref, listub, cons) 49 | 50 | - overide help command. Perhaps just print __doc__ if it starts with '!' or '@command' 51 | 52 | - error handling in wrapper. check TypeError depth. Give help inside exception string. 53 | 54 | - parameter scannables should return current virtual angle __str__ would also show requestd 55 | 56 | - remove need for axis_par scannables - set value, consider e.g. mu scan, and moved from epics. mu scan requires mu to be same level as hkl to work efficiently 57 | 58 | - implement mu_eq_nu mode 59 | 60 | - add eta_half_delta and mu_half_nu modes 61 | 62 | - provide fivec etc plugins (i13 first) 63 | 64 | - provide arbitrary virtual names (and check arbitray motor names work) 65 | 66 | - provide short cut mode access my number (beamline specific) ? Good idea? 67 | 68 | - handle eV / keV properly (wavelength internally, flag to energy_unit equal 'keV' (default) or 'eV' 69 | 70 | - Fix .__doc__ help on hkl (metaclass syetm fails under Jython with a java base class) -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | # Tox (https://tox.readthedocs.io/) is a tool for running tests 2 | # in multiple virtualenvs. This configuration file will run the 3 | # test suite on all supported python versions. To use it, "pip install tox" 4 | # and then run "tox" from this directory. 5 | #py27 6 | 7 | [tox] 8 | envlist = jython 9 | 10 | [testenv:jython] 11 | basepython=/Users/zrb13439/jython/bin/jython 12 | 13 | 14 | [testenv] 15 | commands = 16 | # pytest 17 | # py.test --boxed integration_checks.py 18 | # diffcalc --help 19 | # ./diffcalc.py --modules 20 | # ./diffcalc.py --non-interactive --python sixcircle 21 | # ./diffcalc.py --non-interactive sixcircle 22 | 23 | deps = 24 | --------------------------------------------------------------------------------