Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Geometry from Karabo #330

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions extra_geom/geom_from_karabo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# coding: utf-8
import argparse
import asyncio
import base64
import gzip
import pickle

from karabo_proxy import AsyncKaraboProxy

FRM_DIMS = {
"crystfel": ('frame', 'modno', 'ss', 'fs'),
"cheetah": ('frame', 'ss', 'fs'),
}

presets = {
"SPB/AGIPD1M": {
"proxy_url": "http://spb-rr-sys-con-gui1:8484",
"geometry_device": "SPB_DET_AGIPD1M-1/CAL/GEOMETRY",
"z_motor": "SPB_IRU_AGIPD1M/MOTOR/Z_STEPPER",
"energy_device": "SPB_XTD2_UND/DOOCS/ENERGY",
"clen_min": 0.119,
},
"SPB/JF4M": {
"proxy_url": "http://spb-rr-sys-con-gui1:8484",
"geometry_device": "SPB_IRDA_JF4M/CAL/GEOMETRY",
"z_motor": "SPB_IRDA_JF4M/MOTOR/Z",
"energy_device": "SPB_XTD2_UND/DOOCS/ENERGY",
"clen_min": 0.020,
},
"MID": {
"proxy_url": "http://mid-rr-sys-con-gui1:8484",
"geometry_device": "MID_DET_AGIPD1M-1/CAL/GEOMETRY",
"z_motor": "MID_EXP_UPP/MOTOR/T4",
"energy_device": "MID_XTD1_UND/DOOCS/ENERGY",
"clen_min": 0.0,
},
}


def deserialize_geometry(serialized: str):
return pickle.loads(gzip.decompress(base64.b64decode(serialized.encode())))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realised what this is doing.

Unpickling may not work if the version of EXtra-geom installed in Karabo is different from the version locally. Recent versions haven't changed the structure much, but that's not guaranteed for the future, and the failures if you unpickle something from a different version can be very confusing. It also means that anyone calling this is potentially vulnerable to a MITM attack: unpickling is equivalent to eval() in security terms.

So I'd rather not do this if we can avoid it. If a major use case is to retrieve a .geom file, one option is that the geometry device could expose a slot to create the file, and we call that and write the returned data directly to a file.



async def get_geometry(proxy_url: str, geometry_device: str,
z_motor: str, energy_device: str, clen_min: float):
client = AsyncKaraboProxy(proxy_url)
data = await asyncio.gather(
client.get_device_config_path(geometry_device, "serializedGeometry"),
client.get_device_config_path(z_motor, "actualPosition"),
client.get_device_config_path(energy_device, "actualPosition"),
)
geom = deserialize_geometry(data[0].value)
meta = type("GeometryMetadata", (), dict(
clen=data[1].value * 0.001 + clen_min,
photon_energy=int(1000 * data[2].value + 0.5)
))
return geom, meta


def main():
parser = argparse.ArgumentParser(
description="Dump a crystfel geometry from Karabo to a file"
)
parser.add_argument('detector', choices=list(presets.keys()),
help="Detector: " + ", ".join(presets.keys()))
parser.add_argument('output_file',
help="The name of output file")
parser.add_argument('-f', '--format',
choices=["crystfel", "cheetah"], default="crystfel",
help="The output format dialect, default: crystfel")
parser.add_argument('--adu_per_eV', type=float, default=0.001,
help="Unit factor ADU/eV, default=0.001")
parser.add_argument('--tube_len', type=float, default=0.0,
help="Lenght of additional spacing between detector "
"and sample, e.g. tubes length")

args = parser.parse_args()
prm = presets[args.detector].copy()
prm["clen_min"] += args.tube_len

geom, meta = asyncio.run(get_geometry(**prm))

geom.write_crystfel_geom(
args.output_file,
dims=FRM_DIMS[args.format],
adu_per_ev=args.adu_per_eV,
clen=meta.clen,
photon_energy=meta.photon_energy
)


if __name__ == "__main__":
main()
6 changes: 6 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ def find_version(*parts):
package_data={
'extra_geom.tests': ['dssc_geo_june19.h5', 'lpd_mar_18.h5'],
},
entry_points={
'console_scripts': [
'extra-geom-from-karabo = extra_data.geom_from_karabo:main',
]
},
install_requires=[
'Karabo-proxy',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this an optional dependency, using the extras_require section below? If people are installing our tools in their own environment, I try to keep the number of dependencies minimal.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, then I we also need to catch exception on import...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to, but I think it's also OK to just let the ImportError show in that case.

'cfelpyutils>=2.0, <3.0',
'h5py>=2.7.1',
'matplotlib',
Expand Down