Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ok-landscape
GitHub Repository: Ok-landscape/computational-pipeline
Path: blob/main/latex-templates/templates/optics/diffraction_grating.tex
51 views
unlisted
1
\documentclass[a4paper, 11pt]{article}
2
\usepackage[utf8]{inputenc}
3
\usepackage[T1]{fontenc}
4
\usepackage{amsmath, amssymb}
5
\usepackage{graphicx}
6
\usepackage{booktabs}
7
\usepackage{siunitx}
8
\usepackage[makestderr]{pythontex}
9
10
\title{Diffraction Grating Spectroscopy: Principles and Applications}
11
\author{Computational Optics}
12
\date{\today}
13
14
\begin{document}
15
\maketitle
16
17
\section{Introduction}
18
Diffraction gratings are fundamental optical elements that disperse light into its spectral components
19
through interference effects. This comprehensive analysis explores the physics of multi-slit diffraction,
20
spectral resolution, blazed gratings, and practical applications in spectroscopy. We implement
21
numerical simulations of grating patterns, analyze the trade-offs between resolution and intensity,
22
and demonstrate techniques for spectral line identification and analysis.
23
24
\section{Mathematical Framework}
25
26
\subsection{Grating Equation}
27
Principal maxima occur when:
28
\begin{equation}
29
d(\sin\theta_i + \sin\theta_m) = m\lambda
30
\end{equation}
31
where $d$ is the grating period, $\theta_i$ is the incident angle, $\theta_m$ is the diffraction angle,
32
and $m$ is the diffraction order.
33
34
\subsection{Intensity Distribution}
35
For an N-slit grating with slit width $a$:
36
\begin{equation}
37
I(\theta) = I_0 \left(\frac{\sin\beta}{\beta}\right)^2 \left(\frac{\sin(N\alpha)}{\sin\alpha}\right)^2
38
\end{equation}
39
where:
40
\begin{align}
41
\alpha &= \frac{\pi d \sin\theta}{\lambda} \\
42
\beta &= \frac{\pi a \sin\theta}{\lambda}
43
\end{align}
44
45
\subsection{Resolving Power}
46
The chromatic resolving power:
47
\begin{equation}
48
R = \frac{\lambda}{\Delta\lambda} = mN
49
\end{equation}
50
51
\subsection{Angular Dispersion}
52
\begin{equation}
53
\frac{d\theta}{d\lambda} = \frac{m}{d\cos\theta_m}
54
\end{equation}
55
56
\section{Environment Setup}
57
\begin{pycode}
58
import numpy as np
59
import matplotlib.pyplot as plt
60
from scipy.signal import find_peaks
61
62
plt.rc('text', usetex=True)
63
plt.rc('font', family='serif', size=10)
64
np.random.seed(42)
65
66
def save_plot(filename, caption=""):
67
plt.savefig(filename, bbox_inches='tight', dpi=150)
68
print(r'\begin{figure}[htbp]')
69
print(r'\centering')
70
print(r'\includegraphics[width=0.95\textwidth]{' + filename + '}')
71
if caption:
72
print(r'\caption{' + caption + '}')
73
print(r'\end{figure}')
74
plt.close()
75
\end{pycode}
76
77
\section{Basic Grating Diffraction Pattern}
78
\begin{pycode}
79
def grating_intensity(theta, wavelength, N, d, a):
80
"""Calculate normalized grating diffraction intensity."""
81
alpha = np.pi * d * np.sin(theta) / wavelength
82
beta = np.pi * a * np.sin(theta) / wavelength
83
84
# Avoid division by zero
85
alpha = np.where(np.abs(alpha) < 1e-10, 1e-10, alpha)
86
beta = np.where(np.abs(beta) < 1e-10, 1e-10, beta)
87
88
# Single slit envelope
89
I_slit = (np.sin(beta) / beta)**2
90
91
# Multi-slit interference
92
I_grating = (np.sin(N * alpha) / np.sin(alpha))**2
93
94
return I_slit * I_grating / N**2
95
96
# Grating parameters
97
d = 1e-6 # Grating period (1000 lines/mm)
98
a = d / 2 # Slit width (50% fill factor)
99
wavelength = 550e-9 # Green light
100
101
# Angular range covering multiple orders
102
theta = np.linspace(-0.8, 0.8, 5000)
103
104
# Calculate patterns for different N
105
N_values = [5, 20, 100, 500]
106
107
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
108
109
for idx, N in enumerate(N_values):
110
row, col = divmod(idx, 2)
111
I = grating_intensity(theta, wavelength, N, d, a)
112
113
axes[row, col].plot(np.rad2deg(theta), I, 'b-', linewidth=0.5)
114
axes[row, col].set_xlabel('Angle (degrees)')
115
axes[row, col].set_ylabel('Intensity (normalized)')
116
axes[row, col].set_title(f'N = {N} slits')
117
axes[row, col].set_xlim([-50, 50])
118
axes[row, col].grid(True, alpha=0.3)
119
120
# Mark diffraction orders
121
for m in range(-1, 2):
122
if abs(m * wavelength / d) <= 1:
123
theta_m = np.rad2deg(np.arcsin(m * wavelength / d))
124
axes[row, col].axvline(x=theta_m, color='r', linestyle='--', alpha=0.5)
125
126
plt.tight_layout()
127
save_plot('grating_n_comparison.pdf',
128
'Diffraction patterns for gratings with different numbers of slits.')
129
\end{pycode}
130
131
\section{Spectral Resolution Analysis}
132
\begin{pycode}
133
# Sodium D-lines (classic test of spectral resolution)
134
lambda1 = 589.0e-9 # D1 line
135
lambda2 = 589.6e-9 # D2 line
136
delta_lambda = lambda2 - lambda1
137
138
# Grating parameters for high resolution
139
d = 1e-6 # 1000 lines/mm
140
a = d / 2
141
142
# Test different N values
143
N_test = [100, 500, 1000, 2000]
144
145
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
146
147
for idx, N in enumerate(N_test):
148
row, col = divmod(idx, 2)
149
150
# Angular range around first order
151
theta_center = np.arcsin(lambda1 / d)
152
theta = np.linspace(theta_center - 0.01, theta_center + 0.01, 3000)
153
154
# Calculate patterns for both lines
155
I1 = grating_intensity(theta, lambda1, N, d, a)
156
I2 = grating_intensity(theta, lambda2, N, d, a)
157
I_total = I1 + I2
158
159
axes[row, col].plot(np.rad2deg(theta), I1, 'b-', linewidth=1, alpha=0.7, label='D1')
160
axes[row, col].plot(np.rad2deg(theta), I2, 'r-', linewidth=1, alpha=0.7, label='D2')
161
axes[row, col].plot(np.rad2deg(theta), I_total, 'k-', linewidth=1.5, label='Total')
162
163
# Resolution criterion
164
R_needed = lambda1 / delta_lambda
165
R_actual = N # First order
166
resolved = "Resolved" if R_actual >= R_needed else "Unresolved"
167
168
axes[row, col].set_xlabel('Angle (degrees)')
169
axes[row, col].set_ylabel('Intensity')
170
axes[row, col].set_title(f'N = {N}, R = {R_actual} ({resolved})')
171
axes[row, col].legend(fontsize=8)
172
axes[row, col].grid(True, alpha=0.3)
173
174
plt.tight_layout()
175
save_plot('sodium_resolution.pdf',
176
'Resolution of sodium D-lines with different numbers of grating lines.')
177
178
# Calculate required N for Rayleigh resolution
179
N_required = int(np.ceil(lambda1 / delta_lambda))
180
\end{pycode}
181
182
\section{Multiple Diffraction Orders}
183
\begin{pycode}
184
# Analyze multiple diffraction orders
185
d = 2e-6 # 500 lines/mm for more visible orders
186
a = d / 3 # Smaller fill factor
187
N = 200
188
wavelength = 550e-9
189
190
theta = np.linspace(-1.2, 1.2, 8000)
191
I = grating_intensity(theta, wavelength, N, d, a)
192
193
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
194
195
# Full pattern
196
axes[0, 0].plot(np.rad2deg(theta), I, 'b-', linewidth=0.5)
197
axes[0, 0].set_xlabel('Angle (degrees)')
198
axes[0, 0].set_ylabel('Intensity')
199
axes[0, 0].set_title('Multiple Diffraction Orders')
200
axes[0, 0].grid(True, alpha=0.3)
201
202
# Mark and label orders
203
order_angles = []
204
order_intensities = []
205
for m in range(-3, 4):
206
sin_theta = m * wavelength / d
207
if abs(sin_theta) <= 1:
208
theta_m = np.arcsin(sin_theta)
209
order_angles.append(np.rad2deg(theta_m))
210
211
# Find peak intensity at this order
212
idx = np.argmin(np.abs(theta - theta_m))
213
order_intensities.append(I[idx])
214
215
axes[0, 0].annotate(f'm={m}', xy=(np.rad2deg(theta_m), I[idx]),
216
xytext=(np.rad2deg(theta_m), I[idx] + 0.1),
217
ha='center', fontsize=8)
218
219
# Order intensities comparison
220
valid_orders = list(range(-3, 4))
221
axes[0, 1].bar(valid_orders[:len(order_intensities)], order_intensities,
222
color='green', alpha=0.7, edgecolor='black')
223
axes[0, 1].set_xlabel('Diffraction Order m')
224
axes[0, 1].set_ylabel('Peak Intensity')
225
axes[0, 1].set_title('Intensity vs Diffraction Order')
226
axes[0, 1].grid(True, alpha=0.3)
227
228
# Blaze effect: fill factor variation
229
fill_factors = [0.2, 0.3, 0.5, 0.7]
230
for ff in fill_factors:
231
a_test = d * ff
232
I_test = grating_intensity(theta, wavelength, N, d, a_test)
233
axes[1, 0].plot(np.rad2deg(theta), I_test, linewidth=0.5,
234
label=f'a/d = {ff}', alpha=0.7)
235
236
axes[1, 0].set_xlabel('Angle (degrees)')
237
axes[1, 0].set_ylabel('Intensity')
238
axes[1, 0].set_title('Effect of Fill Factor')
239
axes[1, 0].legend(fontsize=8)
240
axes[1, 0].grid(True, alpha=0.3)
241
axes[1, 0].set_xlim([-70, 70])
242
243
# Angular dispersion across orders
244
wavelengths = np.linspace(400e-9, 700e-9, 100)
245
colors_spectrum = plt.cm.rainbow(np.linspace(0, 1, len(wavelengths)))
246
247
for m in [1, 2, 3]:
248
angles = []
249
valid_wavelengths = []
250
for wl in wavelengths:
251
sin_theta = m * wl / d
252
if abs(sin_theta) <= 1:
253
angles.append(np.rad2deg(np.arcsin(sin_theta)))
254
valid_wavelengths.append(wl * 1e9)
255
256
if len(angles) > 0:
257
axes[1, 1].plot(valid_wavelengths, angles, linewidth=2, label=f'm = {m}')
258
259
axes[1, 1].set_xlabel('Wavelength (nm)')
260
axes[1, 1].set_ylabel('Diffraction Angle (degrees)')
261
axes[1, 1].set_title('Angular Dispersion')
262
axes[1, 1].legend()
263
axes[1, 1].grid(True, alpha=0.3)
264
265
plt.tight_layout()
266
save_plot('multiple_orders.pdf',
267
'Analysis of multiple diffraction orders and angular dispersion.')
268
\end{pycode}
269
270
\section{Blazed Grating Simulation}
271
\begin{pycode}
272
def blazed_grating_intensity(theta, wavelength, N, d, blaze_angle):
273
"""Blazed grating with specified blaze angle."""
274
# Phase from grating period
275
alpha = np.pi * d * np.sin(theta) / wavelength
276
277
# Blaze envelope centered on blaze angle
278
beta_blaze = np.pi * d * (np.sin(theta) - np.sin(blaze_angle)) / wavelength
279
beta_blaze = np.where(np.abs(beta_blaze) < 1e-10, 1e-10, beta_blaze)
280
281
# Intensities
282
I_blaze = (np.sin(beta_blaze) / beta_blaze)**2
283
284
alpha = np.where(np.abs(alpha) < 1e-10, 1e-10, alpha)
285
I_grating = (np.sin(N * alpha) / np.sin(alpha))**2
286
287
return I_blaze * I_grating / N**2
288
289
# Blazed grating parameters
290
d = 1.5e-6
291
N = 300
292
wavelength = 550e-9
293
294
# Blaze angle for maximum in first order
295
blaze_angle = np.arcsin(wavelength / d)
296
297
theta = np.linspace(-0.6, 0.6, 5000)
298
299
# Compare blazed vs non-blazed
300
I_blazed = blazed_grating_intensity(theta, wavelength, N, d, blaze_angle)
301
I_normal = grating_intensity(theta, wavelength, N, d, d/2)
302
303
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
304
305
# Comparison
306
axes[0, 0].plot(np.rad2deg(theta), I_normal, 'b-', linewidth=0.5, label='Symmetric')
307
axes[0, 0].plot(np.rad2deg(theta), I_blazed, 'r-', linewidth=0.5, label='Blazed')
308
axes[0, 0].set_xlabel('Angle (degrees)')
309
axes[0, 0].set_ylabel('Intensity')
310
axes[0, 0].set_title('Blazed vs Symmetric Grating')
311
axes[0, 0].legend()
312
axes[0, 0].grid(True, alpha=0.3)
313
314
# Different blaze angles
315
blaze_angles_deg = [10, 20, 30]
316
for ba_deg in blaze_angles_deg:
317
ba = np.deg2rad(ba_deg)
318
I = blazed_grating_intensity(theta, wavelength, N, d, ba)
319
axes[0, 1].plot(np.rad2deg(theta), I, linewidth=0.5, label=f'Blaze = {ba_deg}$^\\circ$')
320
321
axes[0, 1].set_xlabel('Angle (degrees)')
322
axes[0, 1].set_ylabel('Intensity')
323
axes[0, 1].set_title('Effect of Blaze Angle')
324
axes[0, 1].legend(fontsize=8)
325
axes[0, 1].grid(True, alpha=0.3)
326
327
# Efficiency at different wavelengths
328
wavelengths_test = np.linspace(400e-9, 700e-9, 50)
329
first_order_efficiency = []
330
second_order_efficiency = []
331
332
for wl in wavelengths_test:
333
blaze = np.arcsin(wl / d)
334
theta_1 = np.arcsin(wl / d)
335
theta_2 = np.arcsin(2 * wl / d) if 2*wl/d <= 1 else 0
336
337
# Calculate intensity at first and second order
338
I1 = blazed_grating_intensity(np.array([theta_1]), wl, N, d, blaze)[0]
339
if theta_2 > 0:
340
I2 = blazed_grating_intensity(np.array([theta_2]), wl, N, d, blaze)[0]
341
else:
342
I2 = 0
343
344
first_order_efficiency.append(I1)
345
second_order_efficiency.append(I2)
346
347
axes[1, 0].plot(wavelengths_test*1e9, first_order_efficiency, 'b-',
348
linewidth=2, label='1st order')
349
axes[1, 0].plot(wavelengths_test*1e9, second_order_efficiency, 'r--',
350
linewidth=2, label='2nd order')
351
axes[1, 0].set_xlabel('Wavelength (nm)')
352
axes[1, 0].set_ylabel('Efficiency')
353
axes[1, 0].set_title('Order Efficiency vs Wavelength')
354
axes[1, 0].legend()
355
axes[1, 0].grid(True, alpha=0.3)
356
357
# Grating groove profile
358
x_groove = np.linspace(0, 3*d*1e6, 300)
359
y_groove = np.mod(x_groove, d*1e6) * np.tan(blaze_angle)
360
361
axes[1, 1].plot(x_groove, y_groove, 'k-', linewidth=2)
362
axes[1, 1].fill_between(x_groove, 0, y_groove, alpha=0.3)
363
axes[1, 1].set_xlabel('Position ($\\mu$m)')
364
axes[1, 1].set_ylabel('Height ($\\mu$m)')
365
axes[1, 1].set_title(f'Blazed Groove Profile (blaze = {np.rad2deg(blaze_angle):.1f}$^\\circ$)')
366
axes[1, 1].grid(True, alpha=0.3)
367
368
plt.tight_layout()
369
save_plot('blazed_grating.pdf',
370
'Blazed grating analysis showing efficiency enhancement.')
371
\end{pycode}
372
373
\section{Spectroscopy Application}
374
\begin{pycode}
375
# Simulate a spectrum with multiple emission lines
376
emission_lines = {
377
'H-alpha': 656.3e-9,
378
'H-beta': 486.1e-9,
379
'Na-D1': 589.0e-9,
380
'Na-D2': 589.6e-9,
381
'Hg-green': 546.1e-9
382
}
383
384
d = 1e-6
385
N = 1000
386
a = d / 2
387
388
# Full spectrum
389
theta_full = np.linspace(0.2, 0.8, 10000)
390
391
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
392
393
# Individual line patterns
394
I_total = np.zeros_like(theta_full)
395
colors = ['red', 'blue', 'orange', 'darkorange', 'green']
396
397
for (name, wl), color in zip(emission_lines.items(), colors):
398
I = grating_intensity(theta_full, wl, N, d, a)
399
I_total += I
400
401
if name in ['H-alpha', 'H-beta', 'Na-D1', 'Hg-green']:
402
axes[0, 0].plot(np.rad2deg(theta_full), I, color=color,
403
linewidth=1, alpha=0.7, label=name)
404
405
axes[0, 0].set_xlabel('Angle (degrees)')
406
axes[0, 0].set_ylabel('Intensity')
407
axes[0, 0].set_title('Individual Emission Lines')
408
axes[0, 0].legend(fontsize=8)
409
axes[0, 0].grid(True, alpha=0.3)
410
411
# Combined spectrum
412
axes[0, 1].plot(np.rad2deg(theta_full), I_total, 'k-', linewidth=0.5)
413
axes[0, 1].set_xlabel('Angle (degrees)')
414
axes[0, 1].set_ylabel('Total Intensity')
415
axes[0, 1].set_title('Combined Emission Spectrum')
416
axes[0, 1].grid(True, alpha=0.3)
417
418
# Wavelength calibration
419
# Convert angle to wavelength (first order)
420
wavelength_scale = d * np.sin(theta_full) * 1e9 # nm
421
422
axes[1, 0].plot(wavelength_scale, I_total, 'k-', linewidth=0.5)
423
axes[1, 0].set_xlabel('Wavelength (nm)')
424
axes[1, 0].set_ylabel('Intensity')
425
axes[1, 0].set_title('Calibrated Spectrum')
426
axes[1, 0].grid(True, alpha=0.3)
427
axes[1, 0].set_xlim([400, 700])
428
429
# Mark line positions
430
for name, wl in emission_lines.items():
431
axes[1, 0].axvline(x=wl*1e9, color='r', linestyle='--', alpha=0.3)
432
433
# Peak finding and identification
434
peaks, properties = find_peaks(I_total, height=0.01, distance=50)
435
peak_wavelengths = wavelength_scale[peaks]
436
peak_intensities = I_total[peaks]
437
438
axes[1, 1].scatter(peak_wavelengths, peak_intensities, c='red', s=50)
439
axes[1, 1].set_xlabel('Wavelength (nm)')
440
axes[1, 1].set_ylabel('Peak Intensity')
441
axes[1, 1].set_title('Detected Peaks')
442
axes[1, 1].grid(True, alpha=0.3)
443
axes[1, 1].set_xlim([400, 700])
444
445
# Annotate peaks
446
for i, (wl, intensity) in enumerate(zip(peak_wavelengths, peak_intensities)):
447
if 400 < wl < 700:
448
axes[1, 1].annotate(f'{wl:.1f}', (wl, intensity),
449
textcoords="offset points", xytext=(0, 10),
450
ha='center', fontsize=7)
451
452
plt.tight_layout()
453
save_plot('spectroscopy_application.pdf',
454
'Spectroscopy application showing emission line identification.')
455
456
# Count identified peaks
457
n_peaks_found = len([wl for wl in peak_wavelengths if 400 < wl < 700])
458
\end{pycode}
459
460
\section{Results Summary}
461
462
\subsection{Grating Specifications}
463
\begin{pycode}
464
print(r'\begin{table}[htbp]')
465
print(r'\centering')
466
print(r'\caption{Grating Parameters and Performance}')
467
print(r'\begin{tabular}{lc}')
468
print(r'\toprule')
469
print(r'Parameter & Value \\')
470
print(r'\midrule')
471
print(f'Grating period & {d*1e6:.2f} $\\mu$m \\\\')
472
print(f'Lines per mm & {1/(d*1e3):.0f} \\\\')
473
print(f'Number of lines illuminated & {N} \\\\')
474
print(f'Resolving power (1st order) & {N} \\\\')
475
print(f'Required N for Na D-lines & {N_required} \\\\')
476
print(f'Angular dispersion (1st order) & {1e9/(d*np.cos(np.arcsin(550e-9/d))):.2f} nm/rad \\\\')
477
print(r'\bottomrule')
478
print(r'\end{tabular}')
479
print(r'\end{table}')
480
\end{pycode}
481
482
\subsection{Emission Lines Detected}
483
\begin{pycode}
484
print(r'\begin{table}[htbp]')
485
print(r'\centering')
486
print(r'\caption{Emission Line Identification}')
487
print(r'\begin{tabular}{lcc}')
488
print(r'\toprule')
489
print(r'Line & Wavelength (nm) & First Order Angle \\')
490
print(r'\midrule')
491
492
for name, wl in emission_lines.items():
493
angle = np.rad2deg(np.arcsin(wl / d))
494
print(f'{name} & {wl*1e9:.1f} & {angle:.2f}$^\\circ$ \\\\')
495
496
print(r'\bottomrule')
497
print(r'\end{tabular}')
498
print(r'\end{table}')
499
\end{pycode}
500
501
\section{Statistical Summary}
502
Key diffraction grating results:
503
\begin{itemize}
504
\item Grating lines per mm: \py{f"{1/(d*1e3):.0f}"}
505
\item Resolving power (N=1000): \py{f"{N}"}
506
\item Minimum resolvable wavelength difference: \py{f"{550/N:.3f}"} nm
507
\item Required N for sodium D-lines: \py{f"{N_required}"}
508
\item Blaze angle for 550 nm: \py{f"{np.rad2deg(np.arcsin(550e-9/d)):.2f}"}$^\circ$
509
\item Spectral peaks identified: \py{f"{n_peaks_found}"}
510
\end{itemize}
511
512
\section{Conclusion}
513
This computational analysis demonstrates the principles of diffraction grating spectroscopy.
514
The resolving power scales linearly with the number of illuminated grating lines, enabling
515
high-resolution spectral analysis. Blazed gratings concentrate diffracted energy into specific
516
orders, improving efficiency. The grating equation provides accurate wavelength calibration
517
for spectroscopic measurements. These techniques are fundamental to atomic spectroscopy,
518
astronomical observations, and analytical chemistry applications.
519
520
\end{document}
521
522