syned 1.0.47__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. syned/__init__.py +0 -0
  2. syned/__test/__init__.py +46 -0
  3. syned/__test/test.py +28 -0
  4. syned/beamline/__init__.py +1 -0
  5. syned/beamline/beamline.py +155 -0
  6. syned/beamline/beamline_element.py +76 -0
  7. syned/beamline/element_coordinates.py +199 -0
  8. syned/beamline/optical_element.py +47 -0
  9. syned/beamline/optical_element_with_surface_shape.py +126 -0
  10. syned/beamline/optical_elements/__init__.py +1 -0
  11. syned/beamline/optical_elements/absorbers/__init__.py +0 -0
  12. syned/beamline/optical_elements/absorbers/absorber.py +21 -0
  13. syned/beamline/optical_elements/absorbers/beam_stopper.py +64 -0
  14. syned/beamline/optical_elements/absorbers/filter.py +61 -0
  15. syned/beamline/optical_elements/absorbers/holed_filter.py +67 -0
  16. syned/beamline/optical_elements/absorbers/slit.py +81 -0
  17. syned/beamline/optical_elements/crystals/__init__.py +1 -0
  18. syned/beamline/optical_elements/crystals/crystal.py +70 -0
  19. syned/beamline/optical_elements/gratings/__init__.py +1 -0
  20. syned/beamline/optical_elements/gratings/grating.py +279 -0
  21. syned/beamline/optical_elements/ideal_elements/__init__.py +1 -0
  22. syned/beamline/optical_elements/ideal_elements/ideal_element.py +16 -0
  23. syned/beamline/optical_elements/ideal_elements/ideal_fzp.py +183 -0
  24. syned/beamline/optical_elements/ideal_elements/ideal_lens.py +54 -0
  25. syned/beamline/optical_elements/ideal_elements/screen.py +16 -0
  26. syned/beamline/optical_elements/mirrors/__init__.py +1 -0
  27. syned/beamline/optical_elements/mirrors/mirror.py +39 -0
  28. syned/beamline/optical_elements/multilayers/__init__.py +46 -0
  29. syned/beamline/optical_elements/multilayers/multilayer.py +45 -0
  30. syned/beamline/optical_elements/refractors/__init__.py +1 -0
  31. syned/beamline/optical_elements/refractors/crl.py +79 -0
  32. syned/beamline/optical_elements/refractors/interface.py +61 -0
  33. syned/beamline/optical_elements/refractors/lens.py +105 -0
  34. syned/beamline/shape.py +2803 -0
  35. syned/storage_ring/__init__.py +1 -0
  36. syned/storage_ring/electron_beam.py +804 -0
  37. syned/storage_ring/empty_light_source.py +40 -0
  38. syned/storage_ring/light_source.py +90 -0
  39. syned/storage_ring/magnetic_structure.py +8 -0
  40. syned/storage_ring/magnetic_structures/__init__.py +1 -0
  41. syned/storage_ring/magnetic_structures/bending_magnet.py +329 -0
  42. syned/storage_ring/magnetic_structures/insertion_device.py +169 -0
  43. syned/storage_ring/magnetic_structures/undulator.py +413 -0
  44. syned/storage_ring/magnetic_structures/wiggler.py +27 -0
  45. syned/syned_object.py +264 -0
  46. syned/util/__init__.py +22 -0
  47. syned/util/json_tools.py +198 -0
  48. syned/widget/__init__.py +0 -0
  49. syned/widget/widget_decorator.py +67 -0
  50. syned-1.0.47.dist-info/METADATA +88 -0
  51. syned-1.0.47.dist-info/RECORD +54 -0
  52. syned-1.0.47.dist-info/WHEEL +5 -0
  53. syned-1.0.47.dist-info/licenses/LICENSE +20 -0
  54. syned-1.0.47.dist-info/top_level.txt +1 -0
@@ -0,0 +1,40 @@
1
+ """
2
+ Base class for LighSource, which contains:
3
+ - a name
4
+ - an electron beam
5
+ - a magnetic structure
6
+
7
+ """
8
+ from syned.syned_object import SynedObject
9
+
10
+
11
+ class EmptyLightSource(SynedObject):
12
+ """
13
+ Defines an empty light source. This is for creating "movable" beamlines (using Beamline()). These are beamlines
14
+ that do not have a particular light source.
15
+
16
+ Parameters
17
+ ----------
18
+ name : str, optional
19
+ The name of the (empty) light source.
20
+
21
+ """
22
+ def __init__(self, name="Empty"):
23
+ self._name = name
24
+ # support text containg name of variable, help text and unit. Will be stored in self._support_dictionary
25
+ self._set_support_text([
26
+ ("name", "Name",""),
27
+ ] )
28
+
29
+
30
+ def get_name(self):
31
+ """
32
+ Returns the name of the light source.
33
+
34
+ Returns
35
+ -------
36
+ str
37
+
38
+ """
39
+ return self._name
40
+
@@ -0,0 +1,90 @@
1
+ """
2
+
3
+
4
+ """
5
+ from syned.syned_object import SynedObject
6
+ from syned.storage_ring.magnetic_structure import MagneticStructure
7
+ from syned.storage_ring.electron_beam import ElectronBeam
8
+
9
+ class LightSource(SynedObject):
10
+ """
11
+ Base class for LighSource. A light source contains:
12
+ * a name
13
+ * an electron beam
14
+ * a magnetic structure
15
+
16
+ Parameters
17
+ ----------
18
+ name : str, optional
19
+ The light source name.
20
+ electron_beam : instance of ElectronBeam, optional
21
+ The electron beam. If None, it is initialized with ElectronBeam().
22
+ magnetic_structure : instance of MagneticStructure, optional
23
+ The electron beam. If None, it is initialized with MagneticStructure().
24
+
25
+ """
26
+ def __init__(self, name="Undefined", electron_beam=None, magnetic_structure=None):
27
+ self._name = name
28
+ if electron_beam is None:
29
+ self._electron_beam = ElectronBeam()
30
+ else:
31
+ self._electron_beam = electron_beam
32
+ if magnetic_structure is None:
33
+ self._magnetic_structure = MagneticStructure()
34
+ else:
35
+ self._magnetic_structure = magnetic_structure
36
+ # support text containg name of variable, help text and unit. Will be stored in self._support_dictionary
37
+ self._set_support_text([
38
+ ("name", "Name",""),
39
+ ("electron_beam", "Electron Beam",""),
40
+ ("magnetic_structure","Magnetic Strtructure",""),
41
+ ] )
42
+
43
+
44
+ def get_name(self):
45
+ """
46
+ Returns the name of the light source.
47
+
48
+ Returns
49
+ -------
50
+ str
51
+
52
+ """
53
+ return self._name
54
+
55
+ def get_electron_beam(self):
56
+ """
57
+ Returns the electron beam.
58
+
59
+ Returns
60
+ -------
61
+ instance of ElectronBeam
62
+
63
+ """
64
+ return self._electron_beam
65
+
66
+ def get_magnetic_structure(self):
67
+ """
68
+ Returns the magnetic structure.
69
+
70
+ Returns
71
+ -------
72
+ instance of MagneticStructure
73
+
74
+ """
75
+ return self._magnetic_structure
76
+
77
+
78
+
79
+
80
+ if __name__ == "__main__":
81
+
82
+ from syned.storage_ring.magnetic_structures.undulator import Undulator
83
+
84
+ eb = ElectronBeam.initialize_as_pencil_beam( energy_in_GeV=2.0,energy_spread=0.0,current=0.5)
85
+ ms = Undulator.initialize_as_vertical_undulator( K=1.8, period_length=0.038, periods_number=56.0 )
86
+
87
+ light_source = LightSource(name="",electron_beam=eb,magnetic_structure=ms)
88
+
89
+ print(light_source.info())
90
+
@@ -0,0 +1,8 @@
1
+ from syned.syned_object import SynedObject
2
+
3
+ class MagneticStructure(SynedObject):
4
+ """
5
+ Base clase for magnetic structures (from where BM, Wiggler and Undulator will heritate)
6
+ """
7
+ def __init__(self):
8
+ super().__init__()
@@ -0,0 +1,329 @@
1
+ """
2
+ Base class for a Bending Magnet
3
+
4
+
5
+ """
6
+ from syned.storage_ring.magnetic_structure import MagneticStructure
7
+ import numpy
8
+ import scipy.constants as codata
9
+
10
+ class BendingMagnet(MagneticStructure):
11
+ """
12
+ Constructor.
13
+
14
+ Parameters
15
+ ----------
16
+ radius : float, optional
17
+ Physical Radius/curvature of the magnet in m.
18
+ magnetic_field : float, optional
19
+ Magnetic field strength in T.
20
+ length : float, optional
21
+ physical length of the bending magnet (along the arc) in m.
22
+
23
+ """
24
+ def __init__(self, radius=1.0, magnetic_field=1.0, length=1.0):
25
+ MagneticStructure.__init__(self)
26
+ self._radius = radius
27
+ self._magnetic_field = magnetic_field
28
+ self._length = length
29
+
30
+ # support text contaning name of variable, help text and unit. Will be stored in self._support_dictionary
31
+ self._set_support_text([
32
+ ("radius" , "Radius of bending magnet" , "m" ),
33
+ ("magnetic_field" , "Magnetic field", "T" ),
34
+ ("length" , "Bending magnet length", "m" ),
35
+ ] )
36
+
37
+ #
38
+ #methods for practical calculations
39
+ #
40
+ @classmethod
41
+ def initialize_from_magnetic_field_divergence_and_electron_energy(cls,
42
+ magnetic_field=1.0,
43
+ divergence=1e-3,
44
+ electron_energy_in_GeV=1.0,
45
+ **params):
46
+ """
47
+ Returns an bending magnet from the magnetic field and electron energy.
48
+
49
+ Parameters
50
+ ----------
51
+ magnetic_field : float, optional
52
+ Magnetic field strength in T.
53
+ divergence : float, optional
54
+ The beam divergence also corresponding to the BM angle in rad.
55
+ electron_energy_in_GeV : float, optional
56
+ The electron beam energy in GeV.
57
+
58
+ params :
59
+ Other parameters accepted by BendingMagnet.
60
+
61
+ Returns
62
+ -------
63
+ instance of BendingMagnet
64
+
65
+ """
66
+ magnetic_radius = cls.calculate_magnetic_radius(magnetic_field, electron_energy_in_GeV)
67
+
68
+ return cls(magnetic_radius, magnetic_field, numpy.abs(divergence * magnetic_radius), **params)
69
+
70
+ @classmethod
71
+ def initialize_from_magnetic_radius_divergence_and_electron_energy(cls,
72
+ magnetic_radius=10.0,
73
+ divergence=1e-3,
74
+ electron_energy_in_GeV=1.0,
75
+ **params):
76
+ """
77
+ Returns an bending magnet from the magnetic radius and electron energy.
78
+
79
+ Parameters
80
+ ----------
81
+ magnetic_radius : float, optional
82
+ Magnetic radius in m.
83
+ divergence : float, optional
84
+ The beam divergence also corresponding to the BM angle in rad.
85
+ electron_energy_in_GeV : float, optional
86
+ The electron beam energy in GeV.
87
+
88
+ params :
89
+ Other parameters accepted by BendingMagnet.
90
+
91
+ Returns
92
+ -------
93
+ instance of BendingMagnet
94
+
95
+ """
96
+ magnetic_field = cls.calculate_magnetic_field(magnetic_radius, electron_energy_in_GeV)
97
+
98
+ return cls(magnetic_radius,magnetic_field,numpy.abs(divergence * magnetic_radius), **params)
99
+
100
+
101
+ def length(self):
102
+ """
103
+ returns the BM length in m.
104
+
105
+ Returns
106
+ -------
107
+ float
108
+
109
+ """
110
+ return self._length
111
+
112
+ def magnetic_field(self):
113
+ """
114
+ Returns the bagnetic field in T.
115
+
116
+ Returns
117
+ -------
118
+ float
119
+
120
+ """
121
+ return self._magnetic_field
122
+
123
+ def radius(self):
124
+ """
125
+ Returns the BM radius in m.
126
+
127
+ Returns
128
+ -------
129
+ float
130
+
131
+ """
132
+ return self._radius
133
+
134
+ def horizontal_divergence(self):
135
+ """
136
+ returns the horizontal divergence in rad.
137
+
138
+ Returns
139
+ -------
140
+ float
141
+
142
+ """
143
+ return numpy.abs(self.length()/self.radius())
144
+
145
+ def get_magnetic_field(self, electron_energy_in_GeV):
146
+ """
147
+ returns magnetic field in T (from the magnetic radius and electron energy).
148
+
149
+ Parameters
150
+ ----------
151
+ electron_energy_in_GeV : float, optional
152
+ The electron beam energy in GeV.
153
+
154
+ Returns
155
+ -------
156
+ float
157
+
158
+ """
159
+ return BendingMagnet.calculate_magnetic_field(self._radius, electron_energy_in_GeV)
160
+
161
+ def get_magnetic_radius(self, electron_energy_in_GeV):
162
+ """
163
+ Calculates magnetic radius (from the magnetic field and electron energy).
164
+
165
+ Parameters
166
+ ----------
167
+ electron_energy_in_GeV : float, optional
168
+ The electron beam energy in GeV.
169
+
170
+ Returns
171
+ -------
172
+ float
173
+
174
+ """
175
+ return BendingMagnet.calculate_magnetic_radius(self._magnetic_field, electron_energy_in_GeV)
176
+
177
+
178
+ def get_critical_energy(self, electron_energy_in_GeV, method=1):
179
+ """
180
+ Returns the photon critical energy in eV.
181
+
182
+ Parameters
183
+ ----------
184
+ electron_energy_in_GeV : float, optional
185
+ The electron beam energy in GeV.
186
+ method : int, optional
187
+ 0= uses magnetic radius, 1=uses magnetic field
188
+
189
+ Returns
190
+ -------
191
+ float
192
+
193
+ """
194
+ if method == 0:
195
+ return BendingMagnet.calculate_critical_energy(self._radius, electron_energy_in_GeV)
196
+ else:
197
+ return BendingMagnet.calculate_critical_energy_from_magnetic_field(self._magnetic_field, electron_energy_in_GeV)
198
+
199
+
200
+
201
+ # for equations, see for example https://people.eecs.berkeley.edu/~attwood/srms/2007/Lec09.pdf
202
+ @classmethod
203
+ def calculate_magnetic_field(cls, magnetic_radius, electron_energy_in_GeV):
204
+ """
205
+ Calculates magnetic field from magnetic radius and electron energy.
206
+
207
+ Parameters
208
+ ----------
209
+ magnetic_radius : float
210
+ Magnetic radius in m.
211
+ electron_energy_in_GeV : float
212
+ The electron beam energy in GeV.
213
+
214
+ Returns
215
+ -------
216
+ float
217
+ The magnetic field in T.
218
+
219
+ References
220
+ ----------
221
+ See, for example, https://people.eecs.berkeley.edu/~attwood/srms/2007/Lec09.pdf
222
+
223
+ """
224
+ # return 3.334728*electron_energy_in_GeV/magnetic_radius
225
+ return 1e9 / codata.c * electron_energy_in_GeV / magnetic_radius
226
+
227
+ @classmethod
228
+ def calculate_magnetic_radius(cls, magnetic_field, electron_energy_in_GeV):
229
+ """
230
+ Calculates magnetic radius from magnetic field and electron energy.
231
+
232
+ Parameters
233
+ ----------
234
+ magnetic_field : float
235
+ Magnetic field in T.
236
+ electron_energy_in_GeV : float
237
+ The electron beam energy in GeV.
238
+
239
+ Returns
240
+ -------
241
+ float
242
+ The magnetic radius in m.
243
+
244
+ References
245
+ ----------
246
+ See, for example, https://people.eecs.berkeley.edu/~attwood/srms/2007/Lec09.pdf
247
+
248
+ """
249
+ # return 3.334728*electron_energy_in_GeV/magnetic_field
250
+ return 1e9 / codata.c * electron_energy_in_GeV / magnetic_field
251
+
252
+ @classmethod
253
+ def calculate_critical_energy(cls, magnetic_radius, electron_energy_in_GeV):
254
+ """
255
+ Calculates the photon critical energy from magnetic radius and electron energy.
256
+
257
+ Parameters
258
+ ----------
259
+ magnetic_radius : float
260
+ Magnetic radius in m.
261
+ electron_energy_in_GeV : float
262
+ The electron beam energy in GeV.
263
+
264
+ Returns
265
+ -------
266
+ float
267
+ The photon critical energy in eV.
268
+
269
+ References
270
+ ----------
271
+ See, for example, https://people.eecs.berkeley.edu/~attwood/srms/2007/Lec09.pdf
272
+
273
+ """
274
+ # omega = 3 g3 c / (2r)
275
+ gamma = 1e9 * electron_energy_in_GeV / (codata.m_e * codata.c**2 / codata.e)
276
+ critical_energy_J = 3 * codata.c * codata.hbar * gamma**3 / (2 * numpy.abs(magnetic_radius))
277
+ critical_energy_eV = critical_energy_J / codata.e
278
+ return critical_energy_eV
279
+
280
+ @classmethod
281
+ def calculate_critical_energy_from_magnetic_field(cls, magnetic_field, electron_energy_in_GeV):
282
+ """
283
+ Calculates the photon critical energy from magnetic field and electron energy.
284
+
285
+ Parameters
286
+ ----------
287
+ magnetic_field : float
288
+ Magnetic field in T.
289
+ electron_energy_in_GeV : float
290
+ The electron beam energy in GeV.
291
+
292
+ Returns
293
+ -------
294
+ float
295
+ The critical energy in eV.
296
+
297
+ References
298
+ ----------
299
+ See, for example, https://people.eecs.berkeley.edu/~attwood/srms/2007/Lec09.pdf
300
+
301
+ """
302
+ # omega = 3 g3 c / (2r)
303
+ magnetic_radius = cls.calculate_magnetic_radius(magnetic_field, electron_energy_in_GeV)
304
+ return cls.calculate_critical_energy(magnetic_radius, electron_energy_in_GeV)
305
+
306
+
307
+ if __name__ == "__main__":
308
+ print("input for ESRF: ")
309
+ B = BendingMagnet.calculate_magnetic_field(25.0,6.04)
310
+ print(">> B = ",B)
311
+ print(">> R = ",BendingMagnet.calculate_magnetic_radius(B,6.04))
312
+ print(">> Ec = ",BendingMagnet.calculate_critical_energy(25.0,6.04))
313
+ print(">> Ec = ",BendingMagnet.calculate_critical_energy_from_magnetic_field(B, 6.04))
314
+ BB = BendingMagnet.calculate_magnetic_radius (BendingMagnet.calculate_magnetic_radius (B,6.04),6.04)
315
+ RR = BendingMagnet.calculate_magnetic_radius(BendingMagnet.calculate_magnetic_field(25.0,6.04), 6.04)
316
+ assert(BB == B)
317
+ assert(RR == 25.0)
318
+
319
+
320
+ print("input for ALS: ")
321
+ B = BendingMagnet.calculate_magnetic_field(5.0,1.9)
322
+ print(">> B = ",B)
323
+ print(">> R = ",BendingMagnet.calculate_magnetic_radius (B,1.9))
324
+ print(">> Ec = ",BendingMagnet.calculate_critical_energy(5.0,1.9))
325
+ print(">> Ec = ",BendingMagnet.calculate_critical_energy_from_magnetic_field(B, 1.9))
326
+ BB = BendingMagnet.calculate_magnetic_radius (BendingMagnet.calculate_magnetic_radius (B,1.9),1.9)
327
+ RR = BendingMagnet.calculate_magnetic_radius(BendingMagnet.calculate_magnetic_field(5.0, 1.9), 1.9)
328
+ assert(BB == B)
329
+ assert(RR == 5.0)
@@ -0,0 +1,169 @@
1
+ """
2
+
3
+ Base class for all insertion devices: wiggler, undulator
4
+
5
+ """
6
+
7
+ from numpy import pi
8
+ import scipy.constants as codata
9
+
10
+ from syned.storage_ring.magnetic_structure import MagneticStructure
11
+
12
+ class InsertionDevice(MagneticStructure):
13
+ """
14
+ Base clase for the Insertion Device (ID) (common class for wigglers and undulators).
15
+
16
+ Parameters
17
+ ----------
18
+ K_vertical : float, optional
19
+ The deflection K parameter corresponding to magnetic field in the vertical direction.
20
+ K_horizontal : float, optional
21
+ The deflection K parameter corresponding to magnetic field in the horizontal direction.
22
+ period_length : float, optional
23
+ The ID period in m.
24
+ number_of_periods : float, optional
25
+ The number of periods. It may be a float, considering that number_of_periods = ID_length / period_length.
26
+
27
+ """
28
+ def __init__(self,
29
+ K_vertical = 0.0,
30
+ K_horizontal = 0.0,
31
+ period_length = 0.0,
32
+ number_of_periods = 1.0):
33
+ MagneticStructure.__init__(self)
34
+
35
+ self._K_vertical = K_vertical
36
+ self._K_horizontal = K_horizontal
37
+ self._period_length = period_length
38
+ self._number_of_periods = number_of_periods
39
+
40
+ # support text containg name of variable, help text and unit. Will be stored in self._support_dictionary
41
+ self._set_support_text([
42
+ ("K_vertical" , "K value (vertical)" , "" ),
43
+ ("K_horizontal" , "K value (horizontal)", "" ),
44
+ ("period_length" , "Period length" , "m" ),
45
+ ("number_of_periods" , "Number of periods" , "" ),
46
+ ] )
47
+
48
+ def K_vertical(self):
49
+ """
50
+ Returns K vertical.
51
+
52
+ Returns
53
+ -------
54
+ float
55
+
56
+ """
57
+ return self._K_vertical
58
+
59
+ def K_horizontal(self):
60
+ """
61
+ Returns K horizontal.
62
+
63
+ Returns
64
+ -------
65
+ float
66
+
67
+ """
68
+ return self._K_horizontal
69
+
70
+ def period_length(self):
71
+ """
72
+ Returns the ID period in m.
73
+
74
+ Returns
75
+ -------
76
+ float
77
+
78
+ """
79
+ return self._period_length
80
+
81
+ def number_of_periods(self):
82
+ """
83
+ Returns the number of periods.
84
+
85
+ Returns
86
+ -------
87
+ float
88
+
89
+ """
90
+ return self._number_of_periods
91
+
92
+
93
+ #
94
+ # some easy calculations
95
+ #
96
+
97
+ def K(self):
98
+ """
99
+ Returns K vertical.
100
+
101
+ Returns
102
+ -------
103
+ float
104
+
105
+ """
106
+ return self.K_vertical()
107
+
108
+ def length(self):
109
+ """
110
+ Returns the ID length in m.
111
+
112
+ Returns
113
+ -------
114
+ float
115
+
116
+ """
117
+ return self.number_of_periods() * self.period_length()
118
+
119
+ def magnetic_field_vertical(self):
120
+ """
121
+ Returns the peak magnetic field in T in the vertical direction.
122
+
123
+ Returns
124
+ -------
125
+ float
126
+
127
+ """
128
+ return self.__magnetic_field_from_K(self.K_vertical())
129
+
130
+ def magnetic_field_horizontal(self):
131
+ """
132
+ Returns the peak magnetic field in T in the horizontal direction.
133
+
134
+ Returns
135
+ -------
136
+ float
137
+
138
+ """
139
+ return self.__magnetic_field_from_K(self.K_horizontal())
140
+
141
+ def set_K_vertical_from_magnetic_field(self, B_vertical):
142
+ """
143
+ Set the vertical K value given the corresponding peak magnetic field.
144
+
145
+ Parameters
146
+ ----------
147
+ B_vertical : float
148
+ Peak magnetic field in T.
149
+
150
+ """
151
+ self._K_vertical = self.__K_from_magnetic_field(B_vertical)
152
+
153
+ def set_K_horizontal_from_magnetic_field(self, B_horizontal):
154
+ """
155
+ Set the horizontal K value given the corresponding peak magnetic field.
156
+
157
+ Parameters
158
+ ----------
159
+ B_vertical : float
160
+ Peak magnetic field in T.
161
+
162
+ """
163
+ self._K_horizontal = self.__K_from_magnetic_field(B_horizontal)
164
+
165
+ def __magnetic_field_from_K(self, K):
166
+ return K * 2 * pi * codata.m_e * codata.c / (codata.e * self.period_length())
167
+
168
+ def __K_from_magnetic_field(self, B):
169
+ return B /(2 * pi * codata.m_e * codata.c / (codata.e * self.period_length()))