Compare commits

..

1 Commits

Author SHA1 Message Date
cc2e0ecaa3 refactor: converted to new plugin structure 2024-03-10 21:09:06 +01:00
262 changed files with 12682 additions and 46801 deletions

View File

@@ -1,9 +0,0 @@
# Do not edit this file!
# It is needed to track the repo template version, and editing may break things.
# This file will be overwritten by copier on template updates.
_commit: v1.2.2
_src_path: https://github.com/bec-project/plugin_copier_template.git
make_commit: false
project_name: csaxs_bec
widget_plugins_input: []

View File

@@ -1,3 +0,0 @@
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
semantic-release changelog -D version_variable=$SCRIPT_DIR/../../semantic_release/__init__.py:__version__
semantic-release version -D version_variable=$SCRIPT_DIR/../../semantic_release/__init__.py:__version__

View File

@@ -1,3 +1,2 @@
black --line-length=100 $(git diff --cached --name-only --diff-filter=ACM -- '*.py')
isort --line-length=100 --profile=black --multi-line=3 --trailing-comma $(git diff --cached --name-only --diff-filter=ACM -- '*.py')
git add $(git diff --cached --name-only --diff-filter=ACM -- '*.py')
black --line-length=100 $(git diff --cached --name-only --diff-filter=ACM)
git add $(git diff --cached --name-only --diff-filter=ACM)

View File

@@ -1,85 +0,0 @@
name: CI for csaxs_bec
on:
push:
pull_request:
workflow_dispatch:
inputs:
BEC_WIDGETS_BRANCH:
description: "Branch of BEC Widgets to install"
required: false
type: string
default: "main"
BEC_CORE_BRANCH:
description: "Branch of BEC Core to install"
required: false
type: string
default: "main"
OPHYD_DEVICES_BRANCH:
description: "Branch of Ophyd Devices to install"
required: false
type: string
default: "main"
BEC_PLUGIN_REPO_BRANCH:
description: "Branch of the BEC Plugin Repository to install"
required: false
type: string
default: "main"
PYTHON_VERSION:
description: "Python version to use"
required: false
type: string
default: "3.11"
permissions:
pull-requests: write
jobs:
test:
runs-on: ubuntu-latest
env:
QTWEBENGINE_DISABLE_SANDBOX: 1
QT_QPA_PLATFORM: "offscreen"
steps:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "${{ inputs.PYTHON_VERSION || '3.11' }}"
- name: Checkout BEC Core
run: git clone --depth 1 --branch "${{ inputs.BEC_CORE_BRANCH || 'main' }}" https://github.com/bec-project/bec.git ./bec
- name: Checkout Ophyd Devices
run: git clone --depth 1 --branch "${{ inputs.OPHYD_DEVICES_BRANCH || 'main' }}" https://github.com/bec-project/ophyd_devices.git ./ophyd_devices
- name: Checkout BEC Widgets
run: git clone --depth 1 --branch "${{ inputs.BEC_WIDGETS_BRANCH || 'main' }}" https://github.com/bec-project/bec_widgets.git ./bec_widgets
- name: Checkout BEC Plugin Repository
uses: actions/checkout@v4
with:
repository: bec/csaxs_bec
ref: "${{ inputs.BEC_PLUGIN_REPO_BRANCH || github.head_ref || github.sha }}"
path: ./csaxs_bec
- name: Install dependencies
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y libgl1 libegl1 x11-utils libxkbcommon-x11-0 libdbus-1-3 xvfb
sudo apt-get -y install libnss3 libxdamage1 libasound2t64 libatomic1 libxcursor1
- name: Install Python dependencies
shell: bash
run: |
pip install uv
uv pip install --system -e ./ophyd_devices
uv pip install --system -e ./bec/bec_lib[dev]
uv pip install --system -e ./bec/bec_ipython_client
uv pip install --system -e ./bec/bec_server[dev]
uv pip install --system -e ./bec_widgets[dev,pyside6]
uv pip install --system -e ./csaxs_bec
- name: Run Pytest with Coverage
id: coverage
run: pytest --random-order --cov=./csaxs_bec --cov-config=./csaxs_bec/pyproject.toml --cov-branch --cov-report=xml --no-cov-on-fail ./csaxs_bec/tests/ || test $? -eq 5

3
.gitignore vendored
View File

@@ -8,9 +8,6 @@
**/.pytest_cache
**/*.egg*
# recovery_config files
recovery_config_*
# file writer data
**.h5

View File

@@ -1,20 +0,0 @@
include:
- project: bec/awi_utils
file: /templates/plugin-repo-template.yml
inputs:
name: "csaxs"
target: "csaxs_bec"
branch: $CHILD_PIPELINE_BRANCH
pages:
stage: Deploy
needs: []
variables:
TARGET_BRANCH: $CI_COMMIT_REF_NAME
rules:
- if: "$CI_COMMIT_TAG != null"
variables:
TARGET_BRANCH: $CI_COMMIT_TAG
- if: '$CI_COMMIT_REF_NAME == "main" && $CI_PROJECT_PATH == "bec/csaxs_bec"'
script:
- curl -X POST -d "branches=$CI_COMMIT_REF_NAME" -d "token=$RTD_TOKEN" https://readthedocs.org/api/v2/webhook/sls-csaxs/270162/

View File

@@ -1,29 +0,0 @@
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
version: 2
# Set the version of Python and other tools you might need
build:
os: ubuntu-20.04
tools:
python: "3.10"
jobs:
pre_install:
- pip install .
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py
# If using Sphinx, optionally build your docs in additional formats such as PDF
# formats:
# - pdf
# Optionally declare the Python requirements required to build your docs
python:
install:
- requirements: docs/requirements.txt

29
LICENSE
View File

@@ -1,29 +0,0 @@
BSD 3-Clause License
Copyright (c) 2025, Paul Scherrer Institute
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -6,12 +6,15 @@ You might want to run cSAXS copy scripts before in case you want to have the for
## Overview
- Clone cSAXS BEC repository into e-account (e.g. into ~/Data10/software/.)
- Start Epics iocs
- Start BEC, BEC server and load/modify the device config with relevant hardware
- BEC commands
1. Clone cSAXS BEC repository into e-account (e.g. into ~/Data10/software/.)
2. Install BEC
3. Start Epics iocs
4. Start BEC, BEC server and load/modify the device config with relevant hardware
5. BEC commands
6. Start BEC widgets (GUI for motor control, eiger live plot)
7. Troubleshooting and common problems
## Clone cSAXS BEC repository
## 1. Clone cSAXS BEC repository
Clone the current cSAXS BEC repository from GIT into the new e-account.
Create directory
@@ -21,9 +24,19 @@ cd ~/Data10/software
```
Clone repository
```bash
git clone https://gitlab.psi.ch/bec/csaxs_bec.git
git clone https://gitlab.psi.ch/bec/csaxs-bec.git
```
## Start epics iocs
## 2. Install BEC
There is a bash sript in the followin directory.
Go to the directory and run the script on pc15543 logged in as the e-account (BEC server):
```bash
ssh pc15543
cd ~/Data10/software/csaxs-bec/bin/
./setup_bec.sh
```
## 3. Start epics iocs
You can start up the iocs while the *./setup_bec.sh* script is running. Be aware though that the scripts requires you to interact with it.
@@ -81,7 +94,7 @@ iocsh -7.0.6 startup.script
```
Be aware -7.0.6 is referring to the current epics version and might change in future (SLS 2.0)
## Start BEC, BEC server and load device config
## 4. Start BEC, BEC server and load device config
Step 1 needs to have finished for continuing with these steps.
What remains now is to start the bec server. Connect to pc15543 and open a new terminal to run:
@@ -114,7 +127,7 @@ bec.config.save_current_session('~/Data10/software/current_config.yaml')
```
The second command is helpful if you adjust limits of motors, which will then be stored in the config and loaded if a reload of the configuration is needed.
## BEC commands
## 5. BEC commands
A number of commands that are useful:
@@ -134,3 +147,41 @@ scans.line_scan(dev.samx, -1, 1, dev.samy, -1, 1, steps=20, exp_time=0.5, readou
scans.sgalil_grid(start_y = , end_y = , interval_y = , start_x=, end_x=, interval_x =, exp_time=0.5, readout_time=3e-3, relative=True)
```
## 6. Start BEC widgets (GUI for motor control, eiger live plot)
To start the BEC widgets, the first step is to make the bec_widgets_venv using the start startup script.
Follow the commands below:
``` bash
cd ~/Data10/software/csaxs-bec/bin
./setup_bec_widgets.sh
```
Afterwards, activate the environment on either cons-01 comp-1/2
``` bash
cd ~/Data10/software/
source activate bec_widgets_venv/bin/activate
```
Each Plot needs their own shell with activate environment
1. Eiger Plot
``` bash
cd ~/Data10/software/bec-widgets/bec_widgets/examples/eiger_plot
python eiger_plot.py
```
2. Motor Controller
``` bash
cd ~/Data10/software/bec-widgets/bec_widgets/examples/motor_movement
python motor_example.py --config csaxs_config.yaml
```
## 7. Troubleshooting and common problems
Sometimes the data backend for the Eiger gets stuck or misses frames, this will result in an error
``` python
raise EigerTimeoutError(
ophyd_devices.epics.devices.eiger9m_csaxs.EigerTimeoutError: Reached timeout with detector state 1, std_daq state FINISHED and received frames of 100 for the file writer)
```
This happens more likely after CTRL C of a scan. To recover from this more reliably, perform the an acquisition in burst mode with 100 frames, little exposure until no error message is raised after. This can be up to 3 times from former experience.
``` bash
scans.acquire(exp_time=0.02, frames_per_trigger=100, readout_time= 3e-3)
```
Afterwards, you should be good to continue with 2D gridscans.

1
bec_plugins/__init__.py Normal file
View File

@@ -0,0 +1 @@
from .bec_client import *

View File

@@ -0,0 +1 @@
from .plugins import *

View File

@@ -0,0 +1,245 @@
from bec_lib.devicemanager import Device
from bec_lib.scan_report import ScanReport
# pylint:disable=undefined-variable
# pylint: disable=too-many-arguments
def dscan(
motor1: Device, m1_from: float, m1_to: float, steps: int, exp_time: float, **kwargs
) -> ScanReport:
"""Relative line scan with one device.
Args:
motor1 (Device): Device that should be scanned.
m1_from (float): Start position relative to the current position.
m1_to (float): End position relative to the current position.
steps (int): Number of steps.
exp_time (float): Exposure time.
Returns:
ScanReport: Status object.
Examples:
>>> dscan(dev.motor1, -5, 5, 10, 0.1)
"""
return scans.line_scan(
motor1, m1_from, m1_to, steps=steps, exp_time=exp_time, relative=True, **kwargs
)
def d2scan(
motor1: Device,
m1_from: float,
m1_to: float,
motor2: Device,
m2_from: float,
m2_to: float,
steps: int,
exp_time: float,
**kwargs
) -> ScanReport:
"""Relative line scan with two devices.
Args:
motor1 (Device): First device that should be scanned.
m1_from (float): Start position of the first device relative to its current position.
m1_to (float): End position of the first device relative to its current position.
motor2 (Device): Second device that should be scanned.
m2_from (float): Start position of the second device relative to its current position.
m2_to (float): End position of the second device relative to its current position.
steps (int): Number of steps.
exp_time (float): Exposure time
Returns:
ScanReport: Status object.
Examples:
>>> d2scan(dev.motor1, -5, 5, dev.motor2, -8, 8, 10, 0.1)
"""
return scans.line_scan(
motor1,
m1_from,
m1_to,
motor2,
m2_from,
m2_to,
steps=steps,
exp_time=exp_time,
relative=True,
**kwargs
)
def ascan(motor1, m1_from, m1_to, steps, exp_time, **kwargs):
"""Absolute line scan with one device.
Args:
motor1 (Device): Device that should be scanned.
m1_from (float): Start position.
m1_to (float): End position.
steps (int): Number of steps.
exp_time (float): Exposure time.
Returns:
ScanReport: Status object.
Examples:
>>> ascan(dev.motor1, -5, 5, 10, 0.1)
"""
return scans.line_scan(
motor1, m1_from, m1_to, steps=steps, exp_time=exp_time, relative=False, **kwargs
)
def a2scan(motor1, m1_from, m1_to, motor2, m2_from, m2_to, steps, exp_time, **kwargs):
"""Absolute line scan with two devices.
Args:
motor1 (Device): First device that should be scanned.
m1_from (float): Start position of the first device.
m1_to (float): End position of the first device.
motor2 (Device): Second device that should be scanned.
m2_from (float): Start position of the second device.
m2_to (float): End position of the second device.
steps (int): Number of steps.
exp_time (float): Exposure time
Returns:
ScanReport: Status object.
Examples:
>>> a2scan(dev.motor1, -5, 5, dev.motor2, -8, 8, 10, 0.1)
"""
return scans.line_scan(
motor1,
m1_from,
m1_to,
motor2,
m2_from,
m2_to,
steps=steps,
exp_time=exp_time,
relative=False,
**kwargs
)
def dmesh(motor1, m1_from, m1_to, m1_steps, motor2, m2_from, m2_to, m2_steps, exp_time, **kwargs):
"""Relative mesh scan (grid scan) with two devices.
Args:
motor1 (Device): First device that should be scanned.
m1_from (float): Start position of the first device relative to its current position.
m1_to (float): End position of the first device relative to its current position.
m1_steps (int): Number of steps for motor1.
motor2 (Device): Second device that should be scanned.
m2_from (float): Start position of the second device relative to its current position.
m2_to (float): End position of the second device relative to its current position.
m2_steps (int): Number of steps for motor2.
exp_time (float): Exposure time
Returns:
ScanReport: Status object.
Examples:
>>> dmesh(dev.motor1, -5, 5, 10, dev.motor2, -8, 8, 10, 0.1)
"""
return scans.grid_scan(
motor1,
m1_from,
m1_to,
m1_steps,
motor2,
m2_from,
m2_to,
m2_steps,
exp_time=exp_time,
relative=True,
)
def amesh(motor1, m1_from, m1_to, m1_steps, motor2, m2_from, m2_to, m2_steps, exp_time, **kwargs):
"""Absolute mesh scan (grid scan) with two devices.
Args:
motor1 (Device): First device that should be scanned.
m1_from (float): Start position of the first device.
m1_to (float): End position of the first device.
m1_steps (int): Number of steps for motor1.
motor2 (Device): Second device that should be scanned.
m2_from (float): Start position of the second device.
m2_to (float): End position of the second device.
m2_steps (int): Number of steps for motor2.
exp_time (float): Exposure time
Returns:
ScanReport: Status object.
Examples:
>>> amesh(dev.motor1, -5, 5, 10, dev.motor2, -8, 8, 10, 0.1)
"""
return scans.grid_scan(
motor1,
m1_from,
m1_to,
m1_steps,
motor2,
m2_from,
m2_to,
m2_steps,
exp_time=exp_time,
relative=False,
)
def umv(*args) -> ScanReport:
"""Updated absolute move (i.e. blocking) for one or more devices.
Returns:
ScanReport: Status object.
Examples:
>>> umv(dev.samx, 1)
>>> umv(dev.samx, 1, dev.samy, 2)
"""
return scans.umv(*args, relative=False)
def umvr(*args) -> ScanReport:
"""Updated relative move (i.e. blocking) for one or more devices.
Returns:
ScanReport: Status object.
Examples:
>>> umvr(dev.samx, 1)
>>> umvr(dev.samx, 1, dev.samy, 2)
"""
return scans.umv(*args, relative=True)
def mv(*args) -> ScanReport:
"""Absolute move for one or more devices.
Returns:
ScanReport: Status object.
Examples:
>>> mv(dev.samx, 1)
>>> mv(dev.samx, 1, dev.samy, 2)
"""
return scans.mv(*args, relative=False)
def mvr(*args) -> ScanReport:
"""Relative move for one or more devices.
Returns:
ScanReport: Status object.
Examples:
>>> mvr(dev.samx, 1)
>>> mvr(dev.samx, 1, dev.samy, 2)
"""
return scans.mv(*args, relative=True)

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -0,0 +1,2 @@
from .load_additional_correction import lamni_read_additional_correction
from .x_ray_eye_align import LamNI, XrayEyeAlign, MagLamNI, DataDrivenLamNI

View File

@@ -0,0 +1,269 @@
def bl_show_all '{
local gap
printf("beamline status at %s:\n",date())
if (!_bl_hall_temperature_ok()) {
bl_hall_temperature
printf("\n")
}
if (_bl_sls_status_unusual()) {
bl_sls_status
} else {
bl_ring_current
}
bl_chk_beam _show
printf("\n")
printf("U19 ID gap : ",gap)
gap = _id_get_gap_mm()
if (gap >= 8) {
text_bf
}
printf("%.3f mm\n",gap)
text_non_bf
if (!_id_loss_rate_ok()) {
id_loss_rate
}
bl_shutter_status
if (_bl_cvd_filter_open()) {
text_bf
printf("CVD diamond filter : open / out\n")
text_non_bf
}
if (!_bl_xbox_valve_es1_open()) {
bl_xbox_valve_es1 _show
}
if (_bl_ln2_non_standard()) {
text_bf
printf("\nNon standard liquid nitrogen cooling-warning parameters occur. Please report this to your local contact.\n")
text_non_bf
printf("The macro bl_ln2_warn can be used to control this e-mail warning feature.\n")
bl_ln2_warn "show"
printf("\n")
}
printf("\n")
bl_flight_tube_pressure
printf("\n")
bl_attended _show
_bl_check_alarm_records(1,1)
printf("\n")
bl_op_msg
}'
def _bl_hall_temperature_ok() '{
local temp_ok
local stat
temp_ok = 1
# EH T02 average temperature
stat = epics_get("ILUUL-02AV:TEMP")
if ((stat < 23.0) || (stat > 26.0)) {
temp_ok = 0
}
# EH T02 temperature at T0204 axis 16
stat = epics_get("ILUUL-0200-EB104:TEMP")
if ((stat < 23.0) || (stat > 26.0)) {
temp_ok = 0
}
# EH T02 temperature at T0205 axis 18
stat = epics_get("ILUUL-0200-EB105:TEMP")
if ((stat < 23.0) || (stat > 26.0)) {
temp_ok = 0
}
return (temp_ok)
}'
# ----------------------------------------------------------------------
def bl_hall_temperature '{
local stat
stat = epics_get("ILUUL-02AV:TEMP")
printf("hall T02 average temperature : ")
if ((stat < 23.0) || (stat > 25.0)) {
text_bf
}
printf("%.2f deg.C\n",stat)
text_non_bf
stat = epics_get("ILUUL-0200-EB104:TEMP")
printf("hall temperature at T0204 axis 16 : ")
if ((stat < 23) || (stat > 25)) {
text_bf
}
printf("%.2f deg.C\n",stat)
text_non_bf
stat = epics_get("ILUUL-0200-EB105:TEMP")
printf("hall temperature at T0205 axis 18 : ")
if ((stat < 23) || (stat > 25)) {
text_bf
}
printf("%.2f deg.C\n",stat)
text_non_bf
# stat = epics_get("ILUUL-0300-EB102:TEMP")
# printf("EH T03 temperature at T0302 axis 21: ")
# if ((stat < 23) || (stat > 25)) {
# text_bf
# }
# printf("%.2f deg.C\n",stat)
# text_non_bf
}'
def _bl_sls_status_unusual() '{
local unusual
local stat
unusual = 0
stat = epics_get("X12SA-SR-VAC:SETPOINT")
if (stat != "OK") {
unusual = 1
}
stat = epics_get("ACOAU-ACCU:OP-MODE.VAL")
if ((stat != "Light Available") && (stat != "Light-Available")) {
unusual = 1
}
stat = epics_get("ALIRF-GUN:INJ-MODE")
if (stat != "TOP-UP") {
unusual = 1
}
# current threshold
stat = epics_get("ALIRF-GUN:CUR-LOWLIM")
if (stat < 350) {
unusual = 1
}
# current deadband
stat = epics_get("ALIRF-GUN:CUR-DBAND")
if (stat > 2) {
unusual = 1
}
# orbit feedback mode
stat = epics_get("ARIDI-BPM:OFB-MODE")
if (stat != "fast") {
unusual = 1
}
# fast orbit feedback
stat = epics_get("ARIDI-BPM:FOFBSTATUS-G")
if (stat != "running") {
unusual = 1
}
return(unusual)
}'
def bl_sls_status '{
local stat
stat = epics_get("ACOAU-ACCU:OP-MODE.VAL")
printf("SLS status : ")
if ((stat != "Light Available") && (stat != "Light-Available")) {
text_bf
}
printf("%s\n",stat)
text_non_bf
stat = epics_get("ALIRF-GUN:INJ-MODE")
printf("SLS injection mode : ")
if (stat != "TOP-UP") {
text_bf
}
printf("%s\n",stat)
text_non_bf
stat = epics_get("ALIRF-GUN:CUR-LOWLIM")
printf("SLS current threshold : ")
if (stat < 350) {
text_bf
}
printf("%7.3f\n",stat)
text_non_bf
stat = epics_get("ALIRF-GUN:CUR-DBAND")
printf("SLS current deadband : ")
if (stat > 2) {
text_bf
}
printf("%7.3f\n",stat)
text_non_bf
stat = epics_get("ACORF-FILL:PAT-SELECT")
printf("SLS filling pattern : ")
printf("%s\n",stat)
bl_ring_current
stat = epics_get("ARIDI-PCT:TAU-HOUR")
printf("SLS filling life time : ")
printf("%.2f h\n",stat)
stat = epics_get("ARIDI-BPM:OFB-MODE")
printf("orbit feedback mode : ")
if (stat != "fast") {
text_bf
}
printf("%s\n",stat)
text_non_bf
stat = epics_get("ARIDI-BPM:FOFBSTATUS-G")
printf("fast orbit feedback : ")
if (stat != "running") {
text_bf
}
printf("%s\n",stat)
text_non_bf
}'
def _bl_get_ring_current() '{
return epics_get("ARIDI-PCT:CURRENT")
}'
# ----------------------------------------------------------------------
def _bl_no_ring_current() '{
# set an arbitrary current limit of 100mA as no-beam limit
if (_bl_get_ring_current() < 100) {
return 1
} else {
return 0
}
}'
# ----------------------------------------------------------------------
def bl_ring_current '{
local curr
curr = _bl_get_ring_current()
if (curr < 300) {
text_bf
}
printf("SLS ring current : %.3f mA\n",curr)
text_non_bf
}'

View File

@@ -0,0 +1,161 @@
import builtins
import time
from rich import box
from rich.console import Console
from rich.table import Table
from bec_client.plugins.cSAXS import epics_get, epics_put, fshclose
# import builtins to avoid linter errors
dev = builtins.__dict__.get("dev")
umv = builtins.__dict__.get("umv")
bec = builtins.__dict__.get("bec")
class LamNIOpticsMixin:
@staticmethod
def _get_user_param_safe(device, var):
param = dev[device].user_parameter
if not param or param.get(var) is None:
raise ValueError(f"Device {device} has no user parameter definition for {var}.")
return param.get(var)
def leye_out(self):
self.loptics_in()
fshclose()
leyey_out = self._get_user_param_safe("leyey", "out")
umv(dev.leyey, leyey_out)
epics_put("XOMNYI-XEYE-ACQ:0", 2)
# move rotation stage to zero to avoid problems with wires
umv(dev.lsamrot, 0)
umv(dev.dttrz, 5854, dev.fttrz, 2395)
def leye_in(self):
bec.queue.next_dataset_number += 1
# move rotation stage to zero to avoid problems with wires
umv(dev.lsamrot, 0)
umv(dev.dttrz, 6419.677, dev.fttrz, 2959.979)
while True:
moved_out = (input("Did the flight tube move out? (Y/n)") or "y").lower()
if moved_out == "y":
break
if moved_out == "n":
return
leyex_in = self._get_user_param_safe("leyex", "in")
leyey_in = self._get_user_param_safe("leyey", "in")
umv(dev.leyex, leyex_in, dev.leyey, leyey_in)
self.align.update_frame()
def _lfzp_in(self):
loptx_in = self._get_user_param_safe("loptx", "in")
lopty_in = self._get_user_param_safe("lopty", "in")
umv(
dev.loptx, loptx_in, dev.lopty, lopty_in
) # for 7.2567 keV and 150 mu, 60 nm fzp, loptz 83.6000 for propagation 1.4 mm
def lfzp_in(self):
"""
move in the lamni zone plate.
This will disable rt feedback, move the FZP and re-enabled the feedback.
"""
if "rtx" in dev and dev.rtx.enabled:
dev.rtx.controller.feedback_disable()
self._lfzp_in()
if "rtx" in dev and dev.rtx.enabled:
dev.rtx.controller.feedback_enable_with_reset()
def loptics_in(self):
"""
Move in the lamni optics, including the FZP and the OSA.
"""
self.lfzp_in()
self.losa_in()
def loptics_out(self):
"""Move out the lamni optics"""
if "rtx" in dev and dev.rtx.enabled:
dev.rtx.controller.feedback_disable()
# self.lcs_out()
self.losa_out()
loptx_out = self._get_user_param_safe("loptx", "out")
lopty_out = self._get_user_param_safe("lopty", "out")
umv(dev.loptx, loptx_out, dev.lopty, lopty_out)
if "rtx" in dev and dev.rtx.enabled:
time.sleep(1)
dev.rtx.controller.feedback_enable_with_reset()
def lcs_in(self):
# umv lcsx -1.852 lcsy -0.095
pass
def lcs_out(self):
umv(dev.lcsy, 3)
def losa_in(self):
# 6.2 keV, 170 um FZP
# umv(dev.losax, -1.4450000, dev.losay, -0.1800)
# umv(dev.losaz, -1)
# 6.7, 170
# umv(dev.losax, -1.4850, dev.losay, -0.1930)
# umv(dev.losaz, 1.0000)
# 7.2, 150
losax_in = self._get_user_param_safe("losax", "in")
losay_in = self._get_user_param_safe("losay", "in")
losaz_in = self._get_user_param_safe("losaz", "in")
umv(dev.losax, losax_in, dev.losay, losay_in)
umv(dev.losaz, losaz_in)
# 11 kev
# umv(dev.losax, -1.161000, dev.losay, -0.196)
# umv(dev.losaz, 1.0000)
def losa_out(self):
losay_out = self._get_user_param_safe("losay", "out")
losaz_out = self._get_user_param_safe("losaz", "out")
umv(dev.losaz, losaz_out)
umv(dev.losay, losay_out)
def lfzp_info(self):
loptz_val = dev.loptz.read()["loptz"]["value"]
distance = -loptz_val + 85.6 + 52
print(f"The sample is in a distance of {distance:.1f} mm from the FZP.")
diameters = [80e-6, 100e-6, 120e-6, 150e-6, 170e-6, 200e-6, 220e-6, 250e-6]
mokev_val = dev.mokev.read()["mokev"]["value"]
console = Console()
table = Table(
title=f"At the current energy of {mokev_val:.4f} keV we have following options:",
box=box.SQUARE,
)
table.add_column("Diameter", justify="center")
table.add_column("Focal distance", justify="center")
table.add_column("Current beam size", justify="center")
wavelength = 1.2398e-9 / mokev_val
for diameter in diameters:
outermost_zonewidth = 60e-9
focal_distance = diameter * outermost_zonewidth / wavelength
beam_size = (
-diameter / (focal_distance * 1000) * (focal_distance * 1000 - distance) * 1e6
)
table.add_row(
f"{diameter*1e6:.2f} microns",
f"{focal_distance:.2f} mm",
f"{beam_size:.2f} microns",
)
console.print(table)
print("OSA Information:")
# print(f"Current losaz %.1f\n", A[losaz])
# print("The OSA will collide with the sample plane at %.1f\n\n", 89.3-A[loptz])
print(
"The numbers presented here are for a sample in the plane of the lamni sample holder.\n"
)

View File

@@ -1,6 +1,7 @@
def lamni_read_additional_correction():
# "additional_correction_shift"
# [0][] x , [1][] y, [2][] angle, [3][0] number of elements
import numpy as np
with open("correction_lamni_um_S01405_.txt", "r") as f:
num_elements = f.readline()

View File

@@ -9,14 +9,13 @@ from pathlib import Path
import h5py
import numpy as np
from bec_client.plugins.cSAXS import epics_get, epics_put, fshclose, fshopen
from bec_lib import bec_logger
from bec_lib.alarm_handler import AlarmBase
from bec_lib.pdf_writer import PDFWriter
from typeguard import typechecked
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_get, epics_put, fshopen
from .lamni_optics_mixin import LaMNIInitStagesMixin, LamNIOpticsMixin
from .lamni_optics_mixin import LamNIOpticsMixin
logger = bec_logger.logger
bec = builtins.__dict__.get("bec")
@@ -32,7 +31,7 @@ class XrayEyeAlign:
self.lamni = lamni
self.device_manager = client.device_manager
self.scans = client.scans
# self.xeye = self.device_manager.devices.xeye
self.xeye = self.device_manager.devices.xeye
self.alignment_values = defaultdict(list)
self._reset_init_values()
self.corr_pos_x = []
@@ -189,8 +188,7 @@ class XrayEyeAlign:
val_y = epics_get(f"XOMNYI-XEYE-YVAL_Y:{k}") * self.PIXEL_CALIBRATION # in mm
self.alignment_values[k] = [val_x, val_y]
print(
f"Clicked position {k}: x {self.alignment_values[k][0]}, y"
f" {self.alignment_values[k][1]}"
f"Clicked position {k}: x {self.alignment_values[k][0]}, y {self.alignment_values[k][1]}"
)
if k == 0: # received center value of FZP
@@ -215,10 +213,7 @@ class XrayEyeAlign:
elif (
k == 1
): # received sample center value at samroy 0 ie the final base shift values
msg = (
f"Base shift values from movement are x {self.shift_xy[0]}, y"
f" {self.shift_xy[1]}"
)
msg = f"Base shift values from movement are x {self.shift_xy[0]}, y {self.shift_xy[1]}"
print(msg)
logger.info(msg)
self.shift_xy[0] += (
@@ -228,12 +223,13 @@ class XrayEyeAlign:
self.alignment_values[1][1] - self.alignment_values[0][1]
) * 1000
print(
"Base shift values from movement and clicked position are x"
f" {self.shift_xy[0]}, y {self.shift_xy[1]}"
f"Base shift values from movement and clicked position are x {self.shift_xy[0]}, y {self.shift_xy[1]}"
)
self.scans.lamni_move_to_scan_center(
self.shift_xy[0] / 1000, self.shift_xy[1] / 1000, self.get_tomo_angle()
self.shift_xy[0] / 1000,
self.shift_xy[1] / 1000,
self.get_tomo_angle(),
).wait()
self.send_message("please wait ...")
@@ -242,7 +238,9 @@ class XrayEyeAlign:
time.sleep(1)
self.scans.lamni_move_to_scan_center(
self.shift_xy[0] / 1000, self.shift_xy[1] / 1000, self.get_tomo_angle()
self.shift_xy[0] / 1000,
self.shift_xy[1] / 1000,
self.get_tomo_angle(),
).wait()
epics_put("XOMNYI-XEYE-ANGLE:0", self.get_tomo_angle())
@@ -259,12 +257,16 @@ class XrayEyeAlign:
self._disable_rt_feedback()
self.tomo_rotate((k - 1) * 45 - 45 / 2)
self.scans.lamni_move_to_scan_center(
self.shift_xy[0] / 1000, self.shift_xy[1] / 1000, self.get_tomo_angle()
self.shift_xy[0] / 1000,
self.shift_xy[1] / 1000,
self.get_tomo_angle(),
).wait()
self._disable_rt_feedback()
self.tomo_rotate((k - 1) * 45)
self.scans.lamni_move_to_scan_center(
self.shift_xy[0] / 1000, self.shift_xy[1] / 1000, self.get_tomo_angle()
self.shift_xy[0] / 1000,
self.shift_xy[1] / 1000,
self.get_tomo_angle(),
).wait()
epics_put("XOMNYI-XEYE-ANGLE:0", self.get_tomo_angle())
@@ -291,7 +293,9 @@ class XrayEyeAlign:
self.shift_xy[0] = self.shift_xy[0] + _xrayeyalignmvx
self.shift_xy[1] = self.shift_xy[1] + _xrayeyalignmvy
self.scans.lamni_move_to_scan_center(
self.shift_xy[0] / 1000, self.shift_xy[1] / 1000, self.get_tomo_angle()
self.shift_xy[0] / 1000,
self.shift_xy[1] / 1000,
self.get_tomo_angle(),
).wait()
print(
f"Current center horizontal {self.shift_xy[0]} vertical {self.shift_xy[1]}"
@@ -306,14 +310,12 @@ class XrayEyeAlign:
fovx = self._xray_fov_xy[0] * self.PIXEL_CALIBRATION * 1000 / 2
fovy = self._xray_fov_xy[1] * self.PIXEL_CALIBRATION * 1000 / 2
print(
f"The largest field of view from the xrayeyealign was \nfovx = {fovx:.0f} microns, fovy"
f" = {fovy:.0f} microns"
f"The largest field of view from the xrayeyealign was \nfovx = {fovx:.0f} microns, fovy = {fovy:.0f} microns"
)
print("Use matlab routine to fit the current alignment...")
print(
"This additional shift is applied to the base shift values\n which are x"
f" {self.shift_xy[0]}, y {self.shift_xy[1]}"
f"This additional shift is applied to the base shift values\n which are x {self.shift_xy[0]}, y {self.shift_xy[1]}"
)
self._disable_rt_feedback()
@@ -321,8 +323,7 @@ class XrayEyeAlign:
self.tomo_rotate(0)
print(
"\n\nNEXT LOAD ALIGNMENT PARAMETERS\nby running"
" lamni.align.read_xray_eye_correction()\n"
"\n\nNEXT LOAD ALIGNMENT PARAMETERS\nby running lamni.align.read_xray_eye_correction()\n"
)
self.client.set_global_var("tomo_fov_offset", self.shift_xy)
@@ -331,13 +332,12 @@ class XrayEyeAlign:
with open(
os.path.expanduser("~/Data10/specES1/internal/xrayeye_alignmentvalues"), "w"
) as alignment_values_file:
alignment_values_file.write("angle\thorizontal\tvertical\n")
alignment_values_file.write(f"angle\thorizontal\tvertical\n")
for k in range(2, 11):
fovx_offset = (self.alignment_values[0][0] - self.alignment_values[k][0]) * 1000
fovy_offset = (self.alignment_values[k][1] - self.alignment_values[0][1]) * 1000
print(
f"Writing to file new alignment: number {k}, value x {fovx_offset}, y"
f" {fovy_offset}"
f"Writing to file new alignment: number {k}, value x {fovx_offset}, y {fovy_offset}"
)
alignment_values_file.write(f"{(k-2)*45}\t{fovx_offset}\t{fovy_offset}\n")
@@ -422,8 +422,7 @@ class XrayEyeAlign:
additional_correction_shift_x = self.corr_pos_x[-1]
additional_correction_shift_y = self.corr_pos_y[-1]
print(
"Additional correction shifts:"
f" {additional_correction_shift_x} {additional_correction_shift_y}"
f"Additional correction shifts: {additional_correction_shift_x} {additional_correction_shift_y}"
)
return (additional_correction_shift_x, additional_correction_shift_y)
@@ -477,8 +476,7 @@ class XrayEyeAlign:
additional_correction_shift_x = self.corr_pos_x_2[-1]
additional_correction_shift_y = self.corr_pos_y_2[-1]
print(
"Additional correction shifts 2:"
f" {additional_correction_shift_x} {additional_correction_shift_y}"
f"Additional correction shifts 2: {additional_correction_shift_x} {additional_correction_shift_y}"
)
return (additional_correction_shift_x, additional_correction_shift_y)
@@ -511,7 +509,7 @@ class LamNI(LamNIOpticsMixin):
super().__init__()
self.client = client
self.align = XrayEyeAlign(client, self)
self.init = LaMNIInitStagesMixin()
self.check_shutter = True
self.check_light_available = True
self.check_fofb = True
@@ -527,8 +525,7 @@ class LamNI(LamNIOpticsMixin):
def get_beamline_checks_enabled(self):
print(
f"Shutter: {self.check_shutter}\nFOFB: {self.check_fofb}\nLight available:"
f" {self.check_light_available}"
f"Shutter: {self.check_shutter}\nFOFB: {self.check_fofb}\nLight available: {self.check_light_available}"
)
@property
@@ -586,27 +583,6 @@ class LamNI(LamNIOpticsMixin):
def tomo_circfov(self, val: float):
self.client.set_global_var("tomo_circfov", val)
@property
def tomo_type(self):
val = self.client.get_global_var("tomo_type")
if val is None:
return 1
return val
@tomo_type.setter
def tomo_type(self, val: float):
if val == 1:
# equally spaced tomography with 8 sub tomograms
self.client.set_global_var("tomo_type", val)
# elif val == 2:
# # golden ratio tomography (sorted bunches)
# self.client.set_global_var("tomo_type", val)
# elif val == 3:
# # equally spaced tomography with starting angles shifted by golden ratio
# self.client.set_global_var("tomo_type", val)
else:
raise ValueError("Unknown tomo_type.")
@property
def tomo_countingtime(self):
val = self.client.get_global_var("tomo_countingtime")
@@ -790,18 +766,13 @@ class LamNI(LamNIOpticsMixin):
# pylint: disable=undefined-variable
self._current_scan_list.append(bec.queue.next_scan_number)
logger.info(
f"scans.lamni_fermat_scan(fov_size=[{self.lamni_piezo_range_x},{self.lamni_piezo_range_y}],"
f" step={self.tomo_shellstep}, stitch_x={0}, stitch_y={0},"
f" stitch_overlap={1},center_x={self.align.tomo_fovx_offset},"
f" center_y={self.align.tomo_fovy_offset},"
f" shift_x={self.manual_shift_x+correction_xeye_mu[0]-additional_correction[0]-additional_correction_2[0]},"
f" shift_y={self.manual_shift_y+correction_xeye_mu[1]-additional_correction[1]-additional_correction_2[1]},"
f" fov_circular={self.tomo_circfov}, angle={angle}, scan_type='fly')"
)
log_message = (
f"{str(datetime.datetime.now())}: LamNI scan projection at angle {angle}, scan"
f" number {bec.queue.next_scan_number}.\n"
f"scans.lamni_fermat_scan(fov_size=[{self.lamni_piezo_range_x},{self.lamni_piezo_range_y}], step={self.tomo_shellstep}, stitch_x={0}, stitch_y={0}, stitch_overlap={1},"
f"center_x={self.align.tomo_fovx_offset}, center_y={self.align.tomo_fovy_offset}, "
f"shift_x={self.manual_shift_x+correction_xeye_mu[0]-additional_correction[0]-additional_correction_2[0]}, "
f"shift_y={self.manual_shift_y+correction_xeye_mu[1]-additional_correction[1]-additional_correction_2[1]}, "
f"fov_circular={self.tomo_circfov}, angle={angle}, scan_type='fly')"
)
log_message = f"{str(datetime.datetime.now())}: LamNI scan projection at angle {angle}, scan number {bec.queue.next_scan_number}.\n"
self.write_to_spec_log(log_message)
# self.write_to_scilog(log_message, ["BEC_scans", self.sample_name])
corridor_size = self.corridor_size if self.corridor_size > 0 else None
@@ -843,7 +814,10 @@ class LamNI(LamNIOpticsMixin):
msgs.append("Check beam failed: Shutter is closed.")
if self.check_light_available:
machine_status = dev.sls_machine_status.read(cached=True)
if machine_status["value"] not in ["Light Available", "Light-Available"]:
if machine_status["value"] not in [
"Light Available",
"Light-Available",
]:
self._beam_is_okay = False
msgs.append("Check beam failed: Light not available.")
if self.check_fofb:
@@ -884,8 +858,7 @@ class LamNI(LamNIOpticsMixin):
try:
msg = bec.logbook.LogbookMessage()
msg.add_text(
"<p><mark class='pen-red'><strong>Beamline checks failed at"
f" {str(datetime.datetime.now())}: {''.join(self._check_msgs)}</strong></mark></p>"
f"<p><mark class='pen-red'><strong>Beamline checks failed at {str(datetime.datetime.now())}: {''.join(self._check_msgs)}</strong></mark></p>"
).add_tag(["BEC", "beam_check"])
self.client.logbook.send_logbook_message(msg)
except Exception:
@@ -902,20 +875,25 @@ class LamNI(LamNIOpticsMixin):
try:
msg = bec.logbook.LogbookMessage()
msg.add_text(
"<p><mark class='pen-red'><strong>Operation resumed at"
f" {str(datetime.datetime.now())}.</strong></mark></p>"
f"<p><mark class='pen-red'><strong>Operation resumed at {str(datetime.datetime.now())}.</strong></mark></p>"
).add_tag(["BEC", "beam_check"])
self.client.logbook.send_logbook_message(msg)
except Exception:
logger.warning("Failed to send update to SciLog.")
def add_sample_database(
self, samplename, date, eaccount, scan_number, setup, sample_additional_info, user
self,
samplename,
date,
eaccount,
scan_number,
setup,
sample_additional_info,
user,
):
"""Add a sample to the omny sample database. This also retrieves the tomo id."""
subprocess.run(
"wget --user=omny --password=samples -q -O /tmp/currsamplesnr.txt"
f" 'https://omny.web.psi.ch/samples/newmeasurement.php?sample={samplename}&date={date}&eaccount={eaccount}&scannr={scan_number}&setup={setup}&additional={sample_additional_info}&user={user}'",
f"wget --user=omny --password=samples -q -O /tmp/currsamplesnr.txt 'https://omny.web.psi.ch/samples/newmeasurement.php?sample={samplename}&date={date}&eaccount={eaccount}&scannr={scan_number}&setup={setup}&additional={sample_additional_info}&user={user}'",
shell=True,
)
with open("/tmp/currsamplesnr.txt") as tomo_number_file:
@@ -969,63 +947,25 @@ class LamNI(LamNIOpticsMixin):
# _tomo_shift_angles (potential global variable)
_tomo_shift_angles = 0
angle_end = start_angle + 360
angles = np.linspace(
for angle in np.linspace(
start_angle + _tomo_shift_angles,
angle_end,
num=int(360 / self.tomo_angle_stepsize) + 1,
endpoint=True,
)
# reverse even sub-tomograms
if not (subtomo_number % 2):
angles = np.flip(angles)
for angle in angles:
self.progress["subtomo"] = subtomo_number
self.progress["subtomo_projection"] = angles.index(angle)
self.progress["subtomo_total_projections"] = 180 / self.tomo_angle_stepsize
self.progress["projection"] = (subtomo_number - 1) * self.progress[
"subtomo_total_projections"
] + self.progress["subtomo_projection"]
self.progress["total_projections"] = 180 / self.tomo_angle_stepsize * 8
self.progress["angle"] = angle
self._tomo_scan_at_angle(angle, subtomo_number)
def _print_progress(self):
print("\x1b[95mProgress report:")
print(f"Tomo type: ....................... {self.progress['tomo_type']}")
print(f"Projection: ...................... {self.progress['projection']}")
print(f"Total projections expected ....... {self.progress['total_projections']}")
print(f"Angle: ........................... {self.progress['angle']}")
print(f"Current subtomo: ................. {self.progress['subtomo']}")
print(f"Current projection within subtomo: {self.progress['subtomo_projection']}\x1b[0m")
def _tomo_scan_at_angle(self, angle, subtomo_number):
successful = False
error_caught = False
if 0 <= angle < 360.05:
print(f"Starting LamNI scan for angle {angle} in subtomo {subtomo_number}")
self._print_progress()
while not successful:
self._start_beam_check()
if not self.special_angles:
self._current_special_angles = []
if self._current_special_angles:
next_special_angle = self._current_special_angles[0]
if np.isclose(angle, next_special_angle, atol=0.5):
self._current_special_angles.pop(0)
num_repeats = self.special_angle_repeats
else:
num_repeats = 1
try:
start_scan_number = bec.queue.next_scan_number
for i in range(num_repeats):
self._at_each_angle(angle)
error_caught = False
except AlarmBase as exc:
if exc.alarm_type == "TimeoutError":
bec.queue.request_queue_reset()
time.sleep(2)
error_caught = True
):
successful = False
error_caught = False
if 0 <= angle < 360.05:
print(f"Starting LamNI scan for angle {angle}")
while not successful:
self._start_beam_check()
if not self.special_angles:
self._current_special_angles = []
if self._current_special_angles:
next_special_angle = self._current_special_angles[0]
if np.isclose(angle, next_special_angle, atol=0.5):
self._current_special_angles.pop(0)
num_repeats = self.special_angle_repeats
else:
num_repeats = 1
try:
@@ -1065,7 +1005,7 @@ class LamNI(LamNIOpticsMixin):
scans = builtins.__dict__.get("scans")
self._current_special_angles = self.special_angles.copy()
if self.tomo_type == 1 and subtomo_start == 1 and start_angle is None:
if subtomo_start == 1 and start_angle is None:
# pylint: disable=undefined-variable
self.tomo_id = self.add_sample_database(
self.sample_name,
@@ -1088,16 +1028,14 @@ class LamNI(LamNIOpticsMixin):
print(f"Counting time <ctime> = {self.tomo_countingtime} s")
print(f"Stepsize microns <step> = {self.tomo_shellstep}")
print(
f"Piezo range (max 80) <microns> = {self.lamni_piezo_range_x},"
f" {self.lamni_piezo_range_y}"
f"Piezo range (max 80) <microns> = {self.lamni_piezo_range_x}, {self.lamni_piezo_range_y}"
)
print(f"Stitching number x,y = {self.lamni_stitch_x}, {self.lamni_stitch_y}")
print(f"Stitching overlap = {self.tomo_stitch_overlap}")
print(f"Circuilar FOV diam <microns> = {self.tomo_circfov}")
print(f"Reconstruction queue name = {self.ptycho_reconstruct_foldername}")
print(
"For information, fov offset is rotating and finding the ROI, manual shift moves"
" rotation center"
"For information, fov offset is rotating and finding the ROI, manual shift moves rotation center"
)
print(f" _tomo_fovx_offset <mm> = {self.align.tomo_fovx_offset}")
print(f" _tomo_fovy_offset <mm> = {self.align.tomo_fovy_offset}")
@@ -1153,7 +1091,7 @@ class LamNI(LamNIOpticsMixin):
with open(ptycho_queue_file, "w") as queue_file:
scans = " ".join([str(scan) for scan in self._current_scan_list])
queue_file.write(f"p.scan_number {scans}\n")
queue_file.write("p.check_nextscan_started 1\n")
queue_file.write(f"p.check_nextscan_started 1\n")
def write_pdf_report(self):
"""create and write the pdf report with the current LamNI settings"""
@@ -1178,25 +1116,17 @@ class LamNI(LamNIOpticsMixin):
f"{'Dataset ID:':<{padding}}{dataset_id:>{padding}}\n",
f"{'Sample Info:':<{padding}}{'Sample Info':>{padding}}\n",
f"{'e-account:':<{padding}}{str(self.client.username):>{padding}}\n",
(
f"{'Number of projections:':<{padding}}{int(360 / self.tomo_angle_stepsize * 8):>{padding}}\n"
),
f"{'Number of projections:':<{padding}}{int(360 / self.tomo_angle_stepsize * 8):>{padding}}\n",
f"{'First scan number:':<{padding}}{self.client.queue.next_scan_number:>{padding}}\n",
(
f"{'Last scan number approx.:':<{padding}}{self.client.queue.next_scan_number + int(360 / self.tomo_angle_stepsize * 8) + 10:>{padding}}\n"
),
(
f"{'Current photon energy:':<{padding}}{dev.mokev.read(cached=True)['value']:>{padding}.4f}\n"
),
f"{'Last scan number approx.:':<{padding}}{self.client.queue.next_scan_number + int(360 / self.tomo_angle_stepsize * 8) + 10:>{padding}}\n",
f"{'Current photon energy:':<{padding}}{dev.mokev.read(cached=True)['value']:>{padding}.4f}\n",
f"{'Exposure time:':<{padding}}{self.tomo_countingtime:>{padding}.2f}\n",
f"{'Fermat spiral step size:':<{padding}}{self.tomo_shellstep:>{padding}.2f}\n",
f"{'Piezo range (FOV sample plane):':<{padding}}{piezo_range:>{padding}}\n",
f"{'Restriction to circular FOV:':<{padding}}{self.tomo_circfov:>{padding}.2f}\n",
f"{'Stitching:':<{padding}}{stitching:>{padding}}\n",
f"{'Number of individual sub-tomograms:':<{padding}}{8:>{padding}}\n",
(
f"{'Angular step within sub-tomogram:':<{padding}}{self.tomo_angle_stepsize:>{padding}.2f}\n"
),
f"{'Angular step within sub-tomogram:':<{padding}}{self.tomo_angle_stepsize:>{padding}.2f}\n",
]
content = "".join(content)
user_target = os.path.expanduser(f"~/Data10/documentation/tomo_scan_ID_{self.tomo_id}.pdf")
@@ -1204,13 +1134,20 @@ class LamNI(LamNIOpticsMixin):
file.write(header)
file.write(content)
subprocess.run(
"xterm /work/sls/spec/local/XOMNY/bin/upload/upload_last_pon.sh &", shell=True
"xterm /work/sls/spec/local/XOMNY/bin/upload/upload_last_pon.sh &",
shell=True,
)
# status = subprocess.run(f"cp /tmp/spec-e20131-specES1.pdf {user_target}", shell=True)
msg = bec.logbook.LogbookMessage()
logo_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "LamNI_logo.png")
msg.add_file(logo_path).add_text("".join(content).replace("\n", "</p><p>")).add_tag(
["BEC", "tomo_parameters", f"dataset_id_{dataset_id}", "LamNI", self.sample_name]
[
"BEC",
"tomo_parameters",
f"dataset_id_{dataset_id}",
"LamNI",
self.sample_name,
]
)
self.client.logbook.send_logbook_message(msg)
@@ -1295,12 +1232,16 @@ class DataDrivenLamNI(LamNI):
def sub_tomo_scan(self):
raise NotImplementedError(
"Cannot run sub_tomo_scan with data-driven LamNI. Please use"
" lamni.tomo_scan(subtomo_start=<START_NUM>) instead."
"Cannot run sub_tomo_scan with data-driven LamNI. Please use lamni.tomo_scan(subtomo_start=<START_NUM>) instead."
)
def _at_each_angle(
self, angle=None, stepsize=None, loptz_pos=None, manual_shift_x=0, manual_shift_y=0
self,
angle=None,
stepsize=None,
loptz_pos=None,
manual_shift_x=0,
manual_shift_y=0,
):
# Do something...
# self.tomo_parameters

View File

@@ -0,0 +1,3 @@
from .cSAXS import *
# from .LamNI import *

View File

@@ -0,0 +1 @@
from .cSAXS_beamline import fshopen, fshclose, fshstatus, epics_get, epics_put

View File

@@ -1,9 +1,10 @@
import builtins
from bec_ipython_client.beamline_mixin import BeamlineShowInfo
from rich import box
from rich.table import Table
from bec_client.beamline_mixin import BeamlineShowInfo
class BeamlineInfo(BeamlineShowInfo):
def show(self):

View File

@@ -16,13 +16,14 @@ parse the --session argument, add the following lines to the script:
if args.session == "my_session":
print("Loading my_session session")
from bec_plugins.bec_ipython_client.plugins.my_session import *
from bec_plugins.bec_client.plugins.my_session import *
else:
print("Loading default session")
from bec_plugins.bec_ipython_client.plugins.default_session import *
from bec_plugins.bec_client.plugins.default_session import *
"""
# pylint: disable=invalid-name, unused-import, import-error, undefined-variable, unused-variable, unused-argument, no-name-in-module
import argparse
from bec_lib import bec_logger
@@ -30,39 +31,46 @@ logger = bec_logger.logger
logger.info("Using the cSAXS startup script.")
# pylint: disable=import-error
_args = _main_dict["args"]
parser = argparse.ArgumentParser()
parser.add_argument("--session", help="Session name", type=str, default="cSAXS")
args = parser.parse_args()
_session_name = "cSAXS"
if _args.session.lower() == "lamni":
from csaxs_bec.bec_ipython_client.plugins.cSAXS import *
from csaxs_bec.bec_ipython_client.plugins.LamNI import *
if args.session == "LamNI":
print("Loading LamNI session")
from bec_plugins.bec_client.plugins.cSAXS import *
from bec_plugins.bec_client.plugins.LamNI import *
_session_name = "LamNI"
lamni = LamNI(bec)
logger.success("LamNI session loaded.")
elif _args.session.lower() == "csaxs":
elif args.session == "cSAXS":
print("Loading cSAXS session")
from csaxs_bec.bec_ipython_client.plugins.cSAXS import *
logger.success("cSAXS session loaded.")
from csaxs_bec.bec_ipython_client.plugins.tool_box.debug_tools import DebugTools
debug = DebugTools()
logger.success("Debug tools loaded. Use 'debug' to access them.")
from bec_plugins.bec_client.plugins.cSAXS import *
# SETUP BEAMLINE INFO
from bec_ipython_client.plugins.SLS.sls_info import OperatorInfo, SLSInfo
from bec_client.plugins.SLS.sls_info import OperatorInfo, SLSInfo
from csaxs_bec.bec_ipython_client.plugins.cSAXS.beamline_info import BeamlineInfo
from bec_plugins.bec_client.plugins.cSAXS.beamline_info import BeamlineInfo
bec._beamline_mixin._bl_info_register(BeamlineInfo)
bec._beamline_mixin._bl_info_register(SLSInfo)
bec._beamline_mixin._bl_info_register(OperatorInfo)
# SETUP PROMPTS
bec._ip.prompts.session_name = _session_name
bec._ip.prompts.username = args.session
bec._ip.prompts.status = 1
# REGISTER BEAMLINE CHECKS
from bec_lib.bl_conditions import (
FastOrbitFeedbackCondition,
LightAvailableCondition,
ShutterCondition,
)
# _fast_orbit_feedback_condition = FastOrbitFeedbackCondition(dev.sls_fast_orbit_feedback)
_light_available_condition = LightAvailableCondition(dev.sls_machine_status)
_shutter_condition = ShutterCondition(dev.x12sa_es1_shutter_status)
# bec.bl_checks.register(_fast_orbit_feedback_condition)
bec.bl_checks.register(_light_available_condition)
bec.bl_checks.register(_shutter_condition)

View File

@@ -0,0 +1,25 @@
"""
Pre-startup script for BEC client. This script is executed before the BEC client
is started. It can be used to set up the BEC client configuration. The script is
executed in the global namespace of the BEC client. This means that all
variables defined here are available in the BEC client.
To set up the BEC client configuration, use the ServiceConfig class. For example,
to set the configuration file path, add the following lines to the script:
import pathlib
from bec_lib import ServiceConfig
current_path = pathlib.Path(__file__).parent.resolve()
CONFIG_PATH = f"{current_path}/<path_to_my_config_file.yaml>"
config = ServiceConfig(CONFIG_PATH)
If this startup script defined a ServiceConfig object, the BEC client will use
it to configure itself. Otherwise, the BEC client will use the default config.
"""
# example:
# current_path = pathlib.Path(__file__).parent.resolve()
# CONFIG_PATH = f"{current_path}/../../../bec_config.yaml"
# config = ServiceConfig(CONFIG_PATH)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,152 @@
import yaml
# TODO: fix imports, those classes are located in .../bec/scibec/init_scibec/configs/config.py
# (see also lamni_config.py in bec repository)
from .config import DemoConfig, X12SAConfig
class LamNIConfig(DemoConfig, X12SAConfig):
def run(self):
# self.write_galil_motors()
# self.write_rt_motors()
# self.write_smaract_motors()
# self.write_eiger1p5m()
self.write_x12sa_status()
self.write_sls_status()
self.load_csaxs_config()
# self.write_sim_user_motors()
# self.write_sim_beamline_motors()
# self.write_sim_beamline_monitors()
def write_galil_motors(self):
lamni_galil_motors = [
("lsamx", "A", -1, 0.5, {"center": 8.768000}),
("lsamy", "B", 1, 0.5, {"center": 10.041000}),
("lsamrot", "C", 1, 0.5, {}),
("loptz", "D", -1, 0.5, {}),
("loptx", "E", 1, 0.5, {"in": -0.8380, "out": -0.699}),
("lopty", "F", 1, 0.5, {"in": 3.3540, "out": 3.53}),
("leyex", "G", -1, 0.001, {"in": 14.117000}),
("leyey", "H", -1, 0.001, {"in": 48.069000, "out": 0.5}),
]
out = {}
for m in lamni_galil_motors:
out[m[0]] = dict(
{
"status": {"enabled": True, "enabled_set": True},
"deviceClass": "GalilMotor",
"deviceConfig": {
"axis_Id": m[1],
"name": m[0],
"labels": m[0],
"host": "mpc2680.psi.ch",
"port": 8081,
"sign": m[2],
"limits": [0, 0],
"tolerance": m[3],
"device_access": True,
"device_mapping": {"rt": "rtx"},
},
"acquisitionConfig": {
"schedule": "sync",
"acquisitionGroup": "motor",
"readoutPriority": "baseline",
},
"deviceTags": ["lamni"],
}
)
if m[4]:
out[m[0]]["userParameter"] = m[4]
self.write_section(out, "LamNI Galil motors")
def write_rt_motors(self):
lamni_rt_motors = [
("rtx", "A", 1),
("rty", "B", 1),
]
out = dict()
for m in lamni_rt_motors:
out[m[0]] = dict(
{
"status": {"enabled": True, "enabled_set": True},
"deviceClass": "RtLamniMotor",
"deviceConfig": {
"axis_Id": m[1],
"name": m[0],
"labels": m[0],
"host": "mpc2680.psi.ch",
"port": 3333,
"limits": [0, 0],
"sign": m[2],
"device_access": True,
},
"acquisitionConfig": {
"schedule": "sync",
"acquisitionGroup": "motor",
"readoutPriority": "baseline",
},
"deviceTags": ["lamni"],
}
)
self.write_section(out, "LamNI RT")
def write_smaract_motors(self):
lamni_smaract_motors = [
("losax", "A", -1, {"in": -0.848000}),
("losay", "B", -1, {"in": 0.135000, "out": 3.8}),
("losaz", "C", 1, {"in": -1, "out": -3}),
("lcsx", "D", -1, {}),
("lcsy", "E", -1, {}),
]
out = dict()
for m in lamni_smaract_motors:
out[m[0]] = dict(
{
"status": {"enabled": True, "enabled_set": True},
"deviceClass": "SmaractMotor",
"deviceConfig": {
"axis_Id": m[1],
"name": m[0],
"labels": m[0],
"host": "mpc2680.psi.ch",
"port": 8085,
"limits": [0, 0],
"sign": m[2],
"tolerance": 0.05,
},
"acquisitionConfig": {
"schedule": "sync",
"acquisitionGroup": "motor",
"readoutPriority": "baseline",
},
"deviceTags": ["lamni"],
}
)
if m[3]:
out[m[0]]["userParameter"] = m[3]
self.write_section(out, "LamNI SmarAct motors")
def write_eiger1p5m(self):
out = {
"eiger1p5m": {
"description": "Eiger 1.5M in vacuum detector, in-house developed, PSI",
"status": {"enabled": True, "enabled_set": True},
"deviceClass": "Eiger1p5MDetector",
"deviceConfig": {"device_access": True, "name": "eiger1p5m"},
"acquisitionConfig": {
"schedule": "sync",
"acquisitionGroup": "detector",
"readoutPriority": "monitored",
},
"deviceTags": ["detector"],
}
}
self.write_section(out, "LamNI Eiger 1.5M in vacuum")
def load_csaxs_config(self):
CONFIG_PATH = "./init_scibec/configs/test_config_cSAXS.yaml"
content = {}
with open(CONFIG_PATH, "r") as csaxs_config_file:
content = yaml.safe_load(csaxs_config_file.read())
self.write_section(content, "Default cSAXS config")

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
import os
def setup_epics_ca():
os.environ["EPICS_CA_AUTO_ADDR_LIST"] = "NO"
os.environ["EPICS_CA_ADDR_LIST"] = "129.129.122.255 sls-x12sa-cagw.psi.ch:5836"
os.environ["PYTHONIOENCODING"] = "latin1"
def run():
setup_epics_ca()

View File

@@ -23,10 +23,9 @@ but they are executed in a specific order:
import time
import numpy as np
from bec_lib import bec_logger
from bec_lib.endpoints import MessageEndpoints
from bec_server.scan_server.errors import ScanAbortion
from bec_server.scan_server.scans import RequestBase, ScanArgType, ScanBase
from bec_lib import MessageEndpoints, bec_logger, messages
from scan_server.errors import ScanAbortion
from scan_server.scans import RequestBase, ScanArgType, ScanBase
MOVEMENT_SCALE_X = np.sin(np.radians(15)) * np.cos(np.radians(30))
MOVEMENT_SCALE_Y = np.cos(np.radians(15))
@@ -97,8 +96,8 @@ class LamNIMixin:
coarse_move_req_x = np.abs(lsamx_current - move_x)
coarse_move_req_y = np.abs(lsamy_current - move_y)
self.device_manager.devices.lsamx.read_only = False
self.device_manager.devices.lsamy.read_only = False
self.device_manager.devices.lsamx.enabled_set = True
self.device_manager.devices.lsamy.enabled_set = True
if (
np.abs(y_drift) > 150
@@ -110,8 +109,9 @@ class LamNIMixin:
logger.info(
f"Compensating {[val/1000 for val in lamni_to_stage_coordinates(x_drift,y_drift)]}"
)
yield from self.stubs.set(device="lsamx", value=move_x)
yield from self.stubs.set(device="lsamy", value=move_y)
yield from self.stubs.set_and_wait(
device=["lsamx", "lsamy"], positions=[move_x, move_y]
)
time.sleep(0.01)
rtx_current = yield from self.stubs.send_rpc_and_wait("rtx", "readback.get")
@@ -126,14 +126,12 @@ class LamNIMixin:
x_drift2 = x_center_expect * 1000 - rtx_current
y_drift2 = y_center_expect * 1000 - rty_current
logger.info(
f"Uncompensated drift of setup after first iteration is x={x_drift2:.3f},"
f" y={y_drift2:.3f}"
f"Uncompensated drift of setup after first iteration is x={x_drift2:.3f}, y={y_drift2:.3f}"
)
if np.abs(x_drift2) > 5 or np.abs(y_drift2) > 5:
logger.info(
"Compensating second iteration"
f" {[val/1000 for val in lamni_to_stage_coordinates(x_drift2,y_drift2)]}"
f"Compensating second iteration {[val/1000 for val in lamni_to_stage_coordinates(x_drift2,y_drift2)]}"
)
move_x = (
x_stage
@@ -147,28 +145,26 @@ class LamNIMixin:
+ lamni_to_stage_coordinates(x_drift, y_drift)[1] / 1000
+ lamni_to_stage_coordinates(x_drift2, y_drift2)[1] / 1000
)
yield from self.stubs.set(device="lsamx", value=move_x)
yield from self.stubs.set(device="lsamy", value=move_y)
yield from self.stubs.set_and_wait(
device=["lsamx", "lsamy"], positions=[move_x, move_y]
)
time.sleep(0.01)
rtx_current = yield from self.stubs.send_rpc_and_wait("rtx", "readback.get")
rty_current = yield from self.stubs.send_rpc_and_wait("rty", "readback.get")
logger.info(
f"New scan center interferometer after second iteration {rtx_current:.3f},"
f" {rty_current:.3f} microns"
f"New scan center interferometer after second iteration {rtx_current:.3f}, {rty_current:.3f} microns"
)
x_drift2 = x_center_expect * 1000 - rtx_current
y_drift2 = y_center_expect * 1000 - rty_current
logger.info(
f"Uncompensated drift of setup after second iteration is x={x_drift2:.3f},"
f" y={y_drift2:.3f}"
f"Uncompensated drift of setup after second iteration is x={x_drift2:.3f}, y={y_drift2:.3f}"
)
else:
logger.info("No second iteration required")
self.device_manager.devices.lsamx.read_only = True
self.device_manager.devices.lsamy.read_only = True
self.device_manager.devices.lsamx.enabled_set = False
self.device_manager.devices.lsamy.enabled_set = False
yield from self.stubs.send_rpc_and_wait("rtx", "controller.feedback_enable_without_reset")
@@ -178,12 +174,8 @@ class LamNIMoveToScanCenter(RequestBase, LamNIMixin):
scan_report_hint = None
scan_type = "step"
required_kwargs = []
arg_input = {
"shift_x": ScanArgType.FLOAT,
"shift_y": ScanArgType.FLOAT,
"angle": ScanArgType.FLOAT,
}
arg_bundle_size = {"bundle": len(arg_input), "min": 1, "max": 1}
arg_input = [ScanArgType.FLOAT, ScanArgType.FLOAT, ScanArgType.FLOAT]
arg_bundle_size = None
def __init__(self, *args, parameter=None, **kwargs):
"""
@@ -207,10 +199,10 @@ class LamNIFermatScan(ScanBase, LamNIMixin):
scan_report_hint = "table"
scan_type = "step"
required_kwargs = ["fov_size", "exp_time", "step", "angle"]
arg_input = {}
arg_bundle_size = {"bundle": len(arg_input), "min": None, "max": None}
arg_input = []
arg_bundle_size = None
def __init__(self, *args, parameter: dict = None, **kwargs):
def __init__(self, *args, parameter=None, **kwargs):
"""
A LamNI scan following Fermat's spiral.
@@ -365,8 +357,7 @@ class LamNIFermatScan(ScanBase, LamNIMixin):
self.stitch_x, self.stitch_y, self.angle
)
logger.info(
f"Total shift [mm] {_shfitx+x_stitch_shift/1000+self.shift_x},"
f" {_shfity+y_stitch_shift/1000+self.shift_y}"
f"Total shift [mm] {_shfitx+x_stitch_shift/1000+self.shift_x}, {_shfity+y_stitch_shift/1000+self.shift_y}"
)
return (
_shfitx + x_stitch_shift / 1000 + self.shift_x,
@@ -443,7 +434,7 @@ class LamNIFermatScan(ScanBase, LamNIMixin):
}
}
)
yield from self.stubs.set(device="lsamrot", value=angle)
yield from self.stubs.set_and_wait(device=["lsamrot"], positions=[angle])
def scan_core(self):
if self.scan_type == "step":
@@ -456,18 +447,17 @@ class LamNIFermatScan(ScanBase, LamNIMixin):
# scan ID before sending the message to the device server
yield from self.stubs.kickoff(device="rtx")
while True:
yield from self.stubs.read(group="monitored")
msg = self.device_manager.connector.get(MessageEndpoints.device_status("rt_scan"))
yield from self.stubs.read_and_wait(group="primary", wait_group="readout_primary")
msg = self.device_manager.producer.get(MessageEndpoints.device_status("rt_scan"))
if msg:
status = msg
status = messages.DeviceStatusMessage.loads(msg)
status_id = status.content.get("status", 1)
request_id = status.metadata.get("RID")
if status_id == 0 and self.metadata.get("RID") == request_id:
break
if status_id == 2 and self.metadata.get("RID") == request_id:
raise ScanAbortion(
"An error occured during the LamNI readout:"
f" {status.metadata.get('error')}"
f"An error occured during the LamNI readout: {status.metadata.get('error')}"
)
time.sleep(1)

View File

@@ -25,9 +25,8 @@ but they are executed in a specific order:
# import numpy as np
# from bec_lib import bec_logger, messages
# from bec_lib.endpoints import MessageEndpoints
# from bec_server.scan_server.errors import ScanAbortion
# from bec_server.scan_server.scans import FlyScanBase, RequestBase, ScanArgType, ScanBase
# from bec_lib import MessageEndpoints, bec_logger, messages
# from scan_server.errors import ScanAbortion
# from scan_server.scans import FlyScanBase, RequestBase, ScanArgType, ScanBase
# logger = bec_logger.logger

View File

@@ -0,0 +1,182 @@
import os
import json
import subprocess
import requests
from bec_lib.file_utils import FileWriterMixin
#from bec_lib.bec_service import SERVICE_CONFIG
class csaxs_archiver:
"""Class to archive data from a beamtime.
To run this script from a shell, go to discovery.psi.ch and copy your token.
Complement the information in user_input below in the if __name__ == __main__ part of the script.
Afterwards, get a Keberos token (kinit) for yourself in the shell.
Activate the bec_venv by doing "source bec_venv/bin/activate" and then run this code via python $filename.
As a last step, adjust the dictionary below in if __name__ == '__main__' with your token as well as information about the experiment
"""
def __init__(
self,
start_scan: int,
stop_scan: int,
base_path: str,
log_path: str,
eacc: str,
pi: str,
pi_email: str,
token: str,
type: str = "raw",
overwrite: bool = False,
online: bool = True,
):
self.start_scan = start_scan
self.stop_scan = stop_scan
self.log_path = os.path.expanduser(log_path)
self.eacc = eacc
self.pi = pi
self.pi_email = pi_email
self.token = token
self.type = type
self.overwrite = overwrite
self.online = online
#from bec_lib.bec_service import SERVICE_CONFIG
#SERVICE_CONFIG.config["service_config"]["file_writer"]
self._load_datacatalogue_module()
self._create_directory(base_path)
self._disable_mail_confirmation()
self.service_cfg = {'base_path' : f'{self.base_path}'}
self.file_writer = FileWriterMixin(self.service_cfg)
def _disable_mail_confirmation(self):
# Define the URL and payload
url = "https://dacat.psi.ch/api/v3/Policies/updatewhere"
payload = {
"ownerGroupList": f'p{self.eacc[1:]}',
"data": '{"archiveEmailNotification": false, "accessGroups": ["slscsaxs"]}'
}
# Define headers
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
}
# Add the access_token to the URL
url += "?access_token=" + self.token
# Make a POST request
print(url, payload, headers)
response = requests.post(url, data=payload, headers=headers)
# Check the response
if response.status_code == 200:
print("Request was successful.")
print(response.json())
else:
print("Request failed with status code:", response.status_code)
print(response.text)
def _create_directory(self, base_path: str) -> None:
if self.online:
self.base_path = os.path.expanduser("~/Data10")
else:
self.base_path = base_path
if not os.path.exists(self.log_path):
os.makedirs(self.log_path)
def _load_datacatalogue_module(self):
command = 'module add datacatalog/1.1.9'
os.popen(command)
# result = subprocess.run(
# command,
# shell=False,
# stdout=subprocess.PIPE,
# stderr=subprocess.PIPE,
# universal_newlines=True,
# )
# if result.returncode == 0:
# print(f"Command {command} was succesful")
# else:
# print(f"Failed to run command {command} with return message {result.returncode}")
def prep_metadata(self, scannr: int) -> dict:
user_metadata = {}
user_metadata.update(
{
"principalInvestigator": self.pi_email,
"owner": self.pi,
"ownerEmail": self.pi_email,
"sourceFolder": self.base_path,
"creationLocation": "/PSI/SLS/CSAXS",
"type": "raw",
"ownerGroup": f"p{self.eacc.strip('e')}",
"datasetName": f"S{scannr:05d}",
}
)
return user_metadata
def _write_ingestion_log(self, scannr: int) -> None:
...
def run_for_all_scans(self):
for scan in range(self.start_scan, self.stop_scan + 1):
print(f"Start ingestion for scan {scan}")
fname = os.path.join(os.path.expanduser(self.log_path), f"ingestion_log_S{scan:05d}")
self.datafile_name = f"{fname}.txt"
if os.path.isfile(self.datafile_name) and not self.overwrite == True:
print(
f"Skipping scan {scan}, already ingested due to logs, moving on to next scan {scan+1}"
)
continue
user_metadata = self.prep_metadata(scan)
# Write metadata file in json file
self.metadata_file = f"{fname}.json"
with open(self.metadata_file, "w") as file:
json.dump(user_metadata, file)
# Compile datapath based on structure a cSAXS
datadir_path = os.path.join('data', self.file_writer.get_scan_directory(scan, 1000, 5))
print(f"Archiving directory {datadir_path}")
if not os.path.isdir(os.path.join(self.base_path, datadir_path)):
print(f"Did not find directory {datadir_path}, skipping scan {scan}")
continue
# Create datafile path for archiving
with open(self.datafile_name, "w") as file:
file.write(datadir_path)
print(f"Starting ingestion for S#{scan}")
command = f'datasetIngestor -allowexistingsource -ingest -autoarchive -noninteractive -token {self.token} {self.metadata_file} {self.datafile_name}'
rtr = os.popen(command)
#with open(os.path.join(fname,'_log.txt'), "w") as file:
# print(f'Writing reponse to file')
# file.write(rtr.read())
# result = subprocess.run(command, shell=False, stdout = subprocess.PIPE, stderr = subprocess.PIPE, universal_newlines=True)
# if result.returncode == 0:
# print(f"Command {command} was succesful")
# else:
# print(f"Failed to run command {command} with return message {result.returncode}")
if __name__ == "__main__":
# Generate dictionary with user input.
user_input = {
"base_path": "~/Data10",
"eacc": "e20638",
"pi": "Emma Sparr",
"pi_email": "emma.sparr@fkem1.lu.se",
'log_path' : '~/Data10/documentation/ingestion_logs/',
'token' : 'YK8gkmQmEVxVxjiA57D6tVmpBVs7T235nWEuBT0behN9BPM2BdWARWPPgEsQVrPe',
'start_scan' : 1,
'stop_scan' : 450,
}
archiver = csaxs_archiver(**user_input)
archiver.run_for_all_scans()

View File

@@ -0,0 +1,88 @@
import csv
import os
from collections import defaultdict
from collections.abc import Callable
import numpy as np
class ScanItem:
def __init__(self, offset_xy: Callable) -> None:
self.start_entry = None
self.end_entry = None
self.offset_xy = offset_xy
def to_scan_params(self) -> dict:
scan_params = {
"start_x": float(self.start_entry["X"]) + self.offset_xy()[0],
"start_y": float(self.start_entry["Y"]) + self.offset_xy()[1],
"end_x": float(self.end_entry["X"]) + self.offset_xy()[0],
"end_y": float(self.end_entry["Y"]) + self.offset_xy()[1],
"interval_x": int(
np.round(
np.abs(float(self.start_entry["X"]) - float(self.end_entry["X"]))
/ (float(self.start_entry["step_x [mu]"]) * 1e-3)
)
),
"interval_y": int(
np.round(
np.abs(float(self.start_entry["Y"]) - float(self.end_entry["Y"]))
/ (float(self.start_entry["step_y [mu]"]) * 1e-3)
)
),
"exp_time": float(self.start_entry["exp_time [s]"]),
"readout_time": 3e-3,
"md": {"sample_name": self.start_entry["sample name"]},
}
if scan_params["interval_x"] < 1 or scan_params["interval_x"] < 1:
raise ValueError("Bugger off...")
return scan_params
class SAXSParams:
def __init__(self, offset: Callable):
self.offset_xy = offset
self.data = defaultdict(lambda: ScanItem(offset))
def load_from_csv(self, file_path: str) -> None:
"""
Load the acquisition parameter from a csv file.
"""
if not os.path.exists(file_path):
raise FileNotFoundError(
f"The specified CSV file could not be found. Please check that the given path is correct: {file_path}."
)
data_transposed = defaultdict(lambda: [])
with open(os.path.expanduser(file_path), "r") as file:
csv_reader = csv.DictReader(file)
for row in csv_reader:
for key, val in row.items():
data_transposed[key].append(val)
if int(row["start"]):
self.data[row["sample name"]].start_entry = row
else:
self.data[row["sample name"]].end_entry = row
self._check_params(dict(data_transposed))
def _check_params(self, data_transposed: dict) -> dict:
sample_names = set(data_transposed["sample name"])
if len(data_transposed["start"]) != len(sample_names) * 2:
raise ValueError(
f"The given params file does not provide N*2 start/stop positions. Found {len(sample_names)} samples and {len(data_transposed['start'])} start/stop positions."
)
if __name__ == "__main__":
from pprint import pprint
INPUT_FILE = "/sls/X12SA/data/e21206/Data10/software/test_script.csv"
def my_offset():
return [0, 0]
params = SAXSParams(my_offset)
params.load_from_csv(INPUT_FILE)
for key in params.data:
pprint(params.data[key].to_scan_params())

View File

@@ -1,7 +1,3 @@
""" Script used for parsing scan parameters from a CSV file as created by the motormap GUI.
This needs to be reviewed and tested during the deployment phase."""
# pylint: skip-file
import csv
import os
from collections import defaultdict

View File

@@ -0,0 +1,13 @@
import yaml
CONFIG_PATH = "/sls/X12SA/data/gac-x12saop/bec/config/bec_service_config.yaml"
def load_service_config() -> dict:
"""Load the service configuration from the YAML file."""
with open(CONFIG_PATH, "r", encoding="utf-8") as stream:
try:
config = yaml.safe_load(stream)
except yaml.YAMLError as exc:
print(exc)
return config

1
bin/.gitignore vendored
View File

@@ -1 +0,0 @@
# Add anything you don't want to check in to git, e.g. very large files

View File

@@ -3,9 +3,8 @@ from __future__ import annotations
import os
import subprocess
from bec_lib import bec_logger, messages
from bec_lib.endpoints import MessageEndpoints
from bec_lib.redis_connector import MessageObject, RedisConnector
from bec_lib import MessageEndpoints, RedisConnector, bec_logger, messages
from bec_lib.redis_connector import MessageObject
logger = bec_logger.logger
@@ -13,6 +12,7 @@ logger = bec_logger.logger
class PilatusConverter:
def __init__(self, host: str, port: int) -> None:
self._connector = RedisConnector(f"{host}:{port}")
self._producer = self._connector.producer()
def start(self) -> None:
"""start the consumer"""
@@ -27,7 +27,7 @@ class PilatusConverter:
message (MessageObject): Message object
parent (PilatusConverter): Parent object
"""
msg = message.value
msg = messages.MessageReader.loads(message.value)
print(msg)
if not msg:
return
@@ -56,9 +56,10 @@ class PilatusConverter:
"""
Start the consumer.
"""
self._connector.register(
file_consumer = self._connector.consumer(
MessageEndpoints.file_event("pilatus_2"), cb=self.on_new_message, parent=self
)
file_consumer.start()
if __name__ == "__main__":

5
bin/open_tunnel.sh Executable file
View File

@@ -0,0 +1,5 @@
for i in `seq 1 8`
do
ssh -N -R 6379:localhost:6379 x12sa-cn-$i &
done

48
bin/setup_bec.sh Executable file
View File

@@ -0,0 +1,48 @@
if [ "pc15543.psi.ch" != "$(hostname)" ]; then
echo "Please run this script on pc15543"
exit 1
fi
module use unstable
module add psi-python311/2024.02
echo module add tmux/3.2 >> ~/.bashrc
echo module add redis/7.0.12 >> ~/.bashrc
source ~/.bashrc
cd ~/Data10
mkdir -p software/
mkdir -p ~/bec/scripts
cd software
git clone https://gitlab.psi.ch/bec/bec.git
git clone https://gitlab.psi.ch/bec/ophyd_devices.git
git clone https://gitlab.psi.ch/bec/bec-widgets.git
python -m venv ./bec_venv
source ./bec_venv/bin/activate
cd bec
git checkout sastt-online-changes
pip install -e ./bec_server[dev]
cd ../csaxs-bec
pip install -e .[dev]
#redis-server --protected-mode no &
read -p "Do you want to set the current BEC account to $(whoami)? (yes/no) " yn
val=$(whoami)
case $yn in
yes ) echo ok, setting account to $val;
redis-cli SET internal/account:val $val;;
no ) echo ;;
* ) echo invalid response;
exit 1;;
esac
$(pwd)/open_tunnel.sh

17
bin/setup_bec_widgets.sh Executable file
View File

@@ -0,0 +1,17 @@
module use unstable
module add psi-python311/2024.02
cd ~/Data10/software
python -m venv ./bec_widgets_venv
source ./bec_widgets_venv/bin/activate
pip install --upgrade pip
cd ~/Data10/software/bec/bec_lib
pip install -e .
cd ~/Data10/software/csaxs-bec
pip install -e .
cd ~/Data10/software/bec-widgets
pip install -e .
echo "For the moment widgets only run on beamline consoles comp1/2 and cons1"

View File

@@ -1,2 +0,0 @@
from .load_additional_correction import lamni_read_additional_correction
from .x_ray_eye_align import DataDrivenLamNI, LamNI, MagLamNI, XrayEyeAlign

View File

@@ -1,329 +0,0 @@
import builtins
import time
from rich import box
from rich.console import Console
from rich.table import Table
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_put, fshclose
# import builtins to avoid linter errors
dev = builtins.__dict__.get("dev")
umv = builtins.__dict__.get("umv")
bec = builtins.__dict__.get("bec")
class LamNIInitError(Exception):
pass
class LaMNIInitStagesMixin:
def lamni_init_stages(self):
user_input = input("Starting initialization of LamNI stages. OK? [y/n]")
if user_input == "y":
print("staring...")
dev.lsamrot.enabled = True
else:
return
if self.check_all_axes_of_lamni_referenced():
user_input = input("Continue anyways? [y/n]")
if user_input == "y":
print("ok then...")
else:
return
axis_id_lsamrot = dev.lsamrot._config["deviceConfig"].get("axis_Id")
if dev.lsamrot.controller.get_motor_limit_switch(axis_id_lsamrot)[1] == False:
user_input = input("The rotation stage will be moved to one limit [y/n]")
if user_input == "y":
print("starting...")
else:
return
self.drive_axis_to_limit(dev.lsamrot, "forward")
dev.lsamrot.enabled = False
print("Now hard reboot the controller and run the initialization routine again.")
print("The controller will be disabled in bec. To enable dev.lsamrot.enabled=True")
return
user_input = input(
"Init of loptz. Can the stage move to the upstream limit without collision?? [y/n]"
)
if user_input == "y":
print("ok then...")
else:
return
print("Referencing loptz")
self.drive_axis_to_limit(dev.loptz, "forward")
self.find_reference_mark(dev.loptz)
print("Referencing loptx")
self.drive_axis_to_limit(dev.loptx, "reverse")
self.find_reference_mark(dev.loptx)
print("Referencing lopty")
self.drive_axis_to_limit(dev.lopty, "forward")
self.find_reference_mark(dev.lopty)
print("Referencing lsamx")
self.drive_axis_to_limit(dev.lsamx, "forward")
self.find_reference_mark(dev.lsamx)
print("Referencing lsamy")
self.drive_axis_to_limit(dev.lsamy, "reverse")
self.find_reference_mark(dev.lsamy)
# the dual encoder requires the reference mark to pass on both encoders
print("Referencing lsamrot")
self.drive_axis_to_limit(dev.lsamrot, "reverse")
time.sleep(0.1)
self.find_reference_mark(dev.lsamrot)
user_input = input("Init of leye. Can the stage move to -x limit without collision? [y/n]")
if user_input == "y":
print("starting...")
else:
return
print("Referencing leyex")
self.drive_axis_to_limit(dev.leyex, "forward")
print("Referencing leyey")
self.drive_axis_to_limit(dev.leyey, "forward")
# set_lm lsamx 6 14
# set_lm lsamy 6 14
# set_lm lsamrot -3 362
# set_lm loptx -1 -0.2
# set_lm lopty 3.0 3.6
# set_lm loptz 82 87
# set_lm leyex 0 25
# set_lm leyey 0.5 50
print("Init of Smaract stages")
dev.losax.controller.find_reference_mark(2, 0, 1000, 1)
time.sleep(1)
dev.losax.controller.find_reference_mark(0, 0, 1000, 1)
time.sleep(1)
dev.losax.controller.find_reference_mark(1, 0, 1000, 1)
time.sleep(1)
# dev.losax.controller.find_reference_mark(3, 1, 1000, 1)
# time.sleep(1)
# dev.losax.controller.find_reference_mark(4, 1, 1000, 1)
# time.sleep(1)
# set_lm losax -1.5 0.25
# set_lm losay -2.5 4.1
# set_lm losaz -4.1 -0.5
# set_lm lcsy -1.5 5
self._align_setup()
def find_reference_mark(self, device):
axis_id = device._config["deviceConfig"].get("axis_Id")
axis_id_numeric = self.axis_id_to_numeric(axis_id)
device.controller.find_reference(axis_id_numeric)
def drive_axis_to_limit(self, device, direction):
axis_id = device._config["deviceConfig"].get("axis_Id")
axis_id_numeric = self.axis_id_to_numeric(axis_id)
device.controller.drive_axis_to_limit(axis_id_numeric, direction)
def axis_id_to_numeric(self, axis_id) -> int:
return ord(axis_id.lower()) - 97
def _align_setup(self):
user_input = input("Start moving stages to default initial positions? [y/n]")
if user_input == "y":
print("Start moving stages...")
else:
print("Stopping.")
return
lsamx_center = dev.lsamx.user_parameter.get("center")
if lsamx_center is None:
raise LamNIInitError(
"Could not find a lsamx center position. Please check your device config."
)
lsamy_center = dev.lsamy.user_parameter.get("center")
if lsamy_center is None:
raise LamNIInitError(
"Could not find a lsamy center position. Please check your device config."
)
umv(dev.lsamx, lsamx_center, dev.lsamy, lsamy_center, dev.loptx, -0.3, dev.lopty, 0)
umv(dev.losax, -1)
umv(dev.loptz, 82.25)
umv(dev.lsamrot, -1)
umv(dev.lsamrot, 0)
time.sleep(2)
dev.rtx.controller.feedback_disable_and_even_reset_lamni_angle_interferometer()
def check_all_axes_of_lamni_referenced(self):
if (
dev.losax.controller.axis_is_referenced(0)
& dev.losax.controller.axis_is_referenced(1)
& dev.losax.controller.axis_is_referenced(2)
& dev.lsamx.controller.all_axes_referenced()
):
print("All axes of LamNI are referenced.")
return True
else:
return False
class LamNIOpticsMixin:
@staticmethod
def _get_user_param_safe(device, var):
param = dev[device].user_parameter
if not param or param.get(var) is None:
raise ValueError(f"Device {device} has no user parameter definition for {var}.")
return param.get(var)
def leye_out(self):
self.loptics_in()
fshclose()
leyey_out = self._get_user_param_safe("leyey", "out")
umv(dev.leyey, leyey_out)
epics_put("XOMNYI-XEYE-ACQ:0", 2)
# move rotation stage to zero to avoid problems with wires
umv(dev.lsamrot, 0)
umv(dev.dttrz, 5854, dev.fttrz, 2395)
def leye_in(self):
bec.queue.next_dataset_number += 1
# move rotation stage to zero to avoid problems with wires
umv(dev.lsamrot, 0)
umv(dev.dttrz, 6419.677, dev.fttrz, 2959.979)
while True:
moved_out = (input("Did the flight tube move out? (Y/n)") or "y").lower()
if moved_out == "y":
break
if moved_out == "n":
return
leyex_in = self._get_user_param_safe("leyex", "in")
leyey_in = self._get_user_param_safe("leyey", "in")
umv(dev.leyex, leyex_in, dev.leyey, leyey_in)
self.align.update_frame()
def _lfzp_in(self):
loptx_in = self._get_user_param_safe("loptx", "in")
lopty_in = self._get_user_param_safe("lopty", "in")
umv(
dev.loptx, loptx_in, dev.lopty, lopty_in
) # for 7.2567 keV and 150 mu, 60 nm fzp, loptz 83.6000 for propagation 1.4 mm
def lfzp_in(self):
"""
move in the lamni zone plate.
This will disable rt feedback, move the FZP and re-enabled the feedback.
"""
if "rtx" in dev and dev.rtx.enabled:
dev.rtx.controller.feedback_disable()
self._lfzp_in()
if "rtx" in dev and dev.rtx.enabled:
dev.rtx.controller.feedback_enable_with_reset()
def loptics_in(self):
"""
Move in the lamni optics, including the FZP and the OSA.
"""
self.lfzp_in()
self.losa_in()
def loptics_out(self):
"""Move out the lamni optics"""
if "rtx" in dev and dev.rtx.enabled:
dev.rtx.controller.feedback_disable()
# self.lcs_out()
self.losa_out()
loptx_out = self._get_user_param_safe("loptx", "out")
lopty_out = self._get_user_param_safe("lopty", "out")
umv(dev.loptx, loptx_out, dev.lopty, lopty_out)
if "rtx" in dev and dev.rtx.enabled:
time.sleep(1)
dev.rtx.controller.feedback_enable_with_reset()
def lcs_in(self):
# umv lcsx -1.852 lcsy -0.095
pass
def lcs_out(self):
umv(dev.lcsy, 3)
def losa_in(self):
# 6.2 keV, 170 um FZP
# umv(dev.losax, -1.4450000, dev.losay, -0.1800)
# umv(dev.losaz, -1)
# 6.7, 170
# umv(dev.losax, -1.4850, dev.losay, -0.1930)
# umv(dev.losaz, 1.0000)
# 7.2, 150
losax_in = self._get_user_param_safe("losax", "in")
losay_in = self._get_user_param_safe("losay", "in")
losaz_in = self._get_user_param_safe("losaz", "in")
umv(dev.losax, losax_in, dev.losay, losay_in)
umv(dev.losaz, losaz_in)
# 11 kev
# umv(dev.losax, -1.161000, dev.losay, -0.196)
# umv(dev.losaz, 1.0000)
def losa_out(self):
losay_out = self._get_user_param_safe("losay", "out")
losaz_out = self._get_user_param_safe("losaz", "out")
umv(dev.losaz, losaz_out)
umv(dev.losay, losay_out)
def lfzp_info(self, mokev_val=-1):
if mokev_val == -1:
try:
mokev_val = dev.mokev.readback.get()
except:
print(
"Device mokev does not exist. You can specify the energy in keV as an argument instead."
)
return
loptz_val = dev.loptz.read()["loptz"]["value"]
distance = -loptz_val + 85.6 + 52
print(f"The sample is in a distance of {distance:.1f} mm from the FZP.")
diameters = [80e-6, 100e-6, 120e-6, 150e-6, 170e-6, 200e-6, 220e-6, 250e-6]
console = Console()
table = Table(
title=f"At the current energy of {mokev_val:.4f} keV we have following options:",
box=box.SQUARE,
)
table.add_column("Diameter", justify="center")
table.add_column("Focal distance", justify="center")
table.add_column("Current beam size", justify="center")
wavelength = 1.2398e-9 / mokev_val
for diameter in diameters:
outermost_zonewidth = 60e-9
focal_distance = diameter * outermost_zonewidth / wavelength
beam_size = (
-diameter / (focal_distance * 1000) * (focal_distance * 1000 - distance) * 1e6
)
table.add_row(
f"{diameter*1e6:.2f} microns",
f"{focal_distance:.2f} mm",
f"{beam_size:.2f} microns",
)
console.print(table)
print("OSA Information:")
# print(f"Current losaz %.1f\n", A[losaz])
# print("The OSA will collide with the sample plane at %.1f\n\n", 89.3-A[loptz])
print(
"The numbers presented here are for a sample in the plane of the lamni sample holder.\n"
)

View File

@@ -1,2 +0,0 @@
from .cSAXS_beamline import epics_get, epics_put, fshclose, fshopen, fshstatus
from .csaxs_bl_checks import cSAXSBeamlineChecks

View File

@@ -1,41 +0,0 @@
# import builtins
# import datetime
# import os
# import subprocess
# import time
# from pathlib import Path
# import numpy as np
from bec_lib import bec_logger
# from bec_lib.alarm_handler import AlarmBase
# from bec_lib.pdf_writer import PDFWriter
from typeguard import typechecked
from csaxs_bec.bec_ipython_client.plugins.cSAXS.smaract import cSAXSInitSmaractStages
from csaxs_bec.bec_ipython_client.plugins.cSAXS.smaract import cSAXSSmaract
from csaxs_bec.bec_ipython_client.plugins.omny.omny_general_tools import OMNYTools
from csaxs_bec.bec_ipython_client.plugins.cSAXS.filter_transmission import cSAXSFilterTransmission
class cSAXSError(Exception):
pass
class cSAXS(
cSAXSInitSmaractStages,
cSAXSSmaract,
cSAXSFilterTransmission,
):
def __init__(self, client):
self.client = client
self.device_manager = client.device_manager
self.OMNYTools = OMNYTools(self.client)
super().__init__(client=client)
# this is the csaxs master file that imports all routines from csaxs
# can be imported in the bec client by
# run in bec from folder /sls/x12sa/config/bec/production/csaxs_bec
# from csaxs_bec.bec_ipython_client.plugins.cSAXS.cSAXS import cSAXS
# csaxs = cSAXS(bec)
#
# then all commands can be accessed by for example
# csaxs._cSAXS_smaract_stages_.....

View File

@@ -1,122 +0,0 @@
import builtins
import datetime
import threading
import time
from bec_lib import bec_logger
logger = bec_logger.logger
if builtins.__dict__.get("bec"):
bec = builtins.__dict__.get("bec")
class cSAXSBeamlineChecks:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.check_shutter = True
self.check_light_available = True
self.check_fofb = True
self._check_msgs = []
self._beam_is_okay = True
self._stop_beam_check_event = None
self.beam_check_thread = None
def get_beamline_checks_enabled(self):
print(
f"Shutter: {self.check_shutter}\nFOFB: {self.check_fofb}\nLight available:"
f" {self.check_light_available}"
)
@property
def beamline_checks_enabled(self):
return {
"shutter": self.check_shutter,
"fofb": self.check_fofb,
"light available": self.check_light_available,
}
@beamline_checks_enabled.setter
def beamline_checks_enabled(self, val: bool):
self.check_shutter = val
self.check_light_available = val
self.check_fofb = val
self.get_beamline_checks_enabled()
def _run_beamline_checks(self):
msgs = []
dev = builtins.__dict__.get("dev")
try:
if self.check_shutter:
shutter_val = dev.x12sa_es1_shutter_status.read(cached=True)
if shutter_val["value"].lower() != "open":
self._beam_is_okay = False
msgs.append("Check beam failed: Shutter is closed.")
if self.check_light_available:
machine_status = dev.sls_machine_status.read(cached=True)
if machine_status["value"] not in ["Light Available", "Light-Available"]:
self._beam_is_okay = False
msgs.append("Check beam failed: Light not available.")
if self.check_fofb:
fast_orbit_feedback = dev.sls_fast_orbit_feedback.read(cached=True)
if fast_orbit_feedback["value"] != "running":
self._beam_is_okay = False
msgs.append("Check beam failed: Fast orbit feedback is not running.")
except Exception:
logger.warning("Failed to check beam.")
return msgs
def _check_beam(self):
while not self._stop_beam_check_event.is_set():
self._check_msgs = self._run_beamline_checks()
if not self._beam_is_okay:
self._stop_beam_check_event.set()
time.sleep(1)
def _start_beam_check(self):
self._beam_is_okay = True
self._stop_beam_check_event = threading.Event()
self.beam_check_thread = threading.Thread(target=self._check_beam, daemon=True)
self.beam_check_thread.start()
def _was_beam_okay(self):
self._stop_beam_check_event.set()
self.beam_check_thread.join()
return self._beam_is_okay
def _print_beamline_checks(self):
for msg in self._check_msgs:
logger.warning(msg)
def _wait_for_beamline_checks(self):
self._print_beamline_checks()
try:
msg = bec.logbook.LogbookMessage()
msg.add_text(
"<p><mark class='pen-red'><strong>Beamline checks failed at"
f" {str(datetime.datetime.now())}: {''.join(self._check_msgs)}</strong></mark></p>"
).add_tag(["BEC", "beam_check"])
bec.logbook.send_logbook_message(msg)
except Exception:
logger.warning("Failed to send update to SciLog.")
while True:
self._beam_is_okay = True
self._check_msgs = self._run_beamline_checks()
if self._beam_is_okay:
break
self._print_beamline_checks()
time.sleep(1)
try:
msg = bec.logbook.LogbookMessage()
msg.add_text(
"<p><mark class='pen-red'><strong>Operation resumed at"
f" {str(datetime.datetime.now())}.</strong></mark></p>"
).add_tag(["BEC", "beam_check"])
bec.logbook.send_logbook_message(msg)
except Exception:
logger.warning("Failed to send update to SciLog.")

View File

@@ -1,601 +0,0 @@
4000.00 10.5509
4012.90 10.6470
4025.83 10.7440
4038.81 10.8418
4051.83 10.9406
4064.90 11.0404
4078.00 11.1410
4091.15 11.2426
4104.34 11.3451
4117.57 11.4487
4130.85 11.5532
4144.17 11.6587
4157.53 11.7652
4170.93 11.8726
4184.38 11.9811
4197.87 12.0906
4211.41 12.2011
4224.98 12.3126
4238.60 12.4252
4252.27 12.5389
4265.98 12.6536
4279.73 12.7694
4293.53 12.8863
4307.37 13.0042
4321.26 13.1234
4335.19 13.2436
4349.17 13.3650
4363.19 13.4875
4377.26 13.6111
4391.37 13.7360
4405.53 13.8620
4419.73 13.9892
4433.98 14.1175
4448.28 14.2470
4462.62 14.3779
4477.01 14.5099
4491.44 14.6432
4505.92 14.7777
4520.45 14.9135
4535.02 15.0507
4549.65 15.1891
4564.31 15.3289
4579.03 15.4699
4593.79 15.6123
4608.60 15.7560
4623.46 15.9010
4638.37 16.0473
4653.32 16.1950
4668.33 16.3442
4683.38 16.4948
4698.48 16.6468
4713.62 16.8002
4728.82 16.9551
4744.07 17.1114
4759.36 17.2693
4774.71 17.4287
4790.10 17.5895
4805.54 17.7519
4821.04 17.9157
4836.58 18.0811
4852.17 18.2481
4867.82 18.4166
4883.51 18.5866
4899.26 18.7583
4915.05 18.9317
4930.90 19.1069
4946.80 19.2836
4962.75 19.4619
4978.75 19.6419
4994.80 19.8237
5010.90 20.0072
5027.06 20.1924
5043.26 20.3793
5059.52 20.5680
5075.84 20.7585
5092.20 20.9507
5108.62 21.1448
5125.09 21.3406
5141.61 21.5384
5158.19 21.7383
5174.82 21.9400
5191.50 22.1436
5208.24 22.3491
5225.03 22.5565
5241.88 22.7659
5258.78 22.9772
5275.73 23.1905
5292.74 23.4057
5309.81 23.6231
5326.93 23.8425
5344.10 24.0641
5361.33 24.2876
5378.62 24.5133
5395.96 24.7411
5413.35 24.9712
5430.81 25.2034
5448.32 25.4377
5465.88 25.6742
5483.50 25.9131
5501.18 26.1546
5518.92 26.3982
5536.71 26.6441
5554.56 26.8923
5572.47 27.1429
5590.44 27.3957
5608.46 27.6508
5626.54 27.9084
5644.68 28.1683
5662.88 28.4308
5681.14 28.6958
5699.46 28.9633
5717.83 29.2334
5736.27 29.5059
5754.76 29.7811
5773.31 30.0590
5791.93 30.3395
5810.60 30.6226
5829.33 30.9083
5848.13 31.1968
5866.98 31.4883
5885.90 31.7823
5904.88 32.0791
5923.91 32.3787
5943.01 32.6814
5962.17 32.9873
5981.40 33.2960
6000.68 33.6076
6020.03 33.9221
6039.44 34.2394
6058.91 34.5595
6078.44 34.8826
6098.04 35.2086
6117.70 35.5378
6137.42 35.8704
6157.21 36.2065
6177.06 36.5457
6196.98 36.8881
6216.96 37.2338
6237.00 37.5828
6257.11 37.9350
6277.28 38.2906
6297.52 38.6496
6317.82 39.0118
6338.19 39.3777
6358.63 39.7471
6379.13 40.1200
6399.69 40.4964
6420.33 40.8763
6441.03 41.2599
6461.79 41.6472
6482.63 42.0382
6503.53 42.4328
6524.49 42.8311
6545.53 43.2333
6566.63 43.6396
6587.80 44.0496
6609.04 44.4635
6630.35 44.8813
6651.73 45.3031
6673.17 45.7289
6694.69 46.1588
6716.27 46.5926
6737.93 47.0306
6759.65 47.4730
6781.44 47.9197
6803.31 48.3706
6825.24 48.8258
6847.25 49.2852
6869.32 49.7491
6891.47 50.2174
6913.69 50.6902
6935.98 51.1675
6958.34 51.6491
6980.77 52.1356
7003.28 52.6268
7025.86 53.1226
7048.51 53.6231
7071.24 54.1282
7094.03 54.6384
7116.91 55.1537
7139.85 55.6736
7162.87 56.1985
7185.96 56.7283
7209.13 57.2635
7232.38 57.8038
7255.69 58.3491
7279.09 58.8996
7302.55 59.4554
7326.10 60.0165
7349.72 60.5832
7373.41 61.1551
7397.19 61.7324
7421.03 62.3153
7444.96 62.9039
7468.96 63.4982
7493.04 64.0981
7517.20 64.7037
7541.44 65.3149
7565.75 65.9323
7590.14 66.5556
7614.62 67.1849
7639.17 67.8201
7663.79 68.4612
7688.50 69.1087
7713.29 69.7625
7738.16 70.4224
7763.11 71.0884
7788.14 71.7608
7813.25 72.4400
7838.44 73.1259
7863.71 73.8182
7889.06 74.5170
7914.50 75.2224
7940.01 75.9348
7965.61 76.6538
7991.29 77.3796
8017.06 78.1123
8042.91 78.8520
8068.84 79.5991
8094.85 80.3534
8120.95 81.1149
8147.13 81.8836
8173.40 82.6595
8199.75 83.4434
8226.19 84.2349
8252.71 85.0338
8279.32 85.8404
8306.01 86.6546
8332.79 87.4766
8359.65 88.3065
8386.60 89.1443
8413.64 89.9900
8440.77 90.8436
8467.98 91.7062
8495.29 92.5774
8522.67 93.4567
8550.15 94.3443
8577.72 95.2403
8605.37 96.1451
8633.12 97.0584
8660.95 97.9803
8688.87 98.9109
8716.89 99.8503
8744.99 100.799
8773.19 101.757
8801.47 102.724
8829.85 103.700
8858.32 104.686
8886.88 105.681
8915.53 106.687
8944.27 107.701
8973.11 108.726
9002.04 109.760
9031.06 110.804
9060.18 111.859
9089.39 112.924
9118.69 113.998
9148.09 115.083
9177.59 116.179
9207.18 117.285
9236.86 118.401
9266.64 119.529
9296.52 120.666
9326.49 121.816
9356.56 122.976
9386.72 124.148
9416.99 125.330
9447.35 126.524
9477.81 127.730
9508.37 128.946
9539.02 130.174
9569.78 131.414
9600.63 132.666
9631.58 133.931
9662.63 135.209
9693.79 136.498
9725.04 137.800
9756.39 139.115
9787.85 140.441
9819.41 141.780
9851.07 143.131
9882.83 144.496
9914.69 145.873
9946.65 147.265
9978.72 148.671
10010.9 150.090
10043.2 151.522
10075.5 152.968
10108.0 154.429
10140.6 155.904
10173.3 157.393
10206.1 158.896
10239.0 160.413
10272.0 161.946
10305.2 163.493
10338.4 165.055
10371.7 166.632
10405.1 168.224
10438.7 169.832
10472.3 171.455
10506.1 173.093
10540.0 174.747
10574.0 176.417
10608.1 178.104
10642.3 179.808
10676.6 181.527
10711.0 183.263
10745.5 185.015
10780.2 186.785
10814.9 188.572
10849.8 190.376
10884.8 192.197
10919.9 194.035
10955.1 195.892
10990.4 197.767
11025.8 199.659
11061.4 201.570
11097.0 203.498
11132.8 205.447
11168.7 207.414
11204.7 209.400
11240.8 211.405
11277.1 213.429
11313.4 215.474
11349.9 217.538
11386.5 219.622
11423.2 221.725
11460.0 223.849
11497.0 225.994
11534.1 228.159
11571.2 230.344
11608.6 232.550
11646.0 234.778
11683.5 237.028
11721.2 239.300
11759.0 241.593
11796.9 243.908
11834.9 246.246
11873.1 248.607
11911.4 250.991
11949.8 253.398
11988.3 255.827
12026.9 258.280
12065.7 260.757
12104.6 263.257
12143.7 265.781
12182.8 268.329
12222.1 270.902
12261.5 273.502
12301.0 276.126
12340.7 278.776
12380.5 281.450
12420.4 284.150
12460.4 286.877
12500.6 289.629
12540.9 292.408
12581.3 295.212
12621.9 298.045
12662.6 300.906
12703.4 303.794
12744.4 306.709
12785.5 309.653
12826.7 312.624
12868.0 315.625
12909.5 318.655
12951.1 321.713
12992.9 324.800
13034.8 327.917
13076.8 331.067
13119.0 334.246
13161.3 337.456
13203.7 340.696
13246.3 343.968
13289.0 347.271
13331.8 350.607
13374.8 353.973
13417.9 357.371
13461.2 360.802
13504.6 364.269
13548.1 367.769
13591.8 371.301
13635.6 374.867
13679.6 378.467
13723.7 382.103
13767.9 385.773
13812.3 389.478
13856.9 393.217
13901.5 396.994
13946.4 400.809
13991.3 404.660
14036.4 408.548
14081.7 412.472
14127.1 416.434
14172.6 420.436
14218.3 424.475
14264.2 428.552
14310.2 432.668
14356.3 436.824
14402.6 441.022
14449.0 445.260
14495.6 449.539
14542.3 453.858
14589.2 458.217
14636.2 462.619
14683.4 467.064
14730.8 471.549
14778.3 476.076
14825.9 480.648
14873.7 485.268
14921.7 489.931
14969.8 494.637
15018.0 499.389
15066.5 504.191
15115.0 509.040
15163.8 513.935
15212.7 518.876
15261.7 523.864
15310.9 528.901
15360.3 533.988
15409.8 539.123
15459.5 544.306
15509.3 549.539
15559.3 554.823
15609.5 560.159
15659.8 565.546
15710.3 570.984
15761.0 576.473
15811.8 582.014
15862.7 587.611
15913.9 593.262
15965.2 598.964
16016.7 604.719
16068.3 610.531
16120.1 616.402
16172.1 622.326
16224.2 628.306
16276.5 634.342
16329.0 640.437
16381.7 646.596
16434.5 652.811
16487.5 659.084
16540.6 665.416
16593.9 671.811
16647.4 678.268
16701.1 684.786
16755.0 691.364
16809.0 698.004
16863.2 704.710
16917.5 711.482
16972.1 718.318
17026.8 725.217
17081.7 732.182
17136.8 739.214
17192.0 746.315
17247.4 753.482
17303.1 760.717
17358.8 768.018
17414.8 775.391
17470.9 782.836
17527.3 790.351
17583.8 797.934
17640.5 805.587
17697.4 813.318
17754.4 821.128
17811.6 829.008
17869.1 836.961
17926.7 844.987
17984.5 853.094
18042.5 861.278
18100.6 869.538
18159.0 877.874
18217.5 886.286
18276.3 894.784
18335.2 903.364
18394.3 912.023
18453.6 920.761
18513.1 929.582
18572.8 938.489
18632.7 947.484
18692.8 956.561
18753.0 965.723
18813.5 974.967
18874.1 984.303
18935.0 993.729
18996.0 1003.24
19057.3 1012.84
19118.7 1022.53
19180.4 1032.31
19242.2 1042.19
19304.2 1052.16
19366.5 1062.22
19428.9 1072.37
19491.6 1082.63
19554.4 1092.98
19617.4 1103.42
19680.7 1113.96
19744.1 1124.59
19807.8 1135.38
19871.7 1146.29
19935.7 1157.29
20000.0 1168.40
20081.3 1182.56
20162.8 1196.82
20244.8 1211.23
20327.0 1225.81
20409.6 1240.55
20492.5 1255.47
20575.8 1270.57
20659.4 1285.83
20743.3 1301.26
20827.6 1316.88
20912.2 1332.67
20997.2 1348.64
21082.5 1364.79
21168.1 1381.13
21254.1 1397.65
21340.5 1414.36
21427.2 1431.26
21514.3 1448.35
21601.7 1465.63
21689.4 1483.11
21777.6 1500.78
21866.0 1518.66
21954.9 1536.73
22044.1 1555.01
22133.6 1573.50
22223.6 1592.19
22313.9 1611.09
22404.5 1630.19
22495.5 1649.51
22586.9 1669.05
22678.7 1688.80
22770.8 1708.77
22863.4 1728.96
22956.3 1749.38
23049.5 1770.02
23143.2 1790.88
23237.2 1811.97
23331.6 1833.30
23426.4 1854.85
23521.6 1876.64
23617.1 1898.66
23713.1 1920.93
23809.4 1943.44
23906.2 1966.19
24003.3 1989.19
24100.8 2012.43
24198.7 2035.93
24297.1 2059.67
24395.8 2083.67
24494.9 2107.92
24594.4 2132.44
24694.3 2157.20
24794.7 2182.24
24895.4 2207.53
24996.6 2233.09
25098.1 2258.92
25200.1 2285.02
25302.5 2311.40
25405.3 2338.05
25508.5 2364.98
25612.1 2392.19
25716.2 2419.68
25820.7 2447.45
25925.6 2475.50
26030.9 2503.85
26136.7 2532.50
26242.9 2561.42
26349.5 2590.64
26456.5 2620.16
26564.0 2649.97
26672.0 2680.08
26780.3 2710.49
26889.1 2741.21
26998.4 2772.24
27108.1 2803.57
27218.2 2835.21
27328.8 2867.17
27439.8 2899.44
27551.3 2932.02
27663.2 2964.91
27775.6 2998.14
27888.5 3031.69
28001.8 3065.56
28115.6 3099.75
28229.8 3134.27
28344.5 3169.12
28459.6 3204.30
28575.3 3239.80
28691.4 3275.66
28807.9 3311.85
28925.0 3348.37
29042.5 3385.23
29160.5 3422.44
29279.0 3459.98
29397.9 3497.87
29517.4 3536.09
29637.3 3574.69
29757.7 3613.62
29878.6 3652.90
30000.0 3692.52

View File

@@ -1,713 +0,0 @@
cr Density=7.19, Angle=90.deg
Photon Energy (eV), Atten Length (microns)
4000.00 7.36948
4012.90 7.43487
4025.83 7.50083
4038.81 7.56737
4051.83 7.63450
4064.90 7.70224
4078.00 7.77057
4091.15 7.83951
4104.34 7.90905
4117.57 7.97916
4130.85 8.04989
4144.17 8.12124
4157.53 8.19322
4170.93 8.26584
4184.38 8.33903
4197.87 8.41287
4211.41 8.48736
4224.98 8.56251
4238.60 8.63834
4252.27 8.71478
4265.98 8.79189
4279.73 8.86969
4293.53 8.94819
4307.37 9.02737
4321.26 9.10723
4335.19 9.18779
4349.17 9.26908
4363.19 9.35108
4377.26 9.43379
4391.37 9.51723
4405.53 9.60141
4419.73 9.68634
4433.98 9.77201
4448.28 9.85842
4462.62 9.94550
4477.01 10.0334
4491.44 10.1220
4505.92 10.2114
4520.45 10.3016
4535.02 10.3923
4549.65 10.4839
4564.31 10.5763
4579.03 10.6695
4593.79 10.7635
4608.60 10.8584
4623.46 10.9541
4638.37 11.0507
4653.32 11.1481
4668.33 11.2464
4683.38 11.3454
4698.48 11.4454
4713.62 11.5462
4728.82 11.6479
4744.07 11.7504
4759.36 11.8538
4774.71 11.9581
4790.10 12.0633
4805.54 12.1694
4821.04 12.2764
4836.58 12.3843
4852.17 12.4932
4867.82 12.6031
4883.51 12.7139
4899.26 12.8256
4915.05 12.9381
4930.90 13.0516
4946.80 13.1662
4962.75 13.2817
4978.75 13.3982
4994.80 13.5157
5010.90 13.6342
5027.06 13.7537
5043.26 13.8743
5059.52 13.9959
5075.84 14.1184
5092.20 14.2419
5108.62 14.3665
5125.09 14.4922
5141.61 14.6190
5158.19 14.7468
5174.82 14.8758
5191.50 15.0059
5208.24 15.1371
5225.03 15.2694
5241.88 15.4027
5258.78 15.5371
5275.73 15.6728
5292.74 15.8096
5309.81 15.9475
5326.93 16.0865
5344.10 16.2268
5361.33 16.3682
5378.62 16.5109
5395.96 16.6547
5413.35 16.7997
5430.81 16.9460
5448.32 17.0935
5465.88 17.2423
5483.50 17.3923
5501.18 17.5434
5518.92 17.6959
5536.71 17.8497
5554.56 18.0048
5572.47 18.1612
5590.44 18.3188
5608.46 18.4778
5626.54 18.6382
5644.68 18.7999
5662.88 18.9630
5681.14 19.1272
5699.46 19.2929
5717.83 19.4600
5736.27 19.6286
5754.76 19.7984
5773.31 19.9696
5791.93 20.1423
5810.60 20.3164
5829.33 20.4921
5848.13 20.6691
5866.98 20.8476
5885.90 21.0276
5904.88 21.2091
5923.91 21.3922
5943.01 21.5768
5962.17 21.7631
5981.40 21.9510
5985.00 21.9863
5985.10 21.9873
5985.20 21.9883
5985.30 21.9892
5985.40 21.9902
5985.50 21.9912
5985.60 21.9922
5985.70 21.9932
5985.80 21.9941
5985.90 21.9951
5986.00 21.9961
5986.10 21.9971
5986.20 21.9981
5986.30 21.9990
5986.40 22.0000
5986.50 22.0010
5986.60 22.0020
5986.70 22.0030
5986.80 22.0040
5986.90 22.0049
5987.00 22.0059
5987.10 22.0069
5987.20 22.0079
5987.30 22.0088
5987.40 22.0098
5987.50 22.0108
5987.60 22.0118
5987.70 22.0128
5987.80 22.0138
5987.90 22.0147
5988.00 22.0157
5988.10 22.0167
5988.20 22.0177
5988.30 22.0187
5988.40 22.0196
5988.50 22.0206
5988.60 22.0216
5988.70 22.0226
5988.80 22.0236
5988.90 22.0245
5989.00 22.0255
5989.10 22.0265
5989.11 20.7400
5989.12 18.3877
5989.13 16.3020
5989.14 14.4528
5989.15 13.6083
5989.16 12.0645
5989.17 10.6957
5989.18 9.48212
5989.19 8.40620
5989.20 7.91492
5989.30 2.84297
5989.40 2.67688
5989.50 2.67699
5989.60 2.67710
5989.70 2.67720
5989.80 2.67732
5989.90 2.67742
5990.00 2.67753
5990.10 2.67764
5990.20 2.67775
5990.30 2.67786
5990.40 2.67797
5990.50 2.67808
5990.60 2.67819
5990.70 2.67829
5990.80 2.67841
5990.90 2.67851
5991.00 2.67862
5991.10 2.67874
5991.20 2.67884
5991.30 2.67895
5991.40 2.67906
5991.50 2.67917
5991.60 2.67928
5991.70 2.67939
5991.80 2.67950
5991.90 2.67961
5992.00 2.67972
5992.10 2.67983
5992.20 2.67993
5992.30 2.68004
5992.40 2.68015
5992.50 2.68026
5992.60 2.68037
5992.70 2.68048
5992.80 2.68059
5992.90 2.68070
5993.00 2.68081
5993.10 2.68092
5993.20 2.68103
5993.30 2.68114
5993.40 2.68124
5993.50 2.68136
5993.60 2.68146
5993.70 2.68157
5993.80 2.68168
5993.90 2.68179
5994.00 2.68190
5994.10 2.68201
5994.20 2.68212
5994.30 2.68223
5994.40 2.68234
5994.50 2.68245
5994.60 2.68256
5994.70 2.68267
5994.80 2.68277
5994.90 2.68289
5995.00 2.68299
6000.68 2.68920
6020.03 2.71041
6039.44 2.73179
6058.91 2.75333
6078.44 2.77504
6098.04 2.79692
6117.70 2.81898
6137.42 2.84127
6157.21 2.86379
6177.06 2.88648
6196.98 2.90936
6216.96 2.93243
6237.00 2.95574
6257.11 2.97929
6277.28 3.00304
6297.52 3.02698
6317.82 3.05110
6338.19 3.07550
6358.63 3.10015
6379.13 3.12500
6399.69 3.15005
6420.33 3.17530
6441.03 3.20082
6461.79 3.22661
6482.63 3.25261
6503.53 3.27882
6524.49 3.30523
6545.53 3.33194
6566.63 3.35893
6587.80 3.38613
6609.04 3.41355
6630.35 3.44119
6651.73 3.46915
6673.17 3.49738
6694.69 3.52584
6716.27 3.55453
6737.93 3.58346
6759.65 3.61269
6781.44 3.64220
6803.31 3.67196
6825.24 3.70197
6847.25 3.73221
6869.32 3.76280
6891.47 3.79370
6913.69 3.82485
6935.98 3.85626
6958.34 3.88793
6980.77 3.91995
7003.28 3.95230
7025.86 3.98491
7048.51 4.01779
7071.24 4.05094
7094.03 4.08445
7116.91 4.11828
7139.85 4.15239
7162.87 4.18677
7185.96 4.22145
7209.13 4.25650
7232.38 4.29188
7255.69 4.32756
7279.09 4.36353
7302.55 4.39981
7326.10 4.43648
7349.72 4.47351
7373.41 4.51084
7397.19 4.54849
7421.03 4.58645
7444.96 4.62485
7468.96 4.66363
7493.04 4.70273
7517.20 4.74216
7541.44 4.78192
7565.75 4.82210
7590.14 4.86264
7614.62 4.90353
7639.17 4.94475
7663.79 4.98633
7688.50 5.02838
7713.29 5.07085
7738.16 5.11367
7763.11 5.15684
7788.14 5.20039
7813.25 5.24440
7838.44 5.28883
7863.71 5.33362
7889.06 5.37880
7914.50 5.42435
7940.01 5.47042
7965.61 5.51690
7991.29 5.56378
8017.06 5.61105
8042.91 5.65874
8068.84 5.70693
8094.85 5.75557
8120.95 5.80462
8147.13 5.85410
8173.40 5.90399
8199.75 5.95444
8226.19 6.00537
8252.71 6.05673
8279.32 6.10854
8306.01 6.16078
8332.79 6.21357
8359.65 6.26684
8386.60 6.32058
8413.64 6.37477
8440.77 6.42942
8467.98 6.48472
8495.29 6.54056
8522.67 6.59686
8550.15 6.65365
8577.72 6.71093
8605.37 6.76883
8633.12 6.82725
8660.95 6.88617
8688.87 6.94559
8716.89 7.00554
8744.99 7.06612
8773.19 7.12724
8801.47 7.18888
8829.85 7.25106
8858.32 7.31379
8886.88 7.37722
8915.53 7.44124
8944.27 7.50581
8973.11 7.57095
9002.04 7.63665
9031.06 7.70305
9060.18 7.77005
9089.39 7.83764
9118.69 7.90581
9148.09 7.97457
9177.59 8.04414
9207.18 8.11433
9236.86 8.18516
9266.64 8.25659
9296.52 8.32864
9326.49 8.40145
9356.56 8.47492
9386.72 8.54902
9416.99 8.62377
9447.35 8.69918
9477.81 8.77535
9508.37 8.85219
9539.02 8.92970
9569.78 9.00788
9600.63 9.08677
9631.58 9.16655
9662.63 9.24704
9693.79 9.32825
9725.04 9.41018
9756.39 9.49281
9787.85 9.57645
9819.41 9.66083
9851.07 9.74598
9882.83 9.83186
9914.69 9.91849
9946.65 10.0060
9978.72 10.0943
10010.9 10.1834
10043.2 10.2733
10075.5 10.3640
10108.0 10.4556
10140.6 10.5481
10173.3 10.6413
10206.1 10.7354
10239.0 10.8303
10272.0 10.9263
10305.2 11.0231
10338.4 11.1208
10371.7 11.2194
10405.1 11.3188
10438.7 11.4194
10472.3 11.5208
10506.1 11.6230
10540.0 11.7262
10574.0 11.8304
10608.1 11.9356
10642.3 12.0418
10676.6 12.1490
10711.0 12.2571
10745.5 12.3661
10780.2 12.4764
10814.9 12.5876
10849.8 12.6998
10884.8 12.8130
10919.9 12.9272
10955.1 13.0427
10990.4 13.1592
11025.8 13.2768
11061.4 13.3954
11097.0 13.5150
11132.8 13.6360
11168.7 13.7580
11204.7 13.8811
11240.8 14.0053
11277.1 14.1307
11313.4 14.2574
11349.9 14.3852
11386.5 14.5142
11423.2 14.6443
11460.0 14.7757
11497.0 14.9083
11534.1 15.0422
11571.2 15.1773
11608.6 15.3135
11646.0 15.4511
11683.5 15.5901
11721.2 15.7303
11759.0 15.8718
11796.9 16.0146
11834.9 16.1587
11873.1 16.3043
11911.4 16.4513
11949.8 16.5995
11988.3 16.7491
12026.9 16.9000
12065.7 17.0525
12104.6 17.2064
12143.7 17.3617
12182.8 17.5184
12222.1 17.6765
12261.5 17.8363
12301.0 17.9976
12340.7 18.1603
12380.5 18.3245
12420.4 18.4901
12460.4 18.6575
12500.6 18.8264
12540.9 18.9968
12581.3 19.1688
12621.9 19.3424
12662.6 19.5177
12703.4 19.6947
12744.4 19.8733
12785.5 20.0535
12826.7 20.2353
12868.0 20.4190
12909.5 20.6044
12951.1 20.7915
12992.9 20.9802
13034.8 21.1708
13076.8 21.3633
13119.0 21.5576
13161.3 21.7536
13203.7 21.9515
13246.3 22.1512
13289.0 22.3528
13331.8 22.5564
13374.8 22.7618
13417.9 22.9690
13461.2 23.1782
13504.6 23.3896
13548.1 23.6029
13591.8 23.8181
13635.6 24.0353
13679.6 24.2545
13723.7 24.4759
13767.9 24.6994
13812.3 24.9248
13856.9 25.1523
13901.5 25.3820
13946.4 25.6141
13991.3 25.8482
14036.4 26.0845
14081.7 26.3230
14127.1 26.5638
14172.6 26.8069
14218.3 27.0522
14264.2 27.2998
14310.2 27.5497
14356.3 27.8019
14402.6 28.0567
14449.0 28.3139
14495.6 28.5734
14542.3 28.8353
14589.2 29.0996
14636.2 29.3665
14683.4 29.6359
14730.8 29.9077
14778.3 30.1820
14825.9 30.4590
14873.7 30.7388
14921.7 31.0211
14969.8 31.3061
15018.0 31.5936
15066.5 31.8840
15115.0 32.1772
15163.8 32.4731
15212.7 32.7717
15261.7 33.0731
15310.9 33.3774
15360.3 33.6847
15409.8 33.9948
15459.5 34.3078
15509.3 34.6237
15559.3 34.9426
15609.5 35.2647
15659.8 35.5897
15710.3 35.9178
15761.0 36.2488
15811.8 36.5830
15862.7 36.9205
15913.9 37.2612
15965.2 37.6049
16016.7 37.9518
16068.3 38.3020
16120.1 38.6557
16172.1 39.0126
16224.2 39.3728
16276.5 39.7363
16329.0 40.1034
16381.7 40.4742
16434.5 40.8483
16487.5 41.2259
16540.6 41.6069
16593.9 41.9918
16647.4 42.3803
16701.1 42.7724
16755.0 43.1681
16809.0 43.5676
16863.2 43.9708
16917.5 44.3781
16972.1 44.7890
17026.8 45.2038
17081.7 45.6225
17136.8 46.0452
17192.0 46.4720
17247.4 46.9028
17303.1 47.3376
17358.8 47.7763
17414.8 48.2193
17470.9 48.6665
17527.3 49.1180
17583.8 49.5735
17640.5 50.0333
17697.4 50.4976
17754.4 50.9666
17811.6 51.4398
17869.1 51.9174
17926.7 52.3995
17984.5 52.8862
18042.5 53.3776
18100.6 53.8735
18159.0 54.3740
18217.5 54.8791
18276.3 55.3893
18335.2 55.9043
18394.3 56.4241
18453.6 56.9488
18513.1 57.4783
18572.8 58.0130
18632.7 58.5529
18692.8 59.0978
18753.0 59.6479
18813.5 60.2029
18874.1 60.7633
18935.0 61.3292
18996.0 61.9003
19057.3 62.4767
19118.7 63.0584
19180.4 63.6458
19242.2 64.2390
19304.2 64.8376
19366.5 65.4417
19428.9 66.0514
19491.6 66.6670
19554.4 67.2887
19617.4 67.9160
19680.7 68.5491
19744.1 69.1881
19807.8 69.8335
19871.7 70.4851
19935.7 71.1427
20000.0 71.8064
20081.3 72.6515
20162.8 73.5071
20244.8 74.3726
20327.0 75.2484
20409.6 76.1342
20492.5 77.0315
20575.8 77.9393
20659.4 78.8575
20743.3 79.7867
20827.6 80.7275
20912.2 81.6791
20997.2 82.6420
21082.5 83.6161
21168.1 84.6024
21254.1 85.6003
21340.5 86.6097
21427.2 87.6312
21514.3 88.6652
21601.7 89.7114
21689.4 90.7699
21777.6 91.8408
21866.0 92.9252
21954.9 94.0222
22044.1 95.1321
22133.6 96.2552
22223.6 97.3920
22313.9 98.5423
22404.5 99.7058
22495.5 100.883
22586.9 102.075
22678.7 103.281
22770.8 104.501
22863.4 105.736
22956.3 106.986
23049.5 108.250
23143.2 109.529
23237.2 110.824
23331.6 112.134
23426.4 113.459
23521.6 114.800
23617.1 116.157
23713.1 117.531
23809.4 118.921
23906.2 120.327
24003.3 121.750
24100.8 123.190
24198.7 124.647
24297.1 126.121
24395.8 127.612
24494.9 129.122
24594.4 130.649
24694.3 132.194
24794.7 133.758
24895.4 135.340
24996.6 136.941
25098.1 138.561
25200.1 140.200
25302.5 141.859
25405.3 143.537
25508.5 145.235
25612.1 146.954
25716.2 148.693
25820.7 150.452
25925.6 152.232
26030.9 154.033
26136.7 155.856
26242.9 157.700
26349.5 159.566
26456.5 161.454
26564.0 163.364
26672.0 165.297
26780.3 167.252
26889.1 169.231
26998.4 171.233
27108.1 173.258
27218.2 175.308
27328.8 177.381
27439.8 179.479
27551.3 181.602
27663.2 183.749
27775.6 185.923
27888.5 188.122
28001.8 190.346
28115.6 192.597
28229.8 194.874
28344.5 197.178
28459.6 199.509
28575.3 201.867
28691.4 204.253
28807.9 206.667
28925.0 209.110
29042.5 211.580
29160.5 214.080
29279.0 216.610
29397.9 219.169
29517.4 221.758
29637.3 224.377
29757.7 227.027
29878.6 229.707
30000.0 232.418

View File

@@ -1,636 +0,0 @@
4000.00 3.25746
4016.15 3.29307
4032.37 3.32906
4048.65 3.36546
4065.00 3.40227
4081.41 3.43947
4097.89 3.47709
4114.44 3.51514
4131.06 3.55362
4147.74 3.59251
4164.48 3.63183
4181.30 3.67160
4198.18 3.71182
4215.14 3.75247
4232.16 3.79357
4249.25 3.83514
4266.40 3.87716
4283.63 3.91965
4300.93 3.96259
4318.29 4.00604
4335.73 4.04997
4353.24 4.09438
4370.82 4.13928
4388.47 4.18468
4406.19 4.23059
4423.98 4.27699
4441.84 4.32391
4459.78 4.37138
4477.79 4.41938
4495.87 4.46791
4514.02 4.51696
4532.25 4.56663
4550.55 4.61685
4568.93 4.66763
4587.37 4.71896
4605.90 4.77084
4624.50 4.82328
4643.17 4.87629
4661.92 4.92989
4680.74 4.98413
4699.64 5.03898
4718.62 5.09443
4737.67 5.15049
4756.80 5.20723
4776.01 5.26461
4795.30 5.32262
4814.66 5.38126
4834.10 5.44057
4853.62 5.50053
4873.22 5.56116
4892.90 5.62244
4912.65 5.68447
4932.49 5.74717
4952.41 5.81058
4972.41 5.87468
4992.48 5.93953
5012.64 6.00510
5032.88 6.07139
5053.21 6.13842
5073.61 6.20623
5094.10 6.27479
5114.67 6.34412
5135.32 6.41420
5156.06 6.48511
5176.88 6.55680
5197.78 6.62929
5218.77 6.70258
5239.84 6.77683
5261.00 6.85190
5282.24 6.92781
5303.57 7.00455
5324.99 7.08208
5346.49 7.16047
5368.08 7.23972
5389.76 7.31986
5411.52 7.40104
5433.37 7.48313
5455.31 7.56613
5477.34 7.65005
5499.46 7.73501
5521.66 7.82091
5543.96 7.90777
5566.34 7.99558
5588.82 8.08432
5611.39 8.17404
5634.05 8.26476
5656.80 8.35649
5679.64 8.44953
5702.57 8.54360
5725.60 8.63871
5748.72 8.73487
5771.93 8.83200
5795.24 8.93022
5818.64 9.02952
5842.13 9.12998
5865.72 9.23186
5889.41 9.33488
5913.19 9.43905
5937.07 9.54436
5961.04 9.65080
5985.11 9.75840
6009.28 9.86722
6033.54 9.97725
6057.91 10.0886
6082.37 10.2012
6106.93 10.3150
6131.59 10.4301
6156.35 10.5469
6181.21 10.6649
6206.17 10.7843
6231.23 10.9050
6256.39 11.0271
6281.65 11.1506
6307.01 11.2754
6332.48 11.4017
6358.05 11.5295
6383.73 11.6588
6409.50 11.7895
6435.38 11.9216
6461.37 12.0555
6487.46 12.1909
6513.66 12.3278
6539.96 12.4663
6566.37 12.6064
6592.88 12.7481
6619.50 12.8914
6646.23 13.0364
6673.07 13.1831
6700.01 13.3316
6727.07 13.4816
6754.23 13.6334
6781.50 13.7871
6808.89 13.9425
6836.38 14.0996
6863.99 14.2586
6891.70 14.4197
6919.53 14.5825
6947.47 14.7472
6975.53 14.9137
7003.69 15.0824
7031.97 15.2530
7060.37 15.4255
7088.88 15.6001
7117.50 15.7768
7146.24 15.9555
7175.10 16.1362
7204.07 16.3191
7233.16 16.5043
7262.37 16.6916
7291.69 16.8810
7321.13 17.0726
7350.70 17.2667
7380.38 17.4630
7410.18 17.6615
7440.10 17.8624
7470.14 18.0658
7500.31 18.2715
7530.59 18.4796
7561.00 18.6902
7591.53 18.9034
7622.19 19.1191
7652.96 19.3372
7683.87 19.5580
7714.89 19.7815
7746.05 20.0076
7777.32 20.2363
7808.73 20.4678
7840.26 20.7023
7871.92 20.9395
7903.70 21.1793
7935.62 21.4222
7967.66 21.6681
7999.84 21.9168
8032.14 22.1684
8064.57 22.4232
8097.14 22.6812
8129.83 22.9422
8162.66 23.2061
8195.62 23.4734
8228.71 23.7441
8261.94 24.0178
8295.30 24.2947
8328.80 24.5752
8362.43 24.8594
8396.20 25.1467
8430.10 25.4374
8464.14 25.7318
8498.32 26.0300
8532.63 26.3316
8567.09 26.6368
8601.68 26.9458
8636.41 27.2589
8671.29 27.5756
8706.30 27.8960
8741.46 28.2205
8776.75 28.5491
8812.19 28.8816
8847.78 29.2179
8883.50 29.5581
8919.37 29.9023
8955.00 30.2467
8956.00 30.2564
8957.00 30.2661
8958.00 30.2758
8958.99 30.2855
8959.99 30.2952
8960.99 30.3049
8961.99 30.3146
8962.99 30.3243
8963.99 30.3340
8964.99 30.3438
8965.99 30.3535
8966.98 30.3632
8967.98 30.3729
8968.98 30.3826
8969.98 30.3924
8970.98 30.4021
8971.98 30.4118
8972.98 30.4216
8973.98 30.4313
8974.98 30.4411
8975.98 30.4508
8976.98 30.4605
8977.98 30.4703
8978.00 30.4705
8978.01 30.4706
8978.02 30.4706
8978.03 30.4708
8978.04 30.4709
8978.05 30.4710
8978.06 30.4710
8978.07 30.4711
8978.08 30.4712
8978.09 30.4714
8978.10 30.4715
8978.11 30.4715
8978.12 30.4716
8978.13 30.4717
8978.14 30.4718
8978.15 30.4720
8978.16 30.4720
8978.17 30.4721
8978.18 30.4722
8978.19 30.4723
8978.20 30.4724
8978.21 30.4725
8978.22 30.4726
8978.23 30.4727
8978.24 30.4728
8978.25 30.4729
8978.26 30.4730
8978.27 30.4731
8978.28 30.4732
8978.29 30.4733
8978.30 30.4734
8978.31 30.4735
8978.32 30.4736
8978.33 30.4737
8978.34 30.4738
8978.35 30.4739
8978.36 30.4740
8978.37 30.4741
8978.38 30.4741
8978.39 30.4743
8978.40 30.4744
8978.41 30.4745
8978.42 30.4746
8978.43 30.4746
8978.44 30.4747
8978.45 30.4749
8978.46 30.4750
8978.47 30.4751
8978.48 30.4751
8978.49 30.4752
8978.50 30.4753
8978.51 30.4755
8978.52 30.4756
8978.53 30.4756
8978.54 30.4757
8978.55 30.4758
8978.56 30.4759
8978.57 30.4761
8978.58 30.4761
8978.59 30.4762
8978.60 30.4763
8978.61 30.4764
8978.62 30.4765
8978.63 30.4766
8978.64 30.4767
8978.65 30.4768
8978.66 30.4769
8978.67 30.4770
8978.68 30.4771
8978.69 30.4772
8978.70 30.4773
8978.71 30.4774
8978.72 30.4775
8978.73 30.4776
8978.74 30.4777
8978.75 30.4778
8978.76 30.4779
8978.77 30.4780
8978.78 30.4781
8978.79 30.4782
8978.80 30.4782
8978.81 25.6979
8978.82 23.5962
8978.83 21.6663
8978.84 19.8939
8978.85 18.2664
8978.86 15.3995
8978.87 14.1393
8978.88 12.9822
8978.89 11.9197
8978.90 10.9441
8978.91 10.0483
8978.92 9.22574
8978.93 7.77706
8978.94 7.14036
8978.95 6.55577
8978.96 6.01902
8978.97 5.52620
8978.98 4.65827
8978.99 4.27683
8979.00 3.92662
8979.99 3.92768
8980.99 3.92876
8981.99 3.92983
8982.99 3.93091
8983.99 3.93198
8984.99 3.93306
8985.99 3.93414
8987.00 3.93522
8988.00 3.93630
8989.00 3.93738
8990.00 3.93846
8991.55 3.94013
9027.86 3.97936
9064.31 4.01898
9100.91 4.05900
9137.66 4.09942
9174.56 4.14035
9211.61 4.18176
9248.80 4.22359
9286.15 4.26582
9323.65 4.30865
9361.29 4.35198
9399.09 4.39576
9437.05 4.43996
9475.15 4.48477
9513.41 4.53010
9551.83 4.57590
9590.40 4.62215
9629.12 4.66903
9668.00 4.71646
9707.04 4.76436
9746.24 4.81275
9785.59 4.86176
9825.11 4.91132
9864.78 4.96138
9904.61 5.01195
9944.61 5.06327
9984.76 5.11518
10025.1 5.16764
10065.6 5.22063
10106.2 5.27433
10147.0 5.32865
10188.0 5.38352
10229.1 5.43896
10270.4 5.49516
10311.9 5.55200
10353.5 5.60942
10395.3 5.66744
10437.3 5.72624
10479.5 5.78571
10521.8 5.84579
10564.3 5.90650
10606.9 5.96803
10649.8 6.03027
10692.8 6.09315
10735.9 6.15668
10779.3 6.22107
10822.8 6.28618
10866.5 6.35197
10910.4 6.41844
10954.5 6.48583
10998.7 6.55397
11043.1 6.62282
11087.7 6.69240
11132.5 6.76293
11177.4 6.83425
11222.5 6.90631
11267.9 6.97914
11313.4 7.05296
11359.0 7.12760
11404.9 7.20304
11451.0 7.27925
11497.2 7.35650
11543.6 7.43459
11590.2 7.51351
11637.0 7.59326
11684.0 7.67411
11731.2 7.75584
11778.6 7.83845
11826.1 7.92193
11873.9 8.00656
11921.8 8.09211
11970.0 8.17857
12018.3 8.26597
12066.8 8.35453
12115.6 8.44406
12164.5 8.53453
12213.6 8.62599
12262.9 8.71873
12312.4 8.81246
12362.2 8.90721
12412.1 9.00296
12462.2 9.10001
12512.5 9.19810
12563.0 9.29726
12613.8 9.39747
12664.7 9.49907
12715.8 9.60177
12767.2 9.70556
12818.7 9.81049
12870.5 9.91679
12922.5 10.0243
12974.7 10.1329
13027.0 10.2427
13079.6 10.3541
13132.5 10.4666
13185.5 10.5804
13238.7 10.6954
13292.2 10.8119
13345.9 10.9297
13399.8 11.0488
13453.9 11.1692
13508.2 11.2912
13562.7 11.4146
13617.5 11.5393
13672.5 11.6654
13727.7 11.7931
13783.1 11.9222
13838.8 12.0527
13894.7 12.1847
13950.8 12.3184
14007.1 12.4536
14063.7 12.5903
14120.4 12.7285
14177.5 12.8685
14234.7 13.0101
14292.2 13.1532
14349.9 13.2979
14407.8 13.4445
14466.0 13.5928
14524.4 13.7426
14583.1 13.8942
14642.0 14.0477
14701.1 14.2028
14760.5 14.3597
14820.1 14.5184
14879.9 14.6791
14940.0 14.8416
15000.3 15.0059
15060.9 15.1721
15121.7 15.3405
15182.8 15.5106
15244.1 15.6827
15305.6 15.8567
15367.4 16.0330
15429.5 16.2112
15491.8 16.3915
15554.3 16.5738
15617.1 16.7584
15680.2 16.9451
15743.5 17.1338
15807.1 17.3247
15870.9 17.5180
15935.0 17.7135
15999.3 17.9111
16063.9 18.1110
16128.8 18.3135
16193.9 18.5181
16259.3 18.7251
16325.0 18.9345
16390.9 19.1466
16457.1 19.3610
16523.5 19.5778
16590.3 19.7971
16657.3 20.0192
16724.5 20.2438
16792.0 20.4708
16859.9 20.7006
16927.9 20.9332
16996.3 21.1684
17064.9 21.4062
17133.8 21.6469
17203.0 21.8905
17272.5 22.1368
17342.2 22.3859
17412.2 22.6380
17482.6 22.8931
17553.1 23.1511
17624.0 23.4120
17695.2 23.6760
17766.6 23.9434
17838.4 24.2137
17910.4 24.4870
17982.7 24.7637
18055.3 25.0436
18128.3 25.3268
18201.5 25.6131
18275.0 25.9029
18348.7 26.1961
18422.8 26.4927
18497.2 26.7925
18571.9 27.0961
18646.9 27.4033
18722.2 27.7139
18797.8 28.0281
18873.7 28.3461
18949.9 28.6679
19026.4 28.9934
19103.3 29.3226
19180.4 29.6557
19257.8 29.9929
19335.6 30.3339
19413.7 30.6787
19492.1 31.0276
19570.8 31.3807
19649.8 31.7378
19729.2 32.0989
19808.8 32.4645
19888.8 32.8345
19969.1 33.2087
20049.8 33.5872
20130.7 33.9702
20212.0 34.3579
20293.6 34.7499
20375.6 35.1465
20457.8 35.5478
20540.4 35.9540
20623.4 36.3648
20706.7 36.7803
20790.3 37.2008
20874.2 37.6263
20958.5 38.0566
21043.1 38.4918
21128.1 38.9324
21213.4 39.3782
21299.1 39.8291
21385.1 40.2851
21471.4 40.7466
21558.1 41.2136
21645.2 41.6859
21732.6 42.1637
21820.3 42.6473
21908.5 43.1366
21996.9 43.6316
22085.7 44.1322
22174.9 44.6389
22264.5 45.1516
22354.4 45.6702
22444.6 46.1946
22535.3 46.7256
22626.3 47.2627
22717.6 47.8060
22809.4 48.3556
22901.5 48.9118
22993.9 49.4746
23086.8 50.0438
23180.0 50.6196
23273.6 51.2024
23367.6 51.7921
23461.9 52.3884
23556.7 52.9916
23651.8 53.6023
23747.3 54.2201
23843.2 54.8451
23939.5 55.4771
24036.1 56.1170
24133.2 56.7643
24230.6 57.4191
24328.5 58.0813
24426.7 58.7517
24525.3 59.4300
24624.4 60.1159
24723.8 60.8098
24823.6 61.5120
24923.9 62.2226
25024.5 62.9412
25125.6 63.6682
25227.0 64.4041
25328.9 65.1487
25431.2 65.9019
25533.9 66.6635
25637.0 67.4347
25740.5 68.2147
25844.4 69.0037
25948.8 69.8017
26053.6 70.6097
26158.8 71.4271
26264.4 72.2539
26370.4 73.0902
26476.9 73.9366
26583.8 74.7929
26691.2 75.6589
26799.0 76.5350
26907.2 77.4217
27015.8 78.3188
27124.9 79.2263
27234.4 80.1439
27344.4 81.0731
27454.8 82.0129
27565.7 82.9636
27677.0 83.9250
27788.7 84.8986
27901.0 85.8832
28013.6 86.8793
28126.7 87.8868
28240.3 88.9064
28354.3 89.9379
28468.8 90.9811
28583.8 92.0364
28699.2 93.1048
28815.1 94.1855
28931.4 95.2785
29048.3 96.3842
29165.6 97.5036
29283.3 98.6356
29401.6 99.7807
29520.3 100.939
29639.5 102.111
29759.2 103.297
29879.4 104.497
30000.0 105.710

View File

@@ -1,601 +0,0 @@
4000.00 75.3048
4012.90 76.0470
4025.83 76.7964
4038.81 77.5538
4051.83 78.3243
4064.90 79.1027
4078.00 79.8886
4091.15 80.6822
4104.34 81.4839
4117.57 82.2946
4130.85 83.1132
4144.17 83.9400
4157.53 84.7749
4170.93 85.6183
4184.38 86.4702
4197.87 87.3304
4211.41 88.1993
4224.98 89.0767
4238.60 89.9631
4252.27 90.8593
4265.98 91.7644
4279.73 92.6785
4293.53 93.6018
4307.37 94.5342
4321.26 95.4763
4335.19 96.4277
4349.17 97.3888
4363.19 98.3592
4377.26 99.3393
4391.37 100.330
4405.53 101.330
4419.73 102.341
4433.98 103.361
4448.28 104.392
4462.62 105.433
4477.01 106.486
4491.44 107.549
4505.92 108.622
4520.45 109.706
4535.02 110.802
4549.65 111.909
4564.31 113.026
4579.03 114.155
4593.79 115.296
4608.60 116.449
4623.46 117.613
4638.37 118.789
4653.32 119.976
4668.33 121.176
4683.38 122.388
4698.48 123.612
4713.62 124.848
4728.82 126.097
4744.07 127.358
4759.36 128.632
4774.71 129.920
4790.10 131.220
4805.54 132.533
4821.04 133.859
4836.58 135.200
4852.17 136.554
4867.82 137.921
4883.51 139.302
4899.26 140.697
4915.05 142.107
4930.90 143.531
4946.80 144.969
4962.75 146.421
4978.75 147.888
4994.80 149.371
5010.90 150.869
5027.06 152.382
5043.26 153.910
5059.52 155.454
5075.84 157.014
5092.20 158.590
5108.62 160.181
5125.09 161.789
5141.61 163.412
5158.19 165.053
5174.82 166.709
5191.50 168.382
5208.24 170.072
5225.03 171.779
5241.88 173.505
5258.78 175.249
5275.73 177.010
5292.74 178.788
5309.81 180.584
5326.93 182.400
5344.10 184.235
5361.33 186.087
5378.62 187.958
5395.96 189.848
5413.35 191.759
5430.81 193.689
5448.32 195.638
5465.88 197.606
5483.50 199.595
5501.18 201.604
5518.92 203.634
5536.71 205.683
5554.56 207.753
5572.47 209.844
5590.44 211.955
5608.46 214.088
5626.54 216.241
5644.68 218.416
5662.88 220.614
5681.14 222.837
5699.46 225.082
5717.83 227.350
5736.27 229.639
5754.76 231.953
5773.31 234.292
5791.93 236.655
5810.60 239.040
5829.33 241.449
5848.13 243.884
5866.98 246.346
5885.90 248.831
5904.88 251.341
5923.91 253.876
5943.01 256.437
5962.17 259.024
5981.40 261.636
6000.68 264.273
6020.03 266.939
6039.44 269.632
6058.91 272.352
6078.44 275.100
6098.04 277.874
6117.70 280.677
6137.42 283.510
6157.21 286.375
6177.06 289.268
6196.98 292.190
6216.96 295.141
6237.00 298.122
6257.11 301.134
6277.28 304.176
6297.52 307.249
6317.82 310.352
6338.19 313.487
6358.63 316.655
6379.13 319.855
6399.69 323.086
6420.33 326.349
6441.03 329.647
6461.79 332.980
6482.63 336.345
6503.53 339.744
6524.49 343.176
6545.53 346.645
6566.63 350.150
6587.80 353.689
6609.04 357.264
6630.35 360.873
6651.73 364.522
6673.17 368.208
6694.69 371.931
6716.27 375.690
6737.93 379.487
6759.65 383.324
6781.44 387.200
6803.31 391.114
6825.24 395.068
6847.25 399.060
6869.32 403.095
6891.47 407.171
6913.69 411.288
6935.98 415.446
6958.34 419.644
6980.77 423.888
7003.28 428.176
7025.86 432.507
7048.51 436.880
7071.24 441.297
7094.03 445.759
7116.91 450.268
7139.85 454.820
7162.87 459.417
7185.96 464.060
7209.13 468.753
7232.38 473.493
7255.69 478.280
7279.09 483.113
7302.55 487.996
7326.10 492.927
7349.72 497.909
7373.41 502.939
7397.19 508.019
7421.03 513.150
7444.96 518.336
7468.96 523.575
7493.04 528.866
7517.20 534.209
7541.44 539.604
7565.75 545.056
7590.14 550.562
7614.62 556.123
7639.17 561.737
7663.79 567.406
7688.50 573.135
7713.29 578.922
7738.16 584.765
7763.11 590.665
7788.14 596.622
7813.25 602.644
7838.44 608.728
7863.71 614.870
7889.06 621.071
7914.50 627.333
7940.01 633.662
7965.61 640.054
7991.29 646.507
8017.06 653.027
8042.91 659.613
8068.84 666.267
8094.85 672.988
8120.95 679.774
8147.13 686.627
8173.40 693.545
8199.75 700.536
8226.19 707.596
8252.71 714.725
8279.32 721.924
8306.01 729.191
8332.79 736.537
8359.65 743.956
8386.60 751.447
8413.64 759.010
8440.77 766.645
8467.98 774.359
8495.29 782.151
8522.67 790.016
8550.15 797.956
8577.72 805.973
8605.37 814.075
8633.12 822.254
8660.95 830.511
8688.87 838.848
8716.89 847.264
8744.99 855.773
8773.19 864.364
8801.47 873.036
8829.85 881.791
8858.32 890.632
8886.88 899.564
8915.53 908.583
8944.27 917.687
8973.11 926.879
9002.04 936.156
9031.06 945.529
9060.18 954.991
9089.39 964.544
9118.69 974.186
9148.09 983.918
9177.59 993.754
9207.18 1003.68
9236.86 1013.71
9266.64 1023.83
9296.52 1034.04
9326.49 1044.35
9356.56 1054.77
9386.72 1065.27
9416.99 1075.88
9447.35 1086.59
9477.81 1097.41
9508.37 1108.33
9539.02 1119.35
9569.78 1130.47
9600.63 1141.70
9631.58 1153.05
9662.63 1164.51
9693.79 1176.07
9725.04 1187.74
9756.39 1199.52
9787.85 1211.41
9819.41 1223.40
9851.07 1235.52
9882.83 1247.73
9914.69 1260.07
9946.65 1272.53
9978.72 1285.10
10010.9 1297.80
10043.2 1310.62
10075.5 1323.56
10108.0 1336.63
10140.6 1349.82
10173.3 1363.12
10206.1 1376.55
10239.0 1390.10
10272.0 1403.79
10305.2 1417.60
10338.4 1431.54
10371.7 1445.60
10405.1 1459.79
10438.7 1474.12
10472.3 1488.58
10506.1 1503.17
10540.0 1517.88
10574.0 1532.73
10608.1 1547.73
10642.3 1562.86
10676.6 1578.12
10711.0 1593.52
10745.5 1609.05
10780.2 1624.73
10814.9 1640.56
10849.8 1656.52
10884.8 1672.62
10919.9 1688.86
10955.1 1705.26
10990.4 1721.80
11025.8 1738.48
11061.4 1755.31
11097.0 1772.28
11132.8 1789.42
11168.7 1806.71
11204.7 1824.15
11240.8 1841.73
11277.1 1859.47
11313.4 1877.37
11349.9 1895.43
11386.5 1913.64
11423.2 1932.00
11460.0 1950.51
11497.0 1969.20
11534.1 1988.04
11571.2 2007.04
11608.6 2026.20
11646.0 2045.52
11683.5 2065.01
11721.2 2084.67
11759.0 2104.49
11796.9 2124.47
11834.9 2144.61
11873.1 2164.94
11911.4 2185.44
11949.8 2206.10
11988.3 2226.93
12026.9 2247.93
12065.7 2269.10
12104.6 2290.45
12143.7 2311.97
12182.8 2333.66
12222.1 2355.52
12261.5 2377.58
12301.0 2399.82
12340.7 2422.23
12380.5 2444.81
12420.4 2467.57
12460.4 2490.52
12500.6 2513.65
12540.9 2536.95
12581.3 2560.43
12621.9 2584.10
12662.6 2607.97
12703.4 2632.01
12744.4 2656.23
12785.5 2680.65
12826.7 2705.24
12868.0 2730.02
12909.5 2754.99
12951.1 2780.15
12992.9 2805.48
13034.8 2831.01
13076.8 2856.75
13119.0 2882.68
13161.3 2908.79
13203.7 2935.09
13246.3 2961.58
13289.0 2988.27
13331.8 3015.16
13374.8 3042.22
13417.9 3069.48
13461.2 3096.93
13504.6 3124.59
13548.1 3152.44
13591.8 3180.48
13635.6 3208.71
13679.6 3237.14
13723.7 3265.77
13767.9 3294.58
13812.3 3323.59
13856.9 3352.79
13901.5 3382.19
13946.4 3411.80
13991.3 3441.60
14036.4 3471.59
14081.7 3501.78
14127.1 3532.17
14172.6 3562.75
14218.3 3593.52
14264.2 3624.49
14310.2 3655.65
14356.3 3687.00
14402.6 3718.57
14449.0 3750.32
14495.6 3782.27
14542.3 3814.41
14589.2 3846.74
14636.2 3879.25
14683.4 3911.97
14730.8 3944.86
14778.3 3977.94
14825.9 4011.22
14873.7 4044.71
14921.7 4078.38
14969.8 4112.24
15018.0 4146.37
15066.5 4180.85
15115.0 4215.54
15163.8 4250.41
15212.7 4285.47
15261.7 4320.73
15310.9 4356.18
15360.3 4391.83
15409.8 4427.67
15459.5 4463.69
15509.3 4499.91
15559.3 4536.31
15609.5 4572.91
15659.8 4609.69
15710.3 4646.67
15761.0 4683.81
15811.8 4721.14
15862.7 4758.65
15913.9 4796.35
15965.2 4834.22
16016.7 4872.26
16068.3 4910.49
16120.1 4948.89
16172.1 4987.46
16224.2 5026.21
16276.5 5065.12
16329.0 5104.21
16381.7 5143.49
16434.5 5182.92
16487.5 5222.51
16540.6 5262.27
16593.9 5302.21
16647.4 5342.29
16701.1 5382.53
16755.0 5422.93
16809.0 5463.49
16863.2 5504.19
16917.5 5545.04
16972.1 5586.05
17026.8 5627.20
17081.7 5668.50
17136.8 5709.94
17192.0 5751.52
17247.4 5793.24
17303.1 5835.11
17358.8 5877.10
17414.8 5919.21
17470.9 5961.44
17527.3 6003.81
17583.8 6046.29
17640.5 6088.90
17697.4 6131.63
17754.4 6174.50
17811.6 6217.47
17869.1 6260.56
17926.7 6303.76
17984.5 6347.06
18042.5 6390.45
18100.6 6433.93
18159.0 6477.52
18217.5 6521.21
18276.3 6565.00
18335.2 6608.85
18394.3 6652.80
18453.6 6696.84
18513.1 6740.98
18572.8 6785.17
18632.7 6829.43
18692.8 6873.77
18753.0 6918.19
18813.5 6962.68
18874.1 7007.21
18935.0 7051.79
18996.0 7096.45
19057.3 7141.15
19118.7 7185.91
19180.4 7230.70
19242.2 7275.52
19304.2 7320.39
19366.5 7365.30
19428.9 7410.25
19491.6 7455.20
19554.4 7500.17
19617.4 7545.17
19680.7 7590.19
19744.1 7635.24
19807.8 7676.69
19871.7 7716.04
19935.7 7755.41
20000.0 7794.78
20081.3 7845.79
20162.8 7905.30
20244.8 7965.51
20327.0 8025.78
20409.6 8086.09
20492.5 8146.39
20575.8 8206.73
20659.4 8267.08
20743.3 8327.46
20827.6 8387.78
20912.2 8448.09
20997.2 8508.41
21082.5 8568.71
21168.1 8628.96
21254.1 8689.19
21340.5 8749.37
21427.2 8809.53
21514.3 8869.58
21601.7 8929.59
21689.4 8989.56
21777.6 9049.44
21866.0 9109.23
21954.9 9168.94
22044.1 9228.57
22133.6 9288.12
22223.6 9347.52
22313.9 9406.82
22404.5 9466.02
22495.5 9525.10
22586.9 9584.02
22678.7 9642.81
22770.8 9701.49
22863.4 9760.01
22956.3 9818.35
23049.5 9876.55
23143.2 9934.59
23237.2 9992.46
23331.6 10050.1
23426.4 10107.6
23521.6 10165.0
23617.1 10222.1
23713.1 10279.0
23809.4 10335.7
23906.2 10392.3
24003.3 10448.6
24100.8 10504.6
24198.7 10560.5
24297.1 10616.1
24395.8 10671.5
24494.9 10726.7
24594.4 10781.6
24694.3 10836.3
24794.7 10890.7
24895.4 10944.8
24996.6 10998.7
25098.1 11052.4
25200.1 11105.7
25302.5 11158.8
25405.3 11211.6
25508.5 11264.2
25612.1 11316.4
25716.2 11368.4
25820.7 11420.0
25925.6 11471.4
26030.9 11522.5
26136.7 11573.3
26242.9 11623.8
26349.5 11673.9
26456.5 11723.8
26564.0 11773.3
26672.0 11822.5
26780.3 11871.4
26889.1 11920.0
26998.4 11968.2
27108.1 12016.1
27218.2 12063.7
27328.8 12111.0
27439.8 12157.9
27551.3 12204.5
27663.2 12250.7
27775.6 12296.6
27888.5 12342.2
28001.8 12387.4
28115.6 12432.3
28229.8 12476.8
28344.5 12520.9
28459.6 12564.8
28575.3 12608.3
28691.4 12651.4
28807.9 12694.1
28925.0 12736.5
29042.5 12778.6
29160.5 12820.3
29279.0 12861.6
29397.9 12902.6
29517.4 12943.3
29637.3 12983.5
29757.7 13023.4
29878.6 13062.9
30000.0 13102.1

View File

@@ -1,654 +0,0 @@
4000.00 4.18514
4032.00 4.27608
4064.00 4.36835
4096.00 4.46188
4128.00 4.55672
4160.00 4.65282
4192.00 4.75023
4224.00 4.84893
4256.00 4.94900
4288.00 5.05041
4320.00 5.15311
4352.00 5.25711
4384.00 5.36245
4416.00 5.46917
4448.00 5.57723
4480.00 5.68671
4512.00 5.79754
4544.00 5.90984
4576.00 6.02351
4608.00 6.13856
4640.00 6.25497
4672.00 6.37280
4704.00 6.49212
4736.00 6.61284
4768.00 6.73496
4800.00 6.85847
4832.00 6.98349
4864.00 7.10998
4896.00 7.23792
4928.00 7.36743
4960.00 7.49840
4992.00 7.63088
5024.00 7.76488
5056.00 7.90034
5088.00 8.03728
5120.00 8.17572
5152.00 8.31572
5184.00 8.45730
5216.00 8.60040
5248.00 8.74518
5280.00 8.89151
5312.00 9.03937
5344.00 9.18870
5376.00 9.33957
5408.00 9.49208
5440.00 9.64620
5472.00 9.80192
5504.00 9.95941
5536.00 10.1185
5568.00 10.2793
5600.00 10.4416
5632.00 10.6056
5664.00 10.7712
5696.00 10.9384
5728.00 11.1073
5760.00 11.2779
5792.00 11.4503
5824.00 11.6244
5856.00 11.8001
5888.00 11.9775
5920.00 12.1565
5952.00 12.3374
5984.00 12.5200
6016.00 12.7044
6048.00 12.8905
6080.00 13.0784
6112.00 13.2679
6144.00 13.4594
6176.00 13.6526
6208.00 13.8477
6240.00 14.0445
6272.00 14.2430
6304.00 14.4433
6336.00 14.6454
6368.00 14.8494
6400.00 15.0552
6432.00 15.2628
6464.00 15.4728
6496.00 15.6846
6528.00 15.8982
6560.00 16.1135
6592.00 16.3306
6624.00 16.5496
6656.00 16.7704
6688.00 16.9930
6720.00 17.2175
6752.00 17.4439
6784.00 17.6725
6816.00 17.9030
6848.00 18.1353
6880.00 18.3699
6912.00 18.6065
6944.00 18.8451
6976.00 19.0856
7008.00 19.3280
7040.00 19.5724
7072.00 19.8187
7104.00 20.0672
7136.00 20.3177
7168.00 20.5701
7200.00 20.8246
7232.00 21.0813
7264.00 21.3400
7296.00 21.6007
7328.00 21.8635
7360.00 22.1284
7392.00 22.3954
7424.00 22.6644
7456.00 22.9356
7488.00 23.2089
7520.00 23.4843
7552.00 23.7618
7584.00 24.0416
7616.00 24.3234
7648.00 24.6073
7680.00 24.8934
7712.00 25.1819
7744.00 25.4725
7776.00 25.7652
7808.00 26.0601
7840.00 26.3574
7872.00 26.6568
7904.00 26.9584
7936.00 27.2623
7968.00 27.5685
8000.00 27.8769
8032.00 28.1875
8064.00 28.5004
8096.00 28.8157
8128.00 29.1332
8160.00 29.4529
8192.00 29.7750
8224.00 30.0995
8256.00 30.4263
8288.00 30.7553
8320.00 31.0867
8352.00 31.4206
8384.00 31.7567
8416.00 32.0952
8448.00 32.4360
8480.00 32.7795
8512.00 33.1254
8544.00 33.4736
8576.00 33.8241
8608.00 34.1772
8640.00 34.5327
8672.00 34.8906
8704.00 35.2508
8736.00 35.6136
8768.00 35.9790
8800.00 36.3468
8832.00 36.7170
8864.00 37.0896
8896.00 37.4651
8928.00 37.8431
8960.00 38.2235
8992.00 38.6063
9024.00 38.9918
9056.00 39.3799
9088.00 39.7704
9120.00 40.1635
9152.00 40.5591
9184.00 40.9576
9216.00 41.3587
9248.00 41.7624
9280.00 42.1685
9312.00 42.5773
9344.00 42.9889
9376.00 43.4031
9408.00 43.8199
9440.00 44.2392
9472.00 44.6616
9504.00 45.0866
9536.00 45.5144
9568.00 45.9447
9600.00 46.3776
9632.00 46.8134
9664.00 47.2520
9696.00 47.6933
9728.00 48.1371
9760.00 48.5836
9792.00 49.0336
9824.00 49.4863
9856.00 49.9416
9888.00 50.3996
9920.00 50.8604
9952.00 51.3245
9984.00 51.7913
10016.0 52.2608
10048.0 52.7331
10080.0 53.2082
10112.0 53.6867
10144.0 54.1679
10176.0 54.6518
10208.0 55.1386
10240.0 55.6281
10272.0 56.1213
10304.0 56.6173
10336.0 57.1161
10368.0 57.6177
10400.0 58.1222
10432.0 58.6302
10464.0 59.1412
10496.0 59.6551
10528.0 60.1718
10560.0 60.6913
10592.0 61.2144
10624.0 61.7407
10656.0 62.2698
10688.0 62.8019
10720.0 63.3370
10752.0 63.8753
10784.0 64.4172
10816.0 64.9622
10848.0 65.5099
10880.0 66.0608
10912.0 66.6146
10944.0 67.1722
10976.0 67.7332
11008.0 68.2969
11040.0 68.8638
11072.0 69.4338
11090.0 69.7556
11090.4 69.7628
11090.8 69.7700
11091.2 69.7772
11091.6 69.7843
11092.0 69.7914
11092.4 69.7986
11092.8 69.8058
11093.2 69.8130
11093.6 69.8202
11094.0 69.8273
11094.4 69.8345
11094.8 69.8417
11095.2 69.8489
11095.6 69.8561
11096.0 69.8632
11096.4 69.8704
11096.8 69.8777
11097.2 69.8849
11097.6 69.8921
11098.0 69.8992
11098.4 69.9064
11098.8 69.9136
11099.2 69.9209
11099.6 69.9280
11100.0 69.9352
11100.4 69.9424
11100.8 69.9496
11101.2 69.9569
11101.6 69.9640
11102.0 69.9712
11102.4 69.9784
11102.8 69.9857
11103.0 69.9893
11103.1 26.8271
11103.2 9.23223
11103.3 9.23243
11103.6 9.23305
11104.0 9.23389
11104.4 9.23473
11104.8 9.23557
11105.2 9.23639
11105.6 9.23724
11106.0 9.23807
11106.4 9.23891
11106.8 9.23974
11107.2 9.24058
11107.6 9.24142
11108.0 9.24226
11108.4 9.24310
11108.8 9.24392
11109.2 9.24476
11109.6 9.24560
11110.0 9.24644
11136.0 9.30092
11168.0 9.36821
11200.0 9.43583
11232.0 9.50371
11264.0 9.57189
11296.0 9.64038
11328.0 9.70916
11360.0 9.77823
11392.0 9.84760
11424.0 9.91726
11456.0 9.98722
11488.0 10.0578
11520.0 10.1286
11552.0 10.1998
11584.0 10.2712
11616.0 10.3430
11648.0 10.4151
11680.0 10.4878
11712.0 10.5608
11744.0 10.6341
11776.0 10.7077
11808.0 10.7816
11840.0 10.8559
11872.0 10.9307
11904.0 11.0059
11936.0 11.0814
11968.0 11.1572
12000.0 11.2333
12032.0 11.3098
12064.0 11.3868
12096.0 11.4641
12128.0 11.5417
12160.0 11.6197
12192.0 11.6980
12224.0 11.7767
12256.0 11.8560
12288.0 11.9356
12320.0 12.0155
12352.0 12.0958
12384.0 12.1763
12416.0 12.2573
12448.0 12.3388
12480.0 12.4206
12512.0 12.5028
12544.0 12.5853
12576.0 12.6681
12608.0 12.7513
12640.0 12.8351
12672.0 12.9192
12704.0 13.0037
12736.0 13.0885
12768.0 13.1737
12800.0 13.2592
12832.0 13.3452
12864.0 13.4316
12896.0 13.5184
12928.0 13.6056
12960.0 13.6931
12992.0 13.7809
13024.0 13.8691
13056.0 13.9580
13088.0 14.0472
13120.0 14.1368
13152.0 14.2267
13184.0 14.3170
13216.0 14.4076
13248.0 14.4987
13280.0 14.5903
13312.0 14.6823
13344.0 14.7746
13376.0 14.8673
13408.0 14.9603
13440.0 15.0537
13472.0 15.1477
13504.0 15.2421
13536.0 15.3369
13568.0 15.4321
13600.0 15.5276
13632.0 15.6235
13664.0 15.7198
13696.0 15.8166
13728.0 15.9139
13760.0 16.0115
13792.0 16.1095
13824.0 16.2079
13856.0 16.3066
13888.0 16.4057
13920.0 16.5056
13952.0 16.6057
13984.0 16.7063
14016.0 16.8072
14048.0 16.9086
14080.0 17.0102
14112.0 17.1123
14144.0 17.2151
14176.0 17.3182
14208.0 17.4217
14240.0 17.5256
14272.0 17.6298
14304.0 17.7345
14336.0 17.8395
14368.0 17.9452
14400.0 18.0513
14432.0 18.1578
14464.0 18.2648
14496.0 18.3721
14528.0 18.4797
14560.0 18.5878
14592.0 18.6965
14624.0 18.8056
14656.0 18.9151
14688.0 19.0250
14720.0 19.1353
14752.0 19.2461
14784.0 19.3572
14816.0 19.4687
14848.0 19.5810
14880.0 19.6936
14912.0 19.8067
14944.0 19.9201
14976.0 20.0340
15008.0 20.1483
15040.0 20.2629
15072.0 20.3782
15104.0 20.4940
15136.0 20.6102
15168.0 20.7268
15200.0 20.8439
15232.0 20.9613
15264.0 21.0791
15296.0 21.1974
15328.0 21.3164
15360.0 21.4357
15392.0 21.5556
15424.0 21.6758
15456.0 21.7964
15488.0 21.9174
15520.0 22.0389
15552.0 22.1609
15584.0 22.2836
15616.0 22.4066
15648.0 22.5301
15680.0 22.6540
15712.0 22.7783
15744.0 22.9031
15776.0 23.0283
15808.0 23.1540
15840.0 23.2804
15872.0 23.4071
15904.0 23.5343
15936.0 23.6620
15968.0 23.7900
16000.0 23.9185
16032.0 24.0474
16064.0 24.1769
16096.0 24.3070
16128.0 24.4375
16160.0 24.5685
16192.0 24.6998
16224.0 24.8317
16256.0 24.9640
16288.0 25.0967
16320.0 25.2300
16352.0 25.3639
16384.0 25.4983
16416.0 25.6331
16448.0 25.7683
16480.0 25.9041
16512.0 26.0402
16544.0 26.1768
16576.0 26.3140
16608.0 26.4518
16640.0 26.5901
16672.0 26.7288
16704.0 26.8680
16736.0 27.0076
16768.0 27.1477
16800.0 27.2883
16832.0 27.4292
16864.0 27.5710
16896.0 27.7132
16928.0 27.8559
16960.0 27.9990
16992.0 28.1426
17024.0 28.2867
17056.0 28.4312
17088.0 28.5762
17120.0 28.7218
17152.0 28.8680
17184.0 29.0147
17216.0 29.1619
17248.0 29.3096
17280.0 29.4577
17312.0 29.6063
17344.0 29.7553
17376.0 29.9049
17408.0 30.0551
17440.0 30.2058
17472.0 30.3571
17504.0 30.5087
17536.0 30.6609
17568.0 30.8135
17600.0 30.9667
17632.0 31.1203
17664.0 31.2744
17696.0 31.4293
17728.0 31.5847
17760.0 31.7406
17792.0 31.8969
17824.0 32.0539
17856.0 32.2112
17888.0 32.3690
17920.0 32.5274
17952.0 32.6862
17984.0 32.8457
18016.0 33.0058
18048.0 33.1663
18080.0 33.3274
18112.0 33.4889
18144.0 33.6510
18176.0 33.8135
18208.0 33.9765
18240.0 34.1400
18272.0 34.3043
18304.0 34.4691
18336.0 34.6345
18368.0 34.8003
18400.0 34.9667
18432.0 35.1335
18464.0 35.3009
18496.0 35.4688
18528.0 35.6371
18560.0 35.8062
18592.0 35.9758
18624.0 36.1461
18656.0 36.3168
18688.0 36.4880
18720.0 36.6597
18752.0 36.8320
18784.0 37.0047
18816.0 37.1780
18848.0 37.3518
18880.0 37.5264
18912.0 37.7016
18944.0 37.8772
18976.0 38.0533
19008.0 38.2300
19040.0 38.4072
19072.0 38.5849
19104.0 38.7631
19136.0 38.9418
19168.0 39.1213
19200.0 39.3014
19232.0 39.4821
19264.0 39.6633
19296.0 39.8449
19328.0 40.0272
19360.0 40.2099
19392.0 40.3932
19424.0 40.5770
19456.0 40.7613
19488.0 40.9464
19520.0 41.1321
19552.0 41.3183
19584.0 41.5051
19616.0 41.6923
19648.0 41.8801
19680.0 42.0685
19712.0 42.2573
19744.0 42.4468
19776.0 42.6368
19808.0 42.8276
19840.0 43.0190
19872.0 43.2109
19904.0 43.4034
19936.0 43.5964
19968.0 43.7899
20000.0 43.9840
20081.3 44.4794
20162.8 44.9811
20244.8 45.4884
20327.0 46.0015
20409.6 46.5203
20492.5 47.0458
20575.8 47.5773
20659.4 48.1147
20743.3 48.6582
20827.6 49.2087
20912.2 49.7653
20997.2 50.3283
21082.5 50.8976
21168.1 51.4742
21254.1 52.0573
21340.5 52.6470
21427.2 53.2434
21514.3 53.8472
21601.7 54.4579
21689.4 55.0755
21777.6 55.7001
21866.0 56.3329
21954.9 56.9726
22044.1 57.6197
22133.6 58.2743
22223.6 58.9369
22313.9 59.6071
22404.5 60.2848
22495.5 60.9705
22586.9 61.6647
22678.7 62.3667
22770.8 63.0767
22863.4 63.7950
22956.3 64.5220
23049.5 65.2573
23143.2 66.0009
23237.2 66.7533
23331.6 67.5151
23426.4 68.2854
23521.6 69.0646
23617.1 69.8528
23713.1 70.6508
23809.4 71.4578
23906.2 72.2739
24003.3 73.0998
24100.8 73.9355
24198.7 74.7810
24297.1 75.6360
24395.8 76.5011
24494.9 77.3767
24594.4 78.2624
24694.3 79.1580
24794.7 80.0644
24895.4 80.9815
24996.6 81.9092
25098.1 82.8474
25200.1 83.7969
25302.5 84.7579
25405.3 85.7297
25508.5 86.7128
25612.1 87.7077
25716.2 88.7142
25820.7 89.7324
25925.6 90.7621
26030.9 91.8045
26136.7 92.8592
26242.9 93.9258
26349.5 95.0048
26456.5 96.0966
26564.0 97.2014
26672.0 98.3188
26780.3 99.4487
26889.1 100.593
26998.4 101.750
27108.1 102.920
27218.2 104.104
27328.8 105.303
27439.8 106.515
27551.3 107.741
27663.2 108.981
27775.6 110.237
27888.5 111.507
28001.8 112.791
28115.6 114.091
28229.8 115.406
28344.5 116.736
28459.6 118.082
28575.3 119.443
28691.4 120.821
28807.9 122.214
28925.0 123.624
29042.5 125.050
29160.5 126.493
29279.0 127.953
29397.9 129.430
29517.4 130.924
29637.3 132.436
29757.7 133.965
29878.6 135.512
30000.0 137.076

View File

@@ -1,601 +0,0 @@
4000.00 9.62277
4032.00 9.83842
4064.00 10.0573
4096.00 10.2794
4128.00 10.5051
4160.00 10.7339
4192.00 10.9660
4224.00 11.2014
4256.00 11.4403
4288.00 11.6826
4320.00 11.9284
4352.00 12.1776
4384.00 12.4304
4416.00 12.6865
4448.00 12.9464
4480.00 13.2098
4512.00 13.4767
4544.00 13.7474
4576.00 14.0215
4608.00 14.2994
4640.00 14.5809
4672.00 14.8664
4704.00 15.1555
4736.00 15.4484
4768.00 15.7450
4800.00 16.0453
4832.00 16.3495
4864.00 16.6575
4896.00 16.9695
4928.00 17.2853
4960.00 17.6050
4992.00 17.9287
5024.00 18.2562
5056.00 18.5883
5088.00 18.9244
5120.00 19.2644
5152.00 19.6086
5184.00 19.9567
5216.00 20.3089
5248.00 20.6651
5280.00 21.0254
5312.00 21.3903
5344.00 21.7594
5376.00 22.1326
5408.00 22.5101
5440.00 22.8918
5472.00 23.2781
5504.00 23.6687
5536.00 24.0635
5568.00 24.4631
5600.00 24.8670
5632.00 25.2752
5664.00 25.6881
5696.00 26.1054
5728.00 26.5272
5760.00 26.9536
5792.00 27.3845
5824.00 27.8199
5856.00 28.2600
5888.00 28.7046
5920.00 29.1541
5952.00 29.6085
5984.00 30.0675
6016.00 30.5313
6048.00 31.0001
6080.00 31.4734
6112.00 31.9515
6144.00 32.4345
6176.00 32.9223
6208.00 33.4148
6240.00 33.9124
6272.00 34.4149
6304.00 34.9221
6336.00 35.4342
6368.00 35.9524
6400.00 36.4762
6432.00 37.0050
6464.00 37.5379
6496.00 38.0757
6528.00 38.6185
6560.00 39.1667
6592.00 39.7202
6624.00 40.2787
6656.00 40.8428
6688.00 41.4125
6720.00 41.9874
6752.00 42.5676
6784.00 43.1532
6816.00 43.7441
6848.00 44.3403
6880.00 44.9420
6912.00 45.5490
6944.00 46.1614
6976.00 46.7793
7008.00 47.4032
7040.00 48.0324
7072.00 48.6671
7104.00 49.3076
7136.00 49.9537
7168.00 50.6054
7200.00 51.2625
7232.00 51.9256
7264.00 52.5944
7296.00 53.2688
7328.00 53.9491
7360.00 54.6357
7392.00 55.3279
7424.00 56.0259
7456.00 56.7298
7488.00 57.4395
7520.00 58.1551
7552.00 58.8764
7584.00 59.6041
7616.00 60.3376
7648.00 61.0770
7680.00 61.8224
7712.00 62.5745
7744.00 63.3325
7776.00 64.0965
7808.00 64.8666
7840.00 65.6432
7872.00 66.4257
7904.00 67.2144
7936.00 68.0094
7968.00 68.8110
8000.00 69.6188
8032.00 70.4328
8064.00 71.2532
8096.00 72.0802
8128.00 72.9134
8160.00 73.7529
8192.00 74.5991
8224.00 75.4518
8256.00 76.3108
8288.00 77.1762
8320.00 78.0482
8352.00 78.9273
8384.00 79.8130
8416.00 80.7051
8448.00 81.6036
8480.00 82.5091
8512.00 83.4214
8544.00 84.3400
8576.00 85.2654
8608.00 86.1981
8640.00 87.1375
8672.00 88.0838
8704.00 89.0367
8736.00 89.9967
8768.00 90.9639
8800.00 91.9378
8832.00 92.9185
8864.00 93.9060
8896.00 94.9009
8928.00 95.9025
8960.00 96.9111
8992.00 97.9265
9024.00 98.9496
9056.00 99.9804
9088.00 101.018
9120.00 102.063
9152.00 103.115
9184.00 104.174
9216.00 105.240
9248.00 106.314
9280.00 107.395
9312.00 108.483
9344.00 109.578
9376.00 110.681
9408.00 111.791
9440.00 112.909
9472.00 114.034
9504.00 115.168
9536.00 116.308
9568.00 117.457
9600.00 118.612
9632.00 119.776
9664.00 120.947
9696.00 122.125
9728.00 123.311
9760.00 124.505
9792.00 125.707
9824.00 126.917
9856.00 128.134
9888.00 129.358
9920.00 130.591
9952.00 131.832
9984.00 133.080
10016.0 134.336
10048.0 135.601
10080.0 136.872
10112.0 138.154
10144.0 139.442
10176.0 140.739
10208.0 142.044
10240.0 143.356
10272.0 144.677
10304.0 146.006
10336.0 147.343
10368.0 148.687
10400.0 150.040
10432.0 151.402
10464.0 152.773
10496.0 154.152
10528.0 155.538
10560.0 156.933
10592.0 158.336
10624.0 159.748
10656.0 161.168
10688.0 162.596
10720.0 164.032
10752.0 165.477
10784.0 166.932
10816.0 168.395
10848.0 169.867
10880.0 171.346
10912.0 172.835
10944.0 174.332
10976.0 175.837
11008.0 177.351
11040.0 178.873
11072.0 180.404
11104.0 181.944
11136.0 183.494
11168.0 185.052
11200.0 186.620
11232.0 188.195
11264.0 189.780
11296.0 191.374
11328.0 192.976
11360.0 194.588
11392.0 196.209
11424.0 197.838
11456.0 199.475
11488.0 201.123
11520.0 202.780
11552.0 204.446
11584.0 206.121
11616.0 207.805
11648.0 209.497
11680.0 211.201
11712.0 212.913
11744.0 214.634
11776.0 216.365
11808.0 218.104
11840.0 219.853
11872.0 221.612
11904.0 223.381
11936.0 225.158
11968.0 226.944
12000.0 228.740
12032.0 230.545
12064.0 232.361
12096.0 234.186
12128.0 236.020
12160.0 237.864
12192.0 239.716
12224.0 241.579
12256.0 243.451
12288.0 245.333
12320.0 247.226
12352.0 249.127
12384.0 251.038
12416.0 252.958
12448.0 254.890
12480.0 256.832
12512.0 258.783
12544.0 260.744
12576.0 262.715
12608.0 264.695
12640.0 266.686
12672.0 268.687
12704.0 270.697
12736.0 272.718
12768.0 274.748
12800.0 276.788
12832.0 278.839
12864.0 280.900
12896.0 282.971
12928.0 285.053
12960.0 287.144
12992.0 289.246
13024.0 291.357
13056.0 293.479
13088.0 295.612
13120.0 297.754
13152.0 299.907
13184.0 302.069
13216.0 304.242
13248.0 306.425
13280.0 308.621
13312.0 310.827
13344.0 313.044
13376.0 315.270
13408.0 317.508
13440.0 319.755
13472.0 322.013
13504.0 324.282
13536.0 326.561
13568.0 328.850
13600.0 331.150
13632.0 333.460
13664.0 335.781
13696.0 338.114
13728.0 340.458
13760.0 342.813
13792.0 345.178
13824.0 347.554
13856.0 349.940
13888.0 352.337
13920.0 354.747
13952.0 357.167
13984.0 359.599
14016.0 362.041
14048.0 364.494
14080.0 366.957
14112.0 369.432
14144.0 371.917
14176.0 374.414
14208.0 376.922
14240.0 379.440
14272.0 381.970
14304.0 384.509
14336.0 387.061
14368.0 389.625
14400.0 392.202
14432.0 394.789
14464.0 397.388
14496.0 399.998
14528.0 402.618
14560.0 405.251
14592.0 407.895
14624.0 410.550
14656.0 413.216
14688.0 415.894
14720.0 418.584
14752.0 421.285
14784.0 423.996
14816.0 426.719
14848.0 429.456
14880.0 432.204
14912.0 434.963
14944.0 437.734
14976.0 440.516
15008.0 443.310
15040.0 446.117
15072.0 448.937
15104.0 451.769
15136.0 454.612
15168.0 457.468
15200.0 460.335
15232.0 463.213
15264.0 466.102
15296.0 469.003
15328.0 471.919
15360.0 474.845
15392.0 477.785
15424.0 480.734
15456.0 483.697
15488.0 486.670
15520.0 489.657
15552.0 492.654
15584.0 495.668
15616.0 498.692
15648.0 501.728
15680.0 504.777
15712.0 507.838
15744.0 510.910
15776.0 513.994
15808.0 517.091
15840.0 520.202
15872.0 523.325
15904.0 526.460
15936.0 529.607
15968.0 532.766
16000.0 535.937
16032.0 539.120
16064.0 542.317
16096.0 545.528
16128.0 548.751
16160.0 551.986
16192.0 555.233
16224.0 558.493
16256.0 561.765
16288.0 565.049
16320.0 568.346
16352.0 571.658
16384.0 574.983
16416.0 578.320
16448.0 581.669
16480.0 585.031
16512.0 588.405
16544.0 591.791
16576.0 595.191
16608.0 598.605
16640.0 602.032
16672.0 605.472
16704.0 608.925
16736.0 612.389
16768.0 615.866
16800.0 619.357
16832.0 622.859
16864.0 626.377
16896.0 629.907
16928.0 633.450
16960.0 637.007
16992.0 640.575
17024.0 644.157
17056.0 647.751
17088.0 651.359
17120.0 654.980
17152.0 658.617
17184.0 662.267
17216.0 665.931
17248.0 669.607
17280.0 673.296
17312.0 676.998
17344.0 680.712
17376.0 684.440
17408.0 688.184
17440.0 691.941
17472.0 695.713
17504.0 699.495
17536.0 703.292
17568.0 707.102
17600.0 710.925
17632.0 714.761
17664.0 718.610
17696.0 722.475
17728.0 726.355
17760.0 730.248
17792.0 734.153
17824.0 738.073
17856.0 742.005
17888.0 745.950
17920.0 749.909
17952.0 753.881
17984.0 757.869
18016.0 761.873
18048.0 765.889
18080.0 769.919
18112.0 773.963
18144.0 778.019
18176.0 782.090
18208.0 786.173
18240.0 790.271
18272.0 794.384
18304.0 798.512
18336.0 802.655
18368.0 806.810
18400.0 810.978
18432.0 815.161
18464.0 819.358
18496.0 823.568
18528.0 827.792
18560.0 832.031
18592.0 836.287
18624.0 840.558
18656.0 844.842
18688.0 849.140
18720.0 853.452
18752.0 857.777
18784.0 862.116
18816.0 866.467
18848.0 870.834
18880.0 875.220
18912.0 879.619
18944.0 884.030
18976.0 888.457
19008.0 892.897
19040.0 897.352
19072.0 901.820
19104.0 906.300
19136.0 910.796
19168.0 915.308
19200.0 919.837
19232.0 924.381
19264.0 928.937
19296.0 933.507
19328.0 938.093
19360.0 942.690
19392.0 947.303
19424.0 951.930
19456.0 956.571
19488.0 961.231
19520.0 965.908
19552.0 970.597
19584.0 975.302
19616.0 980.021
19648.0 984.753
19680.0 989.501
19712.0 994.261
19744.0 999.036
19776.0 1003.83
19808.0 1008.64
19840.0 1013.46
19872.0 1018.30
19904.0 1023.16
19936.0 1028.03
19968.0 1032.91
20000.0 1037.81
20081.3 1050.33
20162.8 1063.00
20244.8 1075.81
20327.0 1088.77
20409.6 1101.88
20492.5 1115.15
20575.8 1128.57
20659.4 1142.15
20743.3 1155.88
20827.6 1169.78
20912.2 1183.84
20997.2 1198.06
21082.5 1212.45
21168.1 1227.01
21254.1 1241.73
21340.5 1256.62
21427.2 1271.69
21514.3 1286.92
21601.7 1302.34
21689.4 1317.93
21777.6 1333.69
21866.0 1349.65
21954.9 1365.78
22044.1 1382.10
22133.6 1398.61
22223.6 1415.31
22313.9 1432.20
22404.5 1449.27
22495.5 1466.55
22586.9 1484.02
22678.7 1501.69
22770.8 1519.56
22863.4 1537.63
22956.3 1555.91
23049.5 1574.40
23143.2 1593.09
23237.2 1611.99
23331.6 1631.11
23426.4 1650.44
23521.6 1669.98
23617.1 1689.75
23713.1 1709.74
23809.4 1729.95
23906.2 1750.38
24003.3 1771.04
24100.8 1791.94
24198.7 1813.06
24297.1 1834.42
24395.8 1856.01
24494.9 1877.85
24594.4 1899.93
24694.3 1922.25
24794.7 1944.81
24895.4 1967.62
24996.6 1990.69
25098.1 2014.00
25200.1 2037.56
25302.5 2061.38
25405.3 2085.46
25508.5 2109.80
25612.1 2134.41
25716.2 2159.29
25820.7 2184.43
25925.6 2209.84
26030.9 2235.52
26136.7 2261.48
26242.9 2287.71
26349.5 2314.22
26456.5 2341.01
26564.0 2368.09
26672.0 2395.46
26780.3 2423.11
26889.1 2451.06
26998.4 2479.30
27108.1 2507.82
27218.2 2536.65
27328.8 2565.78
27439.8 2595.22
27551.3 2624.97
27663.2 2655.01
27775.6 2685.37
27888.5 2716.04
28001.8 2747.03
28115.6 2778.33
28229.8 2809.95
28344.5 2841.89
28459.6 2874.14
28575.3 2906.73
28691.4 2939.65
28807.9 2972.90
28925.0 3006.49
29042.5 3040.40
29160.5 3074.66
29279.0 3109.27
29397.9 3144.20
29517.4 3179.48
29637.3 3215.11
29757.7 3251.08
29878.6 3287.40
30000.0 3324.06

View File

@@ -1,689 +0,0 @@
4000.00 14.6403
4012.90 14.7694
4025.83 14.8996
4038.81 15.0310
4051.83 15.1635
4064.90 15.2972
4078.00 15.4320
4091.15 15.5680
4104.34 15.7050
4117.57 15.8433
4130.85 15.9828
4144.17 16.1237
4157.53 16.2662
4170.93 16.4100
4184.38 16.5550
4197.87 16.7012
4211.41 16.8485
4224.98 16.9972
4238.60 17.1472
4252.27 17.2985
4265.98 17.4509
4279.73 17.6047
4293.53 17.7599
4307.37 17.9166
4321.26 18.0750
4335.19 18.2347
4349.17 18.3959
4363.19 18.5586
4377.26 18.7226
4391.37 18.8881
4405.53 19.0551
4419.73 19.2235
4433.98 19.3933
4448.28 19.5646
4462.62 19.7375
4477.01 19.9119
4491.44 20.0878
4505.92 20.2653
4520.45 20.4443
4535.02 20.6251
4549.65 20.8077
4564.31 20.9919
4579.03 21.1778
4593.79 21.3654
4608.60 21.5546
4623.46 21.7455
4638.37 21.9381
4653.32 22.1324
4668.33 22.3285
4683.38 22.5262
4698.48 22.7258
4713.62 22.9271
4728.82 23.1303
4744.07 23.3353
4759.36 23.5420
4774.71 23.7507
4790.10 23.9613
4805.54 24.1737
4821.04 24.3880
4836.58 24.6042
4852.17 24.8225
4867.82 25.0427
4883.51 25.2649
4899.26 25.4891
4915.05 25.7153
4930.90 25.9436
4946.80 26.1739
4960.00 26.3662
4960.20 26.3691
4960.40 26.3720
4960.60 26.3750
4960.80 26.3779
4961.00 26.3808
4961.20 26.3837
4961.40 26.3866
4961.60 26.3896
4961.80 26.3925
4962.00 26.3954
4962.20 26.3983
4962.40 26.4012
4962.60 26.4041
4962.80 26.4071
4963.00 26.4100
4963.20 26.4129
4963.40 26.4158
4963.60 26.4188
4963.80 26.4217
4964.00 26.4246
4964.20 26.4275
4964.40 26.4304
4964.60 26.4334
4964.80 26.4363
4965.00 26.4392
4965.20 26.4421
4965.40 26.4451
4965.60 26.4480
4965.80 26.4509
4966.00 26.4539
4966.20 26.4568
4966.21 26.4570
4966.22 26.4571
4966.23 26.4573
4966.24 26.4574
4966.25 26.4576
4966.26 26.4577
4966.27 26.4579
4966.28 26.4580
4966.29 26.4581
4966.30 26.4583
4966.31 23.8848
4966.32 21.5614
4966.33 19.4639
4966.34 16.6939
4966.35 15.0697
4966.36 13.6035
4966.37 12.2799
4966.38 11.0851
4966.39 10.0065
4966.40 9.03278
4966.41 8.15382
4966.42 7.36037
4966.43 6.31256
4966.44 5.69825
4966.45 5.14372
4966.46 4.64315
4966.47 4.19129
4966.48 3.78339
4966.49 3.41519
4966.50 3.08282
4966.51 3.08283
4966.52 3.08285
4966.53 3.08287
4966.54 3.08288
4966.55 3.08290
4966.56 3.08291
4966.57 3.08293
4966.58 3.08294
4966.59 3.08296
4966.60 3.08297
4966.80 3.08327
4967.00 3.08358
4967.20 3.08388
4967.40 3.08419
4967.60 3.08449
4967.80 3.08479
4968.00 3.08510
4968.20 3.08540
4968.40 3.08570
4968.60 3.08601
4968.80 3.08631
4969.00 3.08662
4969.20 3.08692
4969.40 3.08722
4969.60 3.08753
4969.80 3.08783
4970.00 3.08814
4978.75 3.10144
4994.80 3.12596
5010.90 3.15067
5027.06 3.17557
5043.26 3.20067
5059.52 3.22597
5075.84 3.25146
5092.20 3.27716
5108.62 3.30319
5125.09 3.32942
5141.61 3.35585
5158.19 3.38250
5174.82 3.40948
5191.50 3.43668
5208.24 3.46410
5225.03 3.49173
5241.88 3.51971
5258.78 3.54792
5275.73 3.57634
5292.74 3.60500
5309.81 3.63399
5326.93 3.66323
5344.10 3.69270
5361.33 3.72241
5378.62 3.75246
5395.96 3.78276
5413.35 3.81331
5430.81 3.84410
5448.32 3.87526
5465.88 3.90668
5483.50 3.93837
5501.18 3.97031
5518.92 4.00261
5536.71 4.03521
5554.56 4.06807
5572.47 4.10120
5590.44 4.13469
5608.46 4.16849
5626.54 4.20255
5644.68 4.23691
5662.88 4.27164
5681.14 4.30669
5699.46 4.34202
5717.83 4.37766
5736.27 4.41366
5754.76 4.44998
5773.31 4.48660
5791.93 4.52352
5810.60 4.56084
5829.33 4.59850
5848.13 4.63647
5866.98 4.67476
5885.90 4.71346
5904.88 4.75253
5923.91 4.79192
5943.01 4.83164
5962.17 4.87178
5981.40 4.91229
6000.68 4.95315
6020.03 4.99434
6039.44 5.03595
6058.91 5.07795
6078.44 5.12030
6098.04 5.16301
6117.70 5.20616
6137.42 5.24972
6157.21 5.29365
6177.06 5.33794
6196.98 5.38268
6216.96 5.42785
6237.00 5.47339
6257.11 5.51932
6277.28 5.56570
6297.52 5.61256
6317.82 5.65980
6338.19 5.70744
6358.63 5.75555
6379.13 5.80417
6399.69 5.85320
6420.33 5.90263
6441.03 5.95254
6461.79 6.00294
6482.63 6.05376
6503.53 6.10501
6524.49 6.15675
6545.53 6.20899
6566.63 6.26170
6587.80 6.31484
6609.04 6.36848
6630.35 6.42265
6651.73 6.47729
6673.17 6.53239
6694.69 6.58802
6716.27 6.64423
6737.93 6.70093
6759.65 6.75810
6781.44 6.81583
6803.31 6.87416
6825.24 6.93301
6847.25 6.99235
6869.32 7.05223
6891.47 7.11270
6913.69 7.17368
6935.98 7.23521
6958.34 7.29728
6980.77 7.35997
7003.28 7.42321
7025.86 7.48699
7048.51 7.55137
7071.24 7.61644
7094.03 7.68207
7116.91 7.74827
7139.85 7.81507
7162.87 7.88255
7185.96 7.95061
7209.13 8.01927
7232.38 8.08853
7255.69 8.15854
7279.09 8.22916
7302.55 8.30039
7326.10 8.37226
7349.72 8.44491
7373.41 8.51819
7397.19 8.59211
7421.03 8.66669
7444.96 8.74202
7468.96 8.81801
7493.04 8.89466
7517.20 8.97199
7541.44 9.05018
7565.75 9.12905
7590.14 9.20861
7614.62 9.28887
7639.17 9.36994
7663.79 9.45172
7688.50 9.53421
7713.29 9.61744
7738.16 9.70154
7763.11 9.78637
7788.14 9.87195
7813.25 9.95827
7838.44 10.0456
7863.71 10.1336
7889.06 10.2224
7914.50 10.3120
7940.01 10.4025
7965.61 10.4937
7991.29 10.5858
8017.06 10.6786
8042.91 10.7726
8068.84 10.8674
8094.85 10.9630
8120.95 11.0595
8147.13 11.1570
8173.40 11.2553
8199.75 11.3545
8226.19 11.4546
8252.71 11.5557
8279.32 11.6578
8306.01 11.7607
8332.79 11.8646
8359.65 11.9695
8386.60 12.0754
8413.64 12.1822
8440.77 12.2900
8467.98 12.3988
8495.29 12.5087
8522.67 12.6195
8550.15 12.7312
8577.72 12.8441
8605.37 12.9580
8633.12 13.0730
8660.95 13.1889
8688.87 13.3061
8716.89 13.4244
8744.99 13.5438
8773.19 13.6643
8801.47 13.7858
8829.85 13.9084
8858.32 14.0320
8886.88 14.1568
8915.53 14.2830
8944.27 14.4105
8973.11 14.5392
9002.04 14.6689
9031.06 14.7999
9060.18 14.9320
9089.39 15.0654
9118.69 15.1999
9148.09 15.3357
9177.59 15.4728
9207.18 15.6112
9236.86 15.7509
9266.64 15.8917
9296.52 16.0339
9326.49 16.1773
9356.56 16.3221
9386.72 16.4684
9416.99 16.6162
9447.35 16.7655
9477.81 16.9160
9508.37 17.0680
9539.02 17.2213
9569.78 17.3760
9600.63 17.5322
9631.58 17.6897
9662.63 17.8488
9693.79 18.0092
9725.04 18.1712
9756.39 18.3347
9787.85 18.4999
9819.41 18.6666
9851.07 18.8348
9882.83 19.0044
9914.69 19.1758
9946.65 19.3488
9978.72 19.5234
10010.9 19.6996
10043.2 19.8773
10075.5 20.0569
10108.0 20.2382
10140.6 20.4211
10173.3 20.6057
10206.1 20.7920
10239.0 20.9800
10272.0 21.1700
10305.2 21.3616
10338.4 21.5550
10371.7 21.7500
10405.1 21.9471
10438.7 22.1461
10472.3 22.3469
10506.1 22.5495
10540.0 22.7540
10574.0 22.9605
10608.1 23.1689
10642.3 23.3792
10676.6 23.5915
10711.0 23.8057
10745.5 24.0220
10780.2 24.2404
10814.9 24.4608
10849.8 24.6833
10884.8 24.9077
10919.9 25.1343
10955.1 25.3632
10990.4 25.5942
11025.8 25.8273
11061.4 26.0625
11097.0 26.3000
11132.8 26.5398
11168.7 26.7818
11204.7 27.0260
11240.8 27.2724
11277.1 27.5212
11313.4 27.7726
11349.9 28.0262
11386.5 28.2822
11423.2 28.5405
11460.0 28.8013
11497.0 29.0646
11534.1 29.3304
11571.2 29.5985
11608.6 29.8691
11646.0 30.1424
11683.5 30.4183
11721.2 30.6966
11759.0 30.9775
11796.9 31.2610
11834.9 31.5474
11873.1 31.8366
11911.4 32.1285
11949.8 32.4231
11988.3 32.7203
12026.9 33.0205
12065.7 33.3236
12104.6 33.6295
12143.7 33.9381
12182.8 34.2496
12222.1 34.5641
12261.5 34.8817
12301.0 35.2022
12340.7 35.5256
12380.5 35.8520
12420.4 36.1816
12460.4 36.5144
12500.6 36.8503
12540.9 37.1892
12581.3 37.5312
12621.9 37.8768
12662.6 38.2256
12703.4 38.5776
12744.4 38.9329
12785.5 39.2915
12826.7 39.6536
12868.0 40.0192
12909.5 40.3881
12951.1 40.7605
12992.9 41.1363
13034.8 41.5159
13076.8 41.8991
13119.0 42.2859
13161.3 42.6762
13203.7 43.0702
13246.3 43.4679
13289.0 43.8695
13331.8 44.2748
13374.8 44.6838
13417.9 45.0965
13461.2 45.5134
13504.6 45.9344
13548.1 46.3592
13591.8 46.7880
13635.6 47.2206
13679.6 47.6577
13723.7 48.0990
13767.9 48.5443
13812.3 48.9937
13856.9 49.4473
13901.5 49.9055
13946.4 50.3679
13991.3 50.8346
14036.4 51.3056
14081.7 51.7811
14127.1 52.2613
14172.6 52.7460
14218.3 53.2352
14264.2 53.7291
14310.2 54.2274
14356.3 54.7308
14402.6 55.2389
14449.0 55.7517
14495.6 56.2693
14542.3 56.7917
14589.2 57.3192
14636.2 57.8518
14683.4 58.3893
14730.8 58.9317
14778.3 59.4792
14825.9 60.0323
14873.7 60.5908
14921.7 61.1543
14969.8 61.7231
15018.0 62.2972
15066.5 62.8770
15115.0 63.4622
15163.8 64.0528
15212.7 64.6489
15261.7 65.2506
15310.9 65.8585
15360.3 66.4721
15409.8 67.0915
15459.5 67.7166
15509.3 68.3476
15559.3 68.9847
15609.5 69.6277
15659.8 70.2767
15710.3 70.9319
15761.0 71.5930
15811.8 72.2610
15862.7 72.9353
15913.9 73.6160
15965.2 74.3028
16016.7 74.9961
16068.3 75.6963
16120.1 76.4033
16172.1 77.1167
16224.2 77.8368
16276.5 78.5635
16329.0 79.2975
16381.7 80.0384
16434.5 80.7861
16487.5 81.5408
16540.6 82.3025
16593.9 83.0723
16647.4 83.8492
16701.1 84.6333
16755.0 85.4248
16809.0 86.2237
16863.2 87.0304
16917.5 87.8445
16972.1 88.6662
17026.8 89.4956
17081.7 90.3328
17136.8 91.1786
17192.0 92.0322
17247.4 92.8938
17303.1 93.7636
17358.8 94.6414
17414.8 95.5282
17470.9 96.4233
17527.3 97.3269
17583.8 98.2387
17640.5 99.1590
17697.4 100.088
17754.4 101.027
17811.6 101.973
17869.1 102.929
17926.7 103.893
17984.5 104.868
18042.5 105.852
18100.6 106.844
18159.0 107.846
18217.5 108.858
18276.3 109.879
18335.2 110.911
18394.3 111.951
18453.6 113.002
18513.1 114.062
18572.8 115.133
18632.7 116.214
18692.8 117.305
18753.0 118.406
18813.5 119.518
18874.1 120.640
18935.0 121.773
18996.0 122.917
19057.3 124.071
19118.7 125.236
19180.4 126.413
19242.2 127.601
19304.2 128.800
19366.5 130.010
19428.9 131.232
19491.6 132.465
19554.4 133.710
19617.4 134.967
19680.7 136.235
19744.1 137.516
19807.8 138.809
19871.7 140.115
19935.7 141.432
20000.0 142.762
20081.3 144.456
20162.8 146.170
20244.8 147.905
20327.0 149.660
20409.6 151.436
20492.5 153.234
20575.8 155.052
20659.4 156.892
20743.3 158.755
20827.6 160.641
20912.2 162.549
20997.2 164.479
21082.5 166.432
21168.1 168.409
21254.1 170.409
21340.5 172.433
21427.2 174.481
21514.3 176.554
21601.7 178.652
21689.4 180.774
21777.6 182.922
21866.0 185.095
21954.9 187.294
22044.1 189.520
22133.6 191.772
22223.6 194.051
22313.9 196.357
22404.5 198.690
22495.5 201.051
22586.9 203.441
22678.7 205.858
22770.8 208.305
22863.4 210.781
22956.3 213.287
23049.5 215.822
23143.2 218.387
23237.2 220.984
23331.6 223.611
23426.4 226.269
23521.6 228.958
23617.1 231.679
23713.1 234.433
23809.4 237.220
23906.2 240.038
24003.3 242.892
24100.8 245.779
24198.7 248.701
24297.1 251.656
24395.8 254.648
24494.9 257.675
24594.4 260.737
24694.3 263.835
24794.7 266.971
24895.4 270.144
24996.6 273.355
25098.1 276.603
25200.1 279.890
25302.5 283.216
25405.3 286.580
25508.5 289.984
25612.1 293.430
25716.2 296.915
25820.7 300.442
25925.6 304.009
26030.9 307.621
26136.7 311.275
26242.9 314.971
26349.5 318.710
26456.5 322.494
26564.0 326.323
26672.0 330.195
26780.3 334.113
26889.1 338.079
26998.4 342.092
27108.1 346.150
27218.2 350.256
27328.8 354.412
27439.8 358.616
27551.3 362.869
27663.2 367.171
27775.6 371.526
27888.5 375.930
28001.8 380.385
28115.6 384.893
28229.8 389.455
28344.5 394.070
28459.6 398.738
28575.3 403.460
28691.4 408.239
28807.9 413.071
28925.0 417.960
29042.5 422.906
29160.5 427.911
29279.0 432.974
29397.9 438.094
29517.4 443.275
29637.3 448.518
29757.7 453.821
29878.6 459.184
30000.0 464.610

View File

@@ -1,901 +0,0 @@
4000.00 1.79125
4012.90 1.80643
4025.83 1.82173
4038.81 1.83717
4051.83 1.85277
4064.90 1.86850
4078.00 1.88436
4091.15 1.90036
4104.34 1.91650
4117.57 1.93280
4130.85 1.94923
4144.17 1.96581
4157.53 1.98253
4170.93 1.99939
4184.38 2.01642
4197.87 2.03360
4211.41 2.05093
4224.98 2.06840
4238.60 2.08602
4252.27 2.10383
4265.98 2.12178
4279.73 2.13989
4293.53 2.15815
4307.37 2.17657
4321.26 2.19517
4335.19 2.21393
4349.17 2.23286
4363.19 2.25194
4377.26 2.27119
4391.37 2.29064
4405.53 2.31025
4419.73 2.33003
4433.98 2.34998
4448.28 2.37011
4462.62 2.39043
4477.01 2.41092
4491.44 2.43159
4505.92 2.45244
4520.45 2.47347
4535.02 2.49471
4549.65 2.51612
4564.31 2.53773
4579.03 2.55951
4593.79 2.58150
4608.60 2.60369
4623.46 2.62608
4638.37 2.64865
4653.32 2.67143
4668.33 2.69441
4683.38 2.71761
4698.48 2.74101
4713.62 2.76461
4728.82 2.78842
4744.07 2.81244
4759.36 2.83669
4774.71 2.86115
4790.10 2.88582
4805.54 2.91070
4821.04 2.93581
4836.58 2.96115
4852.17 2.98672
4867.82 3.01250
4883.51 3.03851
4899.26 3.06475
4915.05 3.09123
4930.90 3.11795
4946.80 3.14490
4962.75 3.17208
4978.75 3.19950
4994.80 3.22719
5010.90 3.25511
5027.06 3.28328
5043.26 3.31169
5059.52 3.34036
5075.84 3.36930
5092.20 3.39849
5108.62 3.42794
5125.09 3.45764
5141.61 3.48761
5158.19 3.51787
5174.82 3.54839
5191.50 3.57918
5208.24 3.61023
5225.03 3.64156
5241.88 3.67318
5258.78 3.70507
5275.73 3.73723
5292.74 3.76968
5309.81 3.80242
5326.93 3.83547
5344.10 3.86881
5361.33 3.90244
5378.62 3.93635
5395.96 3.97058
5413.35 4.00513
5430.81 4.03998
5448.32 4.07513
5465.88 4.11059
5483.50 4.14637
5501.18 4.18249
5518.92 4.21891
5536.71 4.25566
5554.56 4.29272
5572.47 4.33013
5590.44 4.36787
5608.46 4.40593
5626.54 4.44433
5644.68 4.48307
5662.88 4.52218
5681.14 4.56165
5699.46 4.60148
5717.83 4.64165
5736.27 4.68217
5754.76 4.72305
5773.31 4.76428
5791.93 4.80589
5810.60 4.84784
5829.33 4.89016
5848.13 4.93287
5866.98 4.97599
5885.90 5.01947
5904.88 5.06333
5923.91 5.10757
5943.01 5.15223
5962.17 5.19730
5981.40 5.24277
6000.68 5.28863
6020.03 5.33489
6039.44 5.38159
6058.91 5.42870
6078.44 5.47622
6098.04 5.52416
6117.70 5.57253
6137.42 5.62133
6157.21 5.67057
6177.06 5.72025
6196.98 5.77036
6216.96 5.82091
6237.00 5.87193
6257.11 5.92342
6277.28 5.97537
6297.52 6.02778
6317.82 6.08064
6338.19 6.13398
6358.63 6.18781
6379.13 6.24212
6399.69 6.29691
6420.33 6.35217
6441.03 6.40791
6461.79 6.46416
6482.63 6.52088
6503.53 6.57811
6524.49 6.63584
6545.53 6.69413
6566.63 6.75299
6587.80 6.81235
6609.04 6.87223
6630.35 6.93264
6651.73 6.99358
6673.17 7.05504
6694.69 7.11704
6716.27 7.17959
6737.93 7.24269
6759.65 7.30638
6781.44 7.37065
6803.31 7.43548
6825.24 7.50090
6847.25 7.56688
6869.32 7.63346
6891.47 7.70065
6913.69 7.76843
6935.98 7.83682
6958.34 7.90580
6980.77 7.97541
7003.28 8.04564
7025.86 8.11651
7048.51 8.18798
7071.24 8.26009
7094.03 8.33285
7116.91 8.40627
7139.85 8.48033
7162.87 8.55504
7185.96 8.63041
7209.13 8.70650
7232.38 8.78327
7255.69 8.86073
7279.09 8.93886
7302.55 9.01770
7326.10 9.09719
7349.72 9.17737
7373.41 9.25825
7397.19 9.33986
7421.03 9.42219
7444.96 9.50534
7468.96 9.58928
7493.04 9.67395
7517.20 9.75939
7541.44 9.84557
7565.75 9.93250
7590.14 10.0202
7614.62 10.1087
7639.17 10.1979
7663.79 10.2880
7688.50 10.3788
7713.29 10.4705
7738.16 10.5630
7763.11 10.6563
7788.14 10.7505
7813.25 10.8454
7838.44 10.9412
7863.71 11.0378
7889.06 11.1352
7914.50 11.2336
7940.01 11.3329
7965.61 11.4331
7991.29 11.5342
8017.06 11.6362
8042.91 11.7391
8068.84 11.8430
8094.85 11.9478
8120.95 12.0536
8147.13 12.1603
8173.40 12.2679
8199.75 12.3765
8226.19 12.4860
8252.71 12.5964
8279.32 12.7079
8306.01 12.8204
8332.79 12.9337
8359.65 13.0481
8386.60 13.1635
8413.64 13.2799
8440.77 13.3973
8467.98 13.5160
8495.29 13.6358
8522.67 13.7566
8550.15 13.8785
8577.72 14.0015
8605.37 14.1256
8633.12 14.2508
8660.95 14.3771
8688.87 14.5045
8716.89 14.6331
8744.99 14.7628
8773.19 14.8936
8801.47 15.0255
8829.85 15.1586
8858.32 15.2930
8886.88 15.4285
8915.53 15.5652
8944.27 15.7032
8973.11 15.8424
9002.04 15.9828
9031.06 16.1245
9060.18 16.2675
9089.39 16.4118
9118.69 16.5574
9148.09 16.7043
9177.59 16.8524
9207.18 17.0019
9236.86 17.1527
9266.64 17.3049
9296.52 17.4583
9326.49 17.6133
9356.56 17.7696
9386.72 17.9273
9416.99 18.0864
9447.35 18.2469
9477.81 18.4089
9508.37 18.5722
9539.02 18.7371
9569.78 18.9033
9600.63 19.0711
9631.58 19.2404
9662.63 19.4113
9693.79 19.5836
9725.04 19.7575
9756.39 19.9329
9787.85 20.1100
9819.41 20.2886
9851.07 20.4689
9882.83 20.6507
9914.69 20.8342
9946.65 21.0193
9978.72 21.2060
10010.9 21.3945
10043.2 21.5845
10075.5 21.7763
10108.0 21.9698
10140.6 22.1651
10173.3 22.3620
10206.1 22.5607
10239.0 22.7612
10272.0 22.9635
10305.2 23.1677
10338.4 23.3736
10371.7 23.5814
10405.1 23.7910
10438.7 24.0026
10472.3 24.2160
10506.1 24.4312
10540.0 24.6484
10574.0 24.8676
10608.1 25.0887
10642.3 25.3119
10676.6 25.5370
10711.0 25.7642
10745.5 25.9933
10780.2 26.2246
10814.9 26.4579
10849.8 26.6933
10884.8 26.9308
10919.9 27.1703
10955.1 27.4121
10990.4 27.6560
11025.8 27.9021
11061.4 28.1503
11097.0 28.4008
11132.8 28.6537
11168.7 28.9088
11204.7 29.1662
11240.8 29.4259
11277.1 29.6879
11313.4 29.9523
11349.9 30.2190
11386.5 30.4880
11423.2 30.7595
11460.0 31.0334
11497.0 31.3098
11534.1 31.5887
11571.2 31.8700
11608.6 32.1539
11646.0 32.4403
11683.5 32.7293
11721.2 33.0208
11759.0 33.3149
11796.9 33.6117
11834.9 33.9111
11873.1 34.2133
11911.4 34.5182
11949.8 34.8259
11988.3 35.1362
12026.9 35.4493
12065.7 35.7652
12104.6 36.0840
12143.7 36.4055
12182.8 36.7300
12222.1 37.0573
12261.5 37.3877
12301.0 37.7211
12340.7 38.0574
12380.5 38.3967
12420.4 38.7391
12460.4 39.0846
12500.6 39.4331
12540.9 39.7847
12581.3 40.1394
12621.9 40.4974
12662.6 40.8587
12703.4 41.2232
12744.4 41.5910
12785.5 41.9621
12826.7 42.3364
12868.0 42.7141
12909.5 43.0951
12951.1 43.4795
12992.9 43.8674
13034.8 44.2587
13076.8 44.6538
13119.0 45.0524
13161.3 45.4547
13203.7 45.8604
13246.3 46.2698
13289.0 46.6829
13331.8 47.0997
13374.8 47.5201
13417.9 47.9443
13461.2 48.3724
13504.6 48.8045
13548.1 49.2404
13591.8 49.6802
13635.6 50.1239
13679.6 50.5715
13723.7 51.0233
13767.9 51.4790
13812.3 51.9388
13856.9 52.4027
13901.5 52.8708
13946.4 53.3433
13991.3 53.8201
14036.4 54.3010
14081.7 54.7863
14127.1 55.2759
14172.6 55.7700
14218.3 56.2685
14264.2 56.7715
14310.2 57.2788
14356.3 57.7909
14402.6 58.3077
14449.0 58.8292
14495.6 59.3554
14542.3 59.8861
14589.2 60.4216
14636.2 60.9620
14683.4 61.5072
14730.8 62.0572
14778.3 62.6121
14825.9 63.1721
14873.7 63.7375
14921.7 64.3078
14969.8 64.8832
15018.0 65.4638
15066.5 66.0497
15115.0 66.6410
15163.8 67.2375
15212.7 67.8394
15261.7 68.4467
15310.9 69.0595
15360.3 69.6780
15409.8 70.3020
15459.5 70.9316
15509.3 71.5669
15559.3 72.2079
15609.5 72.8549
15659.8 73.5076
15710.3 74.1663
15761.0 74.8307
15811.8 75.5011
15862.7 76.1778
15913.9 76.8606
15965.2 77.5494
16016.7 78.2443
16068.3 78.9456
16120.1 79.6534
16172.1 80.3674
16224.2 81.0878
16276.5 81.8145
16329.0 82.5481
16381.7 83.2888
16434.5 84.0359
16487.5 84.7897
16540.6 85.5502
16593.9 86.3179
16647.4 87.0925
16701.1 87.8740
16755.0 88.6625
16809.0 89.4582
16863.2 90.2611
16917.5 91.0715
16972.1 91.8892
17026.8 92.7141
17081.7 93.5466
17136.8 94.3866
17192.0 95.2345
17247.4 96.0899
17303.1 96.9532
17358.8 97.8239
17414.8 98.7027
17470.9 99.5896
17527.3 100.485
17583.8 101.387
17640.5 102.298
17697.4 103.218
17754.4 104.146
17811.6 105.082
17869.1 106.027
17926.7 106.980
17984.0 107.934
17984.1 107.936
17984.2 107.938
17984.3 107.939
17984.4 107.941
17984.5 107.943
17984.6 107.944
17984.7 107.946
17984.8 107.948
17984.9 107.949
17985.0 107.951
17985.1 107.953
17985.2 107.954
17985.3 107.956
17985.4 107.958
17985.5 107.959
17985.6 107.961
17985.7 107.963
17985.8 107.964
17985.9 107.966
17986.0 107.968
17986.1 107.969
17986.2 107.971
17986.3 107.973
17986.4 107.974
17986.5 107.976
17986.6 107.978
17986.7 107.979
17986.8 107.981
17986.9 107.983
17987.0 107.984
17987.1 107.986
17987.2 107.988
17987.3 107.989
17987.4 107.991
17987.5 107.993
17987.6 107.994
17987.7 107.996
17987.8 107.998
17987.9 107.999
17988.0 108.001
17988.1 108.003
17988.2 108.004
17988.3 108.006
17988.4 108.008
17988.5 108.009
17988.6 108.011
17988.7 108.013
17988.8 108.014
17988.9 108.016
17989.0 108.018
17989.1 108.019
17989.2 108.021
17989.3 108.023
17989.4 108.024
17989.5 108.026
17989.6 108.028
17989.7 108.029
17989.8 108.031
17989.9 108.033
17990.0 108.034
17990.1 108.036
17990.2 108.038
17990.3 108.039
17990.4 108.041
17990.5 108.043
17990.6 108.044
17990.7 108.046
17990.8 108.048
17990.9 108.049
17991.0 108.051
17991.1 108.053
17991.2 108.054
17991.3 108.056
17991.4 108.058
17991.5 108.059
17991.6 108.061
17991.7 108.063
17991.8 108.064
17991.9 108.066
17992.0 108.068
17992.1 108.069
17992.2 108.071
17992.3 108.073
17992.4 108.074
17992.5 108.076
17992.6 108.078
17992.7 108.079
17992.8 108.081
17992.9 108.083
17993.0 108.084
17993.1 108.086
17993.2 108.088
17993.3 108.089
17993.4 108.091
17993.5 108.093
17993.6 108.094
17993.7 108.096
17993.8 108.098
17993.9 108.099
17994.0 108.101
17994.1 108.103
17994.2 108.105
17994.3 108.106
17994.4 108.108
17994.5 108.109
17994.6 108.111
17994.7 108.113
17994.8 108.115
17994.9 108.116
17995.0 108.118
17995.1 108.119
17995.2 108.121
17995.3 108.123
17995.4 108.125
17995.5 108.126
17995.6 108.128
17995.7 108.130
17995.8 108.131
17995.9 108.133
17996.0 108.134
17996.1 108.136
17996.2 108.138
17996.3 108.140
17996.4 108.141
17996.5 108.143
17996.6 108.144
17996.7 108.146
17996.8 108.148
17996.9 108.150
17997.0 108.151
17997.1 108.153
17997.2 108.155
17997.3 108.156
17997.4 108.158
17997.5 108.160
17997.6 41.5713
17997.7 15.9385
17997.8 15.9387
17997.9 15.9389
17998.0 15.9391
17998.1 15.9394
17998.2 15.9396
17998.3 15.9398
17998.4 15.9400
17998.5 15.9403
17998.6 15.9405
17998.7 15.9407
17998.8 15.9410
17998.9 15.9412
17999.0 15.9414
17999.1 15.9416
17999.2 15.9419
17999.3 15.9421
17999.4 15.9423
17999.5 15.9425
17999.6 15.9427
17999.7 15.9430
17999.8 15.9432
17999.9 15.9434
18000.0 15.9437
18000.1 15.9439
18000.2 15.9441
18000.3 15.9443
18000.4 15.9446
18000.5 15.9448
18000.6 15.9450
18000.7 15.9452
18000.8 15.9455
18000.9 15.9457
18001.0 15.9459
18001.1 15.9461
18001.2 15.9463
18001.3 15.9466
18001.4 15.9468
18001.5 15.9470
18001.6 15.9473
18001.7 15.9475
18001.8 15.9477
18001.9 15.9479
18002.0 15.9482
18002.1 15.9484
18002.2 15.9486
18002.3 15.9489
18002.4 15.9491
18002.5 15.9493
18002.6 15.9495
18002.7 15.9497
18002.8 15.9500
18002.9 15.9502
18003.0 15.9504
18003.1 15.9506
18003.2 15.9509
18003.3 15.9511
18003.4 15.9513
18003.5 15.9515
18003.6 15.9518
18003.7 15.9520
18003.8 15.9522
18003.9 15.9525
18004.0 15.9527
18004.1 15.9529
18004.2 15.9531
18004.3 15.9534
18004.4 15.9536
18004.5 15.9538
18004.6 15.9540
18004.7 15.9542
18004.8 15.9545
18004.9 15.9547
18005.0 15.9549
18005.1 15.9552
18005.2 15.9554
18005.3 15.9556
18005.4 15.9558
18005.5 15.9561
18005.6 15.9563
18005.7 15.9565
18005.8 15.9567
18005.9 15.9570
18006.0 15.9572
18006.1 15.9574
18006.2 15.9576
18006.3 15.9579
18006.4 15.9581
18006.5 15.9583
18006.6 15.9585
18006.7 15.9588
18006.8 15.9590
18006.9 15.9592
18007.0 15.9594
18007.1 15.9597
18007.2 15.9599
18007.3 15.9601
18007.4 15.9604
18007.5 15.9606
18007.6 15.9608
18007.7 15.9610
18007.8 15.9613
18007.9 15.9615
18008.0 15.9617
18008.1 15.9619
18008.2 15.9621
18008.3 15.9624
18008.4 15.9626
18008.5 15.9628
18008.6 15.9631
18008.7 15.9633
18008.8 15.9635
18008.9 15.9637
18009.0 15.9640
18009.1 15.9642
18009.2 15.9644
18009.3 15.9646
18009.4 15.9649
18009.5 15.9651
18009.6 15.9653
18009.7 15.9655
18009.8 15.9658
18009.9 15.9660
18010.0 15.9662
18010.1 15.9664
18010.2 15.9667
18010.3 15.9669
18010.4 15.9671
18010.5 15.9673
18010.6 15.9676
18010.7 15.9678
18010.8 15.9680
18010.9 15.9683
18011.0 15.9685
18011.1 15.9687
18011.2 15.9689
18011.3 15.9692
18011.4 15.9694
18011.5 15.9696
18011.6 15.9698
18011.7 15.9700
18011.8 15.9703
18011.9 15.9705
18012.0 15.9707
18012.1 15.9709
18012.2 15.9712
18012.3 15.9714
18012.4 15.9716
18012.5 15.9719
18012.6 15.9721
18012.7 15.9723
18012.8 15.9725
18012.9 15.9728
18013.0 15.9730
18013.1 15.9732
18013.2 15.9735
18013.3 15.9737
18013.4 15.9739
18013.5 15.9741
18013.6 15.9743
18013.7 15.9746
18013.8 15.9748
18013.9 15.9750
18014.0 15.9752
18042.5 16.0396
18100.6 16.1715
18159.0 16.3045
18217.5 16.4386
18276.3 16.5738
18335.2 16.7101
18394.3 16.8475
18453.6 16.9861
18513.1 17.1258
18572.8 17.2670
18632.7 17.4095
18692.8 17.5533
18753.0 17.6983
18813.5 17.8444
18874.1 17.9921
18935.0 18.1412
18996.0 18.2916
19057.3 18.4432
19118.7 18.5961
19180.4 18.7506
19242.2 18.9066
19304.2 19.0639
19366.5 19.2225
19428.9 19.3824
19491.6 19.5440
19554.4 19.7072
19617.4 19.8717
19680.7 20.0376
19744.1 20.2048
19807.8 20.3739
19871.7 20.5446
19935.7 20.7167
20000.0 20.8903
20081.3 21.1110
20162.8 21.3347
20244.8 21.5609
20327.0 21.7894
20409.6 22.0204
20492.5 22.2546
20575.8 22.4913
20659.4 22.7305
20743.3 22.9722
20827.6 23.2173
20912.2 23.4650
20997.2 23.7153
21082.5 23.9683
21168.1 24.2248
21254.1 24.4840
21340.5 24.7460
21427.2 25.0109
21514.3 25.2792
21601.7 25.5505
21689.4 25.8246
21777.6 26.1018
21866.0 26.3827
21954.9 26.6666
22044.1 26.9536
22133.6 27.2438
22223.6 27.5378
22313.9 27.8350
22404.5 28.1354
22495.5 28.4392
22586.9 28.7469
22678.7 29.0579
22770.8 29.3723
22863.4 29.6904
22956.3 30.0124
23049.5 30.3380
23143.2 30.6670
23237.2 30.9999
23331.6 31.3370
23426.4 31.6777
23521.6 32.0221
23617.1 32.3705
23713.1 32.7234
23809.4 33.0801
23906.2 33.4407
24003.3 33.8055
24100.8 34.1749
24198.7 34.5483
24297.1 34.9258
24395.8 35.3077
24494.9 35.6943
24594.4 36.0851
24694.3 36.4802
24794.7 36.8800
24895.4 37.2846
24996.6 37.6937
25098.1 38.1073
25200.1 38.5259
25302.5 38.9496
25405.3 39.3779
25508.5 39.8109
25612.1 40.2493
25716.2 40.6927
25820.7 41.1411
25925.6 41.5944
26030.9 42.0533
26136.7 42.5177
26242.9 42.9871
26349.5 43.4618
26456.5 43.9422
26564.0 44.4283
26672.0 44.9197
26780.3 45.4165
26889.1 45.9195
26998.4 46.4284
27108.1 46.9428
27218.2 47.4630
27328.8 47.9896
27439.8 48.5223
27551.3 49.0609
27663.2 49.6054
27775.6 50.1569
27888.5 50.7146
28001.8 51.2787
28115.6 51.8489
28229.8 52.4262
28344.5 53.0102
28459.6 53.6005
28575.3 54.1975
28691.4 54.8021
28807.9 55.4134
28925.0 56.0316
29042.5 56.6567
29160.5 57.2896
29279.0 57.9297
29397.9 58.5769
29517.4 59.2313
29637.3 59.8941
29757.7 60.5643
29878.6 61.2421
30000.0 61.9272

View File

@@ -1,672 +0,0 @@
"""
cSAXS exposure-box filter transmission utilities.
This method has been created based on previous spec implementations
The translation was mainly done by copilot AI.
Implements fil_trans physics:
- Per-material attenuation-length tables loaded from package 'filter_data/'.
- Linear interpolation of attenuation length vs. energy (eV).
- Transmission T = exp(-t / lambda), t in micrometers.
- Enumeration of all enabled combinations across 4 units x 6 positions.
- Selection of the combination with transmission closest to a target.
Motion is executed using provided position tables for each filter_array_*_x stage.
"""
#todo
#check dmm is off
#X12SA-OP-DMM-EMLS-3010:THRU translation THROUGH
#X12SA-OP-DMM-EMLS-3030:THRU bragg through
#X12SA-OP-CCM1:ENERGY-GET > 1
from __future__ import annotations
import math
from typing import Dict, List, Optional, Tuple
from importlib import resources
# Resolve the filter_data/ folder via importlib.resources
import csaxs_bec.bec_ipython_client.plugins.cSAXS.filter_transmission as ft_pkg
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_get
from bec_lib import bec_logger
import builtins
if builtins.__dict__.get("bec") is not None:
bec = builtins.__dict__.get("bec")
dev = builtins.__dict__.get("dev")
umv = builtins.__dict__.get("umv")
umvr = builtins.__dict__.get("umvr")
class cSAXSFilterTransmission:
"""
Mixin providing the fil_trans command.
Assumes self.client and self.OMNYTools exist.
Example:
csaxs.fil_trans(0.10, energy_kev=6.2) # dry-run first, then asks to execute
"""
# -----------------------------
# Material naming & file mapping
# -----------------------------
_MATERIAL_FILES: Dict[str, Optional[str]] = {
"none": None,
"diam": "filter_attenuation-length_diamond.txt",
"al": "filter_attenuation-length_al.txt",
"si": "filter_attenuation-length_si.txt",
"ti": "filter_attenuation-length_ti.txt",
"cu": "filter_attenuation-length_cu.txt",
"ge": "filter_attenuation-length_ge.txt",
"zr": "filter_attenuation-length_zr.txt",
# optional; provide file if you enable Fe5
"fe": "filter_attenuation-length_fe.txt",
}
# -----------------------------------------
# Exposure-box filter configuration (4 x 6)
#
# Current hardware (per your message):
# Unit 1 (filter_array_1_x): out, Si400, Ge300, Ti800, Zr20
# Unit 2 (filter_array_2_x): out, Si200, Si3200, Ti400, Cu20
# Unit 3 (filter_array_3_x): out, Si100, Si1600, Ti200, Ti3200, Fe5
# Unit 4 (filter_array_4_x): out, Si50, Si800, Ti100, Ti1600, Ti20
#
# Positions 1..6 = [out, m1, m2, m3, m4, m5]
# Each entry: ((mat1, th1_um), (mat2, th2_um), enabled_bool)
# -----------------------------------------
_FILTERS: List[Tuple[Tuple[str, float], Tuple[str, float], bool]] = [
# Unit 1
(("none", 0.0), ("none", 0.0), True), # out
(("si", 400.0), ("none", 0.0), True), # Si400
(("ge", 300.0), ("none", 0.0), True), # Ge300
(("ti", 800.0), ("none", 0.0), True), # Ti800
(("zr", 20.0), ("none", 0.0), True), # Zr20
(("none", 0.0), ("none", 0.0), False), # unused
# Unit 2
(("none", 0.0), ("none", 0.0), True), # out
(("si", 200.0), ("none", 0.0), True), # Si200
(("si", 3200.0), ("none", 0.0), True), # Si3200
(("ti", 400.0), ("none", 0.0), True), # Ti400
(("cu", 20.0), ("none", 0.0), True), # Cu20
(("none", 0.0), ("none", 0.0), False), # unused
# Unit 3
(("none", 0.0), ("none", 0.0), True), # out
(("si", 100.0), ("none", 0.0), True), # Si100
(("si", 1600.0), ("none", 0.0), True), # Si1600
(("ti", 200.0), ("none", 0.0), True), # Ti200
(("ti", 3200.0), ("none", 0.0), True), # Ti3200
(("fe", 5.0), ("none", 0.0), False), # Fe5 (disabled unless data file provided)
# Unit 4
(("none", 0.0), ("none", 0.0), True), # out
(("si", 50.0), ("none", 0.0), True), # Si50
(("si", 800.0), ("none", 0.0), True), # Si800
(("ti", 100.0), ("none", 0.0), True), # Ti100
(("ti", 1600.0), ("none", 0.0), True), # Ti1600
(("ti", 20.0), ("none", 0.0), True), # Ti20
]
_UNITS = 4
_PER_UNIT = 6
# -----------------------------------------
# Motion mapping: user-scale coordinates
# [out, m1, m2, m3, m4, m5]
# -----------------------------------------
_POSITIONS_USER: List[List[Optional[float]]] = [
# Unit 1 (filter_array_1_x)
[25.0, 17.9, 7.9, -2.3, -12.1, None],
# Unit 2 (filter_array_2_x)
[25.5, 17.6, 7.8, -2.3, -12.3, None],
# Unit 3 (filter_array_3_x)
[25.8, 17.6, 7.8, -2.2, -12.3, -22.3], # Fe5 at -22.3
# Unit 4 (filter_array_4_x)
[25.0, 17.5, 7.5, -2.2, -12.4, -22.2],
]
# Device axis names (adjust if different)
_AXES: List[str] = [
"filter_array_1_x",
"filter_array_2_x",
"filter_array_3_x",
"filter_array_4_x",
]
# -----------------------------
# Construction / Internals
# -----------------------------
def __init__(self, **kwargs):
super().__init__(**kwargs)
# In multiple-inheritance setups our __init__ might be skipped; guard lazily too.
self._attlen_cache: Dict[str, Tuple[List[float], List[float]]] = {}
def _ensure_internal_state(self):
"""Lazy guard for robustness if __init__ wasnt called."""
if not hasattr(self, "_attlen_cache"):
self._attlen_cache = {}
# -----------------------------
# Public API
# -----------------------------
def fil_trans(
self,
transmission: Optional[float] = None,
energy_kev: Optional[float] = None,
print_only: bool = True,
) -> Optional[None]:
"""
Set exposure-box filters to achieve a target transmission.
If called without 'transmission', prints usage and current status.
Safety:
- fil_trans(1) is always allowed.
- fil_trans(<1) is only allowed if:
- epics_get("X12SA-OP-DMM-EMLS-3010:THRU") == 1 (DMM translation THROUGH)
- epics_get("X12SA-OP-DMM-EMLS-3030:THRU") == 1 (DMM rotation THROUGH)
- epics_get("X12SA-OP-CCM1:ENERGY-GET") > 1 (CCM active, energy in keV)
Otherwise, prompt with default NO.
"""
# --- No-arg usage helper ---
if transmission is None:
print("\nUsage example:")
print(" csaxs.fil_trans(0.10, energy_kev=6.2)")
print(" First parameter is the transmission factor requested.")
print(" If energy is not specified it will be read from the CCM energy PV.")
print("\nCurrent filter transmission:")
self._fil_trans_report(energy_kev=energy_kev)
return None
# --- Validation of transmission ---
try:
transmission = float(transmission)
except Exception:
raise ValueError("Transmission must be numeric.")
if not (0.0 < transmission <= 1.0):
raise ValueError("Transmission must be between 0 and 1.")
# -------------------------------------------------------
# SAFETY CHECK (before any calculation/motion):
# Only allow fil_trans < 1 when DMM is in THROUGH (both)
# and CCM energy > 1 keV. fil_trans(1) is always allowed.
# -------------------------------------------------------
if transmission < 1.0:
try:
dmm_trans = float(epics_get("X12SA-OP-DMM-EMLS-3010:THRU"))
except Exception:
dmm_trans = -1
try:
dmm_rot = float(epics_get("X12SA-OP-DMM-EMLS-3030:THRU"))
except Exception:
dmm_rot = -1
try:
ccm_energy = float(epics_get("X12SA-OP-CCM1:ENERGY-GET"))
except Exception:
ccm_energy = -1
allowed = (dmm_trans == 1) and (dmm_rot == 1) and (ccm_energy > 1)
if not allowed:
print("\n⚠️ SAFETY WARNING: Reducing transmission (< 1) typically requires:")
print(" - DMM translation in THROUGH (THRU == 1)")
print(" - DMM rotation in THROUGH (THRU == 1)")
print(" - CCM energy > 1 keV")
print("\nCurrent state:")
print(f" DMM translation THRU : {dmm_trans}")
print(f" DMM rotation THRU : {dmm_rot}")
print(f" CCM energy (keV) : {ccm_energy}")
# Ask user (default = NO)
if hasattr(self, "OMNYTools") and hasattr(self.OMNYTools, "yesno"):
proceed = self.OMNYTools.yesno(
"Conditions not satisfied. Proceed anyway?",
default="n",
)
else:
# Safe fallback
proceed = False
if not proceed:
print("Aborted. Transmission unchanged.")
return None
# --- Energy handling (EPICS only) ---
if energy_kev is None:
try:
energy_kev = float(epics_get("X12SA-OP-CCM1:ENERGY-GET"))
except Exception as exc:
raise RuntimeError(
"Energy not specified and could not read EPICS PV "
"'X12SA-OP-CCM1:ENERGY-GET'."
) from exc
else:
energy_kev = float(energy_kev)
# --- Summary header ---
print("\nExposure-box filter transmission request")
print("-" * 60)
print(f"Target transmission : {transmission:.6e}")
print(f"Photon energy : {energy_kev:.3f} keV")
print(f"Mode : {'PRINT ONLY' if print_only else 'EXECUTE'}")
print("-" * 60)
# --- Compute best combination ---
best = self._find_best_combination(transmission, energy_kev)
# --- Report selected combination ---
self._print_combination(best, energy_kev, header="Selected combination")
# Nearby: print only code + transmission
neighbors = self._neighbors_around_best(transmission, energy_kev, span=5)
if neighbors:
print("\nNearby combinations (by transmission proximity):")
for row in neighbors:
print(f"{row['transmission']:9.3e}")
# --- Dry run prompt ---
if print_only:
print("\n[DRY RUN] No motion executed yet.")
if hasattr(self, "OMNYTools") and hasattr(self.OMNYTools, "yesno"):
if self.OMNYTools.yesno(
"Execute motion to the selected filter combination now?",
"y", # default YES
):
self._execute_combination(best, energy_kev)
else:
print("Execution skipped.")
else:
# If yesno not available, default to 'skip' on print_only
print("No interactive prompt available. Execution skipped (print_only=True).")
return None
# --- Execute motion directly ---
self._execute_combination(best, energy_kev)
return None
# -----------------------------
# Physics helpers
# -----------------------------
def _load_attlen(self, material: str) -> Tuple[List[float], List[float]]:
"""
Load and cache attenuation-length table for a material from package resources.
Returns:
energies_eV (list), attlen_um (list)
"""
self._ensure_internal_state()
material = material.lower()
if material in self._attlen_cache:
return self._attlen_cache[material]
fname = self._MATERIAL_FILES.get(material)
if not fname:
# 'none' or unsupported mapped to empty
self._attlen_cache[material] = ([], [])
return ([], [])
energies_eV: List[float] = []
attlen_um: List[float] = []
# Load from installed package: <this_module>/filter_data/<fname>
res = resources.files(ft_pkg) / "filter_data" / fname
try:
# as_file yields a concrete filesystem path even if package is zipped
with resources.as_file(res) as p:
with p.open("r") as f:
for line in f:
line = line.strip()
if not line:
continue
parts = line.split()
if len(parts) < 2:
continue
energies_eV.append(float(parts[0]))
attlen_um.append(float(parts[1]))
except FileNotFoundError as e:
raise FileNotFoundError(
f"Attenuation data file not found for '{material}': {fname} "
f"(looked in package filter_data)"
) from e
if not energies_eV:
raise ValueError(
f"Attenuation data for material '{material}' is empty or invalid: {fname}"
)
self._attlen_cache[material] = (energies_eV, attlen_um)
return energies_eV, attlen_um
def _attenuation_length_um(self, energy_kev: float, material: str) -> float:
"""
Linear interpolation of attenuation length λ(energy) in µm.
Input energy in keV; tables are in eV.
"""
material = material.lower()
if material == "none":
return float("inf") # No attenuation
energies_eV, attlen_um = self._load_attlen(material)
if not energies_eV:
# unsupported mapped above
raise ValueError(f"Unsupported material or missing data: '{material}'")
e_ev = energy_kev * 1000.0
# Clip to the nearest edge for practicality
if e_ev <= energies_eV[0]:
bec_logger.logger.warning(
f"[cSAXS] energy {energy_kev:.3f} keV below table range for {material}; "
f"clipping to {energies_eV[0]/1000.0:.3f} keV."
)
return attlen_um[0]
if e_ev >= energies_eV[-1]:
bec_logger.logger.warning(
f"[cSAXS] energy {energy_kev:.3f} keV above table range for {material}; "
f"clipping to {energies_eV[-1]/1000.0:.3f} keV."
)
return attlen_um[-1]
# Binary search for interval
lo, hi = 0, len(energies_eV) - 1
while hi - lo > 1:
mid = (lo + hi) // 2
if energies_eV[mid] >= e_ev:
hi = mid
else:
lo = mid
e_lo, e_hi = energies_eV[lo], energies_eV[hi]
lam_lo, lam_hi = attlen_um[lo], attlen_um[hi]
lam = (e_ev - e_lo) / (e_hi - e_lo) * (lam_hi - lam_lo) + lam_lo
return lam
def _position_transmission(
self,
pos_entry: Tuple[Tuple[str, float], Tuple[str, float], bool],
energy_kev: float,
) -> Optional[float]:
"""Transmission for a single position (possibly two layers)."""
(mat1, th1), (mat2, th2), enabled = pos_entry
if not enabled:
return None
T1 = 1.0
T2 = 1.0
if mat1 != "none" and th1 > 0.0:
lam1 = self._attenuation_length_um(energy_kev, mat1)
T1 = math.exp(-th1 / lam1)
if mat2 != "none" and th2 > 0.0:
lam2 = self._attenuation_length_um(energy_kev, mat2)
T2 = math.exp(-th2 / lam2)
return T1 * T2
def _all_combinations(self, energy_kev: float) -> List[dict]:
"""
Enumerate all enabled combinations across 4 units.
Returns a list of dicts sorted by transmission ascending:
{
'code': 'abcd' # positions 1..6 per unit
'indices': [i0, i1, i2, i3], # 0..5
'materials': [ ((m1,t1), (m2,t2)|None ), ... for 4 units ]
'transmission': float
}
"""
# Slice filters per unit
units = [
self._FILTERS[u * self._PER_UNIT : (u + 1) * self._PER_UNIT]
for u in range(self._UNITS)
]
# Precompute per-position transmissions
per_pos_T: List[List[Optional[float]]] = [
[self._position_transmission(pos_entry, energy_kev) for pos_entry in unit]
for unit in units
]
combos: List[dict] = []
for i0 in range(self._PER_UNIT):
T0 = per_pos_T[0][i0]
if T0 is None:
continue
for i1 in range(self._PER_UNIT):
T1 = per_pos_T[1][i1]
if T1 is None:
continue
for i2 in range(self._PER_UNIT):
T2 = per_pos_T[2][i2]
if T2 is None:
continue
for i3 in range(self._PER_UNIT):
T3 = per_pos_T[3][i3]
if T3 is None:
continue
T = T0 * T1 * T2 * T3
indices = [i0, i1, i2, i3]
code = "".join(str(i + 1) for i in indices)
# Collect materials/thickness for reporting
mats = []
for u, idx in enumerate(indices):
(m1, t1), (m2, t2), _ = units[u][idx]
mats.append(((m1, t1), (m2, t2) if (m2 != "none" and t2 > 0.0) else None))
combos.append(
{
"code": code,
"indices": indices,
"materials": mats,
"transmission": T,
}
)
combos.sort(key=lambda c: c["transmission"]) # ascending
return combos
def _find_best_combination(self, target_T: float, energy_kev: float) -> dict:
"""Pick combination with transmission closest to target."""
combos = self._all_combinations(energy_kev)
best = min(combos, key=lambda c: abs(c["transmission"] - target_T))
return best
def _neighbors_around_best(
self, target_T: float, energy_kev: float, span: int = 5
) -> List[dict]:
"""Return a few combinations around the best, by proximity in transmission."""
combos = self._all_combinations(energy_kev)
ranked = sorted(combos, key=lambda c: abs(c["transmission"] - target_T))
return ranked[1 : 1 + span] # exclude best itself
# -----------------------------
# Formatting & motion
# -----------------------------
def _print_combination(self, comb: dict, energy_kev: float, header: Optional[str] = None):
if header:
print(f"\n{header}:")
code = comb["code"]
T = comb["transmission"]
print(f" Filters {code} transmission at {energy_kev:.3f} keV = {T:9.3e}")
# Per-unit detail for the selected combination only
for u, matinfo in enumerate(comb["materials"], start=1):
first, second = matinfo
(m1, t1) = first
pos = int(code[u - 1])
if second is not None:
(m2, t2) = second
print(
f" unit {u}: #{pos} "
f"{t1:4.0f} mu {m1:<4} + {t2:4.0f} mu {m2:<4}"
)
else:
if m1 != "none" and t1 > 0.0:
print(f" unit {u}: #{pos} {t1:4.0f} mu {m1:<4}")
else:
print(f" unit {u}: #{pos} ----- out")
def _execute_combination(self, comb: dict, energy_kev: float):
"""
Execute motion to the indices encoded in 'comb["code"]'.
Mapping:
- code 'abcd' → per-unit index (a,b,c,d) ∈ {1..6}
- positions are looked up from _POSITIONS_USER
- axes are defined in _AXES
Motion uses: umv(dev.axis, position, dev.axis2, position2, ...)
"""
indices = comb["indices"] # 0-based per unit
move_args = [] # Collect (device, position) pairs
print("\nExecuting combined motion:")
for unit_idx, pos_idx in enumerate(indices):
pos_list = self._POSITIONS_USER[unit_idx]
target_pos = pos_list[pos_idx]
if target_pos is None:
raise RuntimeError(
f"Unit {unit_idx+1} position {pos_idx+1} has no defined coordinate."
)
axis_name = self._AXES[unit_idx]
axis_obj = getattr(dev, axis_name)
print(f" {axis_name}{target_pos:.3f}")
move_args.extend([axis_obj, target_pos])
umv(*move_args)
print("\nVerifying final positions:")
for unit_idx in range(self._UNITS):
axis_name = self._AXES[unit_idx]
axis_obj = getattr(dev, axis_name)
try:
actual = float(axis_obj.readback.get())
print(f" {axis_name} = {actual:.3f}")
except Exception:
print(f" {axis_name}: readback unavailable")
achieved_T = comb["transmission"]
print(f"\nAchieved transmission (approx.): {achieved_T:9.3e} at {energy_kev:.3f} keV")
def _fil_trans_report(self, tol: float = 0.1, energy_kev: Optional[float] = None) -> None:
"""
Report the currently active exposurebox filter combination.
Determines stage positions via dev.<axis>.readback.get()
with a tolerance window of ±tol relative to nominal positions.
Parameters
----------
tol : float
Tolerance for matching positions.
energy_kev : float, optional
Photon energy in keV. If None, tries to read from dev.mokev or defaults to 6.2 keV.
"""
# Ensure global dev is available
if dev is None:
print("ERROR: Global 'dev' object not found.")
return
# --- Energy handling (EPICS only) ---
if energy_kev is None:
try:
energy_kev = float(epics_get("X12SA-OP-CCM1:ENERGY-GET"))
except Exception as exc:
raise RuntimeError(
"Energy not specified and could not read EPICS PV "
"'X12SA-OP-CCM1:ENERGY-GET'."
) from exc
else:
energy_kev = float(energy_kev)
print("\nCurrent filter transmission report")
print("-" * 60)
print(f"Photon energy : {energy_kev:.3f} keV")
indices = [] # 05 per unit
for unit_idx, axis_name in enumerate(self._AXES):
axis_obj = getattr(dev, axis_name, None)
if axis_obj is None:
print(f"ERROR: Device axis '{axis_name}' not found.")
return
try:
rb = float(axis_obj.readback.get())
except Exception:
print(f"ERROR: readback unavailable for axis {axis_name}")
return
# Match readback to nearest nominal
pos_list = self._POSITIONS_USER[unit_idx]
best_idx = None
for i, nominal in enumerate(pos_list):
if nominal is None:
continue
if abs(rb - nominal) <= tol:
best_idx = i
break
if best_idx is None:
print(f"Unit {unit_idx+1}: readback {rb:.3f} does not match any known position.")
return
indices.append(best_idx)
# Build combination code
code = "".join(str(i + 1) for i in indices)
print(f"Matched filter code: {code}")
# Compute transmission and materials
units = [
self._FILTERS[u * self._PER_UNIT : (u + 1) * self._PER_UNIT]
for u in range(self._UNITS)
]
materials = []
total_T = 1.0
for u, pos_idx in enumerate(indices):
(m1, t1), (m2, t2), enabled = units[u][pos_idx]
T = self._position_transmission(units[u][pos_idx], energy_kev)
if T is None:
print(f"Unit {u+1}: position disabled")
T = 1.0
total_T *= T
if m2 != "none" and t2 > 0:
materials.append(((m1, t1), (m2, t2)))
else:
materials.append(((m1, t1), None))
# Print detailed report
self.OMNYTools.printgreenbold(f"Total transmission: {total_T:.6e}")
print("-" * 60)
for u, matinfo in enumerate(materials, start=1):
(m1, t1), second = matinfo
pos = indices[u - 1] + 1
if second:
m2, t2 = second
print(f" unit {u}: #{pos} {t1:4.0f} µm {m1:<4} + {t2:4.0f} µm {m2:<4}")
else:
if m1 != "none" and t1 > 0:
print(f" unit {u}: #{pos} {t1:4.0f} µm {m1:<4}")
else:
print(f" unit {u}: #{pos} ----- out")

View File

@@ -1,447 +0,0 @@
import builtins
import time
from bec_lib import bec_logger
# Logger initialization
logger = bec_logger.logger
# Pull BEC globals if present
bec = builtins.__dict__.get("bec")
dev = builtins.__dict__.get("dev")
umv = builtins.__dict__.get("umv")
umvr = builtins.__dict__.get("umvr")
class cSAXSInitSmaractStagesError(Exception):
pass
class cSAXSInitSmaractStages:
"""
Runtime SmarAct utilities for referencing and moving to initial positions.
This class no longer relies on static mappings. Instead, it:
- discovers available devices from `list(dev.keys())`
- reads the numeric channel/axis from each device's `user_parameter['bl_smar_stage']`
- reads `init_position` from `user_parameter['init_position']`
"""
def __init__(self, client) -> None:
self.client = client
# ------------------------------
# Internal helpers (runtime-based)
# ------------------------------
def _yesno(self, question: str, default: str = "y") -> bool:
"""
Use OMNYTools.yesno if available; otherwise default to 'yes' (or fallback to input()).
"""
try:
if hasattr(self, "OMNYTools") and hasattr(self.OMNYTools, "yesno"):
return self.OMNYTools.yesno(question, default)
except Exception:
pass
# Fallback: default answer without interaction
# (Safe default: 'y' proceeds; adjust if you want interactive input)
logger.info(f"[cSAXS] (yesno fallback) {question} -> default '{default}'")
return (default or "y").lower().startswith("y")
def _get_user_param_safe(self, device_name: str, key: str):
"""
Safe access to device user parameters from current BEC session.
"""
try:
return dev[device_name].user_parameter.get(key)
except Exception:
return None
def _iter_session_devices(self):
"""
Yield device names available in current BEC session.
"""
if dev is None:
return
for name in list(dev.keys()):
yield name
def _build_session_axis_map(self, selection: set | None = None) -> dict:
"""
Build runtime axis map {device_name: channel} for devices that define 'bl_smar_stage'.
If 'selection' is provided, restrict to names in selection.
"""
axis_map = {}
missing = []
for name in self._iter_session_devices() or []:
if selection is not None and name not in selection:
continue
ch = self._get_user_param_safe(name, "bl_smar_stage")
if ch is None:
missing.append(name)
continue
try:
axis_map[name] = int(ch)
except Exception:
missing.append(name)
if missing and selection is None:
logger.info(
"[cSAXS] Devices without 'bl_smar_stage' (ignored): " + ", ".join(sorted(missing))
)
return axis_map
def _get_device_object(self, device_name: str):
"""
Return the live device object from BEC 'dev'.
"""
try:
return getattr(dev, device_name)
except Exception:
return None
# ------------------------------
# Public API
# ------------------------------
def smaract_reference_stages(self, force: bool = False, devices_to_reference=None):
"""
Reference SmarAct stages using runtime discovery.
Parameters
----------
force : bool, optional
If True, re-reference ALL selected stages.
If False (default), only reference stages that are currently NOT referenced.
devices_to_reference : iterable of str or str, optional
If provided, only these devices will be considered for referencing.
If None, all devices in the current session that define 'bl_smar_stage' are considered.
Behavior
--------
- Runtime-based: reads axis channel from user_parameter['bl_smar_stage'].
- If devices_to_reference is given → restrict referencing to those.
- If force=False → skip devices already referenced.
- If force=True → re-reference selected devices always.
- Only newly referenced devices are passed to
smaract_components_to_initial_position(devices_to_move=[...]) afterwards.
Examples
--------
Reference only stages that are NOT referenced yet (default)
csaxs.smaract_reference_stages()
Force re-reference of all stages
csaxs.smaract_reference_stages(force=True)
Reference only specific stages
csaxs.smaract_reference_stages(
devices_to_reference=["sl3trxi", "sl3trxo", "xbpm3x"]
)
Reference selected stages and force re-referencing
csaxs.smaract_reference_stages(
devices_to_reference=["sl4trxi", "sl4trxo"],
force=True
)
Reference a single device
csaxs.smaract_reference_stages(
devices_to_reference="xbimtrx"
)
Reference only the selected devices (skip already-referenced ones)
csaxs.smaract_reference_stages(
devices_to_reference=["sl3trxi", "sl4trxo", "sl5trxt"]
)
Check referencing status of all stages
csaxs.smaract_check_all_referenced()
"""
# Normalize selection
if isinstance(devices_to_reference, str):
devices_to_reference = [devices_to_reference]
selection = set(devices_to_reference) if devices_to_reference else None
# Build axis map for selected devices (or all devices present)
axis_map = self._build_session_axis_map(selection=selection)
if selection:
unknown = sorted(list(selection - set(axis_map.keys())))
if unknown:
print(f"Unknown devices requested or missing 'bl_smar_stage' (ignored): {unknown}")
newly_referenced = []
already_referenced = []
failed = []
to_verify = [] # devices that need a final verification
print("\nStarting SmarAct referencing...\n")
for dev_name in sorted(axis_map.keys()):
ch = axis_map[dev_name]
d = self._get_device_object(dev_name)
if d is None:
print(f"{dev_name}: device not accessible, skipping.")
failed.append(dev_name)
continue
try:
is_ref = d.controller.axis_is_referenced(ch)
# Skip if already referenced and not forcing
if is_ref and not force:
print(f"{dev_name}: already referenced, skipping.")
already_referenced.append(dev_name)
continue
# Start referencing
print(f"{dev_name}: referencing axis...")
d.controller.set_closed_loop_move_speed(ch, 1)
d.controller.find_reference_mark(ch, 0, 1000, 1)
time.sleep(0.1)
# Add to list for final verification
to_verify.append((dev_name, ch, d))
except Exception as e:
print(f"Error referencing {dev_name} (axis {ch}): {e}")
failed.append(dev_name)
time.sleep(1.0)
print("\nVerifying referencing state...\n")
for dev_name, ch, d in to_verify:
try:
if d.controller.axis_is_referenced(ch):
print(f"{dev_name}: successfully referenced.")
newly_referenced.append(dev_name)
else:
print(f"{dev_name}: referencing FAILED.")
failed.append(dev_name)
except Exception as e:
print(f"{dev_name}: verification error: {e}")
failed.append(dev_name)
# --- Summary ---
print("\n--- Referencing summary ---")
print(f"Newly referenced: {newly_referenced}")
print(f"Already referenced (kept): {already_referenced}")
print(f"Failed: {failed}")
print("-----------------------------------------\n")
# --- Move newly referenced only ---
if newly_referenced:
print("Moving newly referenced stages to initial positions...")
self.smaract_components_to_initial_position(devices_to_move=newly_referenced)
else:
print("No newly referenced stages.")
def smaract_check_all_referenced(self):
"""
Check reference state for all SmarAct devices that define 'bl_smar_stage'.
"""
axis_map = self._build_session_axis_map(selection=None)
for dev_name in sorted(axis_map.keys()):
ch = axis_map[dev_name]
d = self._get_device_object(dev_name)
if d is None:
print(f"{dev_name}: device not accessible or unsupported.")
continue
try:
if d.controller.axis_is_referenced(ch):
print(f"{dev_name} (axis {ch}) is referenced.")
else:
print(f"{dev_name} (axis {ch}) is NOT referenced.")
except Exception as e:
print(f"Error checking {dev_name} (axis {ch}): {e}")
def smaract_components_to_initial_position(self, devices_to_move=None):
"""
Move selected (or all) SmarAct-based components to their configured init_position.
Parameters
----------
devices_to_move : iterable of str or str, optional
Specific device names to move (e.g. ["xbpm3x", "sl3trxi"]).
If None, all devices in the current session that define 'bl_smar_stage' are considered.
Behavior
--------
- Runtime-based: uses user_parameter['bl_smar_stage'] (numeric channel) and 'init_position'.
- Only axes that are referenced will be moved.
- Unreferenced axes are skipped with a WARNING; the operation continues.
- Devices missing `init_position` are skipped and listed.
- At the end, a summary warns if some stages could not be moved because they were not referenced.
"""
# Normalize selection
if isinstance(devices_to_move, str):
devices_to_move = [devices_to_move]
selection = set(devices_to_move) if devices_to_move else None
# Resolve axis map based on selection
axis_map = self._build_session_axis_map(selection=selection)
unknown_requested = []
if selection:
unknown_requested = sorted(list(selection - set(axis_map.keys())))
if unknown_requested:
logger.warning(
"[cSAXS] Requested devices unknown or missing 'bl_smar_stage': "
+ ", ".join(unknown_requested)
)
# First confirmation: intent
scope_desc = "all SmarAct-based components" if selection is None else "the selected SmarAct-based components"
if not self._yesno(
f"Do you want to move {scope_desc} to the init position as defined in the config file?",
"y",
):
return
planned_moves = []
not_referenced = []
missing_params = []
inaccessible_devices = []
# --- Pre-check phase ---
for dev_name in sorted(axis_map.keys()):
d = self._get_device_object(dev_name)
if d is None:
logger.warning(f"[cSAXS] Device {dev_name} not accessible, skipping.")
inaccessible_devices.append(dev_name)
continue
ch = axis_map[dev_name]
try:
# Reference check
if not d.controller.axis_is_referenced(ch):
not_referenced.append(dev_name)
continue
# Fetch init_position (from user parameters)
init_pos = self._get_user_param_safe(dev_name, "init_position")
if init_pos is None:
missing_params.append(dev_name)
continue
planned_moves.append((dev_name, float(init_pos)))
except Exception as exc:
logger.error(f"[cSAXS] Error during pre-check for {dev_name}: {exc}")
if not planned_moves:
# Nothing to move—still summarize why.
header = "\nNo motions planned. Summary of issues:"
lines = []
if not_referenced:
lines.append(" - Not referenced: " + ", ".join(sorted(not_referenced)))
if missing_params:
lines.append(" - Missing init_position: " + ", ".join(sorted(missing_params)))
if inaccessible_devices:
lines.append(" - Not accessible: " + ", ".join(sorted(inaccessible_devices)))
if unknown_requested:
lines.append(" - Unknown requested: " + ", ".join(sorted(unknown_requested)))
if not lines:
lines.append(" - (No eligible devices or nothing to do.)")
print(header)
for line in lines:
print(line)
logger.warning("[cSAXS] Nothing to do.")
return
# --- Summary table ---
print("\nPlanned SmarAct motions to initial position:")
print("-" * 60)
print(f"{'Device':<35} {'Init position':>20}")
print("-" * 60)
for dev_name, init_pos in planned_moves:
print(f"{dev_name:<35} {init_pos:>20.6g}")
print("-" * 60)
# Notes / diagnostics
if selection is not None:
print("\nNote: Only the following devices were requested to move:")
print(", ".join(sorted(selection)))
if unknown_requested:
print("\nNote: The following requested devices are unknown and were ignored:")
print(", ".join(unknown_requested))
if not_referenced:
print("\nNote: The following devices are NOT referenced and will be skipped:")
print(", ".join(sorted(not_referenced)))
if missing_params:
print("\nNote: The following devices have no init_position defined and will be skipped:")
print(", ".join(sorted(missing_params)))
if inaccessible_devices:
print("\nNote: The following devices were not accessible and will be skipped:")
print(", ".join(sorted(inaccessible_devices)))
# Second confirmation: execution
if not self._yesno("Proceed with the motions listed above?", "y"):
logger.info("[cSAXS] Motion to initial position aborted by user.")
return
# --- Execution phase (SIMULTANEOUS MOTION) ---
if umv is None:
logger.error("[cSAXS] 'umv' is not available in this session.")
return
# Build a flat argument list: [dev1, pos1, dev2, pos2, ...]
move_args = []
for dev_name, init_pos in planned_moves:
d = self._get_device_object(dev_name)
if d is None:
logger.error(f"[cSAXS] Could not access {dev_name}, skipping.")
continue
move_args.append(d)
move_args.append(init_pos)
logger.info(f"[cSAXS] Preparing move: {dev_name} -> {init_pos}")
if not move_args:
logger.warning("[cSAXS] No valid devices left for simultaneous motion.")
return
# Trigger simultaneous move
try:
logger.info(f"[cSAXS] Starting simultaneous motion of {len(planned_moves)} devices.")
umv(*move_args) # simultaneous move
except Exception as exc:
logger.error(f"[cSAXS] Simultaneous motion failed: {exc}")
return
logger.info("[cSAXS] Simultaneous SmarAct motion to initial positions completed.")
# Final warning summary about unreferenced devices
if not_referenced:
logger.warning(
"[cSAXS] Some stages were NOT moved because they are not referenced:\n"
+ ", ".join(sorted(not_referenced))
+ "\nPlease reference these axes and re-run if needed."
)
class cSAXSSmaract:
def __init__(self, client) -> None:
self.client = client
def _get_user_param_safe(self, device_name: str, key: str):
try:
return dev[device_name].user_parameter.get(key)
except Exception:
return None
def fshn1in(self):
"""
Move fast shutter n1 to its 'in' position defined in user parameters.
"""
in_pos = self._get_user_param_safe("fast_shutter_n1_x", "in")
if in_pos is None:
logger.error("[cSAXS] No 'in' position defined for fast_shutter_n1_x.")
return
if umv is None:
logger.error("[cSAXS] 'umv' is not available in this session.")
return
umv(dev.fast_shutter_n1_x, in_pos)

View File

@@ -1 +0,0 @@
from .flomni import Flomni

View File

@@ -1,351 +0,0 @@
corr_elements = 175
corr_angle[0] = 0.100000
corr_angle[1] = 1.001000
corr_angle[2] = 1.902000
corr_angle[3] = 2.798000
corr_angle[4] = 7.305000
corr_angle[5] = 8.204000
corr_angle[6] = 9.104000
corr_angle[7] = 10.005000
corr_angle[8] = 14.504000
corr_angle[9] = 15.404000
corr_angle[10] = 16.304000
corr_angle[11] = 17.204000
corr_angle[12] = 21.704000
corr_angle[13] = 22.604000
corr_angle[14] = 23.504000
corr_angle[15] = 24.404000
corr_angle[16] = 28.904000
corr_angle[17] = 29.804000
corr_angle[18] = 30.704000
corr_angle[19] = 31.604000
corr_angle[20] = 36.104000
corr_angle[21] = 37.004000
corr_angle[22] = 37.904000
corr_angle[23] = 38.804000
corr_angle[24] = 43.305000
corr_angle[25] = 44.205000
corr_angle[26] = 45.104000
corr_angle[27] = 46.005000
corr_angle[28] = 50.504000
corr_angle[29] = 51.404000
corr_angle[30] = 52.305000
corr_angle[31] = 53.205000
corr_angle[32] = 57.705000
corr_angle[33] = 58.605000
corr_angle[34] = 59.505000
corr_angle[35] = 60.405000
corr_angle[36] = 64.904000
corr_angle[37] = 65.804000
corr_angle[38] = 66.704000
corr_angle[39] = 67.604000
corr_angle[40] = 72.104000
corr_angle[41] = 73.004000
corr_angle[42] = 73.904000
corr_angle[43] = 74.804000
corr_angle[44] = 79.304000
corr_angle[45] = 80.204000
corr_angle[46] = 81.104000
corr_angle[47] = 82.005000
corr_angle[48] = 86.505000
corr_angle[49] = 87.404000
corr_angle[50] = 88.304000
corr_angle[51] = 89.205000
corr_angle[52] = 93.704000
corr_angle[53] = 94.604000
corr_angle[54] = 95.505000
corr_angle[55] = 96.404000
corr_angle[56] = 100.904000
corr_angle[57] = 101.804000
corr_angle[58] = 102.704000
corr_angle[59] = 103.604000
corr_angle[60] = 108.104000
corr_angle[61] = 109.004000
corr_angle[62] = 109.904000
corr_angle[63] = 110.804000
corr_angle[64] = 115.304000
corr_angle[65] = 116.204000
corr_angle[66] = 117.104000
corr_angle[67] = 118.004000
corr_angle[68] = 122.504000
corr_angle[69] = 123.404000
corr_angle[70] = 124.304000
corr_angle[71] = 125.204000
corr_angle[72] = 129.704000
corr_angle[73] = 130.604000
corr_angle[74] = 131.504000
corr_angle[75] = 132.404000
corr_angle[76] = 136.904000
corr_angle[77] = 137.804000
corr_angle[78] = 138.701000
corr_angle[79] = 139.604000
corr_angle[80] = 144.104000
corr_angle[81] = 145.004000
corr_angle[82] = 145.904000
corr_angle[83] = 146.804000
corr_angle[84] = 151.304000
corr_angle[85] = 152.204000
corr_angle[86] = 153.104000
corr_angle[87] = 154.004000
corr_angle[88] = 158.504000
corr_angle[89] = 159.404000
corr_angle[90] = 160.304000
corr_angle[91] = 161.204000
corr_angle[92] = 165.704000
corr_angle[93] = 166.604000
corr_angle[94] = 167.504000
corr_angle[95] = 168.404000
corr_angle[96] = 172.904000
corr_angle[97] = 173.805000
corr_angle[98] = 174.704000
corr_angle[99] = 180.104000
corr_angle[100] = 183.704000
corr_angle[101] = 184.603000
corr_angle[102] = 185.504000
corr_angle[103] = 190.904000
corr_angle[104] = 191.805000
corr_angle[105] = 192.704000
corr_angle[106] = 198.104000
corr_angle[107] = 199.004000
corr_angle[108] = 199.904000
corr_angle[109] = 205.304000
corr_angle[110] = 206.204000
corr_angle[111] = 207.104000
corr_angle[112] = 212.504000
corr_angle[113] = 213.404000
corr_angle[114] = 214.304000
corr_angle[115] = 219.704000
corr_angle[116] = 220.604000
corr_angle[117] = 221.504000
corr_angle[118] = 226.904000
corr_angle[119] = 227.804000
corr_angle[120] = 228.704000
corr_angle[121] = 234.104000
corr_angle[122] = 235.004000
corr_angle[123] = 235.904000
corr_angle[124] = 241.304000
corr_angle[125] = 242.204000
corr_angle[126] = 243.104000
corr_angle[127] = 248.504000
corr_angle[128] = 249.404000
corr_angle[129] = 250.304000
corr_angle[130] = 255.704000
corr_angle[131] = 256.604000
corr_angle[132] = 257.504000
corr_angle[133] = 262.904000
corr_angle[134] = 263.804000
corr_angle[135] = 264.704000
corr_angle[136] = 270.104000
corr_angle[137] = 271.004000
corr_angle[138] = 271.904000
corr_angle[139] = 277.304000
corr_angle[140] = 278.205000
corr_angle[141] = 279.104000
corr_angle[142] = 284.504000
corr_angle[143] = 285.405000
corr_angle[144] = 286.304000
corr_angle[145] = 291.703000
corr_angle[146] = 292.604000
corr_angle[147] = 293.504000
corr_angle[148] = 298.904000
corr_angle[149] = 299.804000
corr_angle[150] = 300.704000
corr_angle[151] = 306.104000
corr_angle[152] = 307.004000
corr_angle[153] = 307.904000
corr_angle[154] = 313.304000
corr_angle[155] = 314.204000
corr_angle[156] = 315.104000
corr_angle[157] = 320.504000
corr_angle[158] = 321.404000
corr_angle[159] = 322.304000
corr_angle[160] = 327.704000
corr_angle[161] = 328.605000
corr_angle[162] = 329.504000
corr_angle[163] = 334.904000
corr_angle[164] = 335.804000
corr_angle[165] = 336.705000
corr_angle[166] = 342.104000
corr_angle[167] = 343.004000
corr_angle[168] = 343.904000
corr_angle[169] = 349.304000
corr_angle[170] = 350.204000
corr_angle[171] = 351.104000
corr_angle[172] = 356.504000
corr_angle[173] = 357.404000
corr_angle[174] = 358.304000
corr_pos[0] = 0.012330
corr_pos[1] = 0.024870
corr_pos[2] = 0.037262
corr_pos[3] = 0.049438
corr_pos[4] = 0.108462
corr_pos[5] = 0.119791
corr_pos[6] = 0.130986
corr_pos[7] = 0.142044
corr_pos[8] = 0.195045
corr_pos[9] = 0.205834
corr_pos[10] = 0.216589
corr_pos[11] = 0.226402
corr_pos[12] = 0.271931
corr_pos[13] = 0.281684
corr_pos[14] = 0.290769
corr_pos[15] = 0.299392
corr_pos[16] = 0.337986
corr_pos[17] = 0.345178
corr_pos[18] = 0.352253
corr_pos[19] = 0.358528
corr_pos[20] = 0.379520
corr_pos[21] = 0.382947
corr_pos[22] = 0.386110
corr_pos[23] = 0.388887
corr_pos[24] = 0.395645
corr_pos[25] = 0.396154
corr_pos[26] = 0.396679
corr_pos[27] = 0.396367
corr_pos[28] = 0.392400
corr_pos[29] = 0.392530
corr_pos[30] = 0.391826
corr_pos[31] = 0.391325
corr_pos[32] = 0.379188
corr_pos[33] = 0.376449
corr_pos[34] = 0.373195
corr_pos[35] = 0.369588
corr_pos[36] = 0.343021
corr_pos[37] = 0.336754
corr_pos[38] = 0.330310
corr_pos[39] = 0.323447
corr_pos[40] = 0.281171
corr_pos[41] = 0.272735
corr_pos[42] = 0.263888
corr_pos[43] = 0.254469
corr_pos[44] = 0.203024
corr_pos[45] = 0.192980
corr_pos[46] = 0.182359
corr_pos[47] = 0.170780
corr_pos[48] = 0.111580
corr_pos[49] = 0.101222
corr_pos[50] = 0.090051
corr_pos[51] = 0.077918
corr_pos[52] = 0.015225
corr_pos[53] = 0.003876
corr_pos[54] = -0.007756
corr_pos[55] = -0.020383
corr_pos[56] = -0.084910
corr_pos[57] = -0.096848
corr_pos[58] = -0.108732
corr_pos[59] = -0.121432
corr_pos[60] = -0.184349
corr_pos[61] = -0.195904
corr_pos[62] = -0.207113
corr_pos[63] = -0.219319
corr_pos[64] = -0.274799
corr_pos[65] = -0.284942
corr_pos[66] = -0.294809
corr_pos[67] = -0.305437
corr_pos[68] = -0.352114
corr_pos[69] = -0.359689
corr_pos[70] = -0.367451
corr_pos[71] = -0.375629
corr_pos[72] = -0.404347
corr_pos[73] = -0.407683
corr_pos[74] = -0.410857
corr_pos[75] = -0.414904
corr_pos[76] = -0.424625
corr_pos[77] = -0.424357
corr_pos[78] = -0.424411
corr_pos[79] = -0.424615
corr_pos[80] = -0.421392
corr_pos[81] = -0.419977
corr_pos[82] = -0.417860
corr_pos[83] = -0.416400
corr_pos[84] = -0.398108
corr_pos[85] = -0.392613
corr_pos[86] = -0.386455
corr_pos[87] = -0.380338
corr_pos[88] = -0.341288
corr_pos[89] = -0.332298
corr_pos[90] = -0.322767
corr_pos[91] = -0.311630
corr_pos[92] = -0.256798
corr_pos[93] = -0.244808
corr_pos[94] = -0.232932
corr_pos[95] = -0.219785
corr_pos[96] = -0.158685
corr_pos[97] = -0.146198
corr_pos[98] = -0.130743
corr_pos[99] = -0.054066
corr_pos[100] = -0.001498
corr_pos[101] = 0.012010
corr_pos[102] = 0.025195
corr_pos[103] = 0.094982
corr_pos[104] = 0.109235
corr_pos[105] = 0.120813
corr_pos[106] = 0.179893
corr_pos[107] = 0.192147
corr_pos[108] = 0.201902
corr_pos[109] = 0.245092
corr_pos[110] = 0.250501
corr_pos[111] = 0.255536
corr_pos[112] = 0.280598
corr_pos[113] = 0.280673
corr_pos[114] = 0.282529
corr_pos[115] = 0.293286
corr_pos[116] = 0.292713
corr_pos[117] = 0.291123
corr_pos[118] = 0.288721
corr_pos[119] = 0.288260
corr_pos[120] = 0.286480
corr_pos[121] = 0.271630
corr_pos[122] = 0.268004
corr_pos[123] = 0.265418
corr_pos[124] = 0.239187
corr_pos[125] = 0.233224
corr_pos[126] = 0.226652
corr_pos[127] = 0.189034
corr_pos[128] = 0.180302
corr_pos[129] = 0.170931
corr_pos[130] = 0.125760
corr_pos[131] = 0.116433
corr_pos[132] = 0.106845
corr_pos[133] = 0.057551
corr_pos[134] = 0.048531
corr_pos[135] = 0.038276
corr_pos[136] = -0.012292
corr_pos[137] = -0.021223
corr_pos[138] = -0.030046
corr_pos[139] = -0.077647
corr_pos[140] = -0.085863
corr_pos[141] = -0.093816
corr_pos[142] = -0.138532
corr_pos[143] = -0.145584
corr_pos[144] = -0.152699
corr_pos[145] = -0.192594
corr_pos[146] = -0.200980
corr_pos[147] = -0.208816
corr_pos[148] = -0.241983
corr_pos[149] = -0.248319
corr_pos[150] = -0.253789
corr_pos[151] = -0.276869
corr_pos[152] = -0.279240
corr_pos[153] = -0.281538
corr_pos[154] = -0.294317
corr_pos[155] = -0.295586
corr_pos[156] = -0.296029
corr_pos[157] = -0.297443
corr_pos[158] = -0.297185
corr_pos[159] = -0.295946
corr_pos[160] = -0.284463
corr_pos[161] = -0.282598
corr_pos[162] = -0.281260
corr_pos[163] = -0.256509
corr_pos[164] = -0.250326
corr_pos[165] = -0.244372
corr_pos[166] = -0.204043
corr_pos[167] = -0.196147
corr_pos[168] = -0.187928
corr_pos[169] = -0.131831
corr_pos[170] = -0.121351
corr_pos[171] = -0.110548
corr_pos[172] = -0.038951
corr_pos[173] = -0.025887
corr_pos[174] = -0.012501

File diff suppressed because it is too large Load Diff

View File

@@ -1,177 +0,0 @@
import time
from rich import box
from rich.console import Console
from rich.table import Table
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_put, fshclose
class FlomniOpticsMixin:
@staticmethod
def _get_user_param_safe(device, var):
param = dev[device].user_parameter
if not param or param.get(var) is None:
raise ValueError(f"Device {device} has no user parameter definition for {var}.")
return param.get(var)
def feye_out(self):
fshclose()
self.foptics_in()
feyex_out = self._get_user_param_safe("feyex", "out")
umv(dev.feyex, feyex_out)
epics_put("XOMNYI-XEYE-ACQ:0", 2)
# move rotation stage to zero to avoid problems with wires
umv(dev.fsamroy, 0)
# umv(dev.fttrx1, 9.2)
def feye_in(self):
bec.queue.next_dataset_number += 1
# umv(dev.fttrx1, -17)
feyex_in = self._get_user_param_safe("feyex", "in")
feyey_in = self._get_user_param_safe("feyey", "in")
umv(dev.feyex, feyex_in, dev.feyey, feyey_in)
#self.align.update_frame()
def _ffzp_in(self):
foptx_in = self._get_user_param_safe("foptx", "in")
fopty_in = self._get_user_param_safe("fopty", "in")
umv(dev.foptx, foptx_in)
umv(
dev.fopty, fopty_in
) # for 7.2567 keV and 150 mu, 60 nm fzp, loptz 83.6000 for propagation 1.4 mm
def ffzp_in(self):
"""
move in the flomni zone plate.
This will disable rt feedback, move the FZP and re-enabled the feedback.
"""
if "rtx" in dev and dev.rtx.enabled:
dev.rtx.controller.feedback_disable()
self._ffzp_in()
if "rtx" in dev and dev.rtx.enabled:
dev.rtx.controller.feedback_enable_with_reset()
def foptics_in(self):
"""
Move in the flomni optics, including the FZP and the OSA.
"""
self.ffzp_in()
self.fosa_in()
def foptics_out(self):
"""Move out the flomni optics"""
if "rtx" in dev and dev.rtx.enabled:
dev.rtx.controller.feedback_disable()
self.fosa_out()
fopty_out = self._get_user_param_safe("fopty", "out")
umv(dev.fopty, fopty_out)
if "rtx" in dev and dev.rtx.enabled:
time.sleep(1)
dev.rtx.controller.feedback_enable_with_reset()
def fosa_in(self):
# 6.2 keV, 170 um FZP
# umv(dev.losax, -1.4450000, dev.losay, -0.1800)
# umv(dev.losaz, -1)
# 6.7, 170
# umv(dev.losax, -1.4850, dev.losay, -0.1930)
# umv(dev.losaz, 1.0000)
# 7.2, 150
fosax_in = self._get_user_param_safe("fosax", "in")
fosay_in = self._get_user_param_safe("fosay", "in")
fosaz_in = self._get_user_param_safe("fosaz", "in")
dev.fosax.limits = [fosax_in - 0.1, fosax_in + 0.1]
dev.fosay.limits = [fosay_in - 0.1, fosay_in + 0.1]
dev.fosaz.limits = [fosaz_in - 0.1, fosaz_in + 0.1]
umv(dev.fosax, fosax_in, dev.fosay, fosay_in)
umv(dev.fosaz, fosaz_in)
# 11 kev
# umv(dev.losax, -1.161000, dev.losay, -0.196)
# umv(dev.losaz, 1.0000)
def fosa_out(self):
self.ensure_fheater_up()
curtain_is_triggered = dev.foptz.controller.fosaz_light_curtain_is_triggered()
if not curtain_is_triggered:
fosaz_out = self._get_user_param_safe("fosaz", "out")
dev.fosaz.limits = [fosaz_out - 0.1, fosaz_out + 0.1]
umv(dev.fosaz, fosaz_out)
fosax_out = self._get_user_param_safe("fosax", "out")
dev.fosax.limits = [fosax_out - 0.1, fosax_out + 0.1]
umv(dev.fosax, fosax_out)
def ffzp_info(self, mokev_val=-1):
if mokev_val == -1:
try:
mokev_val = dev.mokev.readback.get()
except:
print(
"Device mokev does not exist. You can specify the energy in keV as an argument instead."
)
return
foptz_val = dev.foptz.readback.get()
distance = -foptz_val + 43.15 + 36.7
print(f"\nThe sample is in a distance of \033[1m{distance:.1f} mm\033[0m from the FZP.\n")
print(f"At the current energy of {mokev_val:.4f} keV we have following options:\n")
diameters = [80e-6, 100e-6, 120e-6, 150e-6, 170e-6, 200e-6, 220e-6, 250e-6]
console = Console()
table = Table(title="Outermost zone width \033[1m60 nm\033[0m", box=box.SQUARE)
table.add_column("Diameter", justify="center")
table.add_column("Focal distance", justify="center")
table.add_column("Current beam size", justify="center")
wavelength = 1.2398e-9 / mokev_val
for diameter in diameters:
outermost_zonewidth = 60e-9
focal_distance = diameter * outermost_zonewidth / wavelength * 1000
beam_size = -diameter / (focal_distance * 1000) * (focal_distance - distance) * 1e9
table.add_row(
f"{diameter*1e6:.2f} microns",
f"{focal_distance:.2f} mm",
f"{beam_size:.2f} microns",
)
console.print(table)
diameters = [150e-6, 250e-6]
console = Console()
table = Table(title="Outermost zone width \033[1m30 nm\033[0m", box=box.SQUARE)
table.add_column("Diameter", justify="center")
table.add_column("Focal distance", justify="center")
table.add_column("Current beam size", justify="center")
wavelength = 1.2398e-9 / mokev_val
for diameter in diameters:
outermost_zonewidth = 30e-9
focal_distance = diameter * outermost_zonewidth / wavelength * 1000
beam_size = -diameter / (focal_distance * 1000) * (focal_distance - distance) * 1e9
table.add_row(
f"{diameter*1e6:.2f} microns",
f"{focal_distance:.2f} mm",
f"{beam_size:.2f} microns",
)
console.print(table)
fosaz_val = dev.fosaz.readback.get()
print("\nOSA Information:")
print(f" Current fosaz {fosaz_val:.1f}")
print(
f" The OSA will collide with a normal OMNY pin at fosaz \033[1m{(33-fosaz_val):.1f}\033[0m"
)
print(f" Remaining space: \033[1m{-fosaz_val+(33-foptz_val):.1f}\033[0m")

View File

@@ -1,225 +0,0 @@
import builtins
from bec_widgets.cli.client import BECDockArea
# from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_get, epics_put, fshopen, fshclose
if builtins.__dict__.get("bec") is not None:
bec = builtins.__dict__.get("bec")
dev = builtins.__dict__.get("dev")
umv = builtins.__dict__.get("umv")
umvr = builtins.__dict__.get("umvr")
class flomniGuiToolsError(Exception):
pass
class flomniGuiTools:
def __init__(self):
self.text_box = None
self.progressbar = None
def set_client(self, client):
self.client = client
self.gui = self.client.gui
def flomnigui_show_gui(self):
if "flomni" in self.gui.windows:
self.gui.flomni.show()
else:
self.gui.new("flomni")
def flomnigui_stop_gui(self):
self.gui.flomni.hide()
def flomnigui_raise(self):
self.gui.flomni.raise_window()
# def flomnigui_show_xeyealign(self):
# self.flomnigui_show_gui()
# if self.xeyegui is None:
# self.flomnigui_remove_all_docks()
# self.xeyegui = self.gui.flomni.new("xeyegui").new("XRayEye")
# # start live
# if not dev.cam_xeye.live_mode:
# dev.cam_xeye.live_mode = True
def flomnigui_show_xeyealign(self):
self.flomnigui_show_gui()
if self._flomnigui_check_attribute_not_exists("xeyegui"):
self.flomnigui_remove_all_docks()
self.xeyegui = self.gui.flomni.new("xeyegui").new("XRayEye")
# start live
if not dev.cam_xeye.live_mode:
dev.cam_xeye.live_mode = True
def _flomnigui_check_attribute_not_exists(self, attribute_name):
if hasattr(self.gui,"flomni"):
if hasattr(self.gui.flomni,attribute_name):
return False
return True
def flomnigui_show_cameras(self):
self.flomnigui_show_gui()
if self._flomnigui_check_attribute_not_exists("camera_gripper") or self._flomnigui_check_attribute_not_exists("camera_overview"):
self.flomnigui_remove_all_docks()
camera_gripper_image = self.gui.flomni.new("camera_gripper").new("Image")
if self._flomnicam_check_device_exists(dev.cam_flomni_gripper):
camera_gripper_image.image(("cam_flomni_gripper", "preview"))
camera_gripper_image.lock_aspect_ratio = True
camera_gripper_image.enable_fps_monitor = True
camera_gripper_image.enable_toolbar = False
camera_gripper_image.outer_axes = False
camera_gripper_image.inner_axes = False
dev.cam_flomni_gripper.start_live_mode()
else:
print("Cannot open camera_gripper. Device does not exist.")
camera_overview_image = self.gui.flomni.new("camera_overview").new("Image")
if self._flomnicam_check_device_exists(dev.cam_flomni_overview):
camera_overview_image.image(("cam_flomni_overview", "preview"))
camera_overview_image.lock_aspect_ratio = True
camera_overview_image.enable_fps_monitor = True
camera_overview_image.enable_toolbar = False
camera_overview_image.outer_axes = False
camera_overview_image.inner_axes = False
dev.cam_flomni_overview.start_live_mode()
else:
print("Cannot open camera_overview. Device does not exist.")
def flomnigui_remove_all_docks(self):
#dev.cam_flomni_overview.stop_live_mode()
#dev.cam_flomni_gripper.stop_live_mode()
#dev.cam_xeye.live_mode = False
self.gui.flomni.delete_all()
self.progressbar = None
self.text_box = None
def flomnigui_idle(self):
self.flomnigui_show_gui()
if self._flomnigui_check_attribute_not_exists("idle_text_box"):
self.flomnigui_remove_all_docks()
idle_text_box = self.gui.flomni.new("idle_textbox").new("TextBox")
text = (
"<pre>"
+ " ,---.,--. ,-----. ,--. ,--.,--. ,--.,--. \n"
+ "/ .-'| |' .-. '| `.' || ,'.| || | \n"
+ "| `-,| || | | || |'.'| || |' ' || | \n"
+ "| .-'| |' '-' '| | | || | ` || | \n"
+ "`--' `--' `-----' `--' `--'`--' `--'`--' \n"
+ "</pre>"
)
idle_text_box.set_html_text(text)
def flomnigui_docs(self, filename: str | None = None):
import csaxs_bec
from pathlib import Path
print("The general flOMNI documentation is at \nhttps://sls-csaxs.readthedocs.io/en/latest/user/ptychography/flomni.html#user-ptychography-flomni")
csaxs_bec_basepath = Path(csaxs_bec.__file__).parent
docs_folder = (
csaxs_bec_basepath /
"bec_ipython_client" / "plugins" / "flomni" / "docs"
)
if not docs_folder.is_dir():
raise NotADirectoryError(f"Docs folder not found: {docs_folder}")
pdfs = sorted(docs_folder.glob("*.pdf"))
if not pdfs:
raise FileNotFoundError(f"No PDF files found in {docs_folder}")
# --- Resolve PDF ------------------------------------------------------
if filename is not None:
pdf_file = docs_folder / filename
if not pdf_file.exists():
raise FileNotFoundError(f"Requested file not found: {filename}")
else:
print("\nAvailable flOMNI documentation PDFs:\n")
for i, pdf in enumerate(pdfs, start=1):
print(f" {i:2d}) {pdf.name}")
print()
while True:
try:
choice = int(input(f"Select a file (1{len(pdfs)}): "))
if 1 <= choice <= len(pdfs):
pdf_file = pdfs[choice - 1]
break
print(f"Enter a number between 1 and {len(pdfs)}.")
except ValueError:
print("Invalid input. Please enter a number.")
# --- GUI handling (active existence check) ----------------------------
self.flomnigui_show_gui()
if self._flomnigui_check_attribute_not_exists("PdfViewerWidget"):
self.flomnigui_remove_all_docks()
self.pdf_viewer = self.gui.flomni.new(widget="PdfViewerWidget")
# --- Load PDF ---------------------------------------------------------
self.pdf_viewer.PdfViewerWidget.load_pdf(str(pdf_file.resolve()))
print(f"\nLoaded: {pdf_file.name}\n")
def _flomnicam_check_device_exists(self, device):
try:
device
except:
return False
else:
return True
def flomnigui_show_progress(self):
self.flomnigui_show_gui()
if self._flomnigui_check_attribute_not_exists("progressbar"):
self.flomnigui_remove_all_docks()
# Add a new dock with a RingProgressBar widget
self.progressbar = self.gui.flomni.new("progressbar").new("RingProgressBar")
# Customize the size of the progress ring
self.progressbar.set_line_widths(20)
# Disable automatic updates and manually set the self.progressbar value
self.progressbar.enable_auto_updates(False)
# Set precision for the self.progressbar display
self.progressbar.set_precision(1) # Display self.progressbar with one decimal places
# Setting multiple rigns with different values
self.progressbar.set_number_of_bars(3)
self.progressbar.rings[0].set_update("manual")
self.progressbar.rings[1].set_update("manual")
self.progressbar.rings[2].set_update("scan")
# Set the values of the rings to 50, 75, and 25 from outer to inner ring
# self.progressbar.set_value([50, 75])
# Add a new dock with a TextBox widget
self.text_box = self.gui.flomni.new(name="progress_text").new("TextBox")
self._flomnigui_update_progress()
def _flomnigui_update_progress(self):
if self.progressbar is not None:
progress = self.progress["projection"] / self.progress["total_projections"] * 100
subtomo_progress = (
self.progress["subtomo_projection"]
/ self.progress["subtomo_total_projections"]
* 100
)
self.progressbar.set_value([progress, subtomo_progress, 0])
if self.text_box is not None:
text = f"Progress report:\n Tomo type: ....................... {self.progress['tomo_type']}\n Projection: ...................... {self.progress['projection']:.0f}\n Total projections expected ....... {self.progress['total_projections']}\n Angle: ........................... {self.progress['angle']}\n Current subtomo: ................. {self.progress['subtomo']}\n Current projection within subtomo: {self.progress['subtomo_projection']}\n Total projections per subtomo: ... {self.progress['subtomo_total_projections']}"
self.text_box.set_plain_text(text)
if __name__ == "__main__":
from bec_lib.client import BECClient
from bec_widgets.cli.client_utils import BECGuiClient
client = BECClient()
client.start()
client.gui = BECGuiClient()
flomni_gui = flomniGuiTools(client)
flomni_gui.flomnigui_show_gui()
flomni_gui.flomnigui_show_progress()

View File

@@ -1,277 +0,0 @@
from __future__ import annotations
import builtins
import os
import time
from typing import TYPE_CHECKING
from bec_lib import bec_logger
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_get, epics_put, fshopen, fshclose
logger = bec_logger.logger
# import builtins to avoid linter errors
bec = builtins.__dict__.get("bec")
dev = builtins.__dict__.get("dev")
umv = builtins.__dict__.get("umv")
umvr = builtins.__dict__.get("umvr")
if TYPE_CHECKING:
from bec_ipython_client.plugins.flomni import Flomni
class XrayEyeAlign:
# pixel calibration, multiply to get mm
labview=False
PIXEL_CALIBRATION = 0.1 / 113 # .2 with binning
def __init__(self, client, flomni: Flomni) -> None:
self.client = client
self.flomni = flomni
self.device_manager = client.device_manager
self.scans = client.scans
self.alignment_values = {}
self.flomni.reset_correction()
self.flomni.reset_tomo_alignment_fit()
def _reset_init_values(self):
self.shift_xy = [0, 0]
self._xray_fov_xy = [0, 0]
def save_frame(self):
epics_put("XOMNYI-XEYE-SAVFRAME:0", 1)
def update_frame(self,keep_shutter_open=False):
if self.labview:
epics_put("XOMNYI-XEYE-ACQDONE:0", 0)
if not self.labview:
self.flomni.flomnigui_show_xeyealign()
if not dev.cam_xeye.live_mode:
dev.cam_xeye.live_mode = True
epics_put("XOMNYI-XEYE-ACQ:0", 1)
if self.labview:
# wait for start live
while epics_get("XOMNYI-XEYE-ACQDONE:0") == 0:
time.sleep(0.5)
print("waiting for live view to start...")
fshopen()
if self.labview:
epics_put("XOMNYI-XEYE-ACQDONE:0", 0)
while epics_get("XOMNYI-XEYE-ACQDONE:0") == 0:
print("waiting for new frame...")
time.sleep(0.5)
time.sleep(0.5)
# stop live view
if not keep_shutter_open:
epics_put("XOMNYI-XEYE-ACQ:0", 0)
time.sleep(0.1)
fshclose()
print("got new frame")
else:
print("Staying in live view, shutter is and remains open!")
def tomo_rotate(self, val: float):
# pylint: disable=undefined-variable
umv(self.device_manager.devices.fsamroy, val)
def get_tomo_angle(self):
return self.device_manager.devices.fsamroy.readback.get()
def update_fov(self, k: int):
self._xray_fov_xy[0] = max(epics_get(f"XOMNYI-XEYE-XWIDTH_X:{k}"), self._xray_fov_xy[0])
self._xray_fov_xy[1] = max(0, self._xray_fov_xy[0])
@property
def movement_buttons_enabled(self):
return [epics_get("XOMNYI-XEYE-ENAMVX:0"), epics_get("XOMNYI-XEYE-ENAMVY:0")]
@movement_buttons_enabled.setter
def movement_buttons_enabled(self, enabled: bool):
enabled = int(enabled)
epics_put("XOMNYI-XEYE-ENAMVX:0", enabled)
epics_put("XOMNYI-XEYE-ENAMVY:0", enabled)
def send_message(self, msg: str):
epics_put("XOMNYI-XEYE-MESSAGE:0.DESC", msg)
def align(self,keep_shutter_open=False):
if not keep_shutter_open:
print("This routine can be called with paramter keep_shutter_open=True to keep the shutter always open")
self.send_message("Getting things ready. Please wait...")
#potential unresolved movement requests to zero
epics_put("XOMNYI-XEYE-MVX:0", 0)
epics_put("XOMNYI-XEYE-MVY:0", 0)
# reset shift xy and fov params
self._reset_init_values()
self.flomni.lights_off()
self.flomni.flomnigui_show_xeyealign()
self.flomni.flomnigui_raise()
self.tomo_rotate(0)
epics_put("XOMNYI-XEYE-ANGLE:0", 0)
self.flomni.feye_in()
self.flomni.laser_tracker_on()
self.flomni.feedback_enable_with_reset()
# disable movement buttons
self.movement_buttons_enabled = False
sample_name = self.flomni.sample_get_name(0)
epics_put("XOMNYI-XEYE-SAMPLENAME:0.DESC", sample_name)
# this makes sure we are in a defined state
self.flomni.feedback_disable()
epics_put("XOMNYI-XEYE-PIXELSIZE:0", self.PIXEL_CALIBRATION)
self.flomni.fosa_out()
fsamx_in = self.flomni._get_user_param_safe("fsamx", "in")
umv(dev.fsamx, fsamx_in - 0.25)
self.flomni.ffzp_in()
self.update_frame(keep_shutter_open)
# enable submit buttons
self.movement_buttons_enabled = False
epics_put("XOMNYI-XEYE-SUBMIT:0", 0)
epics_put("XOMNYI-XEYE-STEP:0", 0)
self.send_message("Submit center value of FZP.")
k = 0
while True:
if epics_get("XOMNYI-XEYE-SUBMIT:0") == 1:
val_x = epics_get(f"XOMNYI-XEYE-XVAL_X:{k}") / 2 * self.PIXEL_CALIBRATION # in mm
self.alignment_values[k] = val_x
print(f"Clicked position {k}: x {self.alignment_values[k]}")
rtx_position = dev.rtx.readback.get() / 1000
print(f"Current rtx position {rtx_position}")
self.alignment_values[k] -= rtx_position
print(f"Corrected position {k}: x {self.alignment_values[k]}")
if k == 0: # received center value of FZP
self.send_message("please wait ...")
self.movement_buttons_enabled = False
epics_put("XOMNYI-XEYE-SUBMIT:0", -1) # disable submit button
self.flomni.feedback_disable()
fsamx_in = self.flomni._get_user_param_safe("fsamx", "in")
umv(dev.fsamx, fsamx_in)
self.flomni.foptics_out()
self.flomni.feedback_disable()
umv(dev.fsamx, fsamx_in - 0.25)
if self.labview:
self.update_frame(keep_shutter_open)
epics_put("XOMNYI-XEYE-RECBG:0", 1)
while epics_get("XOMNYI-XEYE-RECBG:0") == 1:
time.sleep(0.5)
print("waiting for background frame...")
umv(dev.fsamx, fsamx_in)
time.sleep(0.5)
self.flomni.feedback_enable_with_reset()
self.update_frame(keep_shutter_open)
self.send_message("Adjust sample height and submit center")
epics_put("XOMNYI-XEYE-SUBMIT:0", 0)
self.movement_buttons_enabled = True
elif 1 <= k < 5: # received sample center value at samroy 0 ... 315
self.send_message("please wait ...")
epics_put("XOMNYI-XEYE-SUBMIT:0", -1)
self.movement_buttons_enabled = False
umv(dev.rtx, 0)
self.tomo_rotate(k * 45)
epics_put("XOMNYI-XEYE-ANGLE:0", self.get_tomo_angle())
self.update_frame(keep_shutter_open)
self.send_message("Submit sample center")
epics_put("XOMNYI-XEYE-SUBMIT:0", 0)
epics_put("XOMNYI-XEYE-ENAMVX:0", 1)
self.update_fov(k)
elif k == 5: # received sample center value at samroy 270 and done
self.send_message("done...")
epics_put("XOMNYI-XEYE-SUBMIT:0", -1) # disable submit button
self.movement_buttons_enabled = False
self.update_fov(k)
break
k += 1
epics_put("XOMNYI-XEYE-STEP:0", k)
_xrayeyalignmvx = epics_get("XOMNYI-XEYE-MVX:0")
if _xrayeyalignmvx != 0:
umvr(dev.rtx, _xrayeyalignmvx)
print(f"Current rtx position {dev.rtx.readback.get() / 1000}")
epics_put("XOMNYI-XEYE-MVX:0", 0)
if k > 0:
epics_put(f"XOMNYI-XEYE-STAGEPOSX:{k}", dev.rtx.readback.get() / 1000)
time.sleep(3)
self.update_frame(keep_shutter_open)
if k < 2:
# allow movements, store movements to calculate center
_xrayeyalignmvy = epics_get("XOMNYI-XEYE-MVY:0")
if _xrayeyalignmvy != 0:
self.flomni.feedback_disable()
umvr(dev.fsamy, _xrayeyalignmvy / 1000)
time.sleep(2)
epics_put("XOMNYI-XEYE-MVY:0", 0)
self.flomni.feedback_enable_with_reset()
self.update_frame(keep_shutter_open)
time.sleep(0.2)
self.write_output()
fovx = self._xray_fov_xy[0] * self.PIXEL_CALIBRATION * 1000 / 2
fovy = self._xray_fov_xy[1] * self.PIXEL_CALIBRATION * 1000 / 2
self.tomo_rotate(0)
umv(dev.rtx, 0)
# free camera
if self.labview:
epics_put("XOMNYI-XEYE-ACQ:0", 2)
if keep_shutter_open and not self.labview:
if self.flomni.OMNYTools.yesno("Close the shutter now?","y"):
fshclose()
epics_put("XOMNYI-XEYE-ACQ:0", 0)
if not self.labview:
self.flomni.flomnigui_idle()
print(
f"The largest field of view from the xrayeyealign was \nfovx = {fovx:.0f} microns, fovy"
f" = {fovy:.0f} microns"
)
print("Use the matlab routine to FIT the current alignment...")
print("Then LOAD ALIGNMENT PARAMETERS by running flomni.read_alignment_offset()\n")
def write_output(self):
file = os.path.expanduser("~/Data10/specES1/internal/xrayeye_alignmentvalues")
if not os.path.exists(file):
os.makedirs(os.path.dirname(file), exist_ok=True)
with open(file, "w") as alignment_values_file:
alignment_values_file.write("angle\thorizontal\n")
for k in range(1, 6):
fovx_offset = self.alignment_values[0] - self.alignment_values[k]
print(f"Writing to file new alignment: number {k}, value x {fovx_offset}")
alignment_values_file.write(f"{(k-1)*45}\t{fovx_offset*1000}\n")

View File

@@ -1 +0,0 @@
from .omny import OMNY

View File

@@ -1,715 +0,0 @@
corr_elements = 357
corr_angle[0] = 0.097400
corr_angle[1] = 0.603500
corr_angle[2] = 1.134200
corr_angle[3] = 1.625000
corr_angle[4] = 2.162200
corr_angle[5] = 2.700100
corr_angle[6] = 3.191600
corr_angle[7] = 3.714300
corr_angle[8] = 4.223200
corr_angle[9] = 4.730900
corr_angle[10] = 5.253300
corr_angle[11] = 5.743300
corr_angle[12] = 6.279200
corr_angle[13] = 6.782900
corr_angle[14] = 7.301200
corr_angle[15] = 7.808100
corr_angle[16] = 8.325300
corr_angle[17] = 8.859400
corr_angle[18] = 9.359400
corr_angle[19] = 9.887900
corr_angle[20] = 10.395400
corr_angle[21] = 10.930700
corr_angle[22] = 11.415400
corr_angle[23] = 11.928900
corr_angle[24] = 12.456900
corr_angle[25] = 12.955900
corr_angle[26] = 13.479000
corr_angle[27] = 13.982700
corr_angle[28] = 14.500900
corr_angle[29] = 15.016200
corr_angle[30] = 15.528000
corr_angle[31] = 16.053800
corr_angle[32] = 16.562800
corr_angle[33] = 17.076600
corr_angle[34] = 17.592400
corr_angle[35] = 18.094100
corr_angle[36] = 18.623800
corr_angle[37] = 19.118400
corr_angle[38] = 19.655000
corr_angle[39] = 20.143900
corr_angle[40] = 20.672200
corr_angle[41] = 21.171500
corr_angle[42] = 21.696300
corr_angle[43] = 22.215900
corr_angle[44] = 22.728900
corr_angle[45] = 23.233100
corr_angle[46] = 23.760000
corr_angle[47] = 24.267700
corr_angle[48] = 24.792100
corr_angle[49] = 25.287900
corr_angle[50] = 25.824600
corr_angle[51] = 26.321900
corr_angle[52] = 26.842600
corr_angle[53] = 27.337200
corr_angle[54] = 27.873500
corr_angle[55] = 28.373900
corr_angle[56] = 28.895900
corr_angle[57] = 29.404900
corr_angle[58] = 29.926700
corr_angle[59] = 30.439300
corr_angle[60] = 30.963700
corr_angle[61] = 31.460000
corr_angle[62] = 31.989500
corr_angle[63] = 32.489700
corr_angle[64] = 33.026400
corr_angle[65] = 33.516500
corr_angle[66] = 34.044000
corr_angle[67] = 34.547700
corr_angle[68] = 35.070800
corr_angle[69] = 35.578400
corr_angle[70] = 36.103200
corr_angle[71] = 36.603200
corr_angle[72] = 37.128200
corr_angle[73] = 37.645200
corr_angle[74] = 38.164300
corr_angle[75] = 38.662100
corr_angle[76] = 39.191000
corr_angle[77] = 39.693400
corr_angle[78] = 40.222500
corr_angle[79] = 40.719500
corr_angle[80] = 41.247000
corr_angle[81] = 41.755700
corr_angle[82] = 42.271300
corr_angle[83] = 42.767600
corr_angle[84] = 43.302200
corr_angle[85] = 43.818700
corr_angle[86] = 44.330000
corr_angle[87] = 44.835300
corr_angle[88] = 45.359800
corr_angle[89] = 45.867200
corr_angle[90] = 46.396200
corr_angle[91] = 46.895000
corr_angle[92] = 47.411500
corr_angle[93] = 47.915200
corr_angle[94] = 48.436600
corr_angle[95] = 48.946100
corr_angle[96] = 49.472300
corr_angle[97] = 49.979800
corr_angle[98] = 50.503300
corr_angle[99] = 51.008700
corr_angle[100] = 51.535000
corr_angle[101] = 52.036700
corr_angle[102] = 52.563700
corr_angle[103] = 53.063600
corr_angle[104] = 53.591700
corr_angle[105] = 54.091200
corr_angle[106] = 54.618900
corr_angle[107] = 55.116900
corr_angle[108] = 55.636100
corr_angle[109] = 56.143100
corr_angle[110] = 56.672200
corr_angle[111] = 57.172900
corr_angle[112] = 57.704600
corr_angle[113] = 58.204800
corr_angle[114] = 58.728600
corr_angle[115] = 59.239500
corr_angle[116] = 59.768400
corr_angle[117] = 60.268300
corr_angle[118] = 60.788800
corr_angle[119] = 61.289300
corr_angle[120] = 61.813300
corr_angle[121] = 62.310800
corr_angle[122] = 62.836700
corr_angle[123] = 63.353700
corr_angle[124] = 63.866600
corr_angle[125] = 64.377200
corr_angle[126] = 64.906600
corr_angle[127] = 65.414000
corr_angle[128] = 65.937100
corr_angle[129] = 66.429400
corr_angle[130] = 66.970000
corr_angle[131] = 67.459200
corr_angle[132] = 67.996400
corr_angle[133] = 68.499800
corr_angle[134] = 69.014500
corr_angle[135] = 69.509500
corr_angle[136] = 70.044000
corr_angle[137] = 70.543200
corr_angle[138] = 71.079400
corr_angle[139] = 71.579300
corr_angle[140] = 72.103500
corr_angle[141] = 72.607000
corr_angle[142] = 73.137100
corr_angle[143] = 73.633000
corr_angle[144] = 74.164500
corr_angle[145] = 74.660200
corr_angle[146] = 75.180600
corr_angle[147] = 75.674200
corr_angle[148] = 76.215400
corr_angle[149] = 76.718900
corr_angle[150] = 77.242300
corr_angle[151] = 77.752000
corr_angle[152] = 78.279300
corr_angle[153] = 78.780500
corr_angle[154] = 79.314900
corr_angle[155] = 79.424500
corr_angle[156] = 79.807000
corr_angle[157] = 80.336500
corr_angle[158] = 80.338700
corr_angle[159] = 80.835300
corr_angle[160] = 81.367100
corr_angle[161] = 81.376100
corr_angle[162] = 81.859000
corr_angle[163] = 82.382300
corr_angle[164] = 82.384000
corr_angle[165] = 82.881100
corr_angle[166] = 83.415000
corr_angle[167] = 83.421600
corr_angle[168] = 83.917100
corr_angle[169] = 84.439200
corr_angle[170] = 84.439300
corr_angle[171] = 84.947400
corr_angle[172] = 85.472700
corr_angle[173] = 85.987700
corr_angle[174] = 86.512400
corr_angle[175] = 87.009500
corr_angle[176] = 87.536500
corr_angle[177] = 88.035600
corr_angle[178] = 88.560100
corr_angle[179] = 89.057600
corr_angle[180] = 89.583200
corr_angle[181] = 90.090500
corr_angle[182] = 90.614600
corr_angle[183] = 91.119900
corr_angle[184] = 91.638300
corr_angle[185] = 92.153300
corr_angle[186] = 92.681600
corr_angle[187] = 93.181800
corr_angle[188] = 93.710900
corr_angle[189] = 94.206100
corr_angle[190] = 94.732700
corr_angle[191] = 95.226600
corr_angle[192] = 95.766400
corr_angle[193] = 96.259000
corr_angle[194] = 96.783400
corr_angle[195] = 97.283100
corr_angle[196] = 97.811500
corr_angle[197] = 98.323600
corr_angle[198] = 98.839400
corr_angle[199] = 99.350700
corr_angle[200] = 99.880200
corr_angle[201] = 100.378100
corr_angle[202] = 100.913300
corr_angle[203] = 101.405000
corr_angle[204] = 101.935700
corr_angle[205] = 102.426300
corr_angle[206] = 102.957300
corr_angle[207] = 103.456500
corr_angle[208] = 103.985100
corr_angle[209] = 104.490300
corr_angle[210] = 105.015100
corr_angle[211] = 105.518400
corr_angle[212] = 106.047400
corr_angle[213] = 106.551100
corr_angle[214] = 107.077100
corr_angle[215] = 107.575800
corr_angle[216] = 108.115200
corr_angle[217] = 108.598800
corr_angle[218] = 109.129100
corr_angle[219] = 109.626200
corr_angle[220] = 110.158400
corr_angle[221] = 110.661700
corr_angle[222] = 111.188600
corr_angle[223] = 111.695000
corr_angle[224] = 112.216400
corr_angle[225] = 112.720000
corr_angle[226] = 113.246200
corr_angle[227] = 113.757100
corr_angle[228] = 114.281900
corr_angle[229] = 114.780000
corr_angle[230] = 115.306800
corr_angle[231] = 115.799800
corr_angle[232] = 116.328400
corr_angle[233] = 116.829900
corr_angle[234] = 117.355400
corr_angle[235] = 117.858200
corr_angle[236] = 118.380600
corr_angle[237] = 118.893200
corr_angle[238] = 119.418200
corr_angle[239] = 119.921000
corr_angle[240] = 120.446100
corr_angle[241] = 120.953800
corr_angle[242] = 121.480300
corr_angle[243] = 121.977600
corr_angle[244] = 122.507100
corr_angle[245] = 122.996200
corr_angle[246] = 123.529600
corr_angle[247] = 124.032200
corr_angle[248] = 124.554800
corr_angle[249] = 125.057800
corr_angle[250] = 125.580800
corr_angle[251] = 126.090000
corr_angle[252] = 126.611600
corr_angle[253] = 127.127000
corr_angle[254] = 127.650900
corr_angle[255] = 128.153700
corr_angle[256] = 128.677200
corr_angle[257] = 129.170800
corr_angle[258] = 129.703000
corr_angle[259] = 130.194900
corr_angle[260] = 130.733600
corr_angle[261] = 131.228300
corr_angle[262] = 131.756900
corr_angle[263] = 132.263200
corr_angle[264] = 132.784700
corr_angle[265] = 133.296300
corr_angle[266] = 133.818800
corr_angle[267] = 134.318900
corr_angle[268] = 134.846800
corr_angle[269] = 135.344800
corr_angle[270] = 135.876000
corr_angle[271] = 136.372600
corr_angle[272] = 136.902700
corr_angle[273] = 137.397800
corr_angle[274] = 137.926800
corr_angle[275] = 138.428000
corr_angle[276] = 138.953700
corr_angle[277] = 139.461300
corr_angle[278] = 139.987800
corr_angle[279] = 140.492600
corr_angle[280] = 141.017900
corr_angle[281] = 141.524000
corr_angle[282] = 142.061200
corr_angle[283] = 142.545400
corr_angle[284] = 143.069900
corr_angle[285] = 143.568700
corr_angle[286] = 144.102200
corr_angle[287] = 144.596200
corr_angle[288] = 145.126400
corr_angle[289] = 145.626900
corr_angle[290] = 146.158700
corr_angle[291] = 146.662200
corr_angle[292] = 147.184700
corr_angle[293] = 147.692300
corr_angle[294] = 148.225900
corr_angle[295] = 148.716000
corr_angle[296] = 149.243400
corr_angle[297] = 149.739400
corr_angle[298] = 150.272400
corr_angle[299] = 150.762100
corr_angle[300] = 151.301800
corr_angle[301] = 151.796300
corr_angle[302] = 152.333500
corr_angle[303] = 152.833100
corr_angle[304] = 153.363600
corr_angle[305] = 153.862900
corr_angle[306] = 154.396100
corr_angle[307] = 154.895400
corr_angle[308] = 155.417700
corr_angle[309] = 155.916900
corr_angle[310] = 156.451600
corr_angle[311] = 156.942700
corr_angle[312] = 157.467600
corr_angle[313] = 157.970900
corr_angle[314] = 158.501100
corr_angle[315] = 158.999600
corr_angle[316] = 159.526100
corr_angle[317] = 160.028100
corr_angle[318] = 160.555800
corr_angle[319] = 161.067700
corr_angle[320] = 161.597300
corr_angle[321] = 162.091300
corr_angle[322] = 162.616600
corr_angle[323] = 163.107400
corr_angle[324] = 163.639100
corr_angle[325] = 164.139700
corr_angle[326] = 164.672500
corr_angle[327] = 165.176800
corr_angle[328] = 165.698600
corr_angle[329] = 166.205400
corr_angle[330] = 166.727300
corr_angle[331] = 167.238600
corr_angle[332] = 167.771500
corr_angle[333] = 168.265000
corr_angle[334] = 168.794800
corr_angle[335] = 169.293800
corr_angle[336] = 169.813300
corr_angle[337] = 170.320200
corr_angle[338] = 170.845100
corr_angle[339] = 171.344000
corr_angle[340] = 171.866200
corr_angle[341] = 172.375300
corr_angle[342] = 172.899400
corr_angle[343] = 173.404400
corr_angle[344] = 173.928500
corr_angle[345] = 174.430800
corr_angle[346] = 174.827800
corr_angle[347] = 175.460400
corr_angle[348] = 175.993100
corr_angle[349] = 176.492100
corr_angle[350] = 177.014200
corr_angle[351] = 177.512100
corr_angle[352] = 178.044200
corr_angle[353] = 178.643800
corr_angle[354] = 179.067200
corr_angle[355] = 179.571600
corr_angle[356] = 180.093700
corr_pos[0] = -0.814519
corr_pos[1] = -0.810675
corr_pos[2] = -0.806338
corr_pos[3] = -0.802047
corr_pos[4] = -0.797044
corr_pos[5] = -0.791712
corr_pos[6] = -0.786558
corr_pos[7] = -0.780781
corr_pos[8] = -0.774864
corr_pos[9] = -0.768674
corr_pos[10] = -0.762005
corr_pos[11] = -0.755474
corr_pos[12] = -0.748024
corr_pos[13] = -0.740730
corr_pos[14] = -0.732929
corr_pos[15] = -0.725011
corr_pos[16] = -0.716637
corr_pos[17] = -0.707676
corr_pos[18] = -0.698861
corr_pos[19] = -0.686245
corr_pos[20] = -0.676596
corr_pos[21] = -0.663643
corr_pos[22] = -0.655664
corr_pos[23] = -0.642249
corr_pos[24] = -0.633516
corr_pos[25] = -0.621402
corr_pos[26] = -0.612846
corr_pos[27] = -0.599978
corr_pos[28] = -0.592135
corr_pos[29] = -0.577949
corr_pos[30] = -0.570695
corr_pos[31] = -0.555560
corr_pos[32] = -0.549015
corr_pos[33] = -0.532162
corr_pos[34] = -0.524479
corr_pos[35] = -0.507848
corr_pos[36] = -0.500301
corr_pos[37] = -0.484361
corr_pos[38] = -0.477365
corr_pos[39] = -0.461751
corr_pos[40] = -0.455963
corr_pos[41] = -0.439438
corr_pos[42] = -0.436103
corr_pos[43] = -0.420587
corr_pos[44] = -0.417361
corr_pos[45] = -0.402270
corr_pos[46] = -0.400459
corr_pos[47] = -0.384745
corr_pos[48] = -0.385280
corr_pos[49] = -0.371217
corr_pos[50] = -0.373612
corr_pos[51] = -0.361838
corr_pos[52] = -0.365771
corr_pos[53] = -0.354641
corr_pos[54] = -0.360647
corr_pos[55] = -0.351446
corr_pos[56] = -0.359147
corr_pos[57] = -0.348696
corr_pos[58] = -0.359348
corr_pos[59] = -0.349962
corr_pos[60] = -0.360782
corr_pos[61] = -0.355040
corr_pos[62] = -0.367441
corr_pos[63] = -0.360511
corr_pos[64] = -0.372617
corr_pos[65] = -0.366120
corr_pos[66] = -0.377568
corr_pos[67] = -0.370362
corr_pos[68] = -0.380918
corr_pos[69] = -0.372553
corr_pos[70] = -0.381460
corr_pos[71] = -0.371828
corr_pos[72] = -0.379428
corr_pos[73] = -0.368465
corr_pos[74] = -0.374297
corr_pos[75] = -0.360340
corr_pos[76] = -0.365429
corr_pos[77] = -0.349168
corr_pos[78] = -0.351544
corr_pos[79] = -0.332514
corr_pos[80] = -0.333505
corr_pos[81] = -0.313316
corr_pos[82] = -0.313014
corr_pos[83] = -0.291107
corr_pos[84] = -0.287807
corr_pos[85] = -0.264483
corr_pos[86] = -0.260891
corr_pos[87] = -0.236646
corr_pos[88] = -0.231362
corr_pos[89] = -0.205833
corr_pos[90] = -0.200663
corr_pos[91] = -0.174834
corr_pos[92] = -0.171662
corr_pos[93] = -0.146200
corr_pos[94] = -0.142890
corr_pos[95] = -0.118389
corr_pos[96] = -0.112895
corr_pos[97] = -0.088879
corr_pos[98] = -0.084146
corr_pos[99] = -0.061625
corr_pos[100] = -0.054742
corr_pos[101] = -0.032741
corr_pos[102] = -0.026725
corr_pos[103] = -0.004827
corr_pos[104] = 0.002678
corr_pos[105] = 0.024418
corr_pos[106] = 0.031105
corr_pos[107] = 0.052334
corr_pos[108] = 0.060072
corr_pos[109] = 0.081470
corr_pos[110] = 0.088550
corr_pos[111] = 0.109685
corr_pos[112] = 0.116675
corr_pos[113] = 0.136298
corr_pos[114] = 0.142152
corr_pos[115] = 0.161986
corr_pos[116] = 0.166996
corr_pos[117] = 0.186466
corr_pos[118] = 0.190874
corr_pos[119] = 0.208729
corr_pos[120] = 0.212714
corr_pos[121] = 0.229992
corr_pos[122] = 0.232685
corr_pos[123] = 0.248748
corr_pos[124] = 0.249688
corr_pos[125] = 0.264768
corr_pos[126] = 0.264432
corr_pos[127] = 0.278801
corr_pos[128] = 0.278424
corr_pos[129] = 0.289656
corr_pos[130] = 0.289612
corr_pos[131] = 0.299899
corr_pos[132] = 0.299782
corr_pos[133] = 0.307473
corr_pos[134] = 0.309489
corr_pos[135] = 0.315999
corr_pos[136] = 0.317413
corr_pos[137] = 0.325060
corr_pos[138] = 0.325931
corr_pos[139] = 0.332544
corr_pos[140] = 0.332095
corr_pos[141] = 0.338738
corr_pos[142] = 0.337864
corr_pos[143] = 0.343909
corr_pos[144] = 0.342973
corr_pos[145] = 0.348449
corr_pos[146] = 0.346060
corr_pos[147] = 0.351949
corr_pos[148] = 0.349873
corr_pos[149] = 0.354969
corr_pos[150] = 0.352375
corr_pos[151] = 0.358388
corr_pos[152] = 0.354736
corr_pos[153] = 0.359539
corr_pos[154] = 0.354369
corr_pos[155] = 0.358549
corr_pos[156] = 0.353217
corr_pos[157] = 0.355795
corr_pos[158] = 0.351299
corr_pos[159] = 0.352922
corr_pos[160] = 0.346933
corr_pos[161] = 0.350201
corr_pos[162] = 0.343937
corr_pos[163] = 0.349304
corr_pos[164] = 0.344857
corr_pos[165] = 0.347471
corr_pos[166] = 0.335793
corr_pos[167] = 0.341109
corr_pos[168] = 0.330453
corr_pos[169] = 0.326576
corr_pos[170] = 0.320299
corr_pos[171] = 0.315348
corr_pos[172] = 0.300744
corr_pos[173] = 0.294366
corr_pos[174] = 0.280438
corr_pos[175] = 0.273618
corr_pos[176] = 0.259335
corr_pos[177] = 0.251464
corr_pos[178] = 0.237247
corr_pos[179] = 0.229092
corr_pos[180] = 0.214882
corr_pos[181] = 0.207363
corr_pos[182] = 0.193246
corr_pos[183] = 0.185868
corr_pos[184] = 0.173256
corr_pos[185] = 0.165378
corr_pos[186] = 0.153853
corr_pos[187] = 0.147031
corr_pos[188] = 0.135535
corr_pos[189] = 0.129435
corr_pos[190] = 0.119843
corr_pos[191] = 0.115062
corr_pos[192] = 0.107115
corr_pos[193] = 0.105182
corr_pos[194] = 0.099647
corr_pos[195] = 0.098162
corr_pos[196] = 0.094628
corr_pos[197] = 0.095257
corr_pos[198] = 0.084490
corr_pos[199] = 0.085389
corr_pos[200] = 0.074302
corr_pos[201] = 0.075265
corr_pos[202] = 0.063623
corr_pos[203] = 0.064487
corr_pos[204] = 0.052841
corr_pos[205] = 0.053559
corr_pos[206] = 0.042022
corr_pos[207] = 0.043321
corr_pos[208] = 0.032826
corr_pos[209] = 0.032277
corr_pos[210] = 0.022169
corr_pos[211] = 0.020740
corr_pos[212] = 0.010378
corr_pos[213] = 0.008668
corr_pos[214] = -0.001930
corr_pos[215] = -0.003882
corr_pos[216] = -0.014694
corr_pos[217] = -0.016629
corr_pos[218] = -0.026380
corr_pos[219] = -0.028069
corr_pos[220] = -0.037125
corr_pos[221] = -0.039429
corr_pos[222] = -0.047773
corr_pos[223] = -0.049261
corr_pos[224] = -0.056872
corr_pos[225] = -0.058756
corr_pos[226] = -0.065279
corr_pos[227] = -0.066859
corr_pos[228] = -0.073027
corr_pos[229] = -0.074253
corr_pos[230] = -0.079062
corr_pos[231] = -0.079800
corr_pos[232] = -0.084350
corr_pos[233] = -0.084805
corr_pos[234] = -0.088621
corr_pos[235] = -0.088437
corr_pos[236] = -0.092166
corr_pos[237] = -0.090769
corr_pos[238] = -0.093820
corr_pos[239] = -0.091724
corr_pos[240] = -0.094152
corr_pos[241] = -0.090866
corr_pos[242] = -0.092575
corr_pos[243] = -0.089239
corr_pos[244] = -0.089666
corr_pos[245] = -0.086864
corr_pos[246] = -0.087183
corr_pos[247] = -0.083974
corr_pos[248] = -0.083709
corr_pos[249] = -0.079848
corr_pos[250] = -0.078494
corr_pos[251] = -0.072782
corr_pos[252] = -0.069638
corr_pos[253] = -0.063004
corr_pos[254] = -0.058599
corr_pos[255] = -0.051737
corr_pos[256] = -0.046451
corr_pos[257] = -0.040238
corr_pos[258] = -0.034071
corr_pos[259] = -0.028578
corr_pos[260] = -0.021481
corr_pos[261] = -0.016346
corr_pos[262] = -0.009475
corr_pos[263] = -0.004141
corr_pos[264] = 0.002780
corr_pos[265] = 0.008455
corr_pos[266] = 0.015507
corr_pos[267] = 0.021672
corr_pos[268] = 0.029704
corr_pos[269] = 0.036662
corr_pos[270] = 0.044794
corr_pos[271] = 0.052031
corr_pos[272] = 0.061478
corr_pos[273] = 0.069150
corr_pos[274] = 0.078715
corr_pos[275] = 0.087785
corr_pos[276] = 0.098593
corr_pos[277] = 0.107863
corr_pos[278] = 0.118256
corr_pos[279] = 0.127631
corr_pos[280] = 0.139011
corr_pos[281] = 0.150077
corr_pos[282] = 0.162154
corr_pos[283] = 0.173758
corr_pos[284] = 0.186998
corr_pos[285] = 0.200111
corr_pos[286] = 0.214116
corr_pos[287] = 0.227291
corr_pos[288] = 0.240662
corr_pos[289] = 0.252955
corr_pos[290] = 0.265359
corr_pos[291] = 0.275995
corr_pos[292] = 0.287613
corr_pos[293] = 0.295789
corr_pos[294] = 0.306424
corr_pos[295] = 0.313027
corr_pos[296] = 0.322181
corr_pos[297] = 0.329313
corr_pos[298] = 0.338191
corr_pos[299] = 0.345243
corr_pos[300] = 0.353316
corr_pos[301] = 0.360491
corr_pos[302] = 0.367891
corr_pos[303] = 0.375027
corr_pos[304] = 0.380865
corr_pos[305] = 0.388354
corr_pos[306] = 0.395257
corr_pos[307] = 0.401478
corr_pos[308] = 0.408087
corr_pos[309] = 0.414083
corr_pos[310] = 0.420361
corr_pos[311] = 0.424284
corr_pos[312] = 0.429614
corr_pos[313] = 0.433888
corr_pos[314] = 0.438529
corr_pos[315] = 0.442302
corr_pos[316] = 0.445899
corr_pos[317] = 0.449014
corr_pos[318] = 0.451693
corr_pos[319] = 0.453795
corr_pos[320] = 0.455132
corr_pos[321] = 0.455438
corr_pos[322] = 0.455334
corr_pos[323] = 0.454055
corr_pos[324] = 0.451146
corr_pos[325] = 0.447259
corr_pos[326] = 0.442478
corr_pos[327] = 0.437520
corr_pos[328] = 0.432297
corr_pos[329] = 0.426442
corr_pos[330] = 0.418918
corr_pos[331] = 0.411040
corr_pos[332] = 0.402610
corr_pos[333] = 0.394491
corr_pos[334] = 0.383925
corr_pos[335] = 0.374590
corr_pos[336] = 0.363650
corr_pos[337] = 0.353143
corr_pos[338] = 0.339756
corr_pos[339] = 0.328074
corr_pos[340] = 0.315463
corr_pos[341] = 0.302641
corr_pos[342] = 0.288898
corr_pos[343] = 0.275134
corr_pos[344] = 0.260308
corr_pos[345] = 0.245582
corr_pos[346] = 0.233584
corr_pos[347] = 0.213812
corr_pos[348] = 0.196540
corr_pos[349] = 0.179844
corr_pos[350] = 0.161839
corr_pos[351] = 0.144160
corr_pos[352] = 0.124715
corr_pos[353] = 0.102123
corr_pos[354] = 0.085736
corr_pos[355] = 0.065743
corr_pos[356] = 0.044511

View File

@@ -1,171 +0,0 @@
import builtins
from bec_widgets.cli.client import BECDockArea
# from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_get, epics_put, fshopen, fshclose
if builtins.__dict__.get("bec") is not None:
bec = builtins.__dict__.get("bec")
dev = builtins.__dict__.get("dev")
umv = builtins.__dict__.get("umv")
umvr = builtins.__dict__.get("umvr")
class OMNYGuiToolsError(Exception):
pass
class OMNYGuiTools:
def __init__(self, client):
self.gui = getattr(client, "gui", None)
self.gui_window = self.gui.windows['main'].widget
self.fig200 = None
self.fig201 = None
self.fig202 = None
self.fig203 = None
self.progressbar = None
self.text_box = None
self.idle_text_box = None
def omnygui_show_gui(self):
self.gui_window.show()
def omnygui_stop_gui(self):
self.gui_window.hide()
def _omnycam_parking(self):
self.omnygui_show_omnycam_parking()
def omnygui_show_omnycam_parking(self):
self.omnygui_show_gui()
if self.fig200 is None:
self._omnycam_clear()
self.fig200 = self.gui_window.add_dock(name="omnycam200").add_widget("BECImageWidget")
if self._omnycam_check_device_exists(dev.cam200):
fig = self.fig200.image("cam200")
fig.set_rotation(deg_90=3)
self.fig200.lock_aspect_ratio(True)
else:
print("Cannot open cam200. Device does not exist.")
self.fig203 = self.gui_window.add_dock(name="omnycam203").add_widget("BECImageWidget")
if self._omnycam_check_device_exists(dev.cam203):
fig = self.fig203.image("cam203")
fig.set_rotation(deg_90=3)
self.fig203.lock_aspect_ratio(True)
else:
print("Cannot open cam203. Device does not exist.")
try:
self.gui_window.remove_dock(name="default_figure")
except:
pass
def omnygui_remove_all_docks(self):
self.gui_window.clear_all()
self.fig200 = None
self.fig201 = None
self.fig202 = None
self.fig203 = None
self.progressbar = None
self.text_box = None
self.idle_text_box = None
def omnygui_idle(self):
self.omnygui_show_gui()
if self.idle_text_box is None:
self.omnygui_remove_all_docks()
self.idle_text_box = self.gui_window.add_dock(name="idle_text").add_widget("TextBox")
try:
self.gui_window.remove_dock(name="default_figure")
except:
pass
text = (
"<pre>"
+ " ,o888888o. ,8. ,8. b. 8 `8.`8888. ,8' \n"
+ " . 8888 `88. ,888. ,888. 888o. 8 `8.`8888. ,8' \n"
+ ",8 8888 `8b .`8888. .`8888. Y88888o. 8 `8.`8888. ,8' \n"
+ "88 8888 `8b ,8.`8888. ,8.`8888. .`Y888888o. 8 `8.`8888.,8' \n"
+ "88 8888 88 ,8'8.`8888,8^8.`8888. 8o. `Y888888o. 8 `8.`88888' \n"
+ "88 8888 88 ,8' `8.`8888' `8.`8888. 8`Y8o. `Y88888o8 `8. 8888 \n"
+ "88 8888 ,8P ,8' `8.`88' `8.`8888. 8 `Y8o. `Y8888 `8 8888 \n"
+ "`8 8888 ,8P ,8' `8.`' `8.`8888. 8 `Y8o. `Y8 8 8888 \n"
+ " ` 8888 ,88' ,8' `8 `8.`8888. 8 `Y8o.` 8 8888 \n"
+ " `8888888P' ,8' ` `8.`8888. 8 `Yo 8 8888 \n"
+ "</pre>"
)
self.idle_text_box.set_html_text(text)
def _omnycam_clear(self):
self.omnygui_remove_all_docks()
def _omnycam_check_device_exists(self, device):
try:
device
except:
return False
else:
return True
def _omnycam_samplestage(self):
self.omnygui_show_omnycam_samplestage()
def omnygui_show_omnycam_samplestage(self):
self.omnygui_show_gui()
if self.fig201 is None:
self.omnygui_remove_all_docks()
self.fig201 = self.gui_window.add_dock(name="omnycam201").add_widget("BECImageWidget")
if self._omnycam_check_device_exists(dev.cam201):
fig = self.fig201.image("cam201")
fig.set_rotation(deg_90=3)
self.fig201.lock_aspect_ratio(True)
else:
print("Cannot open cam201. Device does not exist.")
self.fig202 = self.gui_window.add_dock(name="omnycam202").add_widget("BECImageWidget")
if self._omnycam_check_device_exists(dev.cam202):
fig = self.fig202.image("cam202")
fig.set_rotation(deg_90=3)
self.fig202.lock_aspect_ratio(True)
else:
print("Cannot open cam202. Device does not exist.")
try:
self.gui_window.remove_dock(name="default_figure")
except:
pass
def omnygui_show_progress(self):
self.omnygui_show_gui()
if self.progressbar is None:
self.omnygui_remove_all_docks()
# Add a new dock with a RingProgressBar widget
self.progressbar = self.gui_window.add_dock(name="progress").add_widget("RingProgressBar")
# Customize the size of the progress ring
self.progressbar.set_line_widths(20)
# Disable automatic updates and manually set the self.progressbar value
self.progressbar.enable_auto_updates(False)
# Set precision for the self.progressbar display
self.progressbar.set_precision(1) # Display self.progressbar with one decimal places
# Setting multiple rigns with different values
self.progressbar.set_number_of_bars(3)
self.progressbar.rings[2].set_update("scan")
# Set the values of the rings to 50, 75, and 25 from outer to inner ring
# self.progressbar.set_value([50, 75])
# Add a new dock with a TextBox widget
self.text_box = self.gui_window.add_dock(name="progress_text").add_widget("TextBox")
try:
self.gui_window.remove_dock(name="default_figure")
except:
pass
self._omnygui_update_progress()
def _omnygui_update_progress(self):
if self.progressbar is not None:
progress = self.progress["projection"] / self.progress["total_projections"] * 100
subotmo_progress = (
self.progress["subtomo_projection"]
/ self.progress["subtomo_total_projections"]
* 100
)
self.progressbar.set_value([progress, subotmo_progress])
text = f"Progress report:\n Tomo type: ....................... {self.progress['tomo_type']}\n Projection: ...................... {self.progress['projection']:.0f}\n Total projections expected ....... {self.progress['total_projections']}\n Angle: ........................... {self.progress['angle']}\n Current subtomo: ................. {self.progress['subtomo']}\n Current projection within subtomo: {self.progress['subtomo_projection']}\n Total projections per subtomo: ... {self.progress['subtomo_total_projections']}"
self.text_box.set_plain_text(text)

File diff suppressed because it is too large Load Diff

View File

@@ -1,246 +0,0 @@
import time
import numpy as np
import os
from rich import box
from rich.console import Console
from rich.table import Table
from typeguard import typechecked
from bec_lib import bec_logger
logger = bec_logger.logger
class OMNYAlignmentError(Exception):
pass
class OMNYAlignmentMixin:
default_correction_file = "correction_omny_202204.txt"
default_correction_file_x = "correction_omny_202204_x.txt"
def reset_correction(self, use_default_correction=True):
"""
Reset the correction to the default values.
If use_default_correction is False, the correction will be set to empty values.
Otherwise the default values will be loaded.
Args:
use_default_correction (bool, optional): If set to true, a call reset the correction to the default values. Defaults to True.
"""
self.corr_pos_x = []
self.corr_angle_x = []
self.corr_pos_y = []
self.corr_angle_y = []
self.corr_pos_y_2 = []
self.corr_angle_y_2 = []
if use_default_correction:
try:
self.read_additional_correction_x(self.default_correction_file_x)
logger.info(f"Applying default x correction from {self.default_correction_file_x}")
except FileNotFoundError:
logger.warning(
f"Could not find default correction file {self.default_correction_file_x}."
)
logger.warning("Not applying any correction.")
try:
self.read_additional_correction_y(self.default_correction_file)
logger.info(f"Applying default y correction from {self.default_correction_file}")
except FileNotFoundError:
logger.warning(
f"Could not find default correction file {self.default_correction_file}."
)
logger.warning("Not applying any correction.")
def reset_tomo_alignment_fit(self):
self.client.delete_global_var("tomo_alignment_fit")
def read_alignment_offset(
self,
dir_path=os.path.expanduser("~/Data10/specES1/internal/"),
setup="omny",
use_vertical_default_values=True,
):
"""
Read the alignment offset from the given directory and set the global parameter
tomo_alignment_fit.
Args:
dir_path (str, optional): The directory to read the alignment offset from. Defaults to os.path.expanduser("~/Data10/specES1/internal/").
"""
tomo_alignment_fit = np.zeros((2, 5))
with open(os.path.join(dir_path, "ptychotomoalign_Ax.txt"), "r") as file:
tomo_alignment_fit[0][0] = file.readline()
with open(os.path.join(dir_path, "ptychotomoalign_Bx.txt"), "r") as file:
tomo_alignment_fit[0][1] = file.readline()
with open(os.path.join(dir_path, "ptychotomoalign_Cx.txt"), "r") as file:
tomo_alignment_fit[0][2] = file.readline()
with open(os.path.join(dir_path, "ptychotomoalign_Ay.txt"), "r") as file:
tomo_alignment_fit[1][0] = file.readline()
with open(os.path.join(dir_path, "ptychotomoalign_By.txt"), "r") as file:
tomo_alignment_fit[1][1] = file.readline()
with open(os.path.join(dir_path, "ptychotomoalign_Cy.txt"), "r") as file:
tomo_alignment_fit[1][2] = file.readline()
with open(os.path.join(dir_path, "ptychotomoalign_Ay3.txt"), "r") as file:
tomo_alignment_fit[1][3] = file.readline()
with open(os.path.join(dir_path, "ptychotomoalign_Cy3.txt"), "r") as file:
tomo_alignment_fit[1][4] = file.readline()
print("New alignment parameters loaded:")
print(
f"X Amplitude {tomo_alignment_fit[0][0]}, "
f"X Phase {tomo_alignment_fit[0][1]}, "
f"X Offset {tomo_alignment_fit[0][2]}, "
f"Y Amplitude {tomo_alignment_fit[1][0]}, "
f"Y Phase {tomo_alignment_fit[1][1]}, "
f"Y Offset {tomo_alignment_fit[1][2]}, "
f"Y 3rd Order Amplitude {tomo_alignment_fit[1][3]}, "
f"Y 3rd Order Phase {tomo_alignment_fit[1][4]} ."
)
if use_vertical_default_values:
print(
f"Using default values for vertical alignment for setup {setup}. Optional: use_vertical_default_values=False"
)
if setup == "flomni":
tomo_alignment_fit[1][0] = 0
tomo_alignment_fit[1][1] = 0
tomo_alignment_fit[1][2] = 0
tomo_alignment_fit[1][3] = 0
tomo_alignment_fit[1][4] = 0
elif setup == "omny":
tomo_alignment_fit[1][0] = 2.588628
tomo_alignment_fit[1][1] = -2.385422
tomo_alignment_fit[1][2] = 0
tomo_alignment_fit[1][3] = 1.010583
tomo_alignment_fit[1][4] = -1.359157
print("Follwing parameters will be used:")
print(
f"X Amplitude {tomo_alignment_fit[0][0]}, "
f"X Phase {tomo_alignment_fit[0][1]}, "
f"X Offset {tomo_alignment_fit[0][2]}, "
f"Y Amplitude {tomo_alignment_fit[1][0]}, "
f"Y Phase {tomo_alignment_fit[1][1]}, "
f"Y Offset {tomo_alignment_fit[1][2]}, "
f"Y 3rd Order Amplitude {tomo_alignment_fit[1][3]}, "
f"Y 3rd Order Phase {tomo_alignment_fit[1][4]} ."
)
self.client.set_global_var("tomo_alignment_fit", tomo_alignment_fit.tolist())
# x amp, phase, offset, y amp, phase, offset, 3rd order amp, 3rd order phase
# 0 0 0 1 0 2 1 0 1 1 1 2 1 3 1 4
def get_alignment_offset(self, angle: float):
"""
Compute the alignment offset for the given angle.
Args:
angle (float): The angle to compute the alignment offset for.
Returns:
tuple: The alignment offset in x, y and z direction.
"""
tomo_alignment_fit = self.client.get_global_var("tomo_alignment_fit")
if tomo_alignment_fit is None:
print("Not applying any alignment offsets. No tomo alignment fit data available.\n")
return (0, 0, 0)
# x amp, phase, offset, y amp, phase, offset
# 0 0 0 1 0 2 1 0 1 1 1 2
correction_x = (
tomo_alignment_fit[0][0] * np.sin(np.radians(angle) + tomo_alignment_fit[0][1])
+ tomo_alignment_fit[0][2]
)
correction_y = (
tomo_alignment_fit[1][0] * np.sin(np.radians(angle) + tomo_alignment_fit[1][1])
+ tomo_alignment_fit[1][2]
+ tomo_alignment_fit[1][3] * np.sin(3 * np.radians(angle) + tomo_alignment_fit[1][4])
)
correction_z = tomo_alignment_fit[0][0] * np.sin(
np.radians(angle + 90) + tomo_alignment_fit[0][1]
)
print(
f"Alignment offset x {correction_x}, y {correction_y}, z {correction_z} for angle"
f" {angle}\n"
)
return (correction_x, correction_y, correction_z)
def _read_correction_file(self, correction_file: str):
with open(correction_file, "r") as f:
num_elements = f.readline()
int_num_elements = int(num_elements.split(" ")[2])
corr_pos = []
corr_angle = []
for j in range(int_num_elements * 2):
line = f.readline()
value = line.split(" ")[2]
name = line.split(" ")[0].split("[")[0]
if name == "corr_pos":
corr_pos.append(float(value))
elif name == "corr_angle":
corr_angle.append(float(value))
print(
f"Loading default mirror correction from file {correction_file} containing {int_num_elements} elements."
)
# print(corr_pos)
return corr_pos, corr_angle
def read_additional_correction_x(self, correction_file: str):
self.corr_pos_x, self.corr_angle_x = self._read_correction_file(correction_file)
def read_additional_correction_y(self, correction_file: str):
self.corr_pos_y, self.corr_angle_y = self._read_correction_file(correction_file)
def read_additional_correction_y_2(self, correction_file: str):
self.corr_pos_y_2, self.corr_angle_y_2 = self._read_correction_file(correction_file)
def compute_additional_correction_x(self, angle):
return self._compute_additional_correction(angle, iteration="x1")
def compute_additional_correction_y(self, angle):
return self._compute_additional_correction(angle, iteration="y1")
def compute_additional_correction_y_2(self, angle):
return self._compute_additional_correction(angle, iteration="y2")
def _compute_additional_correction(self, angle, iteration="y1"):
if iteration == "x1":
corr_pos = self.corr_pos_x
corr_angle = self.corr_angle_x
elif iteration == "y1":
corr_pos = self.corr_pos_y
corr_angle = self.corr_angle_y
elif iteration == "y2":
corr_pos = self.corr_pos_y_2
corr_angle = self.corr_angle_y_2
if not corr_pos:
print(f"Not applying any additional correction {iteration}. No data available.\n")
return 0
# find index of closest angle
for j, _ in enumerate(corr_pos):
newangledelta = np.fabs(corr_angle[j] - angle)
if j == 0:
angledelta = newangledelta
additional_correction_shift = corr_pos[j]
continue
if newangledelta < angledelta:
additional_correction_shift = corr_pos[j]
angledelta = newangledelta
if additional_correction_shift == 0 and angle > corr_angle[-1]:
additional_correction_shift = corr_pos[-1]
print(f"Additional correction shift {iteration}: {additional_correction_shift}")
return additional_correction_shift

View File

@@ -1,153 +0,0 @@
import time
import numpy as np
import sys
import termios
import tty
import fcntl
import os
import builtins
from rich import box
from rich.console import Console
from rich.table import Table
# from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_get, epics_put, fshopen, fshclose
if builtins.__dict__.get("bec") is not None:
bec = builtins.__dict__.get("bec")
dev = builtins.__dict__.get("dev")
umv = builtins.__dict__.get("umv")
umvr = builtins.__dict__.get("umvr")
class OMNYToolsError(Exception):
pass
class OMNYTools:
HEADER = "\033[95m"
OKBLUE = "\033[94m"
OKCYAN = "\033[96m"
OKGREEN = "\033[92m"
WARNING = "\033[93m"
FAIL = "\033[91m"
ENDC = "\033[0m"
BOLD = "\033[1m"
UNDERLINE = "\033[4m"
def __init__(self, client) -> None:
self.client = client
@staticmethod
def _get_user_param_safe(device, var):
param = dev[device].user_parameter
if not param or param.get(var) is None:
raise ValueError(f"Device {device} has no user parameter definition for {var}.")
return param.get(var)
def printgreen(self, string: str):
print(self.OKGREEN + string + self.ENDC)
def printgreenbold(self, string: str):
print(self.BOLD + self.OKGREEN + string + self.ENDC)
def yesno(self, message: str, default="none", autoconfirm=0) -> bool:
if autoconfirm and default == "y":
self.printgreen(message + " Automatically confirming default: yes")
return True
elif autoconfirm and default == "n":
self.printgreen(message + " Automatically confirming default: no")
return False
if default == "y":
message_ending = " [Y]/n? "
elif default == "n":
message_ending = " y/[N]? "
else:
message_ending = " y/n? "
while True:
user_input = input(self.OKBLUE + message + message_ending + self.ENDC)
if (
user_input == "Y" or user_input == "y" or user_input == "yes" or user_input == "Yes"
) or (default == "y" and user_input == ""):
return True
if (
user_input == "N" or user_input == "n" or user_input == "no" or user_input == "No"
) or (default == "n" and user_input == ""):
return False
else:
print("Please expicitely confirm y or n.")
def tweak_cursor(
self, dev1, step1: float, dev2="none", step2: float = "0", special_command="none"
):
if dev1 not in dev.enabled_devices:
print(f"Device 1 {dev} is not in enabled devices.")
return
if dev2 not in dev.enabled_devices and dev2 != "none":
print(f"Device 2 {dev} is not in enabled devices.")
return
# Save the current terminal settings
fd = sys.stdin.fileno()
old_term = termios.tcgetattr(fd)
try:
# Set the terminal to raw mode to capture single key presses
tty.setraw(fd)
# Set stdin to non-blocking mode
old_flags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, old_flags | os.O_NONBLOCK)
print("Tweak Cursor." + self.BOLD + self.OKBLUE + "Press (q) to quit!\r" + self.ENDC)
while True:
try:
# Read single character input
key = sys.stdin.read(1)
if key == "q":
print("\n\rExiting tweak mode\r")
break
elif key == "\x1b": # Escape sequences for arrow keys
next1, next2 = sys.stdin.read(2)
if next1 == "[":
if next2 == "A":
# print("up")
if dev2 != "none":
umvr(dev2, step2)
if special_command != "none":
special_command()
elif next2 == "B":
# print(" down")
if dev2 != "none":
umvr(dev2, -step2)
if special_command != "none":
special_command()
elif next2 == "C":
# print("right")
umvr(dev1, step1)
if special_command != "none":
special_command()
elif next2 == "D":
# print("left")
umvr(dev1, -step1)
if special_command != "none":
special_command()
elif key == "+":
step1 = step1 * 2
if dev2 != "none":
step2 = step2 * 2
print(f"\rDouble step size. New step size: {step1}, {step2}\r")
elif key == "-":
step1 = step1 / 2
if dev2 != "none":
step2 = step2 / 2
print(f"\rHalf step size. New step size: {step1}, {step2}\r")
except IOError:
# No input available, keep looping
pass
# Sleep for a short period to avoid high CPU usage
time.sleep(0.02)
finally:
# Restore the terminal to its original state
termios.tcsetattr(fd, termios.TCSADRAIN, old_term)
fcntl.fcntl(fd, fcntl.F_SETFL, old_flags)

View File

@@ -1,384 +0,0 @@
import time
import numpy as np
from rich import box
from rich.console import Console
from rich.table import Table
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_put, fshclose
class OMNYError(Exception):
pass
class OMNYOpticsMixin:
@staticmethod
def _get_user_param_safe(device, var):
param = dev[device].user_parameter
if not param or param.get(var) is None:
raise ValueError(f"Device {device} has no user parameter definition for {var}.")
return param.get(var)
def ooptics_in(self):
self.ofzp_in()
# ocs_in
self.oosa_in()
if "rtx" in dev and dev.rtx.enabled:
dev.rtx.controller.feedback_enable()
self.align.update_frame()
user_input = input(
"Is the direct beam gone on the xray eye? Do you see the cone of the FZP?"
)
if user_input == "y":
printf("Next oeye_out...\n")
else:
raise OMNYError("Failed to properly move in the Xray optics")
def _oeyey_mv(self, position):
# direction dependent speeds
if dev.oeyez.get().readback < position:
dev.oeyez.controller.socket_put_confirmed("axspeed[7]=15000")
else:
dev.oeyez.controller.socket_put_confirmed("axspeed[7]=10000")
umv(dev.oeyey, position)
dev.oeyez.controller.socket_put_confirmed("axspeed[7]=10000")
def oeye_out(self):
fshclose()
if self.OMNYTools.yesno("Did you move in the optics?"):
umv(dev.oeyez, -2)
self._oeyey_mv(-60.3)
# free camera
epics_put("XOMNYI-XEYE-ACQ:0", 2)
else:
raise OMNYError("The optics were not moved in. Please do so prior to eyey_out")
self.OMNYTools.printgreen("Oeye is out.")
def oeye_cam_in(self):
if dev.oeyez.get().readback < -80:
umv(dev.oeyez, -50)
if np.fabs(dev.oeyey.get().readback + 4.8) > 0.1:
self._oeyey_mv(-4.8)
if np.fabs(dev.oeyez.get().readback + 2) > 0.1 or np.fabs(dev.oeyex.get().readback) > 0.1:
umv(dev.oeyez, -2, dev.oeyex, 0)
# if still too close in z -- safety check
if np.fabs(dev.oeyez.get().readback + 2) > 0.1:
raise OMNYError("The oeye is too close in z for transfer. ERROR! Aborting.")
self.OMNYTools.printgreen("Oeye is at cam position.")
def _oeye_xray_is_in(self) -> bool:
omny_oeye_xray_inx = self._get_user_param_safe("oeyex", "xray_in")
omny_oeye_xray_iny = self._get_user_param_safe("oeyey", "xray_in")
omny_oeye_currentx = dev.oeyex.get().readback
omny_oeye_currenty = dev.oeyey.get().readback
if (
np.fabs(omny_oeye_currentx - omny_oeye_xray_inx) < 0.1
and np.fabs(omny_oeye_currenty - omny_oeye_xray_iny) < 0.1
):
return True
else:
return False
def oeye_xray_in(self):
if self._oeye_xray_is_in():
pass
else:
# todo
# self._otransfer_gripper_safe_xray_in_operation()
# if(!_oshield_is_ST_closed())
# {
# printf("The shield of the sample stage is not closed. Aborting.\n")
# exit
# }
omny_oeye_xray_inx = self._get_user_param_safe("oeyex", "xray_in")
omny_oeye_xray_iny = self._get_user_param_safe("oeyey", "xray_in")
omny_oeye_xray_inz = self._get_user_param_safe("oeyez", "xray_in")
self._oeyey_mv(omny_oeye_xray_iny)
omny_oeye_currenty = dev.oeyey.get().readback
if np.fabs(omny_oeye_currenty - omny_oeye_xray_iny) > 0.1:
raise OMNYError("The oeye did not move up.\n")
umv(dev.oeyex, omny_oeye_xray_inx, dev.oeyez, omny_oeye_xray_inz)
self.OMNYTools.printgreen("Oeye is at X-ray position.")
# some notes for the vis microscope:
# initial position for the vis light microscope
# do not open the shield when the microscope is at the vis mic position
# found eoeyx -45.13, z -84.9, y 0.64
# for a samy position of 2.8 with delta off
# the osa position should be in z around 7.4. in x it seems better
# around -0.6, where potentially xrays dont pass anymore
#
def _oosa_check_y(self):
omny_oosa_currenty = dev.oosay.get().readback
if np.fabs(omny_oosa_currenty - 0.9) > 0.05:
umv(dev.oosay, 0.9)
omny_oosa_currenty = dev.oosay.get().readback
if np.fabs(omny_oosa_currenty - 0.9) > 0.05:
raise OMNYError("oosay is not around 0.9. Aborting.")
def _oosa_to_move_corridor(self):
self._oosa_check_y()
dev.oosax.limits = [-3, 3.7] # risk collision with shield
umv(dev.oosax, -2)
dev.oosax.read(cached=False)
omny_oosa_currentx = dev.oosax.get().readback
if np.fabs(omny_oosa_currentx + 2) > 0.1:
raise OMNYError("oosax did not reach target position. Not moving in z.\n")
def oosa_in(self):
self._oosa_check_y()
dev.oshield.read(cached=False)
omny_oshield_current = dev.oshield.get().readback
if omny_oshield_current < 15:
self._oshield_ST_close()
if self.near_field == False:
x_in_pos = self._get_user_param_safe("oosax", "far_field_in")
y_in_pos = self._get_user_param_safe("oosay", "far_field_in")
z_in_pos = self._get_user_param_safe("oosaz", "far_field_in")
print("OSA movement in far-field mode.")
dev.oosaz.read(cached=False)
omny_oosa_currentz = dev.oosaz.get().readback
if omny_oosa_currentz < 6.4:
self._oosa_to_move_corridor()
dev.oosaz.limits = [6.4, 6.6]
umv(dev.oosaz, z_in_pos)
umv(dev.oosax, x_in_pos)
umv(dev.oosay, y_in_pos)
#### For the 30 nm FZP 220 um we use this part
# umv oosaz 6.5
# umv oosax 3.2453
# umv oosay 0.386015
if self.near_field == True:
x_in_pos = self._get_user_param_safe("oosax", "near_field_in")
y_in_pos = self._get_user_param_safe("oosay", "near_field_in")
z_in_pos = self._get_user_param_safe("oosaz", "near_field_in")
print("OSA movement in near-field mode.")
dev.oosaz.read(cached=False)
omny_oosa_currentz = dev.oosaz.get().readback
if omny_oosa_currentz > 0:
self._oosa_to_move_corridor()
dev.oosaz.limits = [-0.4, -0.6]
umv(dev.oosaz, z_in_pos)
umv(dev.oosax, x_in_pos)
omny_osamy_current = dev.osamy.get().readback
if omny_osamy_current < 3.25:
umv(dev.oosay, y_in_pos)
else:
raise OMNYError("Failed to move oosa in. osamy position is too large.")
self.OMNYTools.printgreen("OSA is in.")
# todo
# _omny_interferometer_align_tracking
# rt_feedback_enable
def oosa_out(self):
self._oosa_check_y()
dev.oshield.read(cached=False)
omny_oshield_current = dev.oshield.get().readback
if omny_oshield_current < 15:
self._oshield_ST_close()
omny_oosaz_current = dev.oosaz.get().readback
if self.near_field == False:
print("OSA movement in far-field mode.")
if omny_oosaz_current < 6.4:
self._oosa_to_move_corridor()
dev.oosaz.limits = [6.4, 6.6]
umv(dev.oosaz, 6.5)
umv(dev.oosax, -2)
if self.near_field == True:
print("OSA movement in near-field mode.")
if omny_oosaz_current > 0:
self._oosa_to_move_corridor()
dev.oosaz.limits = [-0.4, -0.6]
umv(dev.oosaz, -0.45)
umv(dev.oosax, -2)
# todo _omny_interferometer_align_tracking
self.OMNYTools.printgreen("OSA is out.")
def oosa_move_out_of_shield(self):
# todo: _omnycam_samplestage
self._oosa_check_y()
self._oosa_to_move_corridor()
omny_osamx_current = dev.osamx.get().readback
if np.fabs(omny_osamx_current) > 0.2:
umv(dev.osamx, 0)
omny_oosaz_current = dev.oosaz.get().readback
if omny_oosaz_current > 0.1:
dev.oosaz.limits = [-0.1, 0.1]
umv(dev.oosaz, 0)
self.OMNYTools.printgreen("OSA is out of shield.")
def ofzp_out(self):
if "rtx" in dev and dev.rtx.enabled:
dev.rtx.controller.feedback_disable()
y_out_pos = self._get_user_param_safe("ofzpy", "out")
if np.fabs(dev.ofzpy.get().readback - y_out_pos) > 0.02:
umv(dev.ofzpy, y_out_pos)
self.OMNYTools.printgreen("FZP at out position")
def ofzp_in(self):
if "rtx" in dev and dev.rtx.enabled:
dev.rtx.controller.feedback_disable()
x_in_pos = self._get_user_param_safe("ofzpx", "in")
y_in_pos = self._get_user_param_safe("ofzpy", "in")
if np.fabs(dev.ofzpy.get().readback - y_in_pos) > 0.02:
umv(dev.ofzpy, y_in_pos)
if np.fabs(dev.ofzpx.get().readback - x_in_pos) > 0.02:
umv(dev.ofzpx, x_in_pos)
self.OMNYTools.printgreen("FZP at in position")
# 220 mu FZP at ofzpz 31.8025 for eiger probe (about 2.4 mm propagation after focus)
# umv(dev.ofzpy, 0.7944)
# if np.fabs(dev.ofzpx.get().readback+0.4317)>0.05:
# umv(dev.ofzpx, -0.4317)
# note the 220 fzp also works for near field 6.2 kev by just moving back osa and fzp
# ofzpz 24.8 leads to a 9.5 mm propagation distance.
# With the 220 mu FZP this gives 100 nm pixel recons
# for the oosa macro set near_field=1
# 170 mu FZP at 6.2 kev for large beam at ofzpz 31.8025 of about 58 mu diameter
# 120 mu FZP at ofzpz 28.1991
# 250 mu FZP 60 nm at 5.65 keV
# ofzpz 29.7 for propagation distance 2.2
# umv ofzpx -0.4457
# umv ofzpy 0.193630
# 150 um fzp, 60 nm, ofzpz 33.8 at 8.9 kev for propagation of 1.7 mm after focus
# umv ofzpx -0.756678
# umv ofzpy 0.193515
# 250 um 30 nm FZP upper right
# small abberrations, seems to give good results in weak objects
# ofzpx -0.609240
# umv ofzpy 0.118265
# 250 um 30 nm FZP lower right very aberated
# ofzpx -0.881935
# umv ofzpy 0.537050
# ofzpz 28.4027
# 5.30 mm prop at 8.9 keV, 45 nm pixel in near field
# ofzpz 33.103
# 0.6 mm prop at 8.9 kev far field 7 m flight tube at foptz
# ofzpz 49.4 is reachable just without interferometer swap
# which at 6.2 keV and 250 um diam, 30 nm should gives a propagation of 0.8 after focus
# and a beam size of 6 microns diamter
###coordinates 30 nm FZP for comparing them
# not sure if that is really correct
# FZP 1 - FZP 2
# FZP 5
# FZP 4 - FZP 1
# FZP
##upper right
# umv ofzpx -0.6154 ofzpy 0.1183
# umv ocsx -0.6070 ocsy 0.0540
# lower right
# umv ofzpx -0.8341 ofzpy 0.5683
# umv ocsx -0.3880 ocsy -0.3960
# lower left
# umv ofzpx -0.3876 ofzpy 0.7902
# umv ocsx -0.8380 ocsy -0.6180
# upper left
# umv ofzpx -0.1678 ofzpy 0.3403
# umv ocsx -1.0550 ocsy -0.1680
def ofzp_info(self, mokev_val=-1, ofzpz_val=-1):
print(f"{ofzpz_val}")
if mokev_val == -1:
try:
mokev_val = dev.mokev.readback.get()
except:
print(
"Device mokev does not exist. You can specify the energy in keV as an argument instead."
)
return
if ofzpz_val == -1:
ofzpz_val = dev.ofzpz.readback.get()
distance = 66 + 2.4 + 31.8025 - ofzpz_val
print(
f"\nThe sample is in a distance of \033[1m{distance:.1f} mm\033[0m from the 60 nm FZP.\n"
)
print(f"At the current energy of {mokev_val:.4f} keV we have following options:\n")
diameters = [80e-6, 100e-6, 120e-6, 150e-6, 170e-6, 200e-6, 220e-6, 250e-6]
console = Console()
table = Table(title="Outermost zone width \033[1m60 nm\033[0m", box=box.SQUARE)
table.add_column("Diameter", justify="center")
table.add_column("Focal distance", justify="center")
table.add_column("Current beam size", justify="center")
wavelength = 1.2398e-9 / mokev_val
for diameter in diameters:
outermost_zonewidth = 60e-9
focal_distance = diameter * outermost_zonewidth / wavelength * 1000
beam_size = -diameter / (focal_distance * 1000) * (focal_distance - distance) * 1e9
table.add_row(
f"{diameter*1e6:.2f} microns",
f"{focal_distance:.2f} mm",
f"{beam_size:.2f} microns",
)
console.print(table)
# 30 nm with additional spacer
distance = 53.84 + 0.6 + 33.1 - ofzpz_val
print(
f"\nThe sample is in a distance of \033[1m{distance:.1f} mm\033[0m from the 30 nm FZP.\n"
)
diameters = [150e-6, 250e-6]
console = Console()
table = Table(title="Outermost zone width \033[1m30 nm\033[0m", box=box.SQUARE)
table.add_column("Diameter", justify="center")
table.add_column("Focal distance", justify="center")
table.add_column("Current beam size", justify="center")
wavelength = 1.2398e-9 / mokev_val
for diameter in diameters:
outermost_zonewidth = 30e-9
focal_distance = diameter * outermost_zonewidth / wavelength * 1000
beam_size = -diameter / (focal_distance * 1000) * (focal_distance - distance) * 1e9
table.add_row(
f"{diameter*1e6:.2f} microns",
f"{focal_distance:.2f} mm",
f"{beam_size:.2f} microns",
)
console.print(table)
print(
"This function can be called with explicit energy and ofzpz position.\n Example: omny.ffzp_info(mokev_val=6.2, ofzpz_val=33.2)"
)
# from flomni
# oosaz_val = dev.oosaz.readback.get()
# print("\nOSA Information:")
# print(f" Current fosaz {fosaz_val:.1f}")
# print(
# f" The OSA will collide with a normal OMNY pin at fosaz \033[1m{(33-fosaz_val):.1f}\033[0m"
# )
# print(f" Remaining space: \033[1m{-fosaz_val+(33-foptz_val):.1f}\033[0m")

View File

@@ -1,241 +0,0 @@
import time
import numpy as np
import sys
import termios
import tty
import fcntl
import os
from rich import box
from rich.console import Console
from rich.table import Table
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_get, epics_put, fshopen, fshclose
class OMNY_rt_clientError(Exception):
pass
class OMNY_rt_client:
def __init__(self):
self.mirror_channel = -1
self.mirror_amplitutde_increase = 0
self.mirror_parameters = {}
for j in range(1, 9):
self.mirror_parameters[j] = dev.rtx.controller.get_mirror_parameters(j)
@staticmethod
def _get_user_param_safe(device, var):
param = dev[device].user_parameter
if not param or param.get(var) is None:
raise OMNY_rt_clientError(
f"Device {device} has no user parameter definition for {var}."
)
return param.get(var)
def _omny_interferometer_openloop_steps(self, channel, steps, amplitude):
dev.rtx.controller._omny_interferometer_openloop_steps(channel, steps, amplitude)
def interferometer_tweaking(self):
self._tweak_interferometer()
def _tweak_interferometer(self):
self.mirror_channel = -1
# Save the current terminal settings
fd = sys.stdin.fileno()
old_term = termios.tcgetattr(fd)
print("Ready to tweak the interferometer. Press q to quit.")
print("The arrows adjust directions.")
print("Numbers select the mirror aligner.")
try:
# Set the terminal to raw mode to capture single key presses
tty.setraw(fd)
# Set stdin to non-blocking mode
old_flags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, old_flags | os.O_NONBLOCK)
opt_mirrorname = "none"
max = 0
while True:
try:
# Read single character input
key = sys.stdin.read(1)
if key == "q":
self.mirror_amplitutde_increase = 0
self.mirror_channel = -1
print("\n\rExiting tweak mode\r")
break
elif key == "\x1b": # Escape sequences for arrow keys
next1, next2 = sys.stdin.read(2)
if next1 == "[":
printit = True
if next2 == "A":
# print("up")
if self.mirror_channel != -1:
self._omny_interferometer_openloop_steps(
4,
-self.mirror_parameters[self.mirror_channel][
"opt_steps2_neg"
],
self.mirror_parameters[self.mirror_channel][
"opt_amplitude2_neg"
]
+ self.mirror_amplitutde_increase,
)
elif next2 == "B":
# print(" down")
if self.mirror_channel != -1:
self._omny_interferometer_openloop_steps(
4,
self.mirror_parameters[self.mirror_channel][
"opt_steps2_pos"
],
self.mirror_parameters[self.mirror_channel][
"opt_amplitude2_pos"
]
+ self.mirror_amplitutde_increase,
)
elif next2 == "C":
# print("right")
if self.mirror_channel != -1:
self._omny_interferometer_openloop_steps(
3,
-self.mirror_parameters[self.mirror_channel][
"opt_steps1_neg"
],
self.mirror_parameters[self.mirror_channel][
"opt_amplitude1_neg"
]
+ self.mirror_amplitutde_increase,
)
elif next2 == "D":
# print("left")
if self.mirror_channel != -1:
self._omny_interferometer_openloop_steps(
3,
self.mirror_parameters[self.mirror_channel][
"opt_steps1_pos"
],
self.mirror_parameters[self.mirror_channel][
"opt_amplitude1_pos"
]
+ self.mirror_amplitutde_increase,
)
elif key.isdigit() and 1 <= int(key) <= 8:
self.mirror_channel = int(key)
opt_mirrorname = self.mirror_parameters[self.mirror_channel][
"opt_mirrorname"
]
autostop = self.mirror_parameters[self.mirror_channel]["opt_signal_stop"]
averaging_time = self.mirror_parameters[self.mirror_channel][
"opt_averaging_time"
]
print(
f"\nSelected mirror channel {self.mirror_channel}: {opt_mirrorname}. Autostop {autostop}. Signal averaging time: {averaging_time}\r"
)
if int(key) == 6:
dev.rtx.controller.laser_tracker_on()
dev.rtx.controller._omny_interferometer_switch_channel(self.mirror_channel)
max = 0
printit = True
elif key == "+":
print("\nIncreasing voltage amplitudes by 100.\r")
self.mirror_amplitutde_increase += 100
elif key == "-":
print("\nDecreasing voltage amplitudes by 100.\r")
self.mirror_amplitutde_increase -= 100
elif key == "a":
if self.mirror_channel != -1:
dev.rtx.controller._omny_interferometer_optimize(
mirror_channel=self.mirror_channel, channel=3
)
dev.rtx.controller._omny_interferometer_optimize(
mirror_channel=self.mirror_channel, channel=4
)
dev.rtx.controller._omny_interferometer_optimize(
mirror_channel=self.mirror_channel, channel=3
)
dev.rtx.controller._omny_interferometer_optimize(
mirror_channel=self.mirror_channel, channel=4
)
if self.mirror_channel != -1 and printit:
printit = False
signal = dev.rtx.controller._omny_interferometer_get_signalsample(
self.mirror_parameters[self.mirror_channel]["opt_signalchannel"],
self.mirror_parameters[self.mirror_channel]["opt_averaging_time"],
)
if signal > max:
max = signal
info_str = f"Channel {self.mirror_channel}, {opt_mirrorname}, Current signal: {signal:.0f}"
filling = " " * (50 - len(info_str))
# Calculate the number of filled and unfilled segments
length = 30
percentage = signal / max
filled_length = int(length * percentage)
unfilled_length = length - filled_length
bar = "#" * filled_length + "-" * unfilled_length
print(info_str + filling + "0 " + bar + f" {max:.0f} (q)uit\r", end="")
except IOError:
# No input available, keep looping
pass
# Sleep for a short period to avoid high CPU usage
time.sleep(0.02)
finally:
# Restore the terminal to its original state
termios.tcsetattr(fd, termios.TCSADRAIN, old_term)
fcntl.fcntl(fd, fcntl.F_SETFL, old_flags)
dev.rtx.controller._omny_interferometer_switch_alloff()
self.mirror_channel = -1
self.mirror_amplitutde_increase = 0
dev.rtx.controller.show_signal_strength_interferometer()
def show_signal_strength_interferometer(self):
dev.rtx.controller.show_signal_strength_interferometer()
def omny_interferometer_align_incoupling_angle(self):
dev.rtx.controller.omny_interferometer_align_incoupling_angle()
def interferometer_tweak_otrack(self):
self.OMNYTools.tweak_cursor(
dev.otrackz,
0.1,
dev.otracky,
0.1,
special_command=dev.rtx.controller.laser_tracker_print_intensity_for_otrack_tweaking,
)
def feedback_enable_with_reset(self):
dev.rtx.controller.feedback_enable_with_reset()
def feedback_disable(self):
dev.rtx.controller.feedback_disable()
def feedback_status(self):
if dev.rtx.controller.feedback_is_running():
print("Feedback is running.")
else:
print("Feedback is NOT running.")
def laser_tracker_on(self):
dev.rtx.controller.laser_tracker_on()
def laser_tracker_off(self):
dev.rtx.controller.laser_tracker_off()
def laser_tracker_show_all(self):
dev.rtx.controller.laser_tracker_show_all()
def omny_interferometer_align_tracking(self):
dev.rtx.controller.omny_interferometer_align_tracking()
def laser_tracker_check_and_wait_for_signalstrength(self):
dev.rtx.controller.laser_tracker_check_and_wait_for_signalstrength()

View File

@@ -1,235 +0,0 @@
from __future__ import annotations
import builtins
import os
import time
from typing import TYPE_CHECKING
from bec_lib import bec_logger
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_get, epics_put, fshopen
logger = bec_logger.logger
# import builtins to avoid linter errors
bec = builtins.__dict__.get("bec")
dev = builtins.__dict__.get("dev")
umv = builtins.__dict__.get("umv")
umvr = builtins.__dict__.get("umvr")
if TYPE_CHECKING:
from bec_ipython_client.plugins.omny import OMNY
class XrayEyeAlign:
# pixel calibration, multiply to get mm
PIXEL_CALIBRATION = 0.2 / 218 # .2 with binning
def __init__(self, client, omny: OMNY) -> None:
self.client = client
self.omny = omny
self.device_manager = client.device_manager
self.scans = client.scans
self.alignment_values = {}
self.omny.reset_correction()
self.omny.reset_tomo_alignment_fit()
def _reset_init_values(self):
self.shift_xy = [0, 0]
self._xray_fov_xy = [0, 0]
def save_frame(self):
epics_put("XOMNYI-XEYE-SAVFRAME:0", 1)
def update_frame(self):
epics_put("XOMNYI-XEYE-ACQDONE:0", 0)
# start live
epics_put("XOMNYI-XEYE-ACQ:0", 1)
# wait for start live
while epics_get("XOMNYI-XEYE-ACQDONE:0") == 0:
time.sleep(0.5)
print("waiting for live view to start...")
fshopen()
epics_put("XOMNYI-XEYE-ACQDONE:0", 0)
while epics_get("XOMNYI-XEYE-ACQDONE:0") == 0:
print("waiting for new frame...")
time.sleep(0.5)
time.sleep(0.5)
# stop live view
epics_put("XOMNYI-XEYE-ACQ:0", 0)
time.sleep(1)
# fshclose
print("got new frame")
def tomo_rotate(self, val: float):
# pylint: disable=undefined-variable
umv(self.device_manager.devices.osamroy, val)
def get_tomo_angle(self):
return self.device_manager.devices.osamroy.readback.get()
def update_fov(self, k: int):
self._xray_fov_xy[0] = max(epics_get(f"XOMNYI-XEYE-XWIDTH_X:{k}"), self._xray_fov_xy[0])
self._xray_fov_xy[1] = max(0, self._xray_fov_xy[0])
@property
def movement_buttons_enabled(self):
return [epics_get("XOMNYI-XEYE-ENAMVX:0"), epics_get("XOMNYI-XEYE-ENAMVY:0")]
@movement_buttons_enabled.setter
def movement_buttons_enabled(self, enabled: bool):
enabled = int(enabled)
epics_put("XOMNYI-XEYE-ENAMVX:0", enabled)
epics_put("XOMNYI-XEYE-ENAMVY:0", enabled)
def send_message(self, msg: str):
epics_put("XOMNYI-XEYE-MESSAGE:0.DESC", msg)
def align(self):
# reset shift xy and fov params
self._reset_init_values()
self.tomo_rotate(0)
epics_put("XOMNYI-XEYE-ANGLE:0", 0)
self.omny.oeye_xray_in()
self.omny.feedback_enable_with_reset()
# disable movement buttons
self.movement_buttons_enabled = False
sample_name = dev.omny_samples.get_sample_name_in_samplestage()
epics_put("XOMNYI-XEYE-SAMPLENAME:0.DESC", sample_name)
# this makes sure we are in a defined state
self.omny.feedback_disable()
epics_put("XOMNYI-XEYE-PIXELSIZE:0", self.PIXEL_CALIBRATION)
osamx_in = self.omny.OMNYTools._get_user_param_safe("osamx", "in")
umv(dev.osamx, osamx_in - 0.35)
self.omny.ofzp_in()
self.update_frame()
# enable submit buttons
self.movement_buttons_enabled = False
epics_put("XOMNYI-XEYE-SUBMIT:0", 0)
epics_put("XOMNYI-XEYE-STEP:0", 0)
self.send_message("Submit center value of FZP.")
k = 0
while True:
if epics_get("XOMNYI-XEYE-SUBMIT:0") == 1:
val_x = epics_get(f"XOMNYI-XEYE-XVAL_X:{k}") / 2 * self.PIXEL_CALIBRATION # in mm
self.alignment_values[k] = val_x
print(f"Clicked position {k}: x {self.alignment_values[k]}")
rtx_position = dev.rtx.readback.get() / 1000
print(f"Current rtx position {rtx_position}")
self.alignment_values[k] -= rtx_position
print(f"Corrected position {k}: x {self.alignment_values[k]}")
if k == 0: # received center value of FZP
self.send_message("please wait ...")
self.movement_buttons_enabled = False
epics_put("XOMNYI-XEYE-SUBMIT:0", -1) # disable submit button
self.omny.feedback_disable()
osamx_in = self.omny.OMNYTools._get_user_param_safe("osamx", "in")
umv(dev.osamx, osamx_in)
self.omny.ofzp_out()
self.update_frame()
epics_put("XOMNYI-XEYE-RECBG:0", 1)
while epics_get("XOMNYI-XEYE-RECBG:0") == 1:
time.sleep(0.5)
print("waiting for background frame...")
umv(dev.osamx, osamx_in)
time.sleep(0.5)
self.omny.feedback_enable_with_reset()
self.update_frame()
self.send_message("Adjust sample height and submit center")
epics_put("XOMNYI-XEYE-SUBMIT:0", 0)
self.movement_buttons_enabled = True
elif 1 <= k < 5: # received sample center value at samroy 0 ... 315
self.send_message("please wait ...")
epics_put("XOMNYI-XEYE-SUBMIT:0", -1)
self.movement_buttons_enabled = False
umv(dev.rtx, 0)
self.tomo_rotate(k * 45)
epics_put("XOMNYI-XEYE-ANGLE:0", self.get_tomo_angle())
self.update_frame()
self.send_message("Submit sample center")
epics_put("XOMNYI-XEYE-SUBMIT:0", 0)
epics_put("XOMNYI-XEYE-ENAMVX:0", 1)
self.update_fov(k)
elif k == 5: # received sample center value at samroy 270 and done
self.send_message("done...")
epics_put("XOMNYI-XEYE-SUBMIT:0", -1) # disable submit button
self.movement_buttons_enabled = False
self.update_fov(k)
break
k += 1
epics_put("XOMNYI-XEYE-STEP:0", k)
_xrayeyalignmvx = epics_get("XOMNYI-XEYE-MVX:0")
if _xrayeyalignmvx != 0:
umvr(dev.rtx, _xrayeyalignmvx)
print(f"Current rtx position {dev.rtx.readback.get() / 1000}")
epics_put("XOMNYI-XEYE-MVX:0", 0)
if k > 0:
epics_put(f"XOMNYI-XEYE-STAGEPOSX:{k}", dev.rtx.readback.get() / 1000)
time.sleep(3)
self.update_frame()
if k < 2:
# allow movements, store movements to calculate center
_xrayeyalignmvy = epics_get("XOMNYI-XEYE-MVY:0")
if _xrayeyalignmvy != 0:
self.omny.feedback_disable()
umvr(dev.osamy, _xrayeyalignmvy / 1000)
time.sleep(2)
epics_put("XOMNYI-XEYE-MVY:0", 0)
self.omny.feedback_enable_with_reset()
self.update_frame()
time.sleep(0.2)
self.write_output()
fovx = self._xray_fov_xy[0] * self.PIXEL_CALIBRATION * 1000 / 2
fovy = self._xray_fov_xy[1] * self.PIXEL_CALIBRATION * 1000 / 2
self.tomo_rotate(0)
umv(dev.rtx, 0)
# free camera
epics_put("XOMNYI-XEYE-ACQ:0", 2)
print(
f"The largest field of view from the xrayeyealign was \nfovx = {fovx:.0f} microns, fovy"
f" = {fovy:.0f} microns"
)
print("Use the matlab routine to FIT the current alignment...")
print("Then LOAD ALIGNMENT PARAMETERS by running omny.read_alignment_offset()\n")
def write_output(self):
file = os.path.expanduser("~/Data10/specES1/internal/xrayeye_alignmentvalues")
if not os.path.exists(file):
os.makedirs(os.path.dirname(file), exist_ok=True)
with open(file, "w") as alignment_values_file:
alignment_values_file.write("angle\thorizontal\n")
for k in range(1, 6):
fovx_offset = self.alignment_values[0] - self.alignment_values[k]
print(f"Writing to file new alignment: number {k}, value x {fovx_offset}")
alignment_values_file.write(f"{(k-1)*45}\t{fovx_offset*1000}\n")

View File

@@ -1,250 +0,0 @@
"""Module providing debugging tools for the BEC IPython client at cSAXS."""
from __future__ import annotations
import inspect
import json
import os
import re
import socket
from concurrent.futures import ThreadPoolExecutor
from functools import partial
from typing import TYPE_CHECKING, Literal
import numpy as np
from pydantic import BaseModel
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.text import Text
from slugify import slugify
if TYPE_CHECKING:
from bec_ipython_client.main import BECIPythonClient
from bec_lib.devicemanager import DeviceManagerBase
from bec_lib.scans import Scans
from bec_widgets.cli.client_utils import BECGuiClient
scans: Scans # type: ignore[no-redef]
bec: BECIPythonClient # type: ignore[no-redef]
dev: DeviceManagerBase # type: ignore[no-redef]
class Detector(BaseModel):
"""Model representing a detector configuration."""
name: str
hostnames: list[str]
cfg: dict
def to_identifier(text: str) -> str:
"""
Convert an unsafe string into a valid Python identifier.
"""
name = slugify(text.strip(), separator="_")
name = re.sub(r"[^a-zA-Z0-9_]", "", name)
if not name:
raise ValueError(f"Cannot convert '{text}' to a valid identifier.")
if name[0].isdigit():
name = f"_{name}"
return name
class DebugTools:
"""A collection of debugging tools for the BEC IPython client at cSAXS."""
_PURPOSE = (
"Debugging helpers for the cSAXS BEC IPython client. These tools are intended for advanced users "
"and developers to diagnose and troubleshoot issues within the BEC environment. "
"Below are the available methods together with a brief description of their functionality."
)
######################
## Internal Methods ##
######################
def _describe(self) -> None:
"""Pretty-print a description of this debugging tool."""
console = Console()
# Offset for IPython prompt misplacement
console.print("\n\n", end="")
header = Text("DebugTools", style="bold cyan")
purpose = Text(self._PURPOSE, style="dim")
console.print(Panel(purpose, title=header, expand=False))
table = Table(show_header=True, header_style="bold magenta")
table.add_column("Method", style="bold", no_wrap=True)
table.add_column("Description")
for name, member in inspect.getmembers(self, predicate=inspect.ismethod):
if name.startswith("_"):
continue
doc = inspect.getdoc(member)
short_doc = doc.splitlines()[0] if doc else ""
table.add_row(name, short_doc)
console.print(table)
def _repr_pretty_(self, p, cycle: bool) -> None:
if cycle:
p.text("DebugTools(...)")
else:
self._describe()
#####################
### MCS Card Check ###
#####################
def _check_if_device_is_loaded(self, device_name: str):
"""Check if a device is loaded in the current BEC session."""
if device_name not in dev:
raise RuntimeError(
f"Device {device_name} was not loaded in the current active BEC session."
)
def mcs_test_acquire(
self, mode: Literal["high_frame", "medium_frame", "low_frame"] = "high_frame"
):
"""
Method to perform a test acquisition with randomized exposure time, burst frames, and cycles
on the MCS card using the DDG trigger setup.
Args:
mode (Literal["high_frame", "medium_frame", "low_frame"]): The mode of the test.
- 'high_frame': Tests high frame rates with short exposure times.
- 'medium_frame': Tests medium frame rates with moderate exposure times.
- 'low_frame': Tests low frame rates with longer exposure times.
"""
self._check_if_device_is_loaded("mcs")
self._check_if_device_is_loaded("ddg1")
self._check_if_device_is_loaded("ddg2")
if mode == "high_frame":
burst_frames = np.random.randint(10_000, 100_000) # between 10000 and 100000
cycles = np.random.randint(5, 20) # between 5 and 20
exp_time = (
np.random.rand() * (0.001 - 0.201e-3) + 0.201e-3
) # between 0.000201 ms and 0.001 s
elif mode == "medium_frame":
burst_frames = np.random.randint(50, 500) # between 50 and 500
cycles = np.random.randint(1, 10) # between 1 and 10
exp_time = np.random.rand() * (0.01 - 0.001) + 0.001 # between 0.001 ms and 0.01 s
elif mode == "low_frame":
burst_frames = np.random.randint(5, 20) # between 5 and 20
cycles = np.random.randint(1, 5) # between 1 and 5
exp_time = np.random.rand() * (2 - 0.1) + 0.1 # between 0.1 ms and 2 s
else:
raise ValueError(f"Invalid mode '{mode}' specified for acquire scan test.")
print(
f"Starting acquire measurement with exp_time={exp_time:.6f}, burst_frames={burst_frames}, cycles={cycles}"
)
s = scans.acquire(
exp_time=exp_time, frames_per_trigger=burst_frames, burst_at_each_point=cycles
)
s.wait(file_written=True)
print("Acquire measurement finished.")
print("Checking MCS data...")
scan_data = bec.history.get_by_scan_id(s.scan.scan_id)
mcs_data = scan_data.devices.mcs
print(mcs_data)
shape = mcs_data._info["mcs_mca_mca1"]["value"]["shape"]
expected_shape = (cycles * burst_frames,)
# Assert will raise an error if the shapes do not match
assert (
shape == expected_shape
), f"MCS data shape {shape} does not match expected shape {expected_shape}."
########################
### JFJ/Eiger Checks ###
########################
def _get_jfj_eiger_config(self) -> dict[str, Detector]:
"""Retrieve the current JFJ/Eiger detector configuration from the BEC client."""
# FIXME: Implement REST API call once ready for use from Leo Sala's team.
ret = {}
base_path = os.path.dirname(__file__)
config_path = os.path.join(base_path, "jfj_config.json")
with open(config_path, "r", encoding="utf-8") as fh:
cfg = json.load(fh)
for entry in cfg["detector"]:
det = Detector(
name=to_identifier(entry["description"]), hostnames=entry["hostname"], cfg=cfg
)
ret[det.name] = det
return ret
def list_detectors(self) -> list[str]:
"""
List the names of all JFJ/Eiger detectors configured in the BEC client.
Returns:
list[str]: A list of detector names.
"""
detectors = self._get_jfj_eiger_config()
return list(detectors.keys())
def ping_detector(self, detector_name: str) -> bool:
"""
Ping a JFJ/Eiger detector to check if it is reachable.
Args:
detector_name (str): The name of the detector to ping.
Returns:
bool: True if the detector is reachable, False otherwise.
"""
detectors = self._get_jfj_eiger_config()
if detector_name not in detectors:
raise ValueError(f"Detector '{detector_name}' not found in configuration.")
det = detectors[detector_name]
results = self._ping_many(det.hostnames)
table = Table(title=f"Ping results for detector '{detector_name}'")
table.add_column("Hostname", style="cyan", no_wrap=True)
table.add_column("Status", style="magenta")
for host, alive in results.items():
status = "[green]OK[/green]" if alive else "[red]DOWN[/red]"
table.add_row(host, status)
console = Console()
console.print(table)
def _ping_many(self, hosts: list[str], port=22, timeout=2, max_workers=None):
max_workers = max_workers or len(hosts)
with ThreadPoolExecutor(max_workers=max_workers) as executor:
primed_ping = partial(self._ping, port=port, timeout=timeout)
pings = executor.map(primed_ping, hosts)
return dict(zip(hosts, pings))
def _ping(self, host: str, port=23, timeout=2): # telnet is port 23
address = (host, port)
try:
with socket.create_connection(address, timeout):
return True
except OSError:
return False
def open_it_service_page(self):
"""Open the overview of IT services hosted by Science IT Infrastructure and Services for cSAXS."""
gui: BECGuiClient = bec.gui
dock_area = gui.new()
print("Opening IT service page in new dock...")
url = "https://metrics.psi.ch/d/saf8mxv/x12sa?orgId=1&from=now-24h&to=now&timezone=browser&var-receiver_hosts=sls-jfjoch-001.psi.ch&var-writer_hosts=xbl-daq-34.psi.ch&var-beamline=X12SA&var-slurm_partitions=csaxs&var-receiver_services=broker&var-writer_services=writer&refresh=15m"
# FIXME BEC WIDGETS v3
dock = dock_area.new()
wb = dock.new(widget=gui.available_widgets.WebsiteWidget)
wb.set_url(url)

View File

@@ -1,162 +0,0 @@
{
"zeromq" : {
"image_socket": ["tcp://0.0.0.0:5500"]
},
"zeromq_preview": {
"socket_address": "tcp://0.0.0.0:5400",
"enabled": true,
"period_ms": 1000
},
"zeromq_metadata" : {
"socket_address": "tcp://0.0.0.0:5600",
"enabled": true,
"period_ms": 100
},
"instrument" : {
"source_name": "Swiss Light Source",
"instrument_name": "cSAXS",
"source_type": "Synchrotron X-ray Source"
},
"detector": [
{
"description": "EIGER 9M",
"serial_number": "E1",
"type": "EIGER",
"mirror_y": true,
"base_data_ipv4_address": "10.10.10.10",
"calibration_file":["/opt/jfjoch/calibration/"],
"standard_geometry" : {
"nmodules": 18,
"modules_in_row": 3,
"gap_x": 8,
"gap_y": 36
},
"hostname": [
"beb101",
"beb103",
"beb014",
"beb078",
"beb060",
"beb030",
"beb092",
"beb178",
"beb009",
"beb038",
"beb056",
"beb058",
"beb033",
"beb113",
"beb005",
"beb017",
"beb119",
"beb095",
"beb186",
"beb042",
"beb106",
"beb059",
"beb111",
"beb203",
"beb100",
"beb093",
"beb123",
"beb061",
"beb121",
"beb055",
"beb004",
"beb190",
"beb054",
"beb189",
"beb107",
"beb115"
]
},
{
"description": "EIGER 8.5M (tmp)",
"serial_number": "E1-tmp",
"type": "EIGER",
"mirror_y": true,
"base_data_ipv4_address": "10.10.10.10",
"calibration_file":["/opt/jfjoch/calibration/"],
"standard_geometry" : {
"nmodules": 17,
"modules_in_row": 3,
"gap_x": 8,
"gap_y": 36
},
"hostname": [
"beb101",
"beb103",
"beb014",
"beb078",
"beb060",
"beb030",
"beb092",
"beb178",
"beb009",
"beb038",
"beb056",
"beb058",
"beb033",
"beb113",
"beb005",
"beb017",
"beb119",
"beb095",
"beb186",
"beb042",
"beb106",
"beb059",
"beb100",
"beb093",
"beb123",
"beb061",
"beb121",
"beb055",
"beb004",
"beb190",
"beb054",
"beb189",
"beb107",
"beb115"
]
},
{
"description": "EIGER 1.5M",
"serial_number": "E2",
"type": "EIGER",
"mirror_y": true,
"base_data_ipv4_address": "10.10.11.10",
"calibration_file":["/opt/jfjoch/calibration_e1p5m/"],
"standard_geometry" : {
"nmodules": 3,
"modules_in_row": 1,
"gap_x": 8,
"gap_y": 36
},
"hostname": ["beb062", "beb026", "beb099", "beb084", "beb120", "beb108"]
}
],
"frontend_directory": "/usr/share/jfjoch/frontend/",
"image_pusher": "ZeroMQ",
"numa_policy": "n2g2",
"receiver_threads": 64,
"image_buffer_MiB": 96000,
"pcie": [
{
"blk": "/dev/jfjoch0",
"ipv4": "10.10.10.1"
},
{
"blk": "/dev/jfjoch1",
"ipv4": "10.10.10.2"
},
{
"blk": "/dev/jfjoch2",
"ipv4": "10.10.10.3"
},
{
"blk": "/dev/jfjoch3",
"ipv4": "10.10.10.4"
}
]
}

View File

@@ -1,32 +0,0 @@
"""
Pre-startup script for BEC client. This script is executed before the BEC client
is started. It can be used to add additional command line arguments.
"""
import os
from bec_lib.service_config import ServiceConfig
import csaxs_bec
def extend_command_line_args(parser):
"""
Extend the command line arguments of the BEC client.
"""
parser.add_argument("--session", help="Session name", type=str, default="cSAXS")
return parser
# def get_config() -> ServiceConfig:
# """
# Create and return the ServiceConfig for the plugin repository
# """
# deployment_path = os.path.dirname(os.path.dirname(os.path.dirname(csaxs_bec.__file__)))
# files = os.listdir(deployment_path)
# if "bec_config.yaml" in files:
# return ServiceConfig(config_path=os.path.join(deployment_path, "bec_config.yaml"))
# else:
# return ServiceConfig(redis={"host": "localhost", "port": 6379})

View File

@@ -1,63 +0,0 @@
from __future__ import annotations
from typing import TYPE_CHECKING
from bec_widgets.widgets.containers.auto_update.auto_updates import AutoUpdates
if TYPE_CHECKING: # pragma: no cover
from bec_lib.messages import ScanStatusMessage
class cSAXSUpdate(AutoUpdates):
#######################################################################
################# GUI Callbacks #######################################
#######################################################################
def on_start(self) -> None:
"""
Procedure to run when the auto updates are enabled.
"""
self.start_default_dock()
def on_stop(self) -> None:
"""
Procedure to run when the auto updates are disabled.
"""
def on_scan_open(self, msg: ScanStatusMessage) -> None:
"""
Procedure to run when a scan starts.
Args:
msg (ScanStatusMessage): The scan status message.
"""
if msg.scan_name == "line_scan" and msg.scan_report_devices:
return self.simple_line_scan(msg)
if msg.scan_name == "grid_scan" and msg.scan_report_devices:
return self.simple_grid_scan(msg)
if msg.scan_report_devices:
return self.best_effort(msg)
return None
def on_scan_closed(self, msg: ScanStatusMessage) -> None:
"""
Procedure to run when a scan ends.
Args:
msg (ScanStatusMessage): The scan status message.
"""
def on_scan_abort(self, msg: ScanStatusMessage) -> None:
"""
Procedure to run when a scan is aborted.
Args:
msg (ScanStatusMessage): The scan status message.
"""
class cSAXSUpdateAlignment(AutoUpdates): ...
class cSAXSUpdateScan(AutoUpdates): ...

View File

@@ -1,148 +0,0 @@
# This file was automatically generated by generate_cli.py
# type: ignore
from __future__ import annotations
from bec_lib.logger import bec_logger
from bec_widgets.cli.rpc.rpc_base import RPCBase, rpc_call, rpc_timeout
logger = bec_logger.logger
# pylint: skip-file
_Widgets = {
"OmnyAlignment": "OmnyAlignment",
"XRayEye": "XRayEye",
}
class OmnyAlignment(RPCBase):
@property
@rpc_call
def enable_live_view(self):
"""
None
"""
@enable_live_view.setter
@rpc_call
def enable_live_view(self):
"""
None
"""
@property
@rpc_call
def user_message(self):
"""
None
"""
@user_message.setter
@rpc_call
def user_message(self):
"""
None
"""
@property
@rpc_call
def sample_name(self):
"""
None
"""
@sample_name.setter
@rpc_call
def sample_name(self):
"""
None
"""
@property
@rpc_call
def enable_move_buttons(self):
"""
None
"""
@enable_move_buttons.setter
@rpc_call
def enable_move_buttons(self):
"""
None
"""
class XRayEye(RPCBase):
@rpc_call
def active_roi(self) -> "BaseROI | None":
"""
Return the currently active ROI, or None if no ROI is active.
"""
@property
@rpc_call
def enable_live_view(self):
"""
Get or set the live view enabled state.
"""
@enable_live_view.setter
@rpc_call
def enable_live_view(self):
"""
Get or set the live view enabled state.
"""
@property
@rpc_call
def user_message(self):
"""
None
"""
@user_message.setter
@rpc_call
def user_message(self):
"""
None
"""
@property
@rpc_call
def sample_name(self):
"""
None
"""
@sample_name.setter
@rpc_call
def sample_name(self):
"""
None
"""
@property
@rpc_call
def enable_move_buttons(self):
"""
None
"""
@enable_move_buttons.setter
@rpc_call
def enable_move_buttons(self):
"""
None
"""
class XRayEye2DControl(RPCBase):
@rpc_call
def remove(self):
"""
Cleanup the BECConnector
"""

View File

@@ -1,140 +0,0 @@
from typing import TypedDict
from bec_widgets.utils.error_popups import SafeSlot
import os
from bec_widgets.utils.bec_widget import BECWidget
from bec_widgets.utils.ui_loader import UILoader
from qtpy.QtWidgets import QWidget, QPushButton, QLineEdit, QLabel, QVBoxLayout
from bec_qthemes import material_icon
from bec_lib.logger import bec_logger
logger = bec_logger.logger
# class OmnyAlignmentUIComponents(TypedDict):
# moveRightButton: QPushButton
# moveLeftButton: QPushButton
# moveUpButton: QPushButton
# moveDownButton: QPushButton
# image: Image
class OmnyAlignment(BECWidget, QWidget):
USER_ACCESS = ["enable_live_view", "enable_live_view.setter", "user_message", "user_message.setter","sample_name", "sample_name.setter", "enable_move_buttons", "enable_move_buttons.setter"]
PLUGIN = True
ui_file = "./omny_alignment.ui"
def __init__(self, parent=None, **kwargs):
super().__init__(parent=parent, **kwargs)
self._load_ui()
def _load_ui(self):
current_path = os.path.dirname(__file__)
self.ui = UILoader(self).loader(os.path.join(current_path, self.ui_file))
layout = QVBoxLayout()
layout.addWidget(self.ui)
self.setLayout(layout)
icon_options = {"size": (16, 16), "convert_to_pixmap": False}
self.ui.moveRightButton.setText("")
self.ui.moveRightButton.setIcon(
material_icon(icon_name="keyboard_arrow_right", **icon_options)
)
self.ui.moveLeftButton.setText("")
self.ui.moveLeftButton.setIcon(
material_icon(icon_name="keyboard_arrow_left", **icon_options)
)
self.ui.moveUpButton.setText("")
self.ui.moveUpButton.setIcon(
material_icon(icon_name="keyboard_arrow_up", **icon_options)
)
self.ui.moveDownButton.setText("")
self.ui.moveDownButton.setIcon(
material_icon(icon_name="keyboard_arrow_down", **icon_options)
)
self.ui.confirmButton.setText("OK")
self.ui.liveViewSwitch.enabled.connect(self.on_live_view_enabled)
# self.ui.moveUpButton.clicked.connect(self.on_move_up)
@property
def enable_live_view(self):
return self.ui.liveViewSwitch.checked
@enable_live_view.setter
def enable_live_view(self, enable:bool):
self.ui.liveViewSwitch.checked = enable
@property
def user_message(self):
return self.ui.messageLineEdit.text()
@user_message.setter
def user_message(self, message:str):
self.ui.messageLineEdit.setText(message)
@property
def sample_name(self):
return self.ui.sampleLineEdit.text()
@sample_name.setter
def sample_name(self, message:str):
self.ui.sampleLineEdit.setText(message)
@SafeSlot(bool)
def on_live_view_enabled(self, enabled:bool):
from bec_widgets.widgets.plots.image.image import Image
logger.info(f"Live view is enabled: {enabled}")
image: Image = self.ui.image
if enabled:
image.image("cam_xeye")
return
image.disconnect_monitor("cam_xeye")
@property
def enable_move_buttons(self):
move_up:QPushButton = self.ui.moveUpButton
move_down:QPushButton = self.ui.moveDownButton
move_left:QPushButton = self.ui.moveLeftButton
move_right:QPushButton = self.ui.moveRightButton
return move_up.isEnabled() and move_down.isEnabled() and move_left.isEnabled() and move_right.isEnabled()
@enable_move_buttons.setter
def enable_move_buttons(self, enabled:bool):
move_up:QPushButton = self.ui.moveUpButton
move_down:QPushButton = self.ui.moveDownButton
move_left:QPushButton = self.ui.moveLeftButton
move_right:QPushButton = self.ui.moveRightButton
move_up.setEnabled(enabled)
move_down.setEnabled(enabled)
move_left.setEnabled(enabled)
move_right.setEnabled(enabled)
if __name__ == "__main__":
from qtpy.QtWidgets import QApplication
import sys
app = QApplication(sys.argv)
widget = OmnyAlignment()
widget.show()
sys.exit(app.exec_())

View File

@@ -1 +0,0 @@
{'files': ['omny_alignment.py']}

View File

@@ -1,125 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>988</width>
<height>821</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="2">
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="2">
<widget class="QPushButton" name="moveRightButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="moveLeftButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="moveUpButton">
<property name="text">
<string>Up</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="moveDownButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="confirmButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<widget class="QLineEdit" name="sampleLineEdit"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="messageLineEdit"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Sample</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Message</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0" colspan="3">
<widget class="Image" name="image">
<property name="enable_toolbar" stdset="0">
<bool>false</bool>
</property>
<property name="inner_axes" stdset="0">
<bool>false</bool>
</property>
<property name="monitor" stdset="0">
<string>cam_xeye</string>
</property>
<property name="rotation" stdset="0">
<number>3</number>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="ToggleSwitch" name="liveViewSwitch"/>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Live View</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Image</class>
<extends>QWidget</extends>
<header>image</header>
</customwidget>
<customwidget>
<class>ToggleSwitch</class>
<extends>QWidget</extends>
<header>toggle_switch</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -1,54 +0,0 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
from qtpy.QtDesigner import QDesignerCustomWidgetInterface
from bec_widgets.utils.bec_designer import designer_material_icon
from csaxs_bec.bec_widgets.widgets.omny_alignment.omny_alignment import OmnyAlignment
DOM_XML = """
<ui language='c++'>
<widget class='OmnyAlignment' name='omny_alignment'>
</widget>
</ui>
"""
class OmnyAlignmentPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
def __init__(self):
super().__init__()
self._form_editor = None
def createWidget(self, parent):
t = OmnyAlignment(parent)
return t
def domXml(self):
return DOM_XML
def group(self):
return ""
def icon(self):
return designer_material_icon(OmnyAlignment.ICON_NAME)
def includeFile(self):
return "omny_alignment"
def initialize(self, form_editor):
self._form_editor = form_editor
def isContainer(self):
return False
def isInitialized(self):
return self._form_editor is not None
def name(self):
return "OmnyAlignment"
def toolTip(self):
return "OmnyAlignment"
def whatsThis(self):
return self.toolTip()

View File

@@ -1,15 +0,0 @@
def main(): # pragma: no cover
from qtpy import PYSIDE6
if not PYSIDE6:
print("PYSIDE6 is not available in the environment. Cannot patch designer.")
return
from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
from csaxs_bec.bec_widgets.widgets.omny_alignment.omny_alignment_plugin import OmnyAlignmentPlugin
QPyDesignerCustomWidgetCollection.addCustomWidget(OmnyAlignmentPlugin())
if __name__ == "__main__": # pragma: no cover
main()

View File

@@ -1,15 +0,0 @@
def main(): # pragma: no cover
from qtpy import PYSIDE6
if not PYSIDE6:
print("PYSIDE6 is not available in the environment. Cannot patch designer.")
return
from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
from csaxs_bec.bec_widgets.widgets.xray_eye.x_ray_eye_plugin import XRayEyePlugin
QPyDesignerCustomWidgetCollection.addCustomWidget(XRayEyePlugin())
if __name__ == "__main__": # pragma: no cover
main()

Some files were not shown because too many files have changed in this diff Show More