The related publication is: https://www.nature.com/articles/s41598-023-50089-1. Please cite it if you use this code!
[This Readme documentation was written with AI.]
NetMAP is an algebraic framework, developed in the Aleman lab, designed for the rapid characterization of mechanical resonator networks (monomers, dimers, and higher-order systems). It allows researchers to extract physical parameters—such as mass (
This code is developed by the Horowitz Lab at Hamilton College.
Characterizing nanomechanical or micromechanical resonators often requires fitting complex models to frequency sweeps. NetMAP simplifies this by transforming the differential equations of motion into a linear system
By applying Singular Value Decomposition (SVD) to the Z-matrix, the system's physical constants can be recovered from the nullspace, even in the presence of experimental noise.
- Algebraic Parameter Recovery: No need for "guesses" or iterative fitting; parameters are recovered through direct matrix decomposition.
- Support for Coupled Systems: Specifically designed to handle coupled resonators (e.g., graphene drums or cantilever arrays) where traditional peak-fitting fails due to overlapping modes.
- Noise Robustness: Evaluates recovery accuracy across 1D, 2D, and 3D nullspace assumptions to find the most stable physical solution.
- Validation: Includes a
simulated_experimentsuite to validate the framework against "ground truth" models with controlled noise injection.
Zmat(): The primary engine for constructing the Z-matrix from Pandas DataFrames containing frequency, amplitude, and phase data.- Monomer & Dimer Logic: Dedicated matrix construction for single oscillators or two-resonator coupled systems.
- Normalization Tools: Functions to scale relative SVD results into absolute physical units (kg, N/m, N s/m) based on a known reference (like a known driving force or mass).
This codebase is used for validating algebraic approaches to characterizing resonator networks, as described in:
Horowitz et al., "Validating an algebraic approach to characterizing resonator networks," Scientific Reports 14, 1325 (2024).
numpypandasmatplotlibscipy
- Load your frequency sweep data into a DataFrame.
- Pass the data to
Zmat()to generate the Z-matrix. - Perform SVD (
np.linalg.svd) to identify the parameter ratios. - Normalize the result using
normalize_parameters_1d_by_force(or similar) to extract final$m, b, k$ values.
NetMAP (Network Mapping and Analysis of Parameters) converts the physics of mechanical oscillators into a linear algebra problem. The process follows these specific mathematical steps:
For any linear resonator system (monomer, dimer, or
- M: Mass matrix
- B: Damping matrix
- K: Stiffness (spring constant) matrix
- F: Driving force vector
We assume a steady-state solution where the displacement of each resonator
To solve for unknown physical parameters using real-numbered matrices, we define the complex amplitude as
-
Real Equation:
$-m_1\omega^2X_1 - b_1\omega Y_1 + k_1X_1 - f = 0$ -
Imaginary Equation:
$-m_1\omega^2Y_1 + b_1\omega X_1 + k_1Y_1 = 0$
By collecting data at multiple frequencies (
For a monomer, the system looks like this:
-
Singular Value Decomposition (SVD): We perform SVD on the Z-matrix. The right-singular vector associated with the smallest singular value represents the "best fit" for the parameter vector
$p$ . -
Scaling: SVD identifies the ratios between parameters (e.g.,
$k/m$ or$b/m$ ). To find absolute values, we multiply the entire vector by a scaling factor derived from one known reference value, such as the actual mass ($m_1$ ) or the known driving force ($f$ ).
The simulated_experiment() function is a comprehensive validation tool for the NetMAP framework. It performs "end-to-end" testing by generating synthetic resonance data (with controlled noise), applying the NetMAP Singular Value Decomposition (SVD) recovery process, and statistically comparing the recovered physical parameters against the original "ground truth" values. This was the essential tool for the validation in the paper https://www.nature.com/articles/s41598-023-50089-1.
This function simulates a physical measurement of a resonator (monomer or dimer), introduces noise, and attempts to solve the inverse problem—extracting mass (
| Parameter | Type | Description |
|---|---|---|
measurementfreqs |
list/array | The specific frequencies ( |
vals_set |
list | The "ground truth" parameters: |
noiselevel |
float | Magnitude of Gaussian noise added to the complex amplitude. |
MONOMER |
bool |
True for a single resonator; False for a coupled dimer. |
forceboth |
bool | If True, applies the driving force to both masses in a dimer. |
repeats |
int | Number of simulation iterations (useful for Monte Carlo error analysis). |
verbose |
bool | If True, prints detailed recovery statistics and SVD descriptions. |
demo |
bool | If True, formats plots for presentation (removes axis ticks). |
-
Spectrum Generation: Calculates a noiseless baseline using
calculate_spectra(). -
Noise Injection: Applies Gaussian noise to the complex amplitude response based on the
noiselevel. -
Z-Matrix Construction: Calls
Zmat()(see below) to build the linear system of equations based on the "noisy" measurement points. -
SVD Recovery: * Performs Singular Value Decomposition on the Z-matrix.
- Identifies the singular vector corresponding to the smallest singular value (the suspected solution).
-
Normalization & Scaling: Since SVD returns relative ratios, the function normalizes the vector using three different strategies:
-
1D: Normalizes based on the known force (
$F_{set}$ ). -
2D: Normalizes assuming two known parameters (e.g.,
$m_1$ and$F_{set}$ ). - 3D: Normalizes assuming three known parameters.
-
1D: Normalizes based on the known force (
-
Error Analysis:
- Calculates the Systematic Error (
syserr) for every individual parameter. - Calculates
$R^2$ values to determine how well the recovered model reconstructs the observed data.
- Calculates the Systematic Error (
-
Visualization: If
verboseis enabled, it callsplot_SVD_results()to overlay the recovered model onto the noisy data points.
The function primarily populates the results and theseresults_cols lists. These results include:
-
Recovered Parameters: Values for
$M, B, K,$ and$F$ for all normalization dimensions (1D, 2D, 3D). - Error Metrics: Mean, RMS, and Max systematic errors for the recovery.
- Spectral Data: Signal-to-Noise Ratios (SNR) at each measurement frequency.
-
describeresonator(): Utility to print a summary of the physical system's properties (Quality factor$Q$ , peak width, etc.). -
measurementdfcalc(): Organizes raw frequency/amplitude/phase data into a formatted DataFrame for matrix processing. -
compile_rsqrd(): Calculates the goodness-of-fit for the recovered model in both polar and Cartesian coordinates.
This function is essential for determining the robustness of NetMAP. By sweeping the noiselevel or varying the measurementfreqs (e.g., placing them on or off resonance), researchers can determine the optimal experimental conditions required to recover physical constants with high accuracy. See our publication in Scientific Reports.
This notebook serves as the primary demonstration and validation tool for the NetMAP framework. It implements a complete "simulated experiment" workflow for a dimer system—two mechanical resonators coupled together—to prove that physical parameters can be recovered algebraically from noisy frequency response data.
The goal of this notebook is to demonstrate that the NetMAP (Network Mapping and Analysis of Parameters) can accurately identify physical constants (mass, damping, stiffness, and coupling) of a dimer system by solving a linear system of equations. By using synthetic data, the "recovered" values can be compared against known "ground truth" inputs to calculate systematic error.
The notebook relies on transforming the coupled equations of motion into a linear system
By measuring the complex amplitude response at specific frequencies, the notebook populates a Z-matrix and uses Singular Value Decomposition (SVD) to find the parameter vector
The notebook defines the "True" physical parameters for the two resonators.
-
Physical Constants: Sets
$m_1, m_2, b_1, b_2, k_1, k_2, k_{12}$ and the driving force$F$ . -
System Characteristics: Calculates expected Quality Factors (
$Q$ ) and resonance frequencies to ensure the simulation represents a physically realistic system.
Using the calculate_spectra() function, the notebook generates the frequency response for both resonators.
- Noise Injection: Gaussian noise is added to the complex amplitudes to simulate experimental measurement error.
- Frequency Selection: The notebook identifies the resonance peaks to ensure that "measurement" points are selected from the most informative parts of the spectrum (highest Signal-to-Noise ratio).
The code calls Zmat() to build the algebraic representation.
- Dimensionality: For each frequency point, four rows are added to the matrix (the real and imaginary components for both Resonator 1 and Resonator 2).
-
Nullspace Mapping: The columns are mapped to
$[m_1, m_2, b_1, b_2, k_1, k_2, k_{12}, F_1]$ .
The core mathematical step of NetMAP:
-
SVD Execution: Performs
np.linalg.svd(Zmatrix). - Vector Extraction: Selects the right-singular vector associated with the smallest singular value (the solution closest to the nullspace).
-
Normalization: Since SVD returns relative ratios, the notebook scales the vector using a known reference (usually the driving force
$F$ or mass$m_1$ ) to return values in absolute physical units.
The final cells evaluate the success of the recovery:
- Systematic Error Analysis: Calculates the percent difference between the input "ground truth" and the SVD-recovered values.
- Graphical Verification: Uses
plot_SVD_results()to overlay the recovered model's predicted spectrum onto the noisy data points.
Users can modify the following to test the framework's limits:
-
noiselevel: Adjusts the magnitude of complex amplitude noise. -
k12_set: Modifies the coupling strength (testing weak vs. strong coupling). -
measurementfreqs: Changes the number and location of data points used to build the$Z$ matrix.
NetMAP.py: Core logic for matrix construction.resonatorsimulator.py: Logic for generating synthetic spectra.resonatorfrequencypicker.py: Automated peak detection.resonator_plotting.py:
In the NetMAP framework, the Z-Matrix is the linear algebraic representation of the system's equations of motion. These functions construct the matrix used for Singular Value Decomposition (SVD) or linear least-squares fitting to extract physical parameters (mass, damping, stiffness) from experimental frequency response data.
The primary entry point. This wrapper function directs the data to either the Monomer or Dimer (2-resonator) matrix generator based on the system configuration.
| Parameter | Description |
|---|---|
measurementdf |
Pandas DataFrame containing experimental sweeps. |
MONOMER |
Boolean. If True, uses the single-oscillator model. |
forceboth |
Boolean. Relevant for dimers; indicates if both masses are driven. |
frequencycolumn |
Column name for the driving frequency ( |
complexamplitudeX |
Column names for the complex response ( |
Generates the Z-matrix for a Dimer system. For every frequency point provided, it generates four rows in the matrix (Real/Imaginary components for both Resonator 1 and Resonator 2).
Matrix Structure:
The columns correspond to the following physical parameters:
Logic:
-
Driving Force: If
forcebothisFalse, only$m_1$ is driven ($F_1$ affects$R_1$ ). IfTrue, a coupling factorffis applied to the$R_2$ equations to account for the second drive. -
Coupling: The
$k_{12}$ column accounts for the relative displacement$(ZZ_1 - ZZ_2)$ .
Mathematical Basis (per frequency
Generates the Z-matrix for a Monomer system. For every frequency point, it generates two rows (Real and Imaginary).
Matrix Structure:
The columns correspond to:
Row Construction:
-
Real Row:
$[- \omega^2 \cdot \text{Re}(Z), -\omega \cdot \text{Im}(Z), \text{Re}(Z), -1]$ -
Imaginary Row:
$[- \omega^2 \cdot \text{Im}(Z), \omega \cdot \text{Re}(Z), \text{Im}(Z), 0]$
| System Type | Columns (Parameters) | Rows per Frequency Point |
|---|---|---|
| Monomer | 2 | |
| Dimer | 4 |
import numpy as np
# Assuming 'df' contains your resonance sweep data
z_matrix = Zmat(df, MONOMER=False, forceboth=True)
# Use SVD to solve for the physical parameters (p)
# Z * p = 0 -> The nullspace contains the parameter ratios
u, s, vh = np.linalg.svd(z_matrix)
parameters = vh[-1, :] # The last row of vh is the solutionThe res_freq_numeric() function identifies resonance peak frequencies for physical systems (monomers or dimers) using numerical methods. It combines analytical weak-coupling approximations with iterative peak-finding on amplitude and phase curves.
This function calculates the resonant frequencies of a mechanical or electrical system. While optimized for dimer systems (two coupled oscillators), it also supports monomer systems. It uses an iterative refinement process to find peaks in amplitude response and specific crossings in phase response (e.g.,
| Parameter | Type | Description |
|---|---|---|
vals_set |
dict/list | Parameters for the system (mass, damping, stiffness). |
MONOMER |
bool | If True, treats the system as a single oscillator. |
forceboth |
bool | Boolean flag passed to underlying curve functions to dictate forcing conditions. |
mode |
str | Method to find peaks: 'all' (default), 'amplitude', or 'phase'. |
minfreq / maxfreq |
float | The frequency range to search within. Defaults: 0.1 to 5. |
numtoreturn |
int/None | Specific number of frequencies to return. If None, returns all found. |
iterations |
int | Number of times to refine the frequency mesh around suspected peaks. |
unique / veryunique |
bool | If True, filters out duplicate or near-identical frequencies. |
verbose / verboseplot |
bool | Enables console logging and Matplotlib visualization of peaks. |
-
Parameter Extraction: Reads physical constants (
$m, b, k, F$ ) usingread_params(). -
Initial Approximation: Uses
res_freq_weak_coupling()to find a starting point for the search. -
Mesh Refinement: * Generates a frequency list (
morefrequencies).- Iteratively zooms in on frequencies where peaks are detected to improve precision.
-
Signal Calculation: Generates Amplitude (
curve1,curve2) and Phase (theta1,theta2) data across the mesh. -
Peak Detection: * Amplitude: Uses
find_peaksto locate local maxima.-
Phase: Uses
find_freq_from_angleto locate resonant phase shifts ($\pm\pi/2$ ).
-
Phase: Uses
-
Selection & Filtering: * If
veryuniqueis active, it compares close peaks and keeps the one with the higher amplitude.- If
numtoreturnis set (e.g., to 2), the function logic forces a selection of the most prominent peaks or pads the result with a frequency at a specific phase (-3π/4) if not enough peaks are found.
- If
- freqlist (
listoffloat): A sorted list of identified resonant frequencies. - option_code (
int, optional): Ifreturnoptions=True, returns an integer indicating which internal logic path (1–11) was used to finalize the list.
# Find the two primary resonance peaks for a dimer system
frequencies = res_freq_numeric(my_params, MONOMER=False, forceboth=True, numtoreturn=2)
print(f"Resonant Frequencies: {frequencies}")