Flying Nimbus

Flying Nimbus is a command-line Python tool for turning molecular dynamics trajectories into vibrational spectra.

It is designed for workflows where you already have:

  • an equilibrium geometry in XYZ format,

  • a Hessian or a previously exported hessian eigenvectors matrix (cnorm.dat),

  • and a trajectory containing positions and velocities,

and you want to compute one or more of the following:

  • time-averaged (TA) spectra,

  • correlation-function + Fourier-transform spectra,

  • mode-resolved spectra in normal-mode space,

  • Cartesian velocity autocorrelation spectra,

  • optional CSV exports for spreadsheet tools,

  • and optional PNG plots for quick inspection.

The current implementation lives in a single script, flying_nimbus.py.


Table of Contents


What Flying Nimbus does

Flying Nimbus analyzes MD trajectories using either:

  1. normal-mode coordinates derived from a Hessian, or

  2. Cartesian velocities directly.

In normal-mode mode, the script projects the trajectory onto the normal-mode basis and can compute:

  • cpp correlations and spectra from projected velocities,

  • cqq correlations and spectra from projected coordinates,

  • time-averaged mode-resolved spectra,

  • or correlation + FT mode-resolved spectra.

In Cartesian mode, the script computes the velocity autocorrelation and writes:

  • the Cartesian correlation function (cvv),

  • a Cartesian FT autocorrelation spectrum,

  • or a Cartesian TA spectrum.

The tool is especially useful when you want:

  • mode-specific vibrational analysis from trajectory data,

  • atom-projected contributions,

  • outputs that can be plotted quickly,

  • or spreadsheet-friendly numeric exports.


Core workflow

A typical Flying Nimbus run looks like this:

  1. Read the equilibrium geometry from --xyz.

  2. Determine nat either from -N/--nat or from the first line of the XYZ file.

  3. Assign atomic masses using either:

    • the internal mass database, or

    • a fifth column in the XYZ atom lines.

  4. Build the normal-mode basis by either:

    • reading the Hessian and diagonalizing the mass-weighted Hessian, or

    • reading an existing cnorm.dat.

  5. Read the trajectory from --traj.

  6. Optionally discard early MD steps with --nstart.

  7. Choose one of two coordinate systems:

    • --coord nm for normal-mode analysis,

    • --coord cart for Cartesian analysis.

  8. Choose one of two strategies:

    • TA mode (default), or

    • autocorrelation mode via --no-ta.

  9. Write .dat outputs, and optionally CSV and PNG files.

That makes Flying Nimbus a post-processing tool that sits naturally after geometry/Hessian preparation and trajectory generation.


Features at a glance

Capability

Supported

Read masses from XYZ fifth column

Yes

Fall back to internal masses

Yes

Build cnorm from Hessian

Yes

Reuse existing cnorm.dat

Yes

Normal-mode analysis

Yes

Cartesian analysis

Yes

Time-averaged spectra

Yes

Correlation + FT spectra

Yes

Mode selection

Yes

Atom subset selection (Atom-Wise Spectra)

Yes

CSV export

Yes

Merged multi-mode CSV export

Yes

PNG plot export

Yes

Frequency-axis offset

Yes

Per-spectrum max normalization

Yes


Requirements

Required Python packages

  • numpy

Optional package

  • matplotlib — only needed if you use --plot

Standard-library modules used

  • argparse

  • csv

  • math

  • re

  • dataclasses

  • pathlib

  • typing

Python version

Any modern Python 3 version that supports dataclasses, type annotations, pathlib, and numpy should work.


Installation

Clone the repository

git clone https://github.com/giacomande95-oss/FLYINGNIMBUS_GUI.git
cd flying_nimbus

Create and activate a virtual environment

python -m venv .venv
source .venv/bin/activate

Install dependencies

pip install numpy matplotlib

If you do not need PNG plots, numpy is enough for core functionality.

Check the CLI

python flying_nimbus.py --help

Quick start

Correlation + FT mode (Legacy Mode)

python flying_nimbus.py \
  --xyz geom.xyz \
  --hess Hessian_flat.out \
  --traj traj.xyz \
  --modes 3 4 5 \
  --no-ta

This writes both correlation functions and FT spectra for the selected modes.

Cartesian spectrum

python flying_nimbus.py \
  --xyz geom.xyz \
  --hess Hessian_flat.out \
  --traj traj.xyz \
  --coord cart

Reuse an existing cnorm.dat

python flying_nimbus.py \
  --xyz geom.xyz \
  --traj traj.xyz \
  --readcnorm 1 \
  --cnorm cnorm.dat \
  --modes 2 7 8

General command syntax

The general form is:

python flying_nimbus.py --xyz <geometry.xyz> --traj <trajectory.xyz> [options]

Normal-mode analysis usually looks like:

python flying_nimbus.py \
  --xyz <geometry.xyz> \
  --hess <hessian_file> \
  --traj <trajectory.xyz> \
  --modes <mode1> [mode2 mode3 ...]

Cartesian analysis usually looks like:

python flying_nimbus.py \
  --xyz <geometry.xyz> \
  --hess <hessian_file> \
  --traj <trajectory.xyz> \
  --coord cart

If --readcnorm 1 is used, --hess is no longer required.


What the program expects as input

Equilibrium geometry (--xyz)

The XYZ file is required in every run.

The script expects standard XYZ layout:

N
comment line
Atom1   x   y   z
Atom2   x   y   z
...

It also supports an optional fifth column on each atom line that provides the atomic mass in atomic units:

3
water with explicit masses
O   0.000000   0.000000   0.000000   29156.96
H   0.758602   0.000000   0.504284    1837.15
H  -0.758602   0.000000   0.504284    1837.15

This is important when:

  • you are using an element not present in the internal mass table,

  • or you want to override the built-in masses.

The first line is also used to auto-detect nat when -N/--nat is omitted or set to 0.

Hessian (--hess)

The Hessian is required when --readcnorm 0.

The implementation expects:

  • two header lines at the top of the file,

  • followed by lower-triangle Hessian values,

  • read as a single column

The script reconstructs a full symmetric 3N × 3N matrix from those lower-triangle values.

The parser is flexible about whitespace and accepts Fortran-style D exponents.

Trajectory (--traj)

The trajectory must be an extended XYZ trajectory containing, for each atom:

  • element symbol,

  • x y z,

  • vx vy vz.

Each frame is read as:

N
comment line
Atom1   x   y   z   vx   vy   vz
Atom2   x   y   z   vx   vy   vz
...

Important notes:

  • Positions are assumed to be in Ångström and velocities in bohr.

  • The file must contain complete frames with exactly nat atom lines per frame.

cnorm.dat reuse (--readcnorm 1)

When you run with:

--readcnorm 1 --cnorm cnorm.dat

the script skips Hessian diagonalization and instead loads the normal-mode basis from cnorm.dat.

The current implementation supports:

  1. the script’s own cnorm.dat layout, and

  2. a fallback numeric layout labeled in the code as a legacy or alternate path.

This is useful when you want to:

  • run multiple analyses without repeatedly diagonalizing the Hessian,

  • keep a fixed normal-mode basis across repeated runs.


How Flying Nimbus works internally

Mass assignment

The script first reads symbols and masses from the equilibrium XYZ.

Masses are assigned as follows:

  1. If a fifth column is present and numeric, that value is used.

  2. Otherwise the script looks up the symbol in its internal mass database.

  3. If the symbol is not present and no mass is provided, the run fails.

Building or loading the normal-mode basis

There are two paths.

Path A: compute from Hessian

When --readcnorm 0 (the default):

  1. The lower-triangle Hessian is read and reconstructed.

  2. The Hessian is mass-weighted.

  3. The Hessian is diagonalized.

  4. The eigenpairs are reordered so that vibrational modes come first and roto-translational modes are moved to the end.

  5. A cnorm.dat file is written.

By design, the script writes cnorm.dat during this path. If the target file already exists, the run stops unless you pass:

--rm-cnorm

Path B: read from cnorm.dat

When --readcnorm 1, the script reads:

  • the normal-mode matrix,

  • and the eigenvalue-derived deltaq data,

from the cnorm.dat file itself.

Trajectory reading and unit handling

The trajectory is read frame-by-frame from extended XYZ.

Internally:

  • positions are stored as a NT × 3N array (NT being the number of steps),

  • velocities are stored as a NT × 3N array (NT being the number of steps),

  • positions are converted from Å to bohr,

  • velocities are left numerically unchanged by the current version.

The script then discards the first nstart - 1 frames.

Normal-mode projection

In normal-mode execution, the code projects both:

  • the velocity series v, and

  • the coordinate series x,

into the normal-mode basis.

Before projection, each Cartesian degree of freedom is multiplied by sqrt(mass), so the projection is performed in a mass-weighted way.

If --atoms is used in normal-mode mode, a Cartesian mask is applied before projection. This means only the selected atoms contribute to the projected signal.

Correlation vs time-averaged spectra

Flying Nimbus implements two strategies, that in first approximation differ in the function that is Fourier transformed.

TA mode (default)

If you do nothing, TA is enabled.

For normal-mode analysis:

  • TA-cpp is built from the projected velocity-like mode amplitudes,

  • TA-cqq is built from the projected coordinate-like mode amplitudes.

For Cartesian analysis:

  • a TA Cartesian spectrum is built directly from the selected Cartesian velocity series.

Correlation mode

If you pass --no-ta, the script instead computes correlations and then Fourier transforms them.

For normal-mode analysis:

  • cpp is the mode-resolved correlation built from projected velocities,

  • cqq is the mode-resolved correlation built from projected coordinates,

  • each is Fourier transformed to produce FT-cpp and FT-cqq spectra.

For Cartesian analysis:

  • a Cartesian cvv correlation is computed,

  • then Fourier transformed to FT-cvv_cartesian.

Frequency grid construction

The printed frequency axis is controlled by:

  • --init-wnumb

  • --spec-res

  • --wnumb-span

The number of frequency points is computed internally as:

nf = int(wnumb_span / spec_res)

So the output grid is:

init_wnumb + i * spec_res,  for i = 0 .. nf-1

This means the upper edge is controlled by integer truncation. If wnumb_span is not an exact multiple of spec_res, the last printed point will be below the nominal span limit.


Coordinate systems

Normal-mode mode (--coord nm)

This is the default mode.

You must provide:

--modes ...

Mode indices are:

  • 1-based,

  • interpreted as vibrational mode indices,

  • and must lie between 1 and nvib = 3N - nrototrasl.

In this mode the script can generate:

  • cpp correlations and spectra,

  • cqq correlations and spectra,

  • TA mode spectra,

  • CSV exports per mode,

  • merged CSV files across multiple modes,

  • and PNG plots.

Cartesian mode (--coord cart)

This mode skips mode selection and works directly in Cartesian velocity space.

In this mode:

  • --modes is not used,

  • atom selection still works,

  • the output is a single Cartesian correlation/spectrum rather than one file per mode.

This is the right choice when you want a global or atom-projected velocity-autocorrelation-style spectrum without decomposing into normal modes.


Detailed CLI reference

System and structure options

-N, --nat

Number of atoms.

Default:

0

Behavior:

  • if 0, the script reads nat from the first line of --xyz.

  • if positive, that explicit value is used.

Example:

python flying_nimbus.py --xyz geom.xyz --traj traj.xyz --hess Hessian.out -N 24 --modes 1

--nrototrasl

Number of rotational + translational modes to exclude from the vibrational count.

Default:

6

Use 5 for linear molecules.

Example:

python flying_nimbus.py --xyz co2.xyz --traj co2_traj.xyz --hess hess.dat --modes 1 2 3 --nrototrasl 5

Time and sampling options

--nstart

First MD step to use, 1-based.

Default:

1

The script discards the first nstart - 1 frames.

--ncorr

Length of the correlation window.

Default:

2500

This affects both TA and correlation-based branches because it defines how many time points are used in the spectral transform.

--nbeads

Number of time origins.

Default:

0

Behavior:

  • 0 means automatic: the script uses as many origins as possible given ncorr and trajectory length.

--nbeadsstep

Stride between time origins.

Default:

1

Use values larger than 1 to thin the set of time origins.

--dt

Time step in atomic units.

Default:

8.2682749151502

This value is used directly in the correlation and FT machinery. The script does not infer it from the trajectory file.

Spectral-grid options

--init-wnumb

Initial wavenumber in cm^-1.

Default:

0

--spec-res

Spectral resolution in cm^-1.

Default:

1

--wnumb-span

Total spectral span in cm^-1.

Default:

5000

Example:

python flying_nimbus.py \
  --xyz geom.xyz --traj traj.xyz --hess Hessian.out \
  --modes 2 3 4 \
  --init-wnumb 500 --spec-res 2 --wnumb-span 3500

Analysis mode options

--coord {nm,cart}

Select analysis in:

  • nm = normal-mode space,

  • cart = Cartesian space.

Default:

nm

--no-ta

Disable time-averaged spectra and switch to correlation + FT mode.

Default behavior without this flag: TA is on.

Damping options

These are only relevant in the --no-ta branch.

--alpha-pow

Gaussian damping applied to cpp correlations.

Default:

0.0

--alpha-dip

Gaussian damping applied to cqq correlations.

Default:

1e-8

Example:

python flying_nimbus.py \
  --xyz geom.xyz --traj traj.xyz --hess Hessian.out \
  --modes 5 6 --no-ta \
  --alpha-pow 1e-8 --alpha-dip 1e-8

Selection options

--modes

List of 1-based vibrational mode indices.

Required when --coord nm.

Examples:

--modes 1
--modes 3 4 5 6

--atoms

List of 1-based atom indices to include.

Default: all atoms.

Examples:

--atoms 1 2 3
--atoms 5 8 9 10

Behavior differs slightly by coordinate system:

  • in nm mode, selected atoms contribute through a Cartesian mask before projection;

  • in cart mode, only selected atoms are used in the Cartesian velocity series.

If you explicitly provide all atoms, the script treats that as equivalent to no selection.

Input/output options

--xyz

Required equilibrium geometry file.

--hess

Hessian file.

Required unless:

--readcnorm 1

--traj

Required extended XYZ trajectory with positions and velocities.

--readcnorm {0,1}

Choose whether to:

  • 0: compute cnorm from the Hessian,

  • 1: read cnorm.dat instead.

Default:

0

--cnorm

Path to the cnorm.dat file.

Default:

cnorm.dat

-o, --output

Root output prefix.

Default:

QCT_

Example:

-o water_

--freq-offset

Shift the printed output wavenumber axis by this offset in cm^-1.

Default:

0.0

This changes the written x-axis values, not the underlying trajectory itself.

--norm1

Normalize each printed spectrum so its maximum is 1.

This is applied independently per spectrum.

--rm-cnorm

If the script is about to write cnorm.dat and that file already exists, remove it first.

Without this flag, an existing cnorm.dat causes the run to stop with a file-exists error.

Plotting and spreadsheet export

--plot

Save PNG plots of the spectra.

--plot-dir

Directory where PNG plots are written.

Default:

.

--plot-dpi

PNG resolution.

Default:

200

--excel

Also write spreadsheet-friendly CSV or TSV output without comment headers.

--excel-sep

Delimiter used for spreadsheet export.

Default:

,

Useful values include:

  • ,

  • ;

  • tab

--excel-merge

In normal-mode runs with multiple selected modes, also write one merged CSV per spectrum type, with one column per selected mode.


Outputs

Output filenames are built from:

  • the root prefix from -o/--output,

  • an optional atom-selection tag,

  • the spectrum/correlation type,

  • and, in normal-mode mode, the mode index.

Normal-mode outputs

TA mode (default)

For each selected mode X, the script writes:

<root>_TA-cpp_mode_X.dat
<root>_TA-cqq_mode_X.dat

If --excel is active, it also writes:

<root>_TA-cpp_mode_X.csv
<root>_TA-cqq_mode_X.csv

If --plot is active, it also writes PNGs with matching basenames.

Correlation + FT mode (--no-ta)

For each selected mode X, the script writes:

<root>_cpp_mode_X.dat
<root>_cqq_mode_X.dat
<root>_FT-cpp_mode_X.dat
<root>_FT-cqq_mode_X.dat

Optional CSV exports are added for both correlation and FT outputs.

Cartesian outputs

TA Cartesian mode

<root>_TA-cvv_cartesian.dat

Correlation + FT Cartesian mode

<root>_cvv_cartesian.dat
<root>_FT-cvv_cartesian.dat

Optional .csv and .png companions may also be produced.

What is inside the .dat files

Correlation files

The correlation writers produce two numeric columns:

  • time in atomic units,

  • correlation value.

Examples:

0.000000000000e+00  1.234567890123e-03
8.268274915150e+00  9.876543210987e-04
...

Normal-mode spectrum files

The normal-mode spectrum writers include a large comment header containing:

  • normal-mode frequencies in Hartree, eV, and cm^-1,

  • normal-mode vector components,

  • and the zero-point energy.

After the header, the actual spectrum is printed as two columns:

  • wavenumber (cm^-1),

  • intensity.

This means the .dat files in normal-mode mode are both machine-readable and self-documented, but they are not as convenient as CSV for spreadsheets.

Cartesian spectrum files

Cartesian .dat spectrum files include a smaller header with the zero-point energy followed by two-column spectrum data.

CSV outputs

When --excel is active, the script writes clean tabular files without comment blocks.

Examples:

wn_cm-1,intensity
0.000000,1.234567890123e-05
1.000000,1.456789012345e-05
...

Correlation CSV files use time-axis headers such as:

  • t_au,cpp

  • t_au,cqq

  • t_au,cvv

Spectrum CSV files use:

  • wn_cm-1,intensity

PNG outputs

When --plot is enabled, the script writes one PNG per spectrum using the same basename as the .dat file.

Example:

QCT_TA-cpp_mode_3.png

The plots:

  • use wavenumber on the x-axis,

  • intensity on the y-axis,

  • suppress y tick labels in the saved figure,

  • and are saved at the requested DPI.

Atom-selection filename tags

If --atoms is used, Flying Nimbus appends an atom-selection tag to the root.

For example:

--atoms 1 2 3 5 8 9

becomes:

_atoms_1-3_5_8-9

So a file may look like:

QCT__atoms_1-3_5_8-9_TA-cpp_mode_4.dat

This compression makes filenames manageable even when you select multiple non-consecutive atoms.


Examples

1. Minimal normal-mode time-averaged spectrum

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --modes 1

What happens:

  • nat is read from eq.xyz if not specified,

  • cnorm.dat is computed from the Hessian,

  • the trajectory is projected to normal modes,

  • TA normal mode spectra are written for mode 1.

2. Correlation + FT instead of TA

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --modes 2 3 \
  --no-ta

This produces both:

  • correlation functions (cpp, cqq),

  • and Fourier-transformed spectra (FT-cpp, FT-cqq).

3. Multiple vibrational modes at once

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --modes 4 5 6 7

You get one spectrum file per selected mode.

4. Reuse an existing cnorm.dat

python flying_nimbus.py \
  --xyz eq.xyz \
  --traj md.xyz \
  --readcnorm 1 \
  --cnorm cnorm.dat \
  --modes 4 5 6

This is useful when you are repeating analyses with different:

  • --nstart

  • --ncorr

  • --atoms

  • --freq-offset

  • --norm1

without rebuilding the basis each time. It is also useful if you are working with a cleaned CNORM matrix.

5. Cartesian spectrum

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --coord cart \
  --no-ta

This writes:

QCT__cvv_cartesian.dat
QCT__FT-cvv_cartesian.dat

6. Analyze only selected atoms

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --modes 7 8 9 \
  --atoms 1 2 3

This restricts the signal to atoms 1–3 and adds an atom-selection tag to the filenames.

7. Export CSV files for Excel or LibreOffice

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --modes 2 3 \
  --excel

If your spreadsheet locale expects semicolons:

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --modes 2 3 \
  --excel --excel-sep ';'

8. Merge multiple mode spectra into one CSV

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --modes 3 4 5 6 \
  --excel --excel-merge

This adds merged files such as:

QCT__TA-cpp_modes_3_4_5_6.csv
QCT__TA-cqq_modes_3_4_5_6.csv

or, in non-TA mode:

QCT__FT-cpp_modes_3_4_5_6.csv
QCT__FT-cqq_modes_3_4_5_6.csv

9. Save PNG plots

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --modes 10 11 \
  --plot --plot-dir spectra_png --plot-dpi 300

10. Shift the printed frequency axis

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --modes 3 \
  --freq-offset 35.0

Useful when you want to compare with an externally corrected or empirically shifted reference axis.

11. Normalize spectra to a maximum of 1

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --modes 4 5 6 \
  --norm1

Each printed spectrum is normalized independently.

12. Overwrite an existing cnorm.dat

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --modes 1 \
  --rm-cnorm

Without --rm-cnorm, the script refuses to overwrite an existing cnorm.dat when recomputing the basis.

13. Linear-molecule handling

python flying_nimbus.py \
  --xyz co2.xyz \
  --hess co2_hess.dat \
  --traj co2_traj.xyz \
  --modes 1 2 3 4 \
  --nrototrasl 5

14. Start from a later MD step

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --modes 2 3 \
  --nstart 501

This skips the first 500 frames and starts analysis from frame 501.


Typical workflows

Workflow A: Hessian + trajectory → mode-resolved TA spectra

Use this when you have a single trajectory and want physically interpretable vibrational spectra by mode.

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --modes 1 2 3 4 5

This is the most direct “full analysis” route.

Workflow B: Precomputed cnorm.dat → fast repeat analyses

First run once to generate cnorm.dat.

python flying_nimbus.py \
  --xyz eq.xyz \
  --hess Hessian_flat.out \
  --traj md.xyz \
  --modes 1 \
  --rm-cnorm

Then reuse it repeatedly:

python flying_nimbus.py \
  --xyz eq.xyz \
  --traj md.xyz \
  --readcnorm 1 --cnorm cnorm.dat \
  --modes 3 7 8 12 \
  --nstart 1001 --ncorr 1500 --norm1

This is especially convenient for parameter scans.

Workflow C: Whole-system vs atom-projected comparison

Whole system:

python flying_nimbus.py \
  --xyz eq.xyz --hess Hessian_flat.out --traj md.xyz \
  --modes 5 6 7 --excel

Subset only:

python flying_nimbus.py \
  --xyz eq.xyz --hess Hessian_flat.out --traj md.xyz \
  --modes 5 6 7 --atoms 1 2 3 --excel

This gives you a practical way to compare full-mode behavior with the contribution from a selected fragment or functional group.


Units and conventions

Flying Nimbus mixes a few unit conventions that are worth understanding clearly.

Geometry input

  • XYZ coordinates are read in Ångström.

  • Internally they are converted to bohr.

Velocities

  • Trajectory velocities are read from the trajectory file.

  • The current code requires them directly in bohr by default.

Time step

  • --dt must be given in atomic units.

  • The default is 8.2682749151502 atomic units.

Frequency axis

  • --init-wnumb, --spec-res, --wnumb-span, and --freq-offset are all in cm^-1.

Mode indexing

  • Modes are 1-based at the CLI.

  • Internally the code converts them to 0-based indices.

Atom indexing

  • Atoms are 1-based at the CLI.

  • Internally the code converts them to 0-based indices.


Supported atomic symbols and masses

The built-in mass table includes the following symbols:

Symbol

Mass (au)

H

1837.15

D

3671.48

O

29156.96

Od

32810.46

C

21874.66

N

25526.06

Ti

87256.20

F

34631.97

S

58281.54

I

231332.70

If your element is not listed here, provide the mass explicitly as the fifth column in the XYZ atom line.


Important implementation notes

1. TA is the default

This is easy to miss.

If you do not pass --no-ta, the script computes time-averaged spectra, not correlation + FT outputs. This mode is recommended and is the one that should be used in almost all applications.

2. --modes is mandatory only in normal-mode mode

With --coord nm, omitting --modes causes an argument error.

With --coord cart, mode selection is irrelevant.

3. cnorm.dat is written automatically in the Hessian path

When --readcnorm 0, the script computes the basis from the Hessian and writes cnorm.dat.

This is not just an internal temporary object; it is an explicit output artifact.

4. Existing cnorm.dat is protected by default

If cnorm.dat already exists, the script raises an error instead of overwriting it. Use --rm-cnorm to replace it.

5. Normal-mode spectrum .dat files contain large headers

These files are more informative than minimal two-column spectra because they include:

  • mode vectors,

  • frequencies,

  • and ZPE.

That is useful for archival or manual inspection, but can surprise users expecting a plain two-column file.

6. --freq-offset affects printed/exported axes

The offset is applied to the written wavenumber axis of spectra and plots. It does not re-run the dynamics or alter the normal-mode basis.

7. --excel-merge supplements, not replaces, per-mode CSVs

If --excel and --excel-merge are both active, the merged CSVs are added in addition to the per-mode CSV outputs.

8. Plot display options exist internally but are not exposed in the current CLI

The configuration object has fields related to log-scale y axes and interactive display, but those arguments are not exposed as active CLI options in the current script version.


Troubleshooting

--modes is required when --coord nm

Cause:

  • you are in normal-mode mode and did not provide any modes.

Fix:

--modes 1

or switch to Cartesian mode:

--coord cart

--hess is required when --readcnorm 0

Cause:

  • you asked the script to compute the mode basis but did not provide a Hessian.

Fix:

  • either pass --hess <file>,

  • or switch to --readcnorm 1 --cnorm cnorm.dat.

Mode X is out of range

Cause:

  • one of the selected mode indices exceeds 3N - nrototrasl.

Fix:

  • verify nat,

  • verify --nrototrasl,

  • and check whether your molecule is linear.

atoms selection out of range for nat

Cause:

  • at least one atom index in --atoms is outside 1..nat.

Fix:

  • recheck your indexing against the XYZ file.

Not enough post-nstart steps for ncorr=...

Cause:

  • after dropping the first nstart - 1 frames, the remaining trajectory is shorter than ncorr.

Fix:

  • lower --ncorr,

  • lower --nstart,

  • or provide a longer trajectory.

Not enough Hessian numbers

Cause:

  • the Hessian file does not contain enough lower-triangle values for a 3N × 3N matrix.

Fix:

  • verify the Hessian extraction workflow,

  • and confirm that the file contains all lower-triangle elements after the two header lines.

Element 'X' not in mass database

Cause:

  • your XYZ contains an element missing from the internal mass table.

Fix:

  • add a fifth mass column to each affected atom line.

cnorm.dat already exists; will not overwrite

Cause:

  • a previous cnorm.dat is present and you are in the Hessian-compute path.

Fix:

--rm-cnorm

or change the --cnorm target path.


Limitations

The current script is powerful but intentionally narrow in scope.

Input assumptions are strict

  • The trajectory must be extended XYZ with x y z vx vy vz for every atom line.

  • The Hessian reader expects lower-triangle values after exactly two header lines.

Mass support is limited unless you provide explicit masses

Only a small internal set of atomic symbols is built in. For less common species, explicit mass columns are the safe solution.

Plotting is intentionally simple

The plotting helper saves one PNG per spectrum and does not expose extensive styling controls in the current CLI.

Spectra are post-processed outputs, not full uncertainty analyses

The script gives you spectra and correlations, but it does not attempt statistical error bars, bootstrap analysis, or trajectory-block uncertainty estimates.


License

This project is marked in the source with:

SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0

Check the repository for the full license text and any additional usage notes.


Authors

Authors listed in the source:

  • Giacomo Mandelli, Ph.D., Politecnico di Milano

  • Giacomo Botti, Ph.D., University of South Carolina