lots of (seemingly) unused files

This commit is contained in:
2019-12-17 10:52:42 +00:00
parent 0390237e0a
commit 652993592b
35 changed files with 3633 additions and 0 deletions
+96
View File
@@ -0,0 +1,96 @@
import numpy as np
import h5py
from epics import PV
import os
import data_api as api
import datetime
from threading import Thread
from time import sleep
from .utilities import Acquisition
class Ioxostools:
def __init__(self,
default_channel_list={'listname':[]},
default_file_path='%s',
elog=None,
sleeptime=0.0305,
channel_list = None):
self.sleeptime = sleeptime
self._default_file_path = default_file_path
self._default_channel_list = default_channel_list
self._elog = elog
self.channels = []
if not channel_list:
print('No channels specified, using default list \'%s\' instead.'%list(self._default_channel_list.keys())[0])
self.channel_list = self._default_channel_list[list(self._default_channel_list.keys())[0]]
for channel in self.channel_list:
self.channels.append(PV(channel))
def h5(self,fina=None,channel_list = None, N_pulses=None,default_path=True,queue_size=100):
channel_list = self.channel_list
if default_path:
fina = self._default_file_path%fina
if os.path.isfile(fina):
print('!!! File %s already exists, would you like to delete it?'%fina)
if input('(y/n)')=='y':
print('Deleting %s .'%fina)
os.remove(fina)
else:
return
data = []
counters = []
channels = self.channels
for channel in channels:
channelval = channel.value
if type(channelval) == np.ndarray:
shape = (N_pulses,)+channelval.shape
dtype = channelval.dtype
else:
shape = (N_pulses,)
dtype = type(channelval)
data.append(np.ndarray(shape, dtype = dtype))
counters.append(0)
def cb_getdata(ch=None, m=0,*args, **kwargs):
sleep(0.001)
data[m][counters[m]] = kwargs['value']
counters[m] =counters[m] + 1
if counters[m] == N_pulses:
ch.clear_callbacks()
for (m, channel) in enumerate(channels):
channel.add_callback(callback = cb_getdata, ch = channel, m=m)
while True:
sleep(0.01)
if np.mean(counters) == N_pulses:
break
#for n in range(N_pulses):
# channelvals = []
# sleep(self.sleeptime)
f = h5py.File(name = fina, mode = 'w')
for (n, channel) in enumerate(channel_list):
f.create_dataset(name = channel, data = data[n])
return data
def acquire(self,file_name=None,Npulses=100):
file_name += '.h5'
def acquire():
self.h5(fina=file_name,N_pulses=Npulses)
return Acquisition(acquire=acquire,acquisition_kwargs={'file_names':[file_name], 'Npulses':Npulses},hold=False)
def wait_done(self):
self.check_running()
self.check_still_running()
@@ -0,0 +1,35 @@
from ..devices_general.smaract import SmarActRecord
from epics import PV
class XTG:
def __init__(self,Id,alias_namespace=None):
self.Id = Id
### sample smaract motors ###
self.sx = SmarActRecord(Id+':TRX3')
self.sy = SmarActRecord(Id+':TRY3')
### grating 1 motors ###
self.g1x = SmarActRecord(Id+':TRX1')
self.g1y = SmarActRecord(Id+':TRY1')
self.g1z = SmarActRecord(Id+':TRZ1')
### grating 2 motors ###
self.g2x = SmarActRecord(Id+':TRX2')
self.g2y = SmarActRecord(Id+':TRY2')
self.g2z = SmarActRecord(Id+':TRZ2')
def get_adjustable_positions_str(self):
ostr = '*****SmarAct motor positions******\n'
for tkey,item in self.__dict__.items():
if hasattr(item,'get_current_value'):
pos = item.get_current_value()
ostr += ' ' + tkey.ljust(10) + ' : % 14g\n'%pos
return ostr
def __repr__(self):
return self.get_adjustable_positions_str()
+29
View File
@@ -0,0 +1,29 @@
import sys
sys.path.append("..")
from ..devices_general.motors import MotorRecord
from epics import PV
class EXP:
def __init__(self,Id,alias_namespace=None):
self.Id = Id
### motors 1.5M JF Zaber ###
#self.det_x = MotorRecord(Id+':MOT_TX')
#self.det_y = MotorRecord(Id+':MOT_TY')
self.zaber_x = MotorRecord(Id+':MOT_TZ')
self.qioptiq_zoom = MotorRecord(Id+':MOT_QIOPT_Z')
### motors crystal ###
#self.c_focus = MotorRecord(Id+':MOT_VT80')
#self.c_rot = MotorRecord(Id+':MOT_ROT')
def __repr__(self):
s = "**Detector and crystal positions**\n"
motors = "zaber_x qioptiq_zoom".split()
for motor in motors:
s+= " - %s %.4f\n"%(motor,getattr(self,motor).wm())
s+= "\n"
return s
+64
View File
@@ -0,0 +1,64 @@
import sys
sys.path.append("..")
from ..devices_general.motors import MotorRecord
from epics import PV
class GPS:
def __init__(self,Id,alias_namespace=None):
self.Id = Id
### motors heavy load gps table ###
self.xhl = MotorRecord(Id+':MOT_TBL_TX')
self.zhl = MotorRecord(Id+':MOT_TBL_TZ')
self.yhl = MotorRecord(Id+':MOT_TBL_TY')
self.th = MotorRecord(Id+':MOT_MY_RYTH')
try:
self.rxhl = MotorRecord(Id+':MOT_TBL_RX')
except:
print ('GPS.pitch not found')
pass
try:
self.ryhl = MotorRecord(Id+':MOT_TBL_RY')
except:
print ('GPS.roll not found')
pass
### motors heavy load gonio base ###
self.xmu = MotorRecord(Id+':MOT_HEX_TX')
self.mu = MotorRecord(Id+':MOT_HEX_RX')
self.tth = MotorRecord(Id+':MOT_NY_RY2TH')
self.xbase = MotorRecord(Id+':MOT_TX')
self.ybase = MotorRecord(Id+':MOT_TY')
self.hex_x = PV("SARES20-HEX_PI:POSI-X")
self.hex_y = PV("SARES20-HEX_PI:POSI-Y")
self.hex_z = PV("SARES20-HEX_PI:POSI-Z")
self.hex_u = PV("SARES20-HEX_PI:POSI-U")
self.hex_v = PV("SARES20-HEX_PI:POSI-V")
self.hex_w = PV("SARES20-HEX_PI:POSI-W")
def __repr__(self):
s = "**Heavy Load**\n"
motors = "xmu mu tth xbase ybase".split()
for motor in motors:
s+= " - %s %.4f\n"%(motor,getattr(self,motor).wm())
s+= " - HLX %.4f\n"%(self.xhl.wm())
s+= " - HLY %.4f\n"%(self.yhl.wm())
s+= " - HLZ %.4f\n"%(self.zhl.wm())
s+= " - HLTheta %.4f\n"%(self.th.wm())
s+= "\n"
s+= "**Gonio**\n"
motors = "xmu mu tth xbase ybase".split()
for motor in motors:
s+= " - %s %.4f\n"%(motor,getattr(self,motor).wm())
s+= "\n"
s+= "**Hexapod**\n"
motors = "x y z u v w".split()
for motor in motors:
s+= " - hex_%s %.4f\n"%(motor,getattr(self,"hex_"+motor).get())
return s
+69
View File
@@ -0,0 +1,69 @@
import sys
sys.path.append("..")
from ..devices_general.motors import MotorRecord
from epics import PV
class XRD:
def __init__(self,Id,alias_namespace=None):
self.Id = Id
### motors heavy load table ###
self.xhl = MotorRecord(Id+':MOT_TBL_TX')
self.zhl = MotorRecord(Id+':MOT_TBL_TZ')
self.yhl = MotorRecord(Id+':MOT_TBL_TY')
self.th = MotorRecord(Id+':MOT_MY_RYTH')
self.zaber_x = MotorRecord('SARES20-EXP'+':MOT_TZ')
try:
self.rxhl = MotorRecord(Id+':MOT_TBL_RX')
except:
print ('GPS.pitch not found')
pass
try:
self.ryhl = MotorRecord(Id+':MOT_TBL_RY')
except:
print ('GPS.roll not found')
pass
### motors heavy load gonio base ###
#self.xmu = MotorRecord(Id+':MOT_HEX_TX')
#self.mu = MotorRecord(Id+':MOT_HEX_RX')
self.gamma = MotorRecord(Id+':MOT_NY_RY2TH')
self.xbase = MotorRecord(Id+':MOT_TX')
self.ybase = MotorRecord(Id+':MOT_TY')
#self.hex_x = PV("SARES20-HEX_PI:POSI-X")
#self.hex_y = PV("SARES20-HEX_PI:POSI-Y")
#self.hex_z = PV("SARES20-HEX_PI:POSI-Z")
#self.hex_u = PV("SARES20-HEX_PI:POSI-U")
#self.hex_v = PV("SARES20-HEX_PI:POSI-V")
#self.hex_w = PV("SARES20-HEX_PI:POSI-W")
### motors XRD arm ###
self.delta = MotorRecord(Id+':MOT_DT_RX2TH')
self.det_z = MotorRecord(Id+':MOT_D_T')
self.cam_z = MotorRecord(Id+':MOT_P_T')
def __repr__(self):
s= "**Table**\n"
motors = "xhl yhl zhl zaber_x th".split()
for motor in motors:
s+= " - %s %.4f\n"%(motor,getattr(self,motor).wm())
s+= "\n"
s+= "**Gonio**\n"
motors = " xbase ybase gamma delta det_z cam_z".split()
for motor in motors:
s+= " - %s %.4f\n"%(motor,getattr(self,motor).wm())
s+= "\n"
#s+= "**Hexapod**\n"
#motors = "x y z u v w".split()
#for motor in motors:
# s+= " - hex_%s %.4f\n"%(motor,getattr(self,"hex_"+motor).get())
return s
@@ -0,0 +1,15 @@
class Hexapod_PI:
def __init__(self, Id):
self.Id = Id
self.x, self.y, self.z = [
ValueRdback(self.id + f":SET-POSI-{i}", self.id + f":POSI-{i}")
for i in "XYZ"
]
self.dx, self.dy, self.dz = [
ValueRdback(self.id + f":SET-POSI-{i}", self.id + f":POSI-{i}")
for i in "UVW"
]
self._piv_x, self._piv_y, self._piv_z = [
ValueRdback(self.id + f":SET-PIVOT-{i}", self.id + f":PIVOT-R-{i}")
for i in "RST"
]
@@ -0,0 +1,84 @@
import sys
sys.path.append("..")
from ..devices_general.motors import MotorRecord
from epics import PV
from ..aliases import Alias
class XRD:
def __init__(self, name=None, Id=None, configuration=[]):
"""X-ray diffractometer platform in AiwssFEL Bernina.\
<configuration> : list of elements mounted on
the plaform, options are kappa, nutable, hlgonio, polana"""
self.Id = Id
self.name = name
self.alias = Alias(name)
### motors base platform ###
self.xbase = MotorRecord(Id + ":MOT_TX", name="xbase")
self.ybase = MotorRecord(Id + ":MOT_TY", name="ybase")
self.rxbase = MotorRecord(Id + ":MOT_RX", name="rxbase")
self.omega = MotorRecord(Id + ":MOT_MY_RYTH", name="omega")
### motors XRD detector arm ###
self.gamma = MotorRecord(Id + ":MOT_NY_RY2TH", name="gam")
self.delta = MotorRecord(Id + ":MOT_DT_RX2TH", name="del")
### motors XRD area detector branch ###
self.tdet = MotorRecord(Id + ":MOT_D_T", name="tdet")
### motors XRD polarisation analyzer branch ###
self.tpol = MotorRecord(Id + ":MOT_P_T", name="tpol")
# missing: slits of flight tube
### motors heavy load goniometer ###
self.xhl = MotorRecord(Id + ":MOT_TBL_TX", name="xhl")
self.zhl = MotorRecord(Id + ":MOT_TBL_TZ", name="zhl")
self.yhl = MotorRecord(Id + ":MOT_TBL_TY", name="yhl")
try:
self.rxhl = MotorRecord(Id + ":MOT_TBL_RX", name="rxhl")
except:
print("GPS.pitch not found")
pass
try:
self.ryhl = MotorRecord(Id + ":MOT_TBL_RY", name="rxhl")
except:
print("GPS.roll not found")
pass
### motors nu table ###
self.tnu = MotorRecord(Id + ":MOT_HEX_TX", name="tnu")
self.nu = MotorRecord(Id + ":MOT_HEX_RX", name="nu")
### motors PI hexapod ###
self.hex_x = PV("SARES20-HEX_PI:POSI-X")
self.hex_y = PV("SARES20-HEX_PI:POSI-Y")
self.hex_z = PV("SARES20-HEX_PI:POSI-Z")
self.hex_u = PV("SARES20-HEX_PI:POSI-U")
self.hex_v = PV("SARES20-HEX_PI:POSI-V")
self.hex_w = PV("SARES20-HEX_PI:POSI-W")
def __repr__(self):
s = "**Heavy Load**\n"
motors = "xmu mu tth xbase ybase".split()
for motor in motors:
s += " - %s %.4f\n" % (motor, getattr(self, motor).wm())
s += " - xhl %.4f\n" % (self.xhl.wm())
s += " - yhl %.4f\n" % (self.yhl.wm())
s += " - zhl %.4f\n" % (self.zhl.wm())
s += " - th %.4f\n" % (self.th.wm())
s += "\n"
s += "**Gonio**\n"
motors = "xmu mu tth delta det_z cam_z xbase ybase".split()
for motor in motors:
s += " - %s %.4f\n" % (motor, getattr(self, motor).wm())
s += "\n"
s += "**Hexapod**\n"
motors = "x y z u v w".split()
for motor in motors:
s += " - hex_%s %.4f\n" % (motor, getattr(self, "hex_" + motor).get())
return s
+387
View File
@@ -0,0 +1,387 @@
import numpy as np
from epics import caget
from epics import PV
from ..eco_epics.utilities_epics import EnumWrapper
from cam_server import PipelineClient
from cam_server.utils import get_host_port_from_stream_address
from bsread import source, SUB
import subprocess
import h5py
from time import sleep
from threading import Thread
from datetime import datetime
from ..acquisition.utilities import Acquisition
from bsread import Source
from bsread.h5 import receive
from bsread.avail import dispatcher
import zmq
import os
import data_api as api
#import datetime
#from threading import Thread
#import datetime
#from .utilities import Acquisition
try:
import sys, os
tpath = os.path.dirname(__file__)
sys.path.insert(0,os.path.join(tpath,'../../detector_integration_api'))
#ask Leo(2018.03.14):
#sys.path.insert(0,os.path.join(tpath,'../../jungfrau_utils'))
from detector_integration_api import DetectorIntegrationClient
except:
print('NB: detector integration could not be imported!')
_cameraArrayTypes = ['monochrome','rgb']
class CameraCA:
def __init__(self, pvname, cameraArrayType='monochrome',elog=None):
self.Id = pvname
self.isBS = False
self.px_height = None
self.px_width = None
self.elog = elog
def get_px_height(self):
if not self.px_height:
self.px_height = caget(self.Id + ':HEIGHT')
return self.px_height
def get_px_width(self):
if not self.px_width:
self.px_width = caget(self.Id + ':WIDTH')
return self.px_width
def get_data(self):
w = self.get_px_width()
h = self.get_px_height()
numpix = int(caget(self.Id+':FPICTURE.NORD'))
i = caget(self.Id+':FPICTURE', count=numpix)
return i.reshape(h,w)
def record_images(self,fina,N_images,sleeptime=0.2):
with h5py.File(fina,'w') as f:
d = []
for n in range(N_images):
d.append(self.get_data())
sleep(sleeptime)
f['images'] = np.asarray(d)
def gui(self, guiType='xdm'):
""" Adjustable convention"""
cmd = ['caqtdm','-macro']
cmd.append('\"NAME=%s,CAMNAME=%s\"'%(self.Id, self.Id))
cmd.append('/sf/controls/config/qt/Camera/CameraMiniView.ui')
return subprocess.Popen(' '.join(cmd),shell=True)
#/sf/controls/config/qt/Camera/CameraMiniView.ui" with macro "NAME=SAROP21-PPRM138,CAMNAME=SAROP21-PPRM138
class CameraBS:
def __init__(self,host=None,port=None,elog=None):
self._stream_host = host
self._stream_port = port
def checkServer(self):
# Check if your instance is running on the server.
if self._instance_id not in client.get_server_info()["active_instances"]:
raise ValueError("Requested pipeline is not running.")
def get_images(self,N_images):
data = []
with source(host=self._stream_host, port=self._stream_port, mode=SUB) as input_stream:
input_stream.connect()
for n in range(N_images):
data.append(input_stream.receive().data.data['image'].value)
return data
def record_images(self,fina,N_images,dsetname='images'):
ds = None
with h5py.File(fina,'w') as f:
with source(host=self._stream_host, port=self._stream_port, mode=SUB) as input_stream:
input_stream.connect()
for n in range(N_images):
image = input_stream.receive().data.data['image'].value
if not ds:
ds = f.create_dataset(dsetname,dtype=image.dtype, shape=(N_images,)+image.shape)
ds[n,:,:] = image
class FeDigitizer:
def __init__(self,Id,elog=None):
self.Id = Id
self.gain = EnumWrapper(Id+'-WD-gain')
self._bias = PV(Id+'-HV_SET')
self.channels = [
Id+'-BG-DATA',
Id+'-BG-DRS_TC',
Id+'-BG-PULSEID-valid',
Id+'-DATA',
Id+'-DRS_TC',
Id+'-PULSEID-valid']
def set_bias(self, value):
self._bias.put(value)
def get_bias(self):
return self._bias.value
class DiodeDigitizer:
def __init__(self,Id,VME_crate=None,link=None,
ch_0=7,ch_1=8, elog=None):
self.Id = Id
if VME_crate:
self.diode_0 = FeDigitizer('%s:Lnk%dCh%d'%(VME_crate,link,ch_0))
self.diode_1 = FeDigitizer('%s:Lnk%dCh%d'%(VME_crate,link,ch_1))
class DIAClient:
def __init__(self, Id, instrument=None, api_address = None, jf_name=None):
self.Id = Id
self._api_address = api_address
self.client = DetectorIntegrationClient(api_address)
print("\nDetector Integration API on %s" % api_address)
# No pgroup by default
self.pgroup = 0
self.n_frames = 100
self.jf_name = jf_name
self.pede_file = ""
self.gain_file = ""
self.instrument = instrument
if instrument is None:
print("ERROR: please configure the instrument parameter in DIAClient")
self.gain_file = "/sf/%s/config/jungfrau/gainMaps" % self.instrument
self.update_config()
self.active_clients = list(self.get_active_clients()['clients_enabled'].keys())
def update_config(self, ):
self.writer_config = {
"output_file": "/sf/%s/data/p%d/raw/test_data.h5" % (self.instrument, self.pgroup),
"user_id": self.pgroup,
"n_frames": self.n_frames,
"general/user": str(self.pgroup),
"general/process": __name__,
"general/created": str(datetime.now()),
"general/instrument": self.instrument,
# "general/correction": "test"
}
self.is_HG0 = True
self.backend_config = {
"n_frames": self.n_frames,
"bit_depth": 16,
"gain_corrections_filename": self.gain_file, # "/sf/alvra/config/jungfrau/jungfrau_4p5_gaincorrections_v0.h5",
#"gain_corrections_dataset": "gains",
#"pede_corrections_filename": "/sf/alvra/data/res/p%d/pedestal_20171210_1628_res.h5" % self.pgroup,
#"pede_corrections_dataset": "gains",
#"pede_mask_dataset": "pixel_mask",
#"activate_corrections_preview": True,
# FIXME: HARDCODED!!!
"is_HG0": self.is_HG0
}
if self.pede_file != "":
self.backend_config["gain_corrections_filename"] = self.gain_file # "/sf/alvra/config/jungfrau/jungfrau_4p5_gaincorrections_v0.h5",
self.backend_config["gain_corrections_dataset"] = "gains"
self.backend_config["pede_corrections_filename"] = self.pede_file # "/sf/alvra/data/res/p%d/pedestal_20171210_1628_res.h5" % self.pgroup,
self.backend_config["pede_corrections_dataset"] = "gains"
self.backend_config["pede_mask_dataset"] = "pixel_mask"
self.backend_config["activate_corrections_preview"] = True
else:
self.backend_config["pede_corrections_dataset"] = "gains"
self.backend_config["pede_mask_dataset"] = "pixel_mask"
self.backend_config["gain_corrections_filename"] = ""
self.backend_config["pede_corrections_filename"] = ""
self.backend_config["activate_corrections_preview"] = False
# remove below since it sets the JF to high-gain mode explicitly
# if self.is_HG0:
# print(self.client.set_detector_value("setbit", "0x5d 0"))
# else:
# print(self.client.set_detector_value("clearbit", "0x5d 0"))
self.detector_config = {
"timing": "trigger",
# "setbit" = "0x5d 0"
# FIXME: HARDCODED
"exptime": 0.000005,
"cycles": self.n_frames,
#"delay" : 0.001992,
"frames" : 1,
"dr": 16,
}
# Not needed anymore?
#default_channels_list = parseChannelListFile(
# '/sf/alvra/config/com/channel_lists/default_channel_list')
self.bsread_config = {
'output_file': '/sf/%s/data/p%d/raw/test_bsread.h5' % (self.instrument, self.pgroup),
'user_id': self.pgroup,
"general/user": str(self.pgroup),
"general/process": __name__,
"general/created": str(datetime.now()),
"general/instrument": self.instrument,
#'Npulses':100,
#'channels': default_channels_list
}
# self.default_channels_list = jungfrau_utils.load_default_channel_list()
def reset(self):
self.client.reset()
#pass
def get_status(self):
return self.client.get_status()
def get_config(self):
config = self.client.get_config()
return config
def get_active_clients(self):
return self.client.get_clients_enabled()
def set_pgroup(self, pgroup):
self.pgroup = pgroup
self.update_config()
def set_bs_channels(self, ):
print("Please update /sf/%s/config/com/channel_lists/default_channel_list and restart all services on the DAQ server" % self.instrument)
def set_config(self):
self.reset()
self.client.set_config({"writer": self.writer_config, "backend": self.backend_config, "detector": self.detector_config, "bsread": self.bsread_config})
def check_still_running(self, time_interval=1):
cfg = self.get_config()
running = True
while running:
if not self.get_status()['status'][-7:] == 'RUNNING':
running = False
break
# elif not self.get_status()['status'][-20:]=='BSREAD_STILL_RUNNING':
# running = False
# break
else:
sleep(time_interval)
def take_pedestal(self, n_frames, analyze=True, n_bad_modules=0, update_config=True, period=0.04):
from jungfrau_utils.scripts.jungfrau_run_pedestals import run as jungfrau_utils_run
directory = '/sf/%s/data/p%d/raw/JF_pedestal/' % (self.instrument, self.pgroup)
if not os.path.exists(directory):
print("Directory %s not existing, creating it" % directory)
os.makedirs(directory)
res_dir = directory.replace("/raw/", "/res/")
if not os.path.exists(res_dir):
print("Directory %s not existing, creating it" % res_dir)
os.makedirs(res_dir)
filename = "pedestal_%s.h5" % datetime.now().strftime("%Y%m%d_%H%M")
# period = 0.02 # for 25 Hz this is 0.04, for 10 Hz this 0.1
jungfrau_utils_run(self._api_address, filename, directory, self.pgroup, period, self.detector_config["exptime"],
n_frames, 1, analyze, n_bad_modules, self.instrument, self.jf_name)
if update_config:
self.pede_file = (directory + filename).replace("raw/", "res/").replace(".h5", "_res.h5")
print("Pedestal file updated to %s" % self.pede_file)
return self.pede_file
def start(self):
self.client.start()
print("start acquisition")
pass
def stop(self):
self.client.stop()
print("stop acquisition")
pass
def config_and_start_test(self):
self.reset()
self.set_config()
self.start()
pass
def wait_for_status(self,*args,**kwargs):
return self.client.wait_for_status(*args,**kwargs)
def acquire(self, file_name=None, Npulses=100, JF_factor=1, bsread_padding=0, reset_before=False):
"""
JF_factor?
bsread_padding?
"""
file_rootdir = '/sf/%s/data/p%d/raw/' % (self.instrument, self.pgroup)
if file_name is None:
# FIXME /dev/null crashes the data taking (h5py can't close /dev/null and crashes)
print("Not saving any data, as file_name is not set")
file_name_JF = file_rootdir + "DelMe" + '_JF4p5M.h5'
file_name_bsread = file_rootdir + "DelMe" + '.h5'
else:
# FIXME hardcoded
file_name_JF = file_rootdir + file_name + '_JF4p5M.h5'
file_name_bsread = file_rootdir + file_name + '.h5'
if self.pgroup == 0:
raise ValueError("Please use set_pgroup() to set a pgroup value.")
def acquire():
self.n_frames = Npulses * JF_factor
self.update_config()
#self.detector_config.update({
# 'cycles': n_frames})
self.writer_config.update({
'output_file': file_name_JF,
# 'n_messages': n_frames
})
#self.backend_config.update({
# 'n_frames': n_frames})
self.bsread_config.update({
'output_file':file_name_bsread,
# 'Npulses': Npulses + bsread_padding
})
# self.reset()
if reset_before:
print('Starting reset in acquire')
self.reset()
print('Just resetted in acquire')
self.set_config()
#print(self.get_config())
self.client.start()
done = False
self.client.wait_for_status("IntegrationStatus.FINISHED")
while not done:
stat = self.get_status()
if stat['status'] =='IntegrationStatus.FINISHED':
done = True
if stat['status'] == 'IntegrationStatus.BSREAD_STILL_RUNNING':
done = True
if stat['status'] == 'IntegrationStatus.INITIALIZED':
done = True
if stat['status'] == 'IntegrationStatus.DETECTOR_STOPPED':
done = True
sleep(.1)
outputfilenames = [f'{file_name_JF}.{tcli.upper()}.h5' for tcli in self.active_clients]
return Acquisition(acquire=acquire, acquisition_kwargs={'file_names': outputfilenames, 'Npulses': Npulses},hold=False)
# return Acquisition(acquire=acquire, acquisition_kwargs={'file_names': [file_name_bsread, file_name_JF], 'Npulses': Npulses},hold=False)
def wait_done(self):
# self.check_running()
self.check_still_running()
+7
View File
@@ -0,0 +1,7 @@
from data_api import get_data
class DataApi:
def __init__(self):
pass
def get_data(self):
pass
@@ -0,0 +1,33 @@
from ..aliases import Alias,append_object_to_object
from .adjustable import PvRecord,PvEnum
class CameraBasler:
def __init__(self,pvname,name=None):
self.pvname = pvname
self.name = name
self.alias = Alias(name)
append_object_to_object(self,PvEnum,self.pvname+':INIT',name='initialize')
append_object_to_object(self,PvEnum,self.pvname+':CAMERA',name='running')
append_object_to_object(self,PvRecord,self.pvname+':BOARD',name='board_no')
append_object_to_object(self,PvRecord,self.pvname+':SERIALNR',name='serial_no')
append_object_to_object(self,PvRecord,self.pvname+':EXPOSURE',name='_exposure_time')
append_object_to_object(self,PvEnum,self.pvname+':ACQMODE',name='_acq_mode')
append_object_to_object(self,PvEnum,self.pvname+':RECMODE',name='_req_mode')
append_object_to_object(self,PvEnum,self.pvname+':STOREMODE',name='_store_mode')
append_object_to_object(self,PvRecord,self.pvname+':BINY',name='_binx')
append_object_to_object(self,PvRecord,self.pvname+':BINY',name='_biny')
append_object_to_object(self,PvRecord,self.pvname+':REGIONX_START',name='_roixmin')
append_object_to_object(self,PvRecord,self.pvname+':REGIONX_END',name='_roixmax')
append_object_to_object(self,PvRecord,self.pvname+':REGIONY_START',name='_roiymin')
append_object_to_object(self,PvRecord,self.pvname+':REGIONY_END',name='_roiymax')
append_object_to_object(self,PvEnum,self.pvname+':SET_PARAM',name='_set_parameters')
append_object_to_object(self,PvEnum,self.pvname+':TRIGGER',name='trigger_on')
append_object_to_object(self,PvEnum,self.pvname+':TRIGGERSOURCE',name='trigger_source')
#append_object_to_object(self,PvEnum,self.pvname+':TRIGGEREDGE',name='trigger_edge')
+83
View File
@@ -0,0 +1,83 @@
from ..devices_general.utilities import Changer
from epics import PV
_status_messages = {
-13 : 'invalid value (cannot convert to float). Move not attempted.',
-12 : 'target value outside soft limits. Move not attempted.',
-11 : 'drive PV is not connected: Move not attempted.',
-8 : 'move started, but timed-out.',
-7 : 'move started, timed-out, but appears done.',
-5 : 'move started, unexpected return value from PV.put()',
-4 : 'move-with-wait finished, soft limit violation seen',
-3 : 'move-with-wait finished, hard limit violation seen',
0 : 'move-with-wait finish OK.',
0 : 'move-without-wait executed, not comfirmed',
1 : 'move-without-wait executed, move confirmed' ,
3 : 'move-without-wait finished, hard limit violation seen',
4 : 'move-without-wait finished, soft limit violation seen',
}
class DummyMot:
def __init__(self):
self._mot
self.name = "Dummy Motor"
self.Id = self.Id
def get_current_value(self):
""" Adjustable convention"""
motor_pos = self._stage.get_current_value()
motor_pos -= self.delay_stage_offset
delay = motor_pos*2.*3.33333333*1e-12
return delay
def set_current_value(self, value):
motor_pos = self.delay_to_motor(value) + self.delay_stage_offset
self._stage.set_current_value(motor_pos)
return (value, motor_pos)
def changeTo(self, value, hold=False, check=True):
value = self.delay_to_motor(value) + self.delay_stage_offset
delay = (value - self.delay_stage_offset)*2.*3.33333333*1e-12
return self._stage.changeTo(value, hold, check)
def gui(self, guiType='xdm'):
return self._stage.gui()
# spec-inspired convenience methods
def mv(self,value):
self._stage._currentChange = self.changeTo(value)
def wm(self,*args,**kwargs):
return self.get_current_value(*args,**kwargs)
def mvr(self,value,*args,**kwargs):
motor_pos = self.delay_to_motor(value)
self._stage.mvr(motor_pos)
def wait(self):
self._stage._currentChange.wait()
def stop(self):
""" Adjustable convention"""
try:
self._stage._currentChange.stop()
except:
self._stage.stop()
pass
# return string with motor value as variable representation
def __str__(self):
return "Motor is at %s"%self.wm()
def __repr__(self):
return self.__str__()
def __call__(self,value):
self._currentChange = self.changeTo(value)
@@ -0,0 +1,9 @@
from .devices_general.adjustable import PvEnum
class PowerSocket:
def __init__(self, pvname, name=None):
self.alias = Alias(name)
self.name = name
@@ -0,0 +1,98 @@
from epics import PV
import os
import numpy as np
import time
from .utilities import Changer
from ..aliases import Alias
from time import sleep
class PvRecord:
def __init__(
self,
pvsetname,
pvreadbackname=None,
accuracy=None,
sleeptime=0,
name=None,
elog=None,
):
# alias_fields={"setpv": pvsetname, "readback": pvreadbackname},
# ):
self.Id = pvsetname
self.name = name
self.alias = Alias(name)
self.sleeptime = sleeptime
# for an, af in alias_fields.items():
# self.alias.append(
# Alias(an, channel=".".join([pvname, af]), channeltype="CA")
# )
self._pv = PV(self.Id)
self._currentChange = None
self.accuracy = accuracy
if pvreadbackname is None:
self._pvreadback = PV(self.Id)
else:
self._pvreadback = PV(pvreadbackname)
def get_current_value(self, readback=True):
if readback:
currval = self._pvreadback.get()
if not readback:
currval = self._pv.get()
return currval
def get_moveDone(self):
""" Adjustable convention"""
""" 0: moving 1: move done"""
movedone = 1
if self.accuracy is not None:
if (
np.abs(
self.get_current_value(readback=False)
- self.get_current_value(readback=True)
)
> self.accuracy
):
movedone = 0
else:
sleep(self.sleeptime)
return movedone
def move(self, value):
self._pv.put(value)
time.sleep(0.1)
while self.get_moveDone() == 0:
time.sleep(0.1)
def set_target_value(self, value, hold=False):
""" Adjustable convention"""
changer = lambda value: self.move(value)
return Changer(
target=value, parent=self, changer=changer, hold=hold, stopper=None
)
# spec-inspired convenience methods
def mv(self, value):
self._currentChange = self.set_target_value(value)
def wm(self, *args, **kwargs):
return self.get_current_value(*args, **kwargs)
def mvr(self, value, *args, **kwargs):
if self.get_moveDone == 1:
startvalue = self.get_current_value(readback=True, *args, **kwargs)
else:
startvalue = self.get_current_value(readback=False, *args, **kwargs)
self._currentChange = self.set_target_value(value + startvalue, *args, **kwargs)
def wait(self):
self._currentChange.wait()
def __repr__(self):
return "%s is at: %s" % (self.Id, self.get_current_value())
@@ -0,0 +1,318 @@
import subprocess
from threading import Thread
from epics import PV, ca
import time
from ..eco_epics import device
from ..eco_epics.device import Device
_guiTypes = ['xdm']
def _keywordChecker(kw_key_list_tups):
for tkw,tkey,tlist in kw_key_list_tups:
assert tkey in tlist, "Keyword %s should be one of %s"%(tkw,tlist)
class SmarActException(Exception):
""" raised to indicate a problem with a smartact"""
def __init__(self, msg, *args):
Exception.__init__(self, *args)
self.msg = msg
def __str__(self):
return str(self.msg)
class SmarAct(Device):
_extras = {'disabled':'_able.VAL', }
_init_list = ('VAL', 'DESC', 'RTYP')
_nonpvs = ('_prefix', '_pvs', '_delim', '_init', '_init_list', '_alias', '_extras')
def __init__(self, name=None, timeout=3.0, record=None):
if name is None:
raise SmarActException("must supply SmarAct name")
if name.endswith('.VAL'):
name = name[:-4]
if name.endswith('.'):
name = name[:-1]
self._prefix = name
self._record = record
self._callbacks = {}
device.Device.__init__(self, name, delim='.',
attrs=self._init_list,
timeout=timeout)
# for key, val in self._extras.items():
# pvname = "%s%s" % (name, val)
# self.add_pv(pvname, attr=key)
# self.put('disabled', 0)
class SmarActRecord:
def __init__(self,Id, name=None, elog=None):
self.Id = Id
self._drive = SmarAct(Id+':DRIVE')
self._rbv = SmarAct(Id+':MOTRBV')
self._hlm = SmarAct(Id+':HLM')
self._llm = SmarAct(Id+':LLM')
self._status = SmarAct(Id+':STATUS')
self._set_pos = SmarAct(Id+':SET_POS')
self._stop = SmarAct(Id+':STOP')
self._hold = SmarAct(Id+':HOLD')
self._twv = SmarAct(Id+':TWV')
self._elog = elog
self.name = name
self.units = self._drive.get('EGU')
# Conventional methods and properties for all Adjustable objects
def changeTo(self, value, hold=False, check=True):
""" Adjustable convention"""
mover = lambda value: self.move(\
value, ignore_limits=(not check),
wait=True)
return Changer(
target=value,
parent=self,
mover=mover,
hold=hold,
stopper=self._stop.put('PROC', 1))
def stop(self):
""" Adjustable convention"""
try:
self._currentChange.stop()
except:
self._stop.put('VAL',1)
pass
def within_limits(self, val):
""" returns whether a value for a motor is within drive limits"""
return (val <= self._hlm.get('VAL') and val >= self._llm.get('VAL'))
def move(self, val, relative=False, wait=False, timeout=300.0, ignore_limits=False, confirm_move=False):
""" moves smaract drive to position
arguments:
==========
val value to move to (float) [Must be provided]
relative move relative to current position (T/F) [F]
wait whether to wait for move to complete (T/F) [F]
ignore_limits try move without regard to limits (T/F) [F]
confirm_move try to confirm that move has begun (T/F) [F]
timeout max time for move to complete (in seconds) [300]
return values:
-13 : invalid value (cannot convert to float). Move not attempted.
-12 : target value outside soft limits. Move not attempted.
-11 : drive PV is not connected: Move not attempted.
-8 : move started, but timed-out.
-7 : move started, timed-out, but appears done.
-5 : move started, unexpected return value from PV.put()
-4 : move-with-wait finished, soft limit violation seen
-3 : move-with-wait finished, hard limit violation seen
0 : move-with-wait finish OK.
0 : move-without-wait executed, not cpmfirmed
1 : move-without-wait executed, move confirmed
3 : move-without-wait finished, hard limit violation seen
4 : move-without-wait finished, soft limit violation seen
"""
NONFLOAT, OUTSIDE_LIMITS, UNCONNECTED = -13, -12, -11
TIMEOUT = -8
UNKNOWN_ERROR = -5
DONE_OK = 0
MOVE_BEGUN, MOVE_BEGUN_CONFIRMED = 0, 1
try:
val = float(val)
except TypeError:
return NONFLOAT
if relative:
val += self._drive.get('VAL')
# Check for limit violations
if not ignore_limits:
if not self.within_limits(val):
return OUTSIDE_LIMITS
stat = self._drive.put('VAL', val, wait=wait, timeout=timeout)
if stat is None:
return UNCONNECTED
if wait and stat == -1:
return TIMEOUT
if 1 == stat:
s0 = self._status.get('VAL')
s1 = s0
t0 = time.time()
t1 = t0 + min(10.0, timeout) # should be moving by now
thold = self._hold.get('VAL') * 0.001 + t0
tout = t0 + timeout
if wait or confirm_move:
while time.time() <= thold and s1 == 3:
ca.poll(evt=1.e-2)
s1 = self._status.get('VAL')
while time.time() <= t1 and s1 == 0:
ca.poll(evt=1.e-2)
s1 = self._status.get('VAL')
if s1 == 4:
if wait:
while time.time() <= tout and s1 == 4:
ca.poll(evt=1.e-2)
s1 = self._status.get('VAL')
if s1 == 3 or s1 == 4:
if time.time() > tout:
return TIMEOUT
else:
twv = abs(self._twv.get('VAL'))
while s1==3 and time.time()<=tout and abs(self._rbv.get('VAL')-val)>=twv:
ca.poll(evt=1.e-2)
return DONE_OK
else:
return MOVE_BEGUN_CONFIRMED
elif time.time() > tout:
return TIMEOUT
else:
return UNKNOWN_ERROR
else:
return MOVE_BEGUN
return UNKNOWN_ERROR
def get_current_value(self,readback=True):
if readback:
return self._rbv.get('VAL')
else :
return self._drive.get('VAL')
def set_current_value(self,value):
return self._set_pos.put('VAL',value)
def get_precision(self):
""" Adjustable convention"""
pass
def set_precision(self):
""" Adjustable convention"""
pass
precision = property(get_precision,set_precision)
def set_speed(self):
""" Adjustable convention"""
pass
def get_speed(self):
""" Adjustable convention"""
pass
def set_speedMax(self):
""" Adjustable convention"""
pass
def get_moveDone(self):
pass
def set_limits(self, values, posType='user', relative_to_present=False):
""" Adjustable convention"""
if relative_to_present:
v = self.get_current_value()
values = [v-values[0],v-values[1]]
self._llm.put('VAL',values[0])
self._hlm.put('VAL',values[1])
def get_limits(self, posType='user'):
""" Adjustable convention"""
return self._llm.get('VAL'), self._hlm.get('VAL')
def gui(self, guiType='xdm'):
""" Adjustable convention"""
cmd = ['caqtdm','-macro']
for i in range(len(self.Id)-1):
if self.Id[-i-1].isnumeric() is False:
M = self.Id[-i:]
P = self.Id[:-i]
print(P, M)
break
cmd.append('\"P=%s,M=%s\"'%(P, M))
# #cmd.append('/sf/common/config/qt/motorx_more.ui')
cmd.append('ESB_MX_SMARACT_mot_exp.ui')
# #os.system(' '.join(cmd))
return subprocess.Popen(' '.join(cmd),shell=True)
def mv(self,value):
self._currentChange = self.changeTo(value)
def wm(self,*args,**kwargs):
return self.get_current_value(*args,**kwargs)
def mvr(self,value,*args,**kwargs):
startvalue = self.get_current_value(readback=True,*args,**kwargs)
self._currentChange = self.changeTo(value+startvalue,*args,**kwargs)
def wait(self):
self._currentChange.wait()
# return string with motor value as variable representation
def __str__(self):
return "SmarAct is at %s"%(self.wm())
#return "SmarAct is at %s %s"%(self.wm(),self.units)
def __repr__(self):
return self.__str__()
def __call__(self,value):
self._currentChange = self.changeTo(value)
class SmarActDevice(SmarActRecord):
def __init__(self,Id,alias_namespace=None):
SmarActRecord.__init__(self, Id)
# self.Id = Id
#
# self.x = SmarActRecord(Id+':DRIVE')
class SmarActStage:
def __init__(self, axes, name):
self._keys = axes.keys()
for axis in self._keys:
self.__dict__[axis] = axes[axis]
self.name = name
def __str__(self):
return "SmarAct positions\n%s" % "\n".join(["%s: %s"%(key,self.__dict__[key].wm()) for key in self._keys])
def __repr__(self):
return str({key:self.__dict__[key].wm() for key in self._keys})
class Changer:
def __init__(self, target=None, parent=None, mover=None, hold=True, stopper=None):
self.target = target
self._mover = mover
self._stopper = stopper
self._thread = Thread(target=self._mover,args=(target,))
if not hold:
self._thread.start()
def wait(self):
self._thread.join()
def start(self):
self._thread.start()
def status(self):
if self._thread.ident is None:
return 'waiting'
else:
if self._isAlive:
return 'changing'
else:
return 'done'
def stop(self):
self._stopper()
+85
View File
@@ -0,0 +1,85 @@
from ..devices_general.utilities import Changer
from epics import PV
_status_messages = {
-13: "invalid value (cannot convert to float). Move not attempted.",
-12: "target value outside soft limits. Move not attempted.",
-11: "drive PV is not connected: Move not attempted.",
-8: "move started, but timed-out.",
-7: "move started, timed-out, but appears done.",
-5: "move started, unexpected return value from PV.put()",
-4: "move-with-wait finished, soft limit violation seen",
-3: "move-with-wait finished, hard limit violation seen",
0: "move-with-wait finish OK.",
0: "move-without-wait executed, not comfirmed",
1: "move-without-wait executed, move confirmed",
3: "move-without-wait finished, hard limit violation seen",
4: "move-without-wait finished, soft limit violation seen",
}
class User_to_motor:
def __init__(self, stage, conversion_conv, offset):
self.conv = conversion_conv
self._stage = stage
self.offset = offset
self.name = self._stage.name
self.Id = self._stage.Id
self._elog = self._stage._elog
def user_to_motor(self, user):
motor_pos = user / self.conv
return motor_pos
def get_current_value(self):
""" Adjustable convention"""
motor_pos = self._stage.get_current_value()
motor_pos -= self.offset
user = motor_pos * self.conv
return user
def set_current_value(self, value):
motor_pos = self.user_to_motor(value) + self.offset
self._stage.set_current_value(motor_pos)
return (value, motor_pos)
def set_target_value(self, value, hold=False, check=True):
value = self.user_to_motor(value) + self.offset
user = (value - self.offset) * self.conv
return self._stage.set_target_value(value, hold, check)
def gui(self, guiType="xdm"):
return self._stage.gui()
# spec-inspired convenience methods
def mv(self, value):
self._stage._currentChange = self.set_target_value(value)
def wm(self, *args, **kwargs):
return self.get_current_value(*args, **kwargs)
def mvr(self, value, *args, **kwargs):
motor_pos = self.user_to_motor(value)
self._stage.mvr(motor_pos)
def wait(self):
self._stage._currentChange.wait()
def stop(self):
""" Adjustable convention"""
try:
self._stage._currentChange.stop()
except:
self._stage.stop()
pass
# return string with motor value as variable representation
def __str__(self):
return "Motor is at %s" % self.wm()
def __repr__(self):
return self.__str__()
def __call__(self, value):
self._currentChange = self.set_target_value(value)
+21
View File
@@ -0,0 +1,21 @@
from ..devices_general.smaract import SmarActRecord
from epics import PV
class SmaractTower:
def __init__(self,Id):
self.Id = Id
### Mirrors used in the expeirment ###
try:
self.x = SmarActRecord(Id+'-ESB1')
except:
print('No Smaract x linear stage')
pass
try:
self.gonio = SmarActRecord(Id+'-ESB2')
except:
print('No Smaract Gonio')
pass
+19
View File
@@ -0,0 +1,19 @@
from ..devices_general.motors import MotorRecord
from epics import PV
class Laser_Exp:
def __init__(self, Id):
self.Id = Id
### Mirrors used in the expeirment ###
try:
self.phi = MotorRecord(Id + "-M517:MOT")
except:
print("No Standa steering phi mirror")
pass
try:
self.th = MotorRecord(Id + "-M518:MOT")
except:
print("No Standa steering theta mirror")
pass
+24
View File
@@ -0,0 +1,24 @@
from ..devices_general.motors import MotorRecord
from ..devices_general.smaract import SmarActRecord
from epics import PV
from ..devices_general.delay_stage import DelayStage
class Palm:
def __init__(self, Id):
self.Id = Id
self._delayStg = MotorRecord(self.Id + "-M552:MOT")
self.delay = DelayStage(self._delayStg)
def get_adjustable_positions_str(self):
ostr = "*****Palm motor positions******\n"
for tkey, item in self.__dict__.items():
if hasattr(item, "get_current_value"):
pos = item.get_current_value()
ostr += " " + tkey.ljust(10) + " : % 14g\n" % pos
return ostr
def __repr__(self):
return self.get_adjustable_positions_str()
+24
View File
@@ -0,0 +1,24 @@
from ..devices_general.motors import MotorRecord
from ..devices_general.smaract import SmarActRecord
from epics import PV
from ..devices_general.delay_stage import DelayStage
class Psen:
def __init__(self, Id):
self.Id = Id
self._delayStg = MotorRecord(self.Id + "-M561:MOT")
self.delay = DelayStage(self._delayStg)
def get_adjustable_positions_str(self):
ostr = "*****PSEN motor positions******\n"
for tkey, item in self.__dict__.items():
if hasattr(item, "get_current_value"):
pos = item.get_current_value()
ostr += " " + tkey.ljust(10) + " : % 14g\n" % pos
return ostr
def __repr__(self):
return self.get_adjustable_positions_str()
+35
View File
@@ -0,0 +1,35 @@
import numpy as np
from matplotlib import pylab as plt
def readTraceTextfile(fina, numbers=None):
if not numbers is None:
d = [readTraceTextfile(fina % number) for number in numbers]
else:
d = np.loadtxt(fina, skiprows=5, delimiter=",")
return d
def getRiseTime(t, s, lims=[0.1, 0.9]):
lims = np.asarray(lims)
t = np.asarray(t)
s = np.asarray(s)
sel = t > 0
mxind = np.min((np.diff(s[sel]) < 0).nonzero()[0])
mxind = sel.nonzero()[0][mxind]
sel = t <= 0
mnind = np.max((np.diff(s[sel]) < 0).nonzero()[0])
mnind = sel.nonzero()[0][mnind] + 1
crosspty = lims * (s[mxind] - s[mnind]) + s[mnind]
crossptx = np.interp(crosspty, s[mnind : mxind + 1], t[mnind : mxind + 1])
return float(np.round(np.diff(crossptx), decimals=13)), [crossptx, crosspty]
def plotTrace(fina="./scope2_testdata_2017-02-21/C2Trace00003txt"):
t, s = readTraceTextfile(fina).T
rt, crossers = getRiseTime(t, s)
ax = plt.gca()
ax.plot(t, s, ".-", label="rise time = %3g (fwhm)" % rt)
ax.plot(crossers[0], crossers[1], "xr")
ax.set_xlabel("Time / s")
ax.set_ylabel("Amplitude / V")
+42
View File
@@ -0,0 +1,42 @@
import time
import os
import signal
from subprocess import Popen, PIPE, STDOUT
class ScreenPanel:
def __init__(self, name=None):
self.name = name
self._proc = None
@property
def proc(self):
if not self._proc:
if (
input(
"No screenpanel running, would you like to start now? (y/n)\n"
).strip()
== "y"
):
self.start()
return self._proc
def start(self):
if self._proc:
print(f"Sreenpanel {self.name} is already running")
else:
# self.proc = subprocess.Popen(["screen_panel","-console"],stdout=subprocess.PIPE)
self._proc = Popen(
["bash", "screen_panel", "-console", "-persist"],
stdin=PIPE,
stdout=PIPE,
preexec_fn=os.setsid,
)
def quit(self):
os.killpg(self.proc.pid, signal.SIGTERM)
self._proc = None
def set_camera(self, camera_name):
self.proc.stdin.write(("cam " + camera_name + "\n").encode())
self.proc.stdin.flush()
+47
View File
@@ -0,0 +1,47 @@
from ..devices_general.motors import MotorRecord
from ..devices_general.smaract import SmarActRecord
from epics import PV
from ..devices_general.delay_stage import DelayStage
class palm:
def __init__(self, Id):
self.Id = Id
self.delay = MotorRecord(self.Id + "-M423:MOT")
self.delayTime = DelayStage(self.delay)
# self.delay2 = MotorRecord(self.Id+'-M422:MOT')
# self.delayTime2 = DelayStage(self.delay)
def get_adjustable_positions_str(self):
ostr = "***** PALM motor positions ******\n"
for tkey, item in self.__dict__.items():
if hasattr(item, "get_current_value"):
pos = item.get_current_value()
ostr += " " + tkey.ljust(10) + " : % 14g\n" % pos
return ostr
def __repr__(self):
return self.get_adjustable_positions_str()
class eo:
def __init__(self, Id):
self.Id = Id
self.delay = MotorRecord(self.Id + "-M422:MOT")
self.delayTime = DelayStage(self.delay)
def get_adjustable_positions_str(self):
ostr = "***** PALM EO sampling motor positions ******\n"
for tkey, item in self.__dict__.items():
if hasattr(item, "get_current_value"):
pos = item.get_current_value()
ostr += " " + tkey.ljust(10) + " : % 14g\n" % pos
return ostr
def __repr__(self):
return self.get_adjustable_positions_str()
+26
View File
@@ -0,0 +1,26 @@
from ..devices_general.motors import MotorRecord
from ..devices_general.smaract import SmarActRecord
from epics import PV
from ..devices_general.delay_stage import DelayStage
class psen:
def __init__(self,Id):
self.Id = Id
self.delay = MotorRecord(self.Id+'-M424:MOT')
self.delayTime = DelayStage(self.delay)
def get_adjustable_positions_str(self):
ostr = '*****PSEN motor positions******\n'
for tkey,item in self.__dict__.items():
if hasattr(item,'get_current_value'):
pos = item.get_current_value()
ostr += ' ' + tkey.ljust(10) + ' : % 14g\n'%pos
return ostr
def __repr__(self):
return self.get_adjustable_positions_str()
+426
View File
@@ -0,0 +1,426 @@
from ..devices_general.motors import MotorRecord
from epics import PV
from ..eco_epics.utilities_epics import EnumWrapper
from ..devices_general.utilities import Changer
from time import sleep
import numpy as np
class Double_Crystal_Mono_AramisMacro:
def __init__(self,Id,timeAdjustable=None,timeReferenceEnergy=None,timeReference=None):
self.Id = Id
self.theta = MotorRecord(Id+':RX12')
self.x = MotorRecord(Id+':TX12')
self.gap = MotorRecord(Id+':T2')
self.roll1 = MotorRecord(Id+':RZ1')
self.roll2 = MotorRecord(Id+':RZ2')
self.pitch2 = MotorRecord(Id+':RX2')
self.energy_rbk = PV(Id+':ENERGY')
self.energy_sp = PV(Id+':ENERGY_SP')
self.moving = PV(Id+':MOVING')
self._stop = PV(Id +':STOP.PROC')
self.crystal_type = EnumWrapper(Id + ':CRYSTAL_SP')
self.beam_offset = PV(Id + ':BEAM_OFFSET')
self.timeAdjustable = timeAdjustable
self.timeReferenceEnergy = timeReferenceEnergy
self.timeReference = timeReference
self.correctTime = False
def _calcOffsetDetour(self,E,crystal_type=None,beam_offset=None):
if not crystal_type:
crystal_type = self.crystal_type.get()
if crystal_type is "Si-111":
d = 3.1356124059796264
else:
raise NotImplementedError
if not beam_offset:
beam_offset = self.beam_offset.get()
theta = np.arcsin(12398.419739640718/E/2/d)
return np.tan(theta) * beam_offset
def setTimeReference(self,t=None,E=None):
if not t:
t = self.timeAdjustable.get_current_value()
if not E:
E = self.get_current_value()
print(f"Setting mono time reference to {t} s and {E} eV.")
self.timeReference = t
self.timeReferenceEnergy = E
def move_and_wait(self,value,checktime=.01,precision=.5):
if self.correctTime:
p_ref = self._calcOffsetDetour(self.timeReferenceEnergy)
p_target = self._calcOffsetDetour(value)
t_delta = (p_target-p_ref)*1e-3/299792458.
t_new = self.timeReference + t_delta
print('correcting timing by Dt = {t_delta} s to {t_new} s')
#self.energy_sp.put(value)
#while abs(self.wait_for_valid_value()-value)>precision:
# sleep(checktime)
def changeTo(self,value,hold=False):
changer = lambda value: self.move_and_wait(value)
return Changer(
target=value,
parent=self,
changer=changer,
hold=hold,
stopper=self.stop)
def stop(self):
self._stop.put(1)
def get_current_value(self):
currentenergy = self.energy_rbk.get()
return currentenergy
def wait_for_valid_value(self):
tval = np.nan
while not np.isfinite(tval):
tval = self.energy_rbk.get()
return(tval)
def set_current_value(self,value):
self.energy_sp.put(value)
def get_moveDone(self):
inmotion = int(self.moving.get())
return inmotion
# spec-inspired convenience methods
def mv(self,value):
self._currentChange = self.changeTo(value)
def wm(self,*args,**kwargs):
return self.get_current_value(*args,**kwargs)
def mvr(self,value,*args,**kwargs):
if(self.get_moveDone == 1):
startvalue = self.get_current_value(*args,**kwargs)
else:
startvalue = self.get_current_value(*args,**kwargs)
self._currentChange = self.changeTo(value+startvalue,*args,**kwargs)
def wait(self):
self._currentChange.wait()
def __str__(self):
s = "**Double crystal monochromator**\n\n"
motors = "theta gap x roll1 roll2 pitch2".split()
for motor in motors:
s+= " - %s = %.4f\n" %(motor, getattr(self,motor).wm())
pvs = "energy_rbk".split()
for pv in pvs:
s+= " - %s = %.4f\n" %(pv, getattr(self,pv).value)
return s
def __repr__(self):
return self.__str__()
def __call__(self,value):
self._currentChange = self.changeTo(value)
class EcolEnergy:
def __init__(self,Id, val='SARCL02-MBND100:P-SET',rb='SARCL02-MBND100:P-READ' ,dmov='SFB_BEAM_ENERGY_ECOL:SUM-ERROR-OK'):
self.Id = Id
self.setter = PV(val)
self.readback = PV(rb)
self.dmov = PV(dmov)
self.done = False
def get_current_value(self):
return self.readback.get()
def move_and_wait(self,value,checktime=.01,precision=2):
curr = self.setter.get()
while abs(curr-value)>0.1:
curr = self.setter.get()
self.setter.put(curr + np.sign(value-curr)*.1)
sleep(0.3)
self.setter.put(value)
while abs(self.get_current_value() - value)>precision:
sleep(checktime)
while not self.dmov.get():
#print(self.dmov.get())
sleep(checktime)
def changeTo(self,value,hold=False):
changer = lambda value: self.move_and_wait(value)
return Changer(
target=value,
parent=self,
changer=changer,
hold=hold,
stopper=None)
class Double_Crystal_Mono:
def __init__(self,Id,timeAdjustable=None,timeReferenceEnergy=None,timeReference=None):
self.Id = Id
self.theta = MotorRecord(Id+':RX12')
self.x = MotorRecord(Id+':TX12')
self.gap = MotorRecord(Id+':T2')
self.roll1 = MotorRecord(Id+':RZ1')
self.roll2 = MotorRecord(Id+':RZ2')
self.pitch2 = MotorRecord(Id+':RX2')
self.energy_rbk = PV(Id+':ENERGY')
self.energy_sp = PV(Id+':ENERGY_SP')
self.moving = PV(Id+':MOVING')
self._stop = PV(Id +':STOP.PROC')
self.crystal_type = EnumWrapper(Id + ':CRYSTAL_SP')
self.beam_offset = PV(Id + ':BEAM_OFFSET')
self.timeAdjustable = timeAdjustable
self.timeReferenceEnergy = timeReferenceEnergy
self.timeReference = timeReference
self.correctTime = False
def _calcOffsetDetour(self,E,crystal_type=None,beam_offset=None):
if not crystal_type:
crystal_type = str(self.crystal_type)
if crystal_type=="Si-111":
d = 3.1356124059796264
else:
raise NotImplementedError
if not beam_offset:
beam_offset = self.beam_offset.get()
theta = np.arcsin(12398.419739640718/E/2/d)
return np.tan(theta) * beam_offset
def setTimeReference(self,t=None,E=None):
if not t:
t = self.timeAdjustable.get_current_value()
if not E:
E = self.get_current_value()
print(f"Setting mono time reference to {t} s and {E} eV.")
self.timeReference = t
self.timeReferenceEnergy = E
def move_and_wait(self,value,checktime=.01,precision=.5):
if self.correctTime:
p_ref = self._calcOffsetDetour(self.timeReferenceEnergy)
p_target = self._calcOffsetDetour(value)
t_delta = (p_target-p_ref)*1e-3/299792458.
t_new = self.timeReference - t_delta
print(f'correcting laser to xray timing delay by\nDt = {-t_delta} s to {t_new} s')
time_mover = self.timeAdjustable.changeTo(t_new)
self.energy_sp.put(value)
while abs(self.wait_for_valid_value()-value)>precision:
sleep(checktime)
if self.correctTime:
time_mover.wait()
def changeTo(self,value,hold=False):
changer = lambda value: self.move_and_wait(value)
return Changer(
target=value,
parent=self,
changer=changer,
hold=hold,
stopper=self.stop)
def stop(self):
self._stop.put(1)
def get_current_value(self):
currentenergy = self.energy_rbk.get()
return currentenergy
def wait_for_valid_value(self):
tval = np.nan
while not np.isfinite(tval):
tval = self.energy_rbk.get()
return(tval)
def set_current_value(self,value):
self.energy_sp.put(value)
def get_moveDone(self):
inmotion = int(self.moving.get())
return inmotion
# spec-inspired convenience methods
def mv(self,value):
self._currentChange = self.changeTo(value)
def wm(self,*args,**kwargs):
return self.get_current_value(*args,**kwargs)
def mvr(self,value,*args,**kwargs):
if(self.get_moveDone == 1):
startvalue = self.get_current_value(*args,**kwargs)
else:
startvalue = self.get_current_value(*args,**kwargs)
self._currentChange = self.changeTo(value+startvalue,*args,**kwargs)
def wait(self):
self._currentChange.wait()
def __str__(self):
s = "**Double crystal monochromator**\n\n"
motors = "theta gap x roll1 roll2 pitch2".split()
for motor in motors:
s+= " - %s = %.4f\n" %(motor, getattr(self,motor).wm())
pvs = "energy_rbk".split()
for pv in pvs:
s+= " - %s = %.4f\n" %(pv, getattr(self,pv).value)
return s
def __repr__(self):
return self.__str__()
def __call__(self,value):
self._currentChange = self.changeTo(value)
class EcolEnergy:
def __init__(self,Id, val='SARCL02-MBND100:P-SET',rb='SARCL02-MBND100:P-READ' ,dmov='SFB_BEAM_ENERGY_ECOL:SUM-ERROR-OK'):
self.Id = Id
self.setter = PV(val)
self.readback = PV(rb)
self.dmov = PV(dmov)
self.done = False
def get_current_value(self):
return self.readback.get()
def move_and_wait(self,value,checktime=.01,precision=2):
curr = self.setter.get()
while abs(curr-value)>0.1:
curr = self.setter.get()
self.setter.put(curr + np.sign(value-curr)*.1)
sleep(0.3)
self.setter.put(value)
while abs(self.get_current_value() - value)>precision:
sleep(checktime)
while not self.dmov.get():
#print(self.dmov.get())
sleep(checktime)
def changeTo(self,value,hold=False):
changer = lambda value: self.move_and_wait(value)
return Changer(
target=value,
parent=self,
changer=changer,
hold=hold,
stopper=None)
class MonoEcolEnergy:
def __init__(self,Id):
self.Id = Id
self.name = 'energy_collimator'
self.dcm = Double_Crystal_Mono(Id)
self.ecol = EcolEnergy('ecol_dummy')
self.offset = None
self.MeVperEV = 0.78333
def get_current_value(self):
return self.dcm.get_current_value()
def move_and_wait(self,value):
ch = [self.dcm.changeTo(value),
self.ecol.changeTo(self.calcEcol(value))]
for tc in ch:
tc.wait()
def changeTo(self,value,hold=False):
changer = lambda value: self.move_and_wait(value)
return Changer(
target=value,
parent=self,
changer=changer,
hold=hold,
stopper=self.dcm.stop)
def alignOffsets(self):
mrb = self.dcm.get_current_value()
erb = self.ecol.get_current_value()
self.offset = {'dcm':mrb, 'ecol':erb}
def calcEcol(self,eV):
return (eV-self.offset['dcm'])*self.MeVperEV + self.offset['ecol']
class AlvraDCM_FEL:
def __init__(self,Id):
self.Id = Id
self.name = 'Alvra DCM monochromator coupled to FEL beam'
# self.IOCstatus = PV('ALVRA:running') # bool 0 running, 1 not running
self._FELcoupling = PV('SGE-OP2E-ARAMIS:MODE_SP') # string "Off" or "e-beam"
self._setEnergy = PV('SAROP11-ARAMIS:ENERGY_SP_USER') # float eV
self._getEnergy = PV('SAROP11-ARAMIS:ENERGY') # float eV
self.ebeamEnergy = PV('SARCL02-MBND100:P-READ') # float MeV/c
# self.ebeamEnergySP = PV('ALVRA:Energy_SP') # float MeV
self.dcmStop = PV('SAROP11-ODCM105:STOP.PROC') # stop the DCM motors
self.dcmMoving = PV('SAROP11-ODCM105:MOVING') # DCM moving field
self._energyChanging = PV('SGE-OP2E-ARAMIS:MOVING') # PV telling you something related to the energy is changing
self._alvraMode = PV('SAROP11-ARAMIS:MODE') # string Aramis SAROP11 mode
self.ebeamOK = PV('SFB_BEAM_ENERGY_ECOL:SUM-ERROR-OK') # is ebeam no longer changing
self.photCalib1 = PV('SGE-OP2E-ARAMIS:PH2E_X1') # photon energy calibration low calibration point
self.photCalib2 = PV('SGE-OP2E-ARAMIS:PH2E_X2') # photon energy calibration high calibration point
self.ebeamCalib1 = PV('SGE-OP2E-ARAMIS:PH2E_Y1') # electron energy calibration low calibration point
self.ebeamCalib2 = PV('SGE-OP2E-ARAMIS:PH2E_Y2') # electron energy calibration high calibration point
def __str__(self):
# ioc = self.IOCstatus.get()
# if ioc == 0:
# iocStr = "Soft IOC running"
# else:
# iocStr = "Soft IOC not running"
FELcouplingStr = self._FELcoupling.get(as_string=True)
alvraModeStr = self._alvraMode.get(as_string=True)
currEnergy = self._getEnergy.get()
currebeamEnergy = self.ebeamEnergy.get()
photCalib1Str = self.photCalib1.get()
photCalib2Str = self.photCalib2.get()
ebeamCalib1Str = self.ebeamCalib1.get()
ebeamCalib2Str = self.ebeamCalib2.get()
s = '**Alvra DCM-FEL status**\n\n'
# print('%s'%iocStr)
# print('FEL coupling %s'%FELcouplingStr)
# print('Alvra beamline mode %s'%alvraModeStr)
# print('Photon energy (eV) %'%currEnergy)
# s += '%s\n'%iocStr
s += 'FEL coupling: %s\n'%FELcouplingStr
s += 'Alvra beamline mode: %s\n'%alvraModeStr
s += 'Photon energy: %.2f eV\n'%currEnergy
s += 'Electron energy: %.2f MeV\n'%currebeamEnergy
s += 'Calibration set points:\n'
s += 'Low: Photon %.2f keV, Electron %.2f MeV\n'%(photCalib1Str, ebeamCalib1Str)
s += 'High: Photon %.2f keV, Electron %.2f MeV\n'%(photCalib2Str, ebeamCalib2Str)
return s
def get_current_value(self):
return self._getEnergy.get()
def move_and_wait(self,value,checktime=.1,precision=0.5):
self._FELcoupling.put(1) # ensure the FEL coupling is turned on
self._setEnergy.put(value)
# while self.ebeamOK.get()==0:
# sleep(checktime)
# while abs(self.ebeamEnergy.get()-self.ebeamEnergySP.get())>precision:
# sleep(checktime)
# while self.dcmMoving.get()==1:
# sleep(checktime)
while self._energyChanging == 1:
sleep(checktime)
def changeTo(self,value,hold=False):
changer = lambda value: self.move_and_wait(value)
return Changer(
target=value,
parent=self,
changer=changer,
hold=hold,
stopper=None)
def __repr__(self):
return self.__str__()
@@ -0,0 +1,54 @@
from ..devices_general.motors import MotorRecord
from epics import PV
from ..aliases import Alias, append_object_to_object
class RefLaser_Aramis:
def __init__(self, Id, elog=None, name=None, inpos=-18.818, outpos=-5):
self.Id = Id
self.elog = elog
self.name = name
self.alias = Alias(name)
# append_object_to_object(self,
self._inpos = inpos
self._outpos = outpos
self.mirrmotor = MotorRecord(self.Id + ":MOTOR_1")
def __call__(self, *args, **kwargs):
self.set(*args, **kwargs)
def __str__(self):
status = self.get_status()
if status:
return "Reflaser is In."
elif status == False:
return "Reflaser is Out."
elif status == None:
return "Reflaser status not defined."
def get_status(self):
v = self.mirrmotor.get_current_value()
if abs(v - self._inpos) < 0.2:
isin = True
elif abs(v - self._outpos) < 0.2:
isin = False
else:
isin = None
return isin
def set(self, value):
if type(value) is str:
if value.lower() == "in":
value = True
elif value.lower() == "out":
value = False
else:
print("String %s not recognized!" % value)
if value:
self.mirrmotor.set_target_value(self._inpos)
else:
self.mirrmotor.set_target_value(self._outpos)
def __repr__(self):
return self.__str__()
+24
View File
@@ -0,0 +1,24 @@
#!/opt/gfa/python-3.5/latest/bin/python
from epics import PV
import datetime
import sys
class stationMessage:
def __init__(self, station):
self._BL = station
def post(self, message):
stationStr = self._BL
msg = message
date_formatted = datetime.datetime.strftime(
datetime.datetime.now(), "%a %d-%b-%Y %H:%M:%S"
)
mscroll = PV("SF-OP:" + str(stationStr) + "-MSG:OP-MSCROLL.PROC")
mscroll.value = 1
msg1 = PV("SF-OP:" + str(stationStr) + "-MSG:OP-MSG1")
msg1.value = msg.encode()
date1 = PV("SF-OP:" + str(stationStr) + "-MSG:OP-DATE1")
date1.value = date_formatted.encode()
msg1.disconnect()
date1.disconnect()
+8
View File
@@ -0,0 +1,8 @@
import matplotlib.pyplot as plt
def identifyContrastplotData(x, y, i):
assert i.ndim == 2, "Intensity data needs to be 2 dimensional!"
assert (
x.ndim == y.ndim
), "please provide x and y plotting coordinate in same dimension"
+24
View File
@@ -0,0 +1,24 @@
from time import sleep
import sys, select
_wait_strs = '\|/-\|/-'
class WaitInput:
def __init__(self,text,wait_time=5,update_interval=1):
self.text = text
self.wait_time=wait_time
def start(self):
resttime = self.wait_time
while resttime>0:
print(f"You have {resttime} seconds to answer!")
i, o, e = select.select( [sys.stdin], [], [], 2 )
if (i):
print("You said", sys.stdin.readline().strip())
else:
print("You said nothing!")
@@ -0,0 +1,77 @@
import traceback
from colorama import Fore as _color
from importlib import import_module
import copy
try:
from lazy_object_proxy import Proxy as LazyProxy
except:
print(
"Could not find package lazy-object-proxy for lazy initialisation of devices!"
)
pass
def init_device(devDict, devId, args, kwargs, verbose=True):
imp_p = devDict["eco_type"].split(sep=".")
dev_alias = devDict["alias"]
dev_alias = dev_alias[0].lower() + dev_alias[1:]
eco_type_name = imp_p[-1]
istr = "from .." + ".".join(imp_p[:-1]) + " import "
istr += "%s as _%s" % (eco_type_name, eco_type_name)
# print(istr)
if verbose:
print(("Configuring %s " % (dev_alias)).ljust(25), end="")
print(("(%s)" % (devId)).ljust(25), end="")
error = None
try:
exec(istr)
tdev = eval("_%s(Id='%s',*args,**kwargs)" % (eco_type_name, devId))
tdev.name = dev_alias
tdev._z_und = devDict["z_und"]
if verbose:
print((_color.GREEN + "OK" + _color.RESET).rjust(5))
return tdev
except Exception as expt:
# tb = traceback.format_exc()
if verbose:
print((_color.RED + "FAILED" + _color.RESET).rjust(5))
# print(sys.exc_info())
raise expt
def initDeviceAliasList(aliases, lazy=False, verbose=True):
devices = {}
problems = {}
for device_Id in aliases.keys():
alias = aliases[device_Id]["alias"]
alias = alias[0].lower() + alias[1:]
if "eco_type" in aliases[device_Id].keys() and aliases[device_Id]["eco_type"]:
if "args" in aliases[device_Id].keys() and aliases[device_Id]["args"]:
args = aliases[device_Id]["args"]
else:
args = tuple()
if "kwargs" in aliases[device_Id].keys() and aliases[device_Id]["kwargs"]:
kwargs = aliases[device_Id]["kwargs"]
else:
kwargs = dict()
try:
devices[alias] = {}
devices[alias]["device_Id"] = device_Id
if lazy:
devices[alias]["factory"] = lambda: init_device(
aliases[device_Id], device_Id, args, kwargs, verbose=verbose
)
dev = LazyProxy(devices[alias]["factory"])
else:
dev = init_device(
aliases[device_Id], device_Id, args, kwargs, verbose=verbose
)
devices[alias]["instance"] = dev
except:
device.pop(alias)
problems[alias] = {}
problems[alias]["device_Id"] = device_Id
problems[alias]["trace"] = traceback.format_exc()
return devices, problems
+1
View File
@@ -0,0 +1 @@
from . import materials
File diff suppressed because it is too large Load Diff
+110
View File
@@ -0,0 +1,110 @@
import xrayutilities as xu
from . import consts as _consts
from scipy.constants import torr, bar, k, N_A, R
import numpy as np
# This module holds relevant materials of the
# xrayutilities materials class,
class MaterialCollection:
""" Dummy class collections of materials (dict-like)."""
def __init__(self, **entries):
self.__dict__.update(entries)
def __setitem__(self, key, value):
self.__dict__.update({key: value})
_amorphous = dict()
_crystal = dict()
_gas = dict()
amorphous = MaterialCollection()
crystal = MaterialCollection()
gas = MaterialCollection()
def _get_transmission(self, d, E="config"):
""" calculate the transmittion after thickness d (in m) of material at energy E (in eV)."""
return np.exp(-d * 1e6 / self.absorption_length(E))
xu.materials.Material.transmission = _get_transmission
crystal["Si"] = xu.materials.Si
crystal["Ge"] = xu.materials.Ge
crystal["GaAs"] = xu.materials.GaAs
crystal["Al"] = xu.materials.Al
crystal["Diamond"] = xu.materials.C
crystal["Be"] = xu.materials.material.Crystal(
"Be",
xu.materials.spacegrouplattice.SGLattice(
194, 2.2858, 3.5843, atoms=[xu.materials.elements.Be], pos=["2c"]
),
)
amorphous["B4C"] = xu.materials.material.Amorphous("B4C", 2520, [("B", 4), ("C", 1)])
amorphous["Mo"] = xu.materials.material.Amorphous("Mo", 10220, [("Mo", 1)])
amorphous["polyimide"] = xu.materials.material.Amorphous(
"polyimide", 1430, [("C", 22), ("H", 10), ("N", 2), ("O", 5)]
)
amorphous["mylar"] = xu.materials.material.Amorphous(
"mylar", 1400, [("C", 10), ("H", 8), ("O", 4)]
)
amorphous["polycarbonate"] = xu.materials.material.Amorphous(
"polycarbonate", 1200, [("C", 16), ("H", 14), ("O", 3)]
)
amorphous["Si3N4"] = xu.materials.material.Amorphous(
"Silicon nitride", 3440, [("Si", 3), ("N", 4)]
)
amorphous["air"] = xu.materials.material.Amorphous(
"air", 1000, [("N", 1.562), ("O", 0.42), ("C", 0.0003), ("Ar", 0.0094)]
)
# more useful values and constants
# elementName = DummyClassDict(_consts.elementName)
# meltPoint = DummyClassDict(_consts.meltPoint)
# density = DummyClassDict(_consts.Density)
class Gas(xu.materials.material.Amorphous):
def __init__(
self, name, pressure=bar, temperature=295, molecule_size=1, atoms=None, cij=None
):
"""pressure in Pascal, temperature in Kelvin"""
self.pressure = pressure
self.temperature = temperature
self.molecule_size = molecule_size
super(Gas, self).__init__(name, 0, atoms=atoms, cij=cij)
def _getdensity(self):
"""
calculates the mass density of an material from the atomic composition and the average molecule size (ideal gas).
Returns
-------
mass density in kg/m^3
"""
num_dens = self.pressure / k / self.temperature
return self._get_composition_mass() * num_dens * self.molecule_size
density = property(_getdensity)
def _get_composition_mass(self):
w = 0
for atom, occ in self.base:
w += atom.weight * occ
return w
gas["air"] = Gas(
"air",
molecule_size=1.9917,
atoms=[("N", 1.562), ("O", 0.42), ("C", 0.0003), ("Ar", 0.0094)],
)
gas["He"] = Gas("He", molecule_size=1, atoms=[("He", 1)])
gas["N"] = Gas("He", molecule_size=2, atoms=[("N", 1)])
+44
View File
@@ -0,0 +1,44 @@
import xrayutilities as xu
import xraylib as xl
import numpy as np
from . import materials
def getKBMirrorLayer():
subst = xu.simpack.Layer(materials.crystal.Si, np.inf)
highZ = xu.simpack.Layer(materials.amorphous.Mo, 200)
lowZ = xu.simpack.Layer(materials.amorphous.B4C, 150)
return subst + highZ + lowZ
def calcReflectivity(
mirror=getKBMirrorLayer(),
energys=np.linspace(2000, 12000, 200),
alphais=np.linspace(0, 3, 200),
sample_width=500,
**kwargs
):
Refl = []
for E in energys:
m = xu.simpack.SpecularReflectivityModel(mirror, energy=E, **kwargs)
Refl.append(m.simulate(alphais))
return np.asarray(Refl), energys, alphais
def absorptionEdge(element, edge=None):
if type(element) is str:
element = xl.SymbolToAtomicNumber(element)
shells = ["K", "L1", "L2", "L3", "M1", "M2", "M3", "M4", "M5"]
if edge is not None:
shell_ind = shells.index(edge)
return xl.EdgeEnergy(element, shell_ind)
else:
shell_inds = range(8)
print("Absorption edges %s" % xl.AtomicNumberToSymbol(element))
for shell_ind in shell_inds:
print(
" "
+ shells[shell_ind].ljust(3)
+ " = %7.1f eV" % (xl.EdgeEnergy(element, shell_ind) * 1000)
)
+82
View File
@@ -0,0 +1,82 @@
import numpy as np
from scipy import constants
import xraylib as xl
def cartesian(arrays, out=None):
"""
Generate a cartesian product of input arrays.
Parameters
----------
arrays : list of array-like
1-D arrays to form the cartesian product of.
out : ndarray
Array to place the cartesian product in.
Returns
-------
out : ndarray
2-D array of shape (M, len(arrays)) containing cartesian products
formed of input arrays.
Examples
--------
>>> cartesian(([1, 2, 3], [4, 5], [6, 7]))
array([[1, 4, 6],
[1, 4, 7],
[1, 5, 6],
[1, 5, 7],
[2, 4, 6],
[2, 4, 7],
[2, 5, 6],
[2, 5, 7],
[3, 4, 6],
[3, 4, 7],
[3, 5, 6],
[3, 5, 7]])
"""
arrays = [np.asarray(x) for x in arrays]
dtype = arrays[0].dtype
n = np.prod([x.size for x in arrays])
if out is None:
out = np.zeros([n, len(arrays)], dtype=dtype)
m = n / arrays[0].size
out[:, 0] = np.repeat(arrays[0], m)
if arrays[1:]:
cartesian(arrays[1:], out=out[0:m, 1:])
for j in range(1, arrays[0].size):
out[j * m : (j + 1) * m, 1:] = out[0:m, 1:]
return out
def E2lam(energy):
"""energy in eV, lambda in Ångstrøm"""
return constants.h * constants.c / constants.e / energy * 1e10
def QE2theta(Q, energy):
"""Q in Å**(-1), energy in eV, theta in radians"""
return np.arcsin(E2lam(energy) / 4 / np.pi * Q)
def absorptionEdge(element, edge=None):
if type(element) is str:
element = xl.SymbolToAtomicNumber(element)
shells = ["K", "L1", "L2", "L3", "M1", "M2", "M3", "M4", "M5"]
if edge is not None:
shell_ind = shells.index(edge)
return xl.EdgeEnergy(element, shell_ind)
else:
shell_inds = range(8)
print("Absorption edges %s" % xl.AtomicNumberToSymbol(element))
for shell_ind in shell_inds:
print(
" "
+ shells[shell_ind].ljust(3)
+ " = %7.1f eV" % (xl.EdgeEnergy(element, shell_ind) * 1000)
)