Skip to content
Snippets Groups Projects
Commit 0b7a0687 authored by Loïc Le Guyader's avatar Loïc Le Guyader
Browse files

Adds Flat liquid Jet

parent 6d28daeb
No related branches found
No related tags found
1 merge request!12Flat Liquid Jet
This commit is part of merge request !12. Comments created here will be created in the context of that merge request.
...@@ -10,8 +10,9 @@ ...@@ -10,8 +10,9 @@
import numpy as np import numpy as np
import pandas as pd import pandas as pd
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle, Polygon from matplotlib.patches import PathPatch, Rectangle, Polygon
from matplotlib.colors import hsv_to_rgb from matplotlib.colors import hsv_to_rgb
from matplotlib.path import Path
import ipywidgets as widgets import ipywidgets as widgets
from ipywidgets import HBox, VBox from ipywidgets import HBox, VBox
...@@ -32,7 +33,8 @@ TZPG_db = { ...@@ -32,7 +33,8 @@ TZPG_db = {
'TZPGoffaxis': 0.75, 'TZPGoffaxis': 0.75,
'grating': 3.8, 'grating': 3.8,
'F_x': 0.25, 'F_x': 0.25,
'F_y': 0.25 'F_y': 0.25,
'3beams': True
}, },
'O': { 'O': {
'design_nrj': 530, 'design_nrj': 530,
...@@ -41,7 +43,8 @@ TZPG_db = { ...@@ -41,7 +43,8 @@ TZPG_db = {
'TZPGoffaxis': 0.55, 'TZPGoffaxis': 0.55,
'grating': 3.1, 'grating': 3.1,
'F_x': 0.25, 'F_x': 0.25,
'F_y': 0.25 'F_y': 0.25,
'3beams': True
}, },
'Fe': { 'Fe': {
'design_nrj': 715, 'design_nrj': 715,
...@@ -50,7 +53,8 @@ TZPG_db = { ...@@ -50,7 +53,8 @@ TZPG_db = {
'TZPGoffaxis': 0.55, 'TZPGoffaxis': 0.55,
'grating': 3.1, 'grating': 3.1,
'F_x': 0.25, 'F_x': 0.25,
'F_y': 0.25 'F_y': 0.25,
'3beams': True
}, },
'Co': { 'Co': {
'design_nrj': 785, 'design_nrj': 785,
...@@ -59,7 +63,8 @@ TZPG_db = { ...@@ -59,7 +63,8 @@ TZPG_db = {
'TZPGoffaxis': 0.55, 'TZPGoffaxis': 0.55,
'grating': 3.1, 'grating': 3.1,
'F_x': 0.25, 'F_x': 0.25,
'F_y': 0.25 'F_y': 0.25,
'3beams': True
}, },
'Ni': { 'Ni': {
'design_nrj': 860, 'design_nrj': 860,
...@@ -68,7 +73,8 @@ TZPG_db = { ...@@ -68,7 +73,8 @@ TZPG_db = {
'TZPGoffaxis': 0.55, 'TZPGoffaxis': 0.55,
'grating': 3.1, 'grating': 3.1,
'F_x': 0.25, 'F_x': 0.25,
'F_y': 0.25 'F_y': 0.25,
'3beams': True
}, },
'Cu': { 'Cu': {
'design_nrj': 927, 'design_nrj': 927,
...@@ -77,7 +83,8 @@ TZPG_db = { ...@@ -77,7 +83,8 @@ TZPG_db = {
'TZPGoffaxis': 0.55, 'TZPGoffaxis': 0.55,
'grating': 3.1, 'grating': 3.1,
'F_x': 0.25, 'F_x': 0.25,
'F_y': 0.25 'F_y': 0.25,
'3beams': True
}, },
'Gd': { 'Gd': {
'design_nrj': 1210, 'design_nrj': 1210,
...@@ -86,7 +93,8 @@ TZPG_db = { ...@@ -86,7 +93,8 @@ TZPG_db = {
'TZPGoffaxis': 0.55, 'TZPGoffaxis': 0.55,
'grating': 3.1, 'grating': 3.1,
'F_x': 0.25, 'F_x': 0.25,
'F_y': 0.25 'F_y': 0.25,
'3beams': True
} }
} }
...@@ -94,8 +102,8 @@ TZPG_db = { ...@@ -94,8 +102,8 @@ TZPG_db = {
class TZPGcalc(): class TZPGcalc():
def __init__(self): def __init__(self):
self.geo_beams = GeoBeams() self.geo_beams = GeoBeams()
self.initFig()
self.initWidgets() self.initWidgets()
self.initFig()
self.init_beam_transport() self.init_beam_transport()
# spot sizes of all beams # spot sizes of all beams
...@@ -216,7 +224,7 @@ class TZPGcalc(): ...@@ -216,7 +224,7 @@ class TZPGcalc():
angle=45)) angle=45))
} }
# 5x5 membranes # SampleNxSampleN membranes
self.sampleLines = {} self.sampleLines = {}
self.etchLines = {} self.etchLines = {}
for k in range(SampleN*SampleN): for k in range(SampleN*SampleN):
...@@ -226,6 +234,63 @@ class TZPGcalc(): ...@@ -226,6 +234,63 @@ class TZPGcalc():
Rectangle((0, 0), 1, 1, fill=False, facecolor='k', Rectangle((0, 0), 1, 1, fill=False, facecolor='k',
alpha=0.4, ls='--')) alpha=0.4, ls='--'))
# Flat Liquid Jet
self.FLJ_lines = {}
self.FlatLiquidJet()
def FlatLiquidJet(self):
"""Draw a Flat Liquid jet.
"""
sw = self.widgets
HW = 0.5*sw['FLJ_W'].value # [mm]
L = sw['FLJ_L'].value # [mm]
mf = sw['FLJ_mf'].value # [mm]
incidence = np.deg2rad(sw['samIncidence'].value) # [rad]
ox = sw['samX'].value # [mm]
oy = -L/2 + sw['samY'].value # [mm]
# incidence angle squeezes sample
ci = np.cos(incidence)
verts = [
[(0*ci, L + oy), # P0
(HW/2*ci, L + oy), # P1
(HW*ci, 0.5*(1+mf)*L + oy), # P2
(HW*ci, mf*L + oy)], # P3
[(HW*ci, mf*L + oy), # P0
(HW*ci, 0.5*mf*L + oy), # P1
(0, 0 + oy), # P2
(0, 0 + oy)] # P3
]
# second half image of liquid jet
mirror = []
for v in verts:
mirror.append([(-p[0], p[1]) for p in v])
verts += mirror
# apply offsets
fverts = []
for v in verts:
fverts.append([(p[0] + ox, p[1]) for p in v])
codes = [
Path.MOVETO, # P0
Path.CURVE4, # P1
Path.CURVE4, # P2
Path.CURVE4 # P3
]
for k, v in enumerate(fverts):
path = Path(v, codes)
if k in self.FLJ_lines:
self.FLJ_lines[k].remove()
self.FLJ_lines[k] = self.ax_sam.add_patch(
PathPatch(path, alpha=0.4, facecolor='none', lw=2)
)
def RectUpdate(self, rect, xLeft, yBottom, xRight, yTop): def RectUpdate(self, rect, xLeft, yBottom, xRight, yTop):
"""Updates the position and size of the given Rectangle. """Updates the position and size of the given Rectangle.
...@@ -303,6 +368,11 @@ class TZPGcalc(): ...@@ -303,6 +368,11 @@ class TZPGcalc():
self.SpotSizes[img['type']][conf['Energy']][z, k] = ( self.SpotSizes[img['type']][conf['Energy']][z, k] = (
1e3*(np.max(vs) - np.min(vs))) 1e3*(np.max(vs) - np.min(vs)))
# 3 beams configuration
b = self.widgets['3beams'].value
Beams['F0G0'].set_visible(b)
Beams['F1G0'].set_visible(b)
def DetectorUpdate(self, Xoff, Yoff): def DetectorUpdate(self, Xoff, Yoff):
"""Draws DSSC detector module with filter mask. """Draws DSSC detector module with filter mask.
...@@ -338,8 +408,28 @@ class TZPGcalc(): ...@@ -338,8 +408,28 @@ class TZPGcalc():
self.detLines['diamond'].set_xy(( self.detLines['diamond'].set_xy((
self.scale*Xoff, self.scale*(Yoff - diamondW/2*np.sqrt(2)))) self.scale*Xoff, self.scale*(Yoff - diamondW/2*np.sqrt(2))))
def SampleUpdate(self, w, p, Xoff, Yoff, thickness=0.525, def SampleUpdate(self):
incidence=0, etch_angle=54.74): if self.widgets['SampleType'].value == 'Membranes Array':
b = True
elif self.widgets['SampleType'].value == 'Flat Liquid Jet':
b = False
else:
raise ValueError('Sample type must be either "Membranes Array" or'
'"Flat Liquid Jet"')
for k in range(SampleN*SampleN):
self.sampleLines[k].set_visible(b)
self.etchLines[k].set_visible(b)
for k in range(4):
self.FLJ_lines[k].set_visible(not(b))
if b:
self.MembraneSampleUpdate()
else:
self.FlatLiquidJet()
def MembraneSampleUpdate(self):
"""Draws the sample. """Draws the sample.
Inputs Inputs
...@@ -352,6 +442,15 @@ class TZPGcalc(): ...@@ -352,6 +442,15 @@ class TZPGcalc():
incidence: incidence angle in rad incidence: incidence angle in rad
etch_angle: etching angle from surface in rad etch_angle: etching angle from surface in rad
""" """
sw = self.widgets
w = sw['samw'].value*1e-3 # [m]
p = sw['samp'].value*1e-3 # [m]
Xoff = sw['samX'].value*1e-3 # [m]
Yoff = sw['samY'].value*1e-3 # [m]
thickness = sw['samthickness'].value*1e-6 # [m]
etch_angle = np.deg2rad(sw['samEtchAngle'].value) # [rad]
incidence = np.deg2rad(sw['samIncidence'].value) # [rad]
# Si etching angle # Si etching angle
wp = w + 2*thickness/np.tan(etch_angle) wp = w + 2*thickness/np.tan(etch_angle)
...@@ -462,14 +561,7 @@ class TZPGcalc(): ...@@ -462,14 +561,7 @@ class TZPGcalc():
self.DetectorUpdate(detXoff, detYoff) self.DetectorUpdate(detXoff, detYoff)
# update the sample # update the sample
samw = self.widgets['samw'].value*1e-3 # [m] self.SampleUpdate()
samp = self.widgets['samp'].value*1e-3 # [m]
samXoff = self.widgets['samX'].value*1e-3 # [m]
samYoff = self.widgets['samY'].value*1e-3 # [m]
samthickness = self.widgets['samthickness'].value*1e-6 # [m]
samEtchAngle = np.deg2rad(self.widgets['samEtchAngle'].value) # [rad]
self.SampleUpdate(samw, samp, samXoff, samYoff, samthickness,
samIncidence, samEtchAngle)
def initWidgets(self): def initWidgets(self):
""" Creates the necessary interactive widget controls. """ Creates the necessary interactive widget controls.
...@@ -568,6 +660,7 @@ class TZPGcalc(): ...@@ -568,6 +660,7 @@ class TZPGcalc():
self.widgets['grating'].value = v['grating'] self.widgets['grating'].value = v['grating']
self.widgets['F_x'].value = v['F_x'] self.widgets['F_x'].value = v['F_x']
self.widgets['F_y'].value = v['F_y'] self.widgets['F_y'].value = v['F_y']
self.widgets['3beams'].value = v['3beams']
# necessary to recompute grating pitch and outer zone plate width # necessary to recompute grating pitch and outer zone plate width
self.UpdateFig() self.UpdateFig()
...@@ -658,6 +751,12 @@ class TZPGcalc(): ...@@ -658,6 +751,12 @@ class TZPGcalc():
style=style, style=style,
layout=layout layout=layout
) )
self.widgets['3beams'] = widgets.Checkbox(
value=True,
description='3 beams:',
style=style,
layout=layout
)
self.widgets['dr_label_x'] = widgets.Label(value='dr_x') self.widgets['dr_label_x'] = widgets.Label(value='dr_x')
self.widgets['dr_label_y'] = widgets.Label(value='dr_y') self.widgets['dr_label_y'] = widgets.Label(value='dr_y')
self.widgets['d_label'] = widgets.Label(value='dr') self.widgets['d_label'] = widgets.Label(value='dr')
...@@ -668,7 +767,8 @@ class TZPGcalc(): ...@@ -668,7 +767,8 @@ class TZPGcalc():
self.widgets['F_y'] self.widgets['F_y']
]), ]),
HBox([self.widgets['grating'], HBox([self.widgets['grating'],
self.widgets['TZPGoffaxis']]), self.widgets['TZPGoffaxis'],
self.widgets['3beams']]),
HBox([self.widgets['dr_label_x'], HBox([self.widgets['dr_label_x'],
self.widgets['dr_label_y']]), self.widgets['dr_label_y']]),
HBox([widgets.Label(value='Energy range (eV):'), HBox([widgets.Label(value='Energy range (eV):'),
...@@ -679,6 +779,13 @@ class TZPGcalc(): ...@@ -679,6 +779,13 @@ class TZPGcalc():
]) ])
# sample part # sample part
self.widgets['SampleType'] = widgets.Dropdown(
options=['Membranes Array', 'Flat Liquid Jet'],
value='Membranes Array',
decription='Sample type:',
style=style,
layout=layout
)
self.widgets['SAMZ'] = widgets.BoundedFloatText( self.widgets['SAMZ'] = widgets.BoundedFloatText(
value=30., value=30.,
min=-10., min=-10.,
...@@ -688,12 +795,14 @@ class TZPGcalc(): ...@@ -688,12 +795,14 @@ class TZPGcalc():
style=style, style=style,
layout=layout layout=layout
) )
# membranes
self.widgets['samw'] = widgets.BoundedFloatText( self.widgets['samw'] = widgets.BoundedFloatText(
value=.5, value=.5,
min=0.01, min=0.01,
max=2.0, max=2.0,
step=.01, step=.01,
description='width:', description='width (mm):',
style=style, style=style,
layout=layout layout=layout
) )
...@@ -702,10 +811,58 @@ class TZPGcalc(): ...@@ -702,10 +811,58 @@ class TZPGcalc():
min=0.01, min=0.01,
max=2.0, max=2.0,
step=.01, step=.01,
description='pitch:', description='pitch (mm):',
style=style,
layout=layout
)
self.widgets['samthickness'] = widgets.BoundedFloatText(
value=381,
min=1,
max=1000,
step=1,
description='Substrate thickness (um):',
style=style,
layout=layout
)
self.widgets['samEtchAngle'] = widgets.BoundedFloatText(
value=54.74,
min=0,
max=90,
step=0.01,
description='etch angle (deg):',
style=style,
layout=layout
)
# Flat Liquid Jet
self.widgets['FLJ_W'] = widgets.BoundedFloatText(
value=1.0,
min=0,
max=5,
step=0.1,
description='Flat Liquid Jet width (mm):',
style=style,
layout=layout
)
self.widgets['FLJ_L'] = widgets.BoundedFloatText(
value=4.6,
min=0,
max=15,
step=0.1,
description='of length (mm):',
style=style,
layout=layout
)
self.widgets['FLJ_mf'] = widgets.BoundedFloatText(
value=0.75,
min=0,
max=1,
step=0.01,
description='at:',
style=style, style=style,
layout=layout layout=layout
) )
self.widgets['samX'] = widgets.BoundedFloatText( self.widgets['samX'] = widgets.BoundedFloatText(
value=0., value=0.,
min=-10, min=-10,
...@@ -724,15 +881,6 @@ class TZPGcalc(): ...@@ -724,15 +881,6 @@ class TZPGcalc():
style=style, style=style,
layout=layout layout=layout
) )
self.widgets['samthickness'] = widgets.BoundedFloatText(
value=381,
min=1,
max=1000,
step=1,
description='Substrate thickness (um):',
style=style,
layout=layout
)
self.widgets['samIncidence'] = widgets.BoundedFloatText( self.widgets['samIncidence'] = widgets.BoundedFloatText(
value=0, value=0,
min=0, min=0,
...@@ -742,26 +890,22 @@ class TZPGcalc(): ...@@ -742,26 +890,22 @@ class TZPGcalc():
style=style, style=style,
layout=layout layout=layout
) )
self.widgets['samEtchAngle'] = widgets.BoundedFloatText(
value=54.74,
min=0,
max=90,
step=0.01,
description='Etch angle from surface (deg):',
style=style,
layout=layout
)
samTab = VBox([ samTab = VBox([
self.widgets['SAMZ'], self.widgets['SAMZ'],
HBox([widgets.Label(value='Membrane (mm), '), self.widgets['SampleType'],
HBox([widgets.Label(value='Membranes array, '),
self.widgets['samw'], self.widgets['samw'],
self.widgets['samp']]), self.widgets['samp']]),
HBox([self.widgets['samthickness'],
self.widgets['samEtchAngle']]),
HBox([self.widgets['FLJ_W'],
self.widgets['FLJ_mf'],
self.widgets['FLJ_L']]),
HBox([widgets.Label(value='Sample Offset (mm), '), HBox([widgets.Label(value='Sample Offset (mm), '),
self.widgets['samX'], self.widgets['samX'],
self.widgets['samY']]), self.widgets['samY']]),
self.widgets['samthickness'],
HBox([self.widgets['samIncidence'], HBox([self.widgets['samIncidence'],
self.widgets['samEtchAngle']]) ])
]) ])
# Detector tab # Detector tab
...@@ -775,7 +919,7 @@ class TZPGcalc(): ...@@ -775,7 +919,7 @@ class TZPGcalc():
layout=layout layout=layout
) )
self.widgets['detX'] = widgets.BoundedFloatText( self.widgets['detX'] = widgets.BoundedFloatText(
value=20., value=34.5,
min=-50, min=-50,
max=50, max=50,
step=0.5, step=0.5,
...@@ -784,7 +928,7 @@ class TZPGcalc(): ...@@ -784,7 +928,7 @@ class TZPGcalc():
layout=layout layout=layout
) )
self.widgets['detY'] = widgets.BoundedFloatText( self.widgets['detY'] = widgets.BoundedFloatText(
value=0., value=-2.,
min=-50, min=-50,
max=50, max=50,
step=0.5, step=0.5,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment