Homework #2
EE 541: Fall 2025
Assigned: 08 September
Due: Sunday, 14 September at 23:59
BrightSpace Assignment: Homework 2
Getting Started Guide: View Guide Data: External Link
Problem 1: Peak Finding
You may use any standard NumPy
or SciPy
packages or experiment with your own algorithms for this problem.
Raman spectroscopy is a technique that uses inelastic scattering of light to identify unknown chemical substances. Spectral “peaks” indicate vibrational and rotational modes and are of special importance because they act like a chemical fingerprint. Raman spectroscopy measures photon intensity vs. Raman shift. The Raman shift relates the frequencies of the exciting laser and the scattered photons and is often reported as a wavenumber – the frequency difference in wavelengths per cm (i.e., cm\(^{-1}\)).
Generate a molecular fingerprint using the spectroscopic data in raman.rod
. The file contains intensity vs. wavenumber data for an unknown chemical sample. A Raman Open Database (ROD
) file includes content in addition to the raw intensity data:
# content
more content
_raman_spectrum.intensity
wavenumber1 intensity1
wavenumber2 intensity2
...
wavenumbern intensityn
Use string matching to ignore all lines before _raman_spectrum.intensity
. Load valid (wavenumber, intensity)
pairs until the first invalid intensity line (or upon reaching the end of file).
Use the method below to estimate the wavenumbers of all spectral peaks.
First detect peaks in the raw spectral data. Use the peak locations to focus on regions of interest within the spectrum. For instance: if you detect peaks at \(x_1\) cm\(^{-1}\) and \(x_2\) cm\(^{-1}\) use regions of interest: \([x_1 - n_1, x_1 + n_1]\) and \([x_2 - n_2, x_2 + n_2]\). Experiment to find “good” widths \(n_1\), \(n_2\), etc. Then use a spline to interpolate intensity within each region of interest. Calculate zero-crossings of the derivative to estimate wavenumbers with maximum intensity.
Print the wavenumber estimates for the eight largest spectral peak to STDOUT sorted by magnitude (largest first).
Create a figure that shows the Raman data (intensity vs. wavenumber) and mark each of the maximum intensity values.
Produce a “zoomed-in” figure for the “regions of interest” corresponding to the four largest peaks. Plot the raw spectral data and overlay your interpolating function. Use a marker to show the wavenumber with maximal intensity.
Problem 2: Gibbs Sampler
Use only Python standard library modules, numpy
, and matplotlib
for this problem.
A Gibbs sampler generates samples from a joint probability distribution by iteratively sampling each variable conditioned on the others. In this problem, you will implement Gibbs sampling to analyze the 2-dimensional Ising model, which represents a lattice of binary spins interacting with nearest neighbors. This model is used in statistical physics to study phase transitions and collective behavior arising from local spin interactions.
Implement a Gibbs sampler for a \(N = 20\) grid (i.e. \(20 \times 20\)) where each site has state \(s_i \in \{-1, +1\}\). The system energy is: \[E(\mathbf{s}) = -\sum_{\langle i,j \rangle} s_i s_j\] where the sum is over nearest-neighbor pairs. The probability of a configuration is: \[P(\mathbf{s}) \propto \exp(-\beta E(\mathbf{s}))\] Initialize the grid randomly and store the initial state.
Run the sampler for \(\beta = \{0.2, 0.4, 0.6\}\). For each site update: \[P(\text{flip}) = \frac{1}{1 + \exp(\beta\Delta E_i)},\] where \(\Delta E_i = \text{energy change if site } i \text{ flips}\). Record the energy after every 10 iterations for 1000 total iterations. Create a figure showing \(E(\mathbf{s})\) versus iteration number for each \(\beta\).
Calculate the average magnetization: \[M = \frac{1}{N^2} \sum_{\langle i,j \rangle} s_i.\] Plot \(M\) versus iteration number. Create visualizations of the grid state at iterations \(\{0, 100, 500, 1000\}\) using:
='binary') plt.imshow(grid, cmap plt.colorbar()f'state_{beta}_{iter}.png') plt.savefig(
Problem 3: Root Finding
Use only Python standard library modules (https://docs.python.org/3/library/) and matplotlib
for this problem, i.e. do not import numpy
, scikit
, or any other non-standard package.
The secant method is an iterative root-finding algorithm. It uses a sequence of secant line roots to approximate \(c\) such that \(f(c) = 0\) for a continuous function \(f\). Unlike Newton’s method it does not require knowledge or evaluation of the derivative \(f'\). The secant method is defined by the recurrence:
\[x_n = x_{n-1} - f(x_{n-1}) \frac{x_{n-1} - x_{n-2}}{f(x_{n-1}) - f(x_{n-2})}.\]
Write a python script that uses the secant method to approximate the root of a continuous function \(f\) in the interval \([a, b]\). You may assume that \(f\) has at most one root in \([a,b]\). Use \(|x_{k+1} - x_{k}| < 10^{-10}\) as the convergence criterion. Let \(N\) be the number of iterations to reach convergence. Output \(N\) followed by the three root approximations \(x_{N-2}\), \(x_{N-1}\), \(x_N\). Output each number to its own line and use precision sufficient to show convergence.
Import the function \(f\) from a file named func.py
in the same directory as your script – i.e. from func import f
. You may assume that \(f\) is continuous on \([a,b]\) and that func.f(x)
returns a scalar float for all \(x \in [a,b]\).
Your script should accept a
and b
as two numeric command line arguments, i.e. python hw2p3.py "1.1" "1.4"
. Your script must validate that a
and b
are numeric, verify that a < b
, and check that f(a)f(b) < 0
– see Bolzano’s Theorem. Write “Range error
” to STDERR
(standard error) if any of these three conditions fail and immediately terminate.
Your script should not produce any output except as described above.
Problem 1: Peak Finding
Submit the wavenumber estimates, intensity vs. wavenumber figure, and zoomed-in figures to BrightSpace. Submit your Python code as an appendix to Gradescope. A suitably annotated Jupyter notebook with inline analysis is sufficient.
Gradescope: Problem 1
Problem 2: Gibbs Sampler
Submit energy and magnetization plots and grid state visualizations to BrightSpace. Submit your Python code as an appendix to Gradescope. A suitably annotated Jupyter notebook with inline analysis is sufficient.
Gradescope: Problem 2
Problem 3: Root Finding
Submit your Python script to Gradescope. Ensure your script produces output exactly as specified. No other submission required.
Gradescope: Problem 3