syned 1.0.47__py3-none-any.whl → 1.0.49__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 (52) hide show
  1. syned/beamline/__init__.py +1 -1
  2. syned/beamline/beamline.py +155 -155
  3. syned/beamline/beamline_element.py +76 -76
  4. syned/beamline/element_coordinates.py +199 -199
  5. syned/beamline/optical_element.py +47 -47
  6. syned/beamline/optical_element_with_surface_shape.py +126 -126
  7. syned/beamline/optical_elements/__init__.py +1 -1
  8. syned/beamline/optical_elements/absorbers/absorber.py +21 -21
  9. syned/beamline/optical_elements/absorbers/beam_stopper.py +63 -63
  10. syned/beamline/optical_elements/absorbers/filter.py +61 -61
  11. syned/beamline/optical_elements/absorbers/holed_filter.py +67 -67
  12. syned/beamline/optical_elements/absorbers/slit.py +80 -80
  13. syned/beamline/optical_elements/crystals/__init__.py +1 -1
  14. syned/beamline/optical_elements/crystals/crystal.py +70 -70
  15. syned/beamline/optical_elements/gratings/__init__.py +1 -1
  16. syned/beamline/optical_elements/gratings/grating.py +279 -279
  17. syned/beamline/optical_elements/ideal_elements/__init__.py +1 -1
  18. syned/beamline/optical_elements/ideal_elements/ideal_element.py +15 -15
  19. syned/beamline/optical_elements/ideal_elements/ideal_fzp.py +183 -183
  20. syned/beamline/optical_elements/ideal_elements/ideal_lens.py +54 -54
  21. syned/beamline/optical_elements/ideal_elements/screen.py +15 -15
  22. syned/beamline/optical_elements/mirrors/__init__.py +1 -1
  23. syned/beamline/optical_elements/mirrors/mirror.py +39 -39
  24. syned/beamline/optical_elements/multilayers/__init__.py +46 -46
  25. syned/beamline/optical_elements/multilayers/multilayer.py +45 -45
  26. syned/beamline/optical_elements/refractors/__init__.py +1 -1
  27. syned/beamline/optical_elements/refractors/crl.py +79 -79
  28. syned/beamline/optical_elements/refractors/interface.py +60 -60
  29. syned/beamline/optical_elements/refractors/lens.py +105 -105
  30. syned/beamline/shape.py +2884 -2803
  31. syned/storage_ring/__init__.py +1 -1
  32. syned/storage_ring/electron_beam.py +804 -804
  33. syned/storage_ring/empty_light_source.py +40 -40
  34. syned/storage_ring/light_source.py +90 -90
  35. syned/storage_ring/magnetic_structure.py +8 -8
  36. syned/storage_ring/magnetic_structures/__init__.py +1 -1
  37. syned/storage_ring/magnetic_structures/bending_magnet.py +329 -329
  38. syned/storage_ring/magnetic_structures/insertion_device.py +169 -169
  39. syned/storage_ring/magnetic_structures/undulator.py +413 -413
  40. syned/storage_ring/magnetic_structures/wiggler.py +27 -27
  41. syned/syned_object.py +273 -264
  42. syned/util/__init__.py +21 -21
  43. syned/util/json_tools.py +196 -198
  44. syned/widget/widget_decorator.py +66 -66
  45. {syned-1.0.47.dist-info → syned-1.0.49.dist-info}/METADATA +88 -88
  46. syned-1.0.49.dist-info/RECORD +52 -0
  47. {syned-1.0.47.dist-info → syned-1.0.49.dist-info}/WHEEL +1 -1
  48. {syned-1.0.47.dist-info → syned-1.0.49.dist-info}/licenses/LICENSE +20 -20
  49. syned/__test/__init__.py +0 -46
  50. syned/__test/test.py +0 -28
  51. syned-1.0.47.dist-info/RECORD +0 -54
  52. {syned-1.0.47.dist-info → syned-1.0.49.dist-info}/top_level.txt +0 -0
@@ -1,413 +1,413 @@
1
- """
2
- Implement an undulator with vertical and horizontal magnetic fields.
3
- """
4
- import numpy
5
- import scipy.constants as codata
6
-
7
- cte = codata.e/(2*numpy.pi*codata.electron_mass*codata.c)
8
-
9
- from syned.storage_ring.magnetic_structures.insertion_device import InsertionDevice
10
-
11
- class Undulator(InsertionDevice):
12
- """
13
- Constructor.
14
-
15
- Parameters
16
- ----------
17
- K_vertical : float, optional
18
- The deflection K parameter corresponding to magnetic field in the vertical direction.
19
- K_horizontal : float, optional
20
- The deflection K parameter corresponding to magnetic field in the horizontal direction.
21
- period_length : float, optional
22
- The ID period in m.
23
- number_of_periods : float, optional
24
- The number of periods. It may be a float, considering that number_of_periods = ID_length / period_length.
25
-
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
- InsertionDevice.__init__(self, K_vertical, K_horizontal, period_length, number_of_periods)
34
-
35
- def resonance_wavelength(self, gamma, theta_x=0.0, theta_z=0.0, harmonic=1.0):
36
- """
37
- Returns the resonant wavelength in m.
38
-
39
- Parameters
40
- ----------
41
- gamma : float
42
- The gamma or Lorentz factor of the electron beam.
43
- theta_x : float, optional
44
- The angle along the horizontal direction in rad.
45
- theta_z : float, optional
46
- The angle along the vertical direction in rad.
47
- harmonic : float, optional
48
- The harmonic number (1,2,3...) to be considered.
49
-
50
- Returns
51
- -------
52
- float
53
-
54
-
55
- """
56
- wavelength = (self.period_length() / (2.0 * gamma **2)) * \
57
- (1 + self.K_vertical()**2 / 2.0 + self.K_horizontal()**2 / 2.0 + \
58
- gamma**2 * (theta_x**2 + theta_z**2))
59
-
60
- return wavelength / harmonic
61
-
62
- def resonance_frequency(self, gamma, theta_x=0.0, theta_z=0.0, harmonic=1.0):
63
- """
64
- Returns the resonant frequency in Hz.
65
-
66
- Parameters
67
- ----------
68
- gamma : float
69
- The gamma or Lorentz factor of the electron beam.
70
- theta_x : float, optional
71
- The angle along the horizontal direction in rad.
72
- theta_z : float, optional
73
- The angle along the vertical direction in rad.
74
- harmonic : float, optional
75
- The harmonic number (1,2,3...) to be considered.
76
-
77
- Returns
78
- -------
79
- float
80
-
81
-
82
- """
83
- frequency = codata.c / self.resonance_wavelength(gamma, theta_x, theta_z)
84
-
85
- return frequency * harmonic
86
-
87
- def resonance_energy(self, gamma, theta_x=0.0, theta_z=0.0, harmonic=1.0):
88
- """
89
- Returns the resonant energy in eV.
90
-
91
- Parameters
92
- ----------
93
- gamma : float
94
- The gamma or Lorentz factor of the electron beam.
95
- theta_x : float, optional
96
- The angle along the horizontal direction in rad.
97
- theta_z : float, optional
98
- The angle along the vertical direction in rad.
99
- harmonic : float, optional
100
- The harmonic number (1,2,3...) to be considered.
101
-
102
- Returns
103
- -------
104
- float
105
-
106
-
107
- """
108
- energy_in_ev = codata.h * self.resonance_frequency(gamma, theta_x, theta_z) / codata.e
109
-
110
- return energy_in_ev*harmonic
111
-
112
- def gaussian_central_cone_aperture(self, gamma, n=1.0):
113
- """
114
- Returns the approximated angular width (sigma) in rad of the central cone.
115
-
116
- Parameters
117
- ----------
118
- gamma : float
119
- The gamma or Lorentz factor of the electron beam.
120
- n : float, optional
121
- The harmonic number (1,2,3...) to be considered.
122
-
123
- Returns
124
- -------
125
- float
126
-
127
- References
128
- ----------
129
- Eq. 15 in https://xdb.lbl.gov/Section2/Sec_2-1.html
130
-
131
- """
132
- return (1/gamma)*numpy.sqrt((1.0/(2.0*n*self.number_of_periods())) * (1.0 + self.K_horizontal()**2/2.0 + self.K_vertical()**2/2.0))
133
-
134
- @classmethod
135
- def initialize_as_vertical_undulator(cls, K = 0.0, period_length = 0.0, periods_number = 1.0, **params):
136
- """
137
- Create an undulator with vertical magnetic field.
138
-
139
- Parameters
140
- ----------
141
- K : float, optional
142
- The deflection K parameter corresponding to magnetic field in the vertical direction.
143
- period_length : float, optional
144
- The ID period in m.
145
- periods_number : float, optional
146
- The number of periods. It may be a float, considering that number_of_periods = ID_length / period_length.
147
- params : other parameters accepted by Undulator.
148
-
149
- Returns
150
- -------
151
- instance of Undulator
152
-
153
- """
154
- return cls(K_vertical=K,
155
- K_horizontal=0.0,
156
- period_length=period_length,
157
- number_of_periods=periods_number, **params)
158
- #
159
- #
160
- #
161
-
162
- def get_sigmas_radiation(self, gamma, harmonic=1.0):
163
- """
164
- Returns the approximated radiation sigmas (size and divergence).
165
-
166
- Parameters
167
- ----------
168
- gamma : float
169
- The gamma or Lorentz factor of the electron beam.
170
- harmonic : float, optional
171
- The harmonic number (1,2,3...) to be considered.
172
-
173
- Returns
174
- -------
175
- tuple
176
- (sigma_in_real_space [m], sigma_in_divergence_space [rad])
177
-
178
- References
179
- ----------
180
-
181
- See formulas 25 & 30 in Elleaume (Onuki & Elleaume) for the calculated sizes of the photon undulator beam.
182
- Onuki & Elleaume "Undulators, Wigglers and Their Applications" (2002) CRC Press.
183
-
184
-
185
- """
186
- # calculate sizes of the photon undulator beam
187
- # see formulas 25 & 30 in Elleaume (Onuki & Elleaume)
188
- photon_energy = self.resonance_energy(gamma,harmonic=harmonic)
189
- lambdan = 1e-10 * codata.h * codata.c / codata.e * 1e10 / photon_energy # in m
190
- sigma_r = 2.740 / 4 / numpy.pi * numpy.sqrt(lambdan * self.number_of_periods() * self.period_length())
191
- sigma_r_prime = 0.69 * numpy.sqrt(lambdan / (self.length()))
192
- return sigma_r, sigma_r_prime
193
-
194
- def get_resonance_ring(self, gamma, harmonic=1.0, ring_order=1):
195
- """
196
- Return the angular position of the rings at resonance.
197
-
198
- Parameters
199
- ----------
200
- gamma : float
201
- The gamma or Lorentz factor of the electron beam.
202
- harmonic : float, optional
203
- The harmonic number (1,2,3...) to be considered.
204
- ring_order : int, optional
205
- The ring order (1,2,3...)
206
-
207
- Returns
208
- -------
209
- float
210
- The angular position in rad.
211
-
212
- """
213
- K_value = numpy.sqrt( self.K_vertical()**2 + self.K_horizontal()**2)
214
- return 1.0 / gamma * numpy.sqrt( ring_order / harmonic * (1 + 0.5 * K_value**2) )
215
-
216
-
217
- def undulator_full_emitted_power(self, gamma, ring_current):
218
- """
219
- Returns the total emitted power by an undulator.
220
-
221
- Parameters
222
- ----------
223
- gamma : float
224
- The gamma or Lorentz factor of the electron beam.
225
- ring_current : float
226
- The current of the electron beam in A.
227
-
228
- Returns
229
- -------
230
- float
231
- The power in W.
232
-
233
- References
234
- ----------
235
- Eq. 18 in https://xdb.lbl.gov/Section2/Sec_2-1.html
236
-
237
- """
238
- ptot = (self.number_of_periods() / 6) * codata.value('characteristic impedance of vacuum') * \
239
- ring_current * codata.e * 2 * numpy.pi * codata.c * gamma**2 * \
240
- (self.K_vertical()**2 + self.K_horizontal()**2) / self.period_length()
241
- return ptot
242
-
243
- def get_photon_sizes_and_divergences(self, syned_electron_beam, harmonic=1):
244
- """
245
- Return the photon beam sizes and divergences.
246
-
247
- They are calculates as a convolution of the radiation sigmas (get_sigmas_radiation()) and
248
- the electron beam sizes.
249
-
250
- Parameters
251
- ----------
252
- syned_electron_beam : instance of ElectronBeam
253
- The electron bean used to get the electron beam sizes and electron energy.
254
- harmonic : int
255
- The harmonic number (1,2,3...).
256
-
257
- Returns
258
- -------
259
- tuple
260
- (Sx [m], Sz [m], Sxp [rad], Szp [rad])
261
-
262
- """
263
- sr,srp = self.get_sigmas_radiation(syned_electron_beam.gamma(), harmonic=harmonic)
264
- sx,sxp,sz,szp = syned_electron_beam.get_sigmas_all()
265
-
266
- Sx = numpy.sqrt( sx**2 + sr**2)
267
- Sz = numpy.sqrt( sz**2 + sr**2)
268
- Sxp = numpy.sqrt( sxp**2 + srp**2)
269
- Szp = numpy.sqrt( szp**2 + srp**2)
270
-
271
- return Sx,Sz,Sxp,Szp
272
-
273
- def get_K_from_photon_energy(self, photon_energy, gamma, harmonic=1):
274
- """
275
- Calculate K for a given resonance energy.
276
-
277
- Parameters
278
- ----------
279
- photon_energy : float
280
- The photon energy in eV.
281
- gamma : float
282
- The electron gamma (Lorentz factor).
283
- harmonic : int
284
- The harmonic number.
285
-
286
- Returns
287
- -------
288
- float
289
-
290
- """
291
- m2ev = codata.c * codata.h / codata.e
292
- wavelength = harmonic * m2ev / photon_energy
293
- return numpy.sqrt(2 * (((wavelength * 2 * gamma**2) / self.period_length()) - 1))
294
-
295
- def approximated_coherent_fraction_horizontal(self, syned_electron_beam, harmonic=1):
296
- """
297
- Gets the approximated coherent fraction at resonance in the horizontal direction.
298
-
299
- It is calculated as the ratio of the phase space of the coherent emission (zero emittance) over
300
- the actual emission (finite emittance).
301
-
302
- Parameters
303
- ----------
304
- syned_electron_beam : instance of ElectronBeam
305
- The electron bean used to get the electron beam sizes and electron energy.
306
- harmonic : int
307
- The harmonic number (1,2,3...).
308
-
309
- Returns
310
- -------
311
- float
312
-
313
- """
314
- Sx,Sy,Sxp,Syp = self.get_photon_sizes_and_divergences(syned_electron_beam, harmonic=harmonic)
315
- srad,sradp = self.get_sigmas_radiation(syned_electron_beam.gamma(), harmonic=harmonic)
316
- return srad * sradp / ( Sx * Sxp)
317
-
318
- def approximated_coherent_fraction_vertical(self, syned_electron_beam,harmonic=1):
319
- """
320
- Gets the approximated coherent fraction at resonance in the vertical direction.
321
-
322
- It is calculated as the ratio of the phase space of the coherent emission (zero emittance) over
323
- the actual emission (finite emittance).
324
-
325
- Parameters
326
- ----------
327
- syned_electron_beam : instance of ElectronBeam
328
- The electron bean used to get the electron beam sizes and electron energy.
329
- harmonic : int
330
- The harmonic number (1,2,3...).
331
-
332
- Returns
333
- -------
334
- float
335
-
336
- """
337
- Sx,Sy,Sxp,Syp = self.get_photon_sizes_and_divergences(syned_electron_beam, harmonic=harmonic)
338
- srad,sradp = self.get_sigmas_radiation(syned_electron_beam.gamma(), harmonic=harmonic)
339
- return srad * sradp / ( Sy * Syp)
340
-
341
- def approximated_coherent_fraction(self, syned_electron_beam, harmonic=1):
342
- """
343
- Gets the approximated coherent fraction at resonance.
344
-
345
- It is calculated as the product of the horizontal and vertical coherent fractions.
346
-
347
- Parameters
348
- ----------
349
- syned_electron_beam : instance of ElectronBeam
350
- The electron bean used to get the electron beam sizes and electron energy.
351
- harmonic : int
352
- The harmonic number (1,2,3...).
353
-
354
- Returns
355
- -------
356
- float
357
-
358
- """
359
- return self.approximated_coherent_fraction_horizontal(syned_electron_beam, harmonic=harmonic) * \
360
- self.approximated_coherent_fraction_vertical(syned_electron_beam, harmonic=harmonic)
361
-
362
-
363
- if __name__ == "__main__":
364
-
365
- a = Undulator(number_of_periods=61.5, period_length=0.057)
366
- a.set_K_vertical_from_magnetic_field(0.187782)
367
-
368
- print(a._K_vertical)
369
-
370
- print (a.resonance_energy(gamma=5870.8540997356595))
371
-
372
- fd = a.to_full_dictionary()
373
- dict = a.to_dictionary()
374
-
375
- print(dict)
376
-
377
- for key in fd:
378
- print(key,fd[key][0])
379
-
380
- for key in fd:
381
- print(key,dict[key])
382
-
383
- print(a.keys())
384
- print(a.info())
385
-
386
-
387
- print("####### derived quantities ##########")
388
-
389
- from syned.storage_ring.electron_beam import ElectronBeam
390
- ebeam = ElectronBeam.initialize_as_pencil_beam(energy_in_GeV=2.0,energy_spread=0.0,current=0.5)
391
-
392
- sigmas_radiation = a.get_sigmas_radiation(ebeam.gamma(),harmonic=1.0)
393
- print("sigmas radiation [m rad]:",sigmas_radiation)
394
-
395
-
396
- ring = a.get_resonance_ring(ebeam.gamma(), harmonic=1.0, ring_order=1)
397
- print("first ring at [rad]:",ring)
398
-
399
- pow = a.undulator_full_emitted_power(ebeam.gamma(), ebeam.current())
400
- print("Total emission [W]",pow)
401
-
402
- sizes = a.get_photon_sizes_and_divergences(ebeam,harmonic=1)
403
- print("Sizes: ",sizes)
404
-
405
- print("Resonance: ",a.resonance_energy(ebeam.gamma()))
406
-
407
- print("K at 444 eV",a.get_K_from_photon_energy(444.0,ebeam.gamma()))
408
- print("K at 200 eV", a.get_K_from_photon_energy(200.0, ebeam.gamma()))
409
-
410
- print("CF H V HV: ",
411
- a.approximated_coherent_fraction_horizontal(ebeam,harmonic=1),
412
- a.approximated_coherent_fraction_vertical(ebeam, harmonic=1),
413
- a.approximated_coherent_fraction(ebeam, harmonic=1),)
1
+ """
2
+ Implement an undulator with vertical and horizontal magnetic fields.
3
+ """
4
+ import numpy
5
+ import scipy.constants as codata
6
+
7
+ cte = codata.e/(2*numpy.pi*codata.electron_mass*codata.c)
8
+
9
+ from syned.storage_ring.magnetic_structures.insertion_device import InsertionDevice
10
+
11
+ class Undulator(InsertionDevice):
12
+ """
13
+ Constructor.
14
+
15
+ Parameters
16
+ ----------
17
+ K_vertical : float, optional
18
+ The deflection K parameter corresponding to magnetic field in the vertical direction.
19
+ K_horizontal : float, optional
20
+ The deflection K parameter corresponding to magnetic field in the horizontal direction.
21
+ period_length : float, optional
22
+ The ID period in m.
23
+ number_of_periods : float, optional
24
+ The number of periods. It may be a float, considering that number_of_periods = ID_length / period_length.
25
+
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
+ InsertionDevice.__init__(self, K_vertical, K_horizontal, period_length, number_of_periods)
34
+
35
+ def resonance_wavelength(self, gamma, theta_x=0.0, theta_z=0.0, harmonic=1.0):
36
+ """
37
+ Returns the resonant wavelength in m.
38
+
39
+ Parameters
40
+ ----------
41
+ gamma : float
42
+ The gamma or Lorentz factor of the electron beam.
43
+ theta_x : float, optional
44
+ The angle along the horizontal direction in rad.
45
+ theta_z : float, optional
46
+ The angle along the vertical direction in rad.
47
+ harmonic : float, optional
48
+ The harmonic number (1,2,3...) to be considered.
49
+
50
+ Returns
51
+ -------
52
+ float
53
+
54
+
55
+ """
56
+ wavelength = (self.period_length() / (2.0 * gamma **2)) * \
57
+ (1 + self.K_vertical()**2 / 2.0 + self.K_horizontal()**2 / 2.0 + \
58
+ gamma**2 * (theta_x**2 + theta_z**2))
59
+
60
+ return wavelength / harmonic
61
+
62
+ def resonance_frequency(self, gamma, theta_x=0.0, theta_z=0.0, harmonic=1.0):
63
+ """
64
+ Returns the resonant frequency in Hz.
65
+
66
+ Parameters
67
+ ----------
68
+ gamma : float
69
+ The gamma or Lorentz factor of the electron beam.
70
+ theta_x : float, optional
71
+ The angle along the horizontal direction in rad.
72
+ theta_z : float, optional
73
+ The angle along the vertical direction in rad.
74
+ harmonic : float, optional
75
+ The harmonic number (1,2,3...) to be considered.
76
+
77
+ Returns
78
+ -------
79
+ float
80
+
81
+
82
+ """
83
+ frequency = codata.c / self.resonance_wavelength(gamma, theta_x, theta_z)
84
+
85
+ return frequency * harmonic
86
+
87
+ def resonance_energy(self, gamma, theta_x=0.0, theta_z=0.0, harmonic=1.0):
88
+ """
89
+ Returns the resonant energy in eV.
90
+
91
+ Parameters
92
+ ----------
93
+ gamma : float
94
+ The gamma or Lorentz factor of the electron beam.
95
+ theta_x : float, optional
96
+ The angle along the horizontal direction in rad.
97
+ theta_z : float, optional
98
+ The angle along the vertical direction in rad.
99
+ harmonic : float, optional
100
+ The harmonic number (1,2,3...) to be considered.
101
+
102
+ Returns
103
+ -------
104
+ float
105
+
106
+
107
+ """
108
+ energy_in_ev = codata.h * self.resonance_frequency(gamma, theta_x, theta_z) / codata.e
109
+
110
+ return energy_in_ev*harmonic
111
+
112
+ def gaussian_central_cone_aperture(self, gamma, n=1.0):
113
+ """
114
+ Returns the approximated angular width (sigma) in rad of the central cone.
115
+
116
+ Parameters
117
+ ----------
118
+ gamma : float
119
+ The gamma or Lorentz factor of the electron beam.
120
+ n : float, optional
121
+ The harmonic number (1,2,3...) to be considered.
122
+
123
+ Returns
124
+ -------
125
+ float
126
+
127
+ References
128
+ ----------
129
+ Eq. 15 in https://xdb.lbl.gov/Section2/Sec_2-1.html
130
+
131
+ """
132
+ return (1/gamma)*numpy.sqrt((1.0/(2.0*n*self.number_of_periods())) * (1.0 + self.K_horizontal()**2/2.0 + self.K_vertical()**2/2.0))
133
+
134
+ @classmethod
135
+ def initialize_as_vertical_undulator(cls, K = 0.0, period_length = 0.0, periods_number = 1.0, **params):
136
+ """
137
+ Create an undulator with vertical magnetic field.
138
+
139
+ Parameters
140
+ ----------
141
+ K : float, optional
142
+ The deflection K parameter corresponding to magnetic field in the vertical direction.
143
+ period_length : float, optional
144
+ The ID period in m.
145
+ periods_number : float, optional
146
+ The number of periods. It may be a float, considering that number_of_periods = ID_length / period_length.
147
+ params : other parameters accepted by Undulator.
148
+
149
+ Returns
150
+ -------
151
+ instance of Undulator
152
+
153
+ """
154
+ return cls(K_vertical=K,
155
+ K_horizontal=0.0,
156
+ period_length=period_length,
157
+ number_of_periods=periods_number, **params)
158
+ #
159
+ #
160
+ #
161
+
162
+ def get_sigmas_radiation(self, gamma, harmonic=1.0):
163
+ """
164
+ Returns the approximated radiation sigmas (size and divergence).
165
+
166
+ Parameters
167
+ ----------
168
+ gamma : float
169
+ The gamma or Lorentz factor of the electron beam.
170
+ harmonic : float, optional
171
+ The harmonic number (1,2,3...) to be considered.
172
+
173
+ Returns
174
+ -------
175
+ tuple
176
+ (sigma_in_real_space [m], sigma_in_divergence_space [rad])
177
+
178
+ References
179
+ ----------
180
+
181
+ See formulas 25 & 30 in Elleaume (Onuki & Elleaume) for the calculated sizes of the photon undulator beam.
182
+ Onuki & Elleaume "Undulators, Wigglers and Their Applications" (2002) CRC Press.
183
+
184
+
185
+ """
186
+ # calculate sizes of the photon undulator beam
187
+ # see formulas 25 & 30 in Elleaume (Onuki & Elleaume)
188
+ photon_energy = self.resonance_energy(gamma,harmonic=harmonic)
189
+ lambdan = 1e-10 * codata.h * codata.c / codata.e * 1e10 / photon_energy # in m
190
+ sigma_r = 2.740 / 4 / numpy.pi * numpy.sqrt(lambdan * self.number_of_periods() * self.period_length())
191
+ sigma_r_prime = 0.69 * numpy.sqrt(lambdan / (self.length()))
192
+ return sigma_r, sigma_r_prime
193
+
194
+ def get_resonance_ring(self, gamma, harmonic=1.0, ring_order=1):
195
+ """
196
+ Return the angular position of the rings at resonance.
197
+
198
+ Parameters
199
+ ----------
200
+ gamma : float
201
+ The gamma or Lorentz factor of the electron beam.
202
+ harmonic : float, optional
203
+ The harmonic number (1,2,3...) to be considered.
204
+ ring_order : int, optional
205
+ The ring order (1,2,3...)
206
+
207
+ Returns
208
+ -------
209
+ float
210
+ The angular position in rad.
211
+
212
+ """
213
+ K_value = numpy.sqrt( self.K_vertical()**2 + self.K_horizontal()**2)
214
+ return 1.0 / gamma * numpy.sqrt( ring_order / harmonic * (1 + 0.5 * K_value**2) )
215
+
216
+
217
+ def undulator_full_emitted_power(self, gamma, ring_current):
218
+ """
219
+ Returns the total emitted power by an undulator.
220
+
221
+ Parameters
222
+ ----------
223
+ gamma : float
224
+ The gamma or Lorentz factor of the electron beam.
225
+ ring_current : float
226
+ The current of the electron beam in A.
227
+
228
+ Returns
229
+ -------
230
+ float
231
+ The power in W.
232
+
233
+ References
234
+ ----------
235
+ Eq. 18 in https://xdb.lbl.gov/Section2/Sec_2-1.html
236
+
237
+ """
238
+ ptot = (self.number_of_periods() / 6) * codata.value('characteristic impedance of vacuum') * \
239
+ ring_current * codata.e * 2 * numpy.pi * codata.c * gamma**2 * \
240
+ (self.K_vertical()**2 + self.K_horizontal()**2) / self.period_length()
241
+ return ptot
242
+
243
+ def get_photon_sizes_and_divergences(self, syned_electron_beam, harmonic=1):
244
+ """
245
+ Return the photon beam sizes and divergences.
246
+
247
+ They are calculates as a convolution of the radiation sigmas (get_sigmas_radiation()) and
248
+ the electron beam sizes.
249
+
250
+ Parameters
251
+ ----------
252
+ syned_electron_beam : instance of ElectronBeam
253
+ The electron bean used to get the electron beam sizes and electron energy.
254
+ harmonic : int
255
+ The harmonic number (1,2,3...).
256
+
257
+ Returns
258
+ -------
259
+ tuple
260
+ (Sx [m], Sz [m], Sxp [rad], Szp [rad])
261
+
262
+ """
263
+ sr,srp = self.get_sigmas_radiation(syned_electron_beam.gamma(), harmonic=harmonic)
264
+ sx,sxp,sz,szp = syned_electron_beam.get_sigmas_all()
265
+
266
+ Sx = numpy.sqrt( sx**2 + sr**2)
267
+ Sz = numpy.sqrt( sz**2 + sr**2)
268
+ Sxp = numpy.sqrt( sxp**2 + srp**2)
269
+ Szp = numpy.sqrt( szp**2 + srp**2)
270
+
271
+ return Sx,Sz,Sxp,Szp
272
+
273
+ def get_K_from_photon_energy(self, photon_energy, gamma, harmonic=1):
274
+ """
275
+ Calculate K for a given resonance energy.
276
+
277
+ Parameters
278
+ ----------
279
+ photon_energy : float
280
+ The photon energy in eV.
281
+ gamma : float
282
+ The electron gamma (Lorentz factor).
283
+ harmonic : int
284
+ The harmonic number.
285
+
286
+ Returns
287
+ -------
288
+ float
289
+
290
+ """
291
+ m2ev = codata.c * codata.h / codata.e
292
+ wavelength = harmonic * m2ev / photon_energy
293
+ return numpy.sqrt(2 * (((wavelength * 2 * gamma**2) / self.period_length()) - 1))
294
+
295
+ def approximated_coherent_fraction_horizontal(self, syned_electron_beam, harmonic=1):
296
+ """
297
+ Gets the approximated coherent fraction at resonance in the horizontal direction.
298
+
299
+ It is calculated as the ratio of the phase space of the coherent emission (zero emittance) over
300
+ the actual emission (finite emittance).
301
+
302
+ Parameters
303
+ ----------
304
+ syned_electron_beam : instance of ElectronBeam
305
+ The electron bean used to get the electron beam sizes and electron energy.
306
+ harmonic : int
307
+ The harmonic number (1,2,3...).
308
+
309
+ Returns
310
+ -------
311
+ float
312
+
313
+ """
314
+ Sx,Sy,Sxp,Syp = self.get_photon_sizes_and_divergences(syned_electron_beam, harmonic=harmonic)
315
+ srad,sradp = self.get_sigmas_radiation(syned_electron_beam.gamma(), harmonic=harmonic)
316
+ return srad * sradp / ( Sx * Sxp)
317
+
318
+ def approximated_coherent_fraction_vertical(self, syned_electron_beam,harmonic=1):
319
+ """
320
+ Gets the approximated coherent fraction at resonance in the vertical direction.
321
+
322
+ It is calculated as the ratio of the phase space of the coherent emission (zero emittance) over
323
+ the actual emission (finite emittance).
324
+
325
+ Parameters
326
+ ----------
327
+ syned_electron_beam : instance of ElectronBeam
328
+ The electron bean used to get the electron beam sizes and electron energy.
329
+ harmonic : int
330
+ The harmonic number (1,2,3...).
331
+
332
+ Returns
333
+ -------
334
+ float
335
+
336
+ """
337
+ Sx,Sy,Sxp,Syp = self.get_photon_sizes_and_divergences(syned_electron_beam, harmonic=harmonic)
338
+ srad,sradp = self.get_sigmas_radiation(syned_electron_beam.gamma(), harmonic=harmonic)
339
+ return srad * sradp / ( Sy * Syp)
340
+
341
+ def approximated_coherent_fraction(self, syned_electron_beam, harmonic=1):
342
+ """
343
+ Gets the approximated coherent fraction at resonance.
344
+
345
+ It is calculated as the product of the horizontal and vertical coherent fractions.
346
+
347
+ Parameters
348
+ ----------
349
+ syned_electron_beam : instance of ElectronBeam
350
+ The electron bean used to get the electron beam sizes and electron energy.
351
+ harmonic : int
352
+ The harmonic number (1,2,3...).
353
+
354
+ Returns
355
+ -------
356
+ float
357
+
358
+ """
359
+ return self.approximated_coherent_fraction_horizontal(syned_electron_beam, harmonic=harmonic) * \
360
+ self.approximated_coherent_fraction_vertical(syned_electron_beam, harmonic=harmonic)
361
+
362
+
363
+ if __name__ == "__main__":
364
+
365
+ a = Undulator(number_of_periods=61.5, period_length=0.057)
366
+ a.set_K_vertical_from_magnetic_field(0.187782)
367
+
368
+ print(a._K_vertical)
369
+
370
+ print (a.resonance_energy(gamma=5870.8540997356595))
371
+
372
+ fd = a.to_full_dictionary()
373
+ dict = a.to_dictionary()
374
+
375
+ print(dict)
376
+
377
+ for key in fd:
378
+ print(key,fd[key][0])
379
+
380
+ for key in fd:
381
+ print(key,dict[key])
382
+
383
+ print(a.keys())
384
+ print(a.info())
385
+
386
+
387
+ print("####### derived quantities ##########")
388
+
389
+ from syned.storage_ring.electron_beam import ElectronBeam
390
+ ebeam = ElectronBeam.initialize_as_pencil_beam(energy_in_GeV=2.0,energy_spread=0.0,current=0.5)
391
+
392
+ sigmas_radiation = a.get_sigmas_radiation(ebeam.gamma(),harmonic=1.0)
393
+ print("sigmas radiation [m rad]:",sigmas_radiation)
394
+
395
+
396
+ ring = a.get_resonance_ring(ebeam.gamma(), harmonic=1.0, ring_order=1)
397
+ print("first ring at [rad]:",ring)
398
+
399
+ pow = a.undulator_full_emitted_power(ebeam.gamma(), ebeam.current())
400
+ print("Total emission [W]",pow)
401
+
402
+ sizes = a.get_photon_sizes_and_divergences(ebeam,harmonic=1)
403
+ print("Sizes: ",sizes)
404
+
405
+ print("Resonance: ",a.resonance_energy(ebeam.gamma()))
406
+
407
+ print("K at 444 eV",a.get_K_from_photon_energy(444.0,ebeam.gamma()))
408
+ print("K at 200 eV", a.get_K_from_photon_energy(200.0, ebeam.gamma()))
409
+
410
+ print("CF H V HV: ",
411
+ a.approximated_coherent_fraction_horizontal(ebeam,harmonic=1),
412
+ a.approximated_coherent_fraction_vertical(ebeam, harmonic=1),
413
+ a.approximated_coherent_fraction(ebeam, harmonic=1),)