oilftir.astm_utils¶
FTIR Spectrum Processing Utilities for Lubricating Oil Analysis Based on ASTM E2412 standard methodology.
- Provides:
Spectrum loading (CSV/TXT; optional PerkinElmer .sp via specio)
Baseline correction and spectral normalisation
Net area calculation for ASTM-defined absorption bands
Hit Quality Index (HQI) library search
General-purpose plotting
Dependencies¶
numpy, pandas, scipy, matplotlib, pybaselines specio (optional – only needed for .sp files)
Usage example¶
from oilftir.astm_utils import load_spectrum, astm_areas
df, meta = load_spectrum(“sample.csv”) results = astm_areas(df) print(results)
References
- ASTM E2412-23 Standard Practice for Condition Monitoring of Used Lubricants
by Trend Analysis Using Fourier Transform Infrared (FT-IR) Spectrometry
Functions¶
|
Load an FTIR spectrum from a file. |
|
Subtract a polynomial baseline from the spectrum using the modified |
|
Scale a reference spectrum to best match a sample spectrum using |
|
Scale and subtract a reference spectrum from a sample spectrum over a |
|
Oxidation band area (1800–1670 cm⁻¹) – ASTM E2412. |
|
Nitration band area (1600–1650 cm⁻¹) – ASTM E2412. |
|
Sulfation band area (1120–1180 cm⁻¹) – ASTM E2412. |
|
Water contamination band area (3150–3500 cm⁻¹) – ASTM E2412. |
|
Ethylene glycol (coolant) band area (1030–1100 cm⁻¹) – ASTM E2412. |
|
Petrol (gasoline) fuel dilution band area (745–755 cm⁻¹) – ASTM E2412. |
|
Diesel fuel dilution band area (805–815 cm⁻¹) – ASTM E2412. |
|
ZDDP antiwear additive band area (960–1025 cm⁻¹) – ASTM E2412. |
|
Soot (carbon black) load index – ASTM E2412. |
|
Compute all standard ASTM E2412 band areas in a single call. |
|
Convert a band area to a concentration using a polynomial calibration curve. |
|
Compute the Hit Quality Index (HQI) between two spectra. |
|
Parallel brute-force HQI library search. |
|
Plot one or more FTIR spectra (absorbance and transmittance panels). |
Module Contents¶
- oilftir.astm_utils.load_spectrum(path: str, magnitude: str = 'A') tuple[pandas.DataFrame, dict][source]¶
Load an FTIR spectrum from a file.
Supported formats¶
- CSV / TXT – two-column file (wavenumber, amplitude); delimiter is
auto-detected (comma or whitespace).
.sp – PerkinElmer binary format (requires the specio package).
- param path:
Path to the spectrum file.
- type path:
- param magnitude:
Indicates whether amplitudes in the file are Absorbance (‘A’) or Transmittance (‘T’, expressed as a fraction 0–1 or percentage 0–100).
- type magnitude:
{'A', 'T'}- returns:
df (
pd.DataFrame) – Columns:cm-1(wavenumber),A(absorbance),T(transmittance 0–1).meta (
dict) – Metadata extracted from the file (empty dict for plain text files).
- raises ValueError:
If magnitude is not ‘A’ or ‘T’.
- raises ImportError:
If a .sp file is requested but specio is not installed.
- oilftir.astm_utils.remove_baseline(df: pandas.DataFrame, units: str = 'A', poly_order: int = 5) pandas.DataFrame[source]¶
Subtract a polynomial baseline from the spectrum using the modified polynomial method (ModPoly).
- oilftir.astm_utils.scale_reference(df_sample: pandas.DataFrame, df_ref: pandas.DataFrame, units: str = 'A') pandas.DataFrame[source]¶
Scale a reference spectrum to best match a sample spectrum using least-squares projection (scalar factor k).
The scaling factor is computed as:
k = (sample · reference) / (reference · reference)
- Parameters:
df_sample (
pd.DataFrame) – Sample spectrum.df_ref (
pd.DataFrame) – Reference spectrum to be scaled.units (
str) – Column used for comparison.
- Returns:
Scaled copy of df_ref.
- Return type:
pd.DataFrame
- oilftir.astm_utils.subtract_reference(df_sample: pandas.DataFrame, df_ref: pandas.DataFrame, wavenumber_range: tuple[float, float], units: str = 'A') tuple[numpy.ndarray, float, numpy.ndarray][source]¶
Scale and subtract a reference spectrum from a sample spectrum over a specified wavenumber range.
The reference is first interpolated onto the sample’s wavenumber axis, then scaled using the least-squares projection within wavenumber_range.
- Parameters:
df_sample (
pd.DataFrame) – Sample spectrum.df_ref (
pd.DataFrame) – Reference spectrum (may have a different wavenumber axis).wavenumber_range (
(float,float)) –(k_min, k_max)– region used to compute the scaling factor.units (
str) – Column to use (‘A’ or ‘T’).
- Returns:
y_diff (
np.ndarray) – Difference spectrum (sample − scaled reference).k (
float) – Scaling factor applied to the reference.y_ref_scaled (
np.ndarray) – Scaled reference interpolated onto the sample axis.
- oilftir.astm_utils.area_oxidation(df: pandas.DataFrame) float[source]¶
Oxidation band area (1800–1670 cm⁻¹) – ASTM E2412.
Baseline anchored at the minima in 550–650 cm⁻¹ and 1900–2200 cm⁻¹.
- Parameters:
df (
pd.DataFrame) – Spectrum with columnscm-1andA.- Returns:
Net integrated area (absorbance·cm⁻¹).
- Return type:
- oilftir.astm_utils.area_nitration(df: pandas.DataFrame) float[source]¶
Nitration band area (1600–1650 cm⁻¹) – ASTM E2412.
Baseline anchored at the minima in 550–650 cm⁻¹ and 1900–2200 cm⁻¹.
- Parameters:
df (
pd.DataFrame) – Spectrum with columnscm-1andA.- Returns:
Net integrated area (absorbance·cm⁻¹).
- Return type:
- oilftir.astm_utils.area_sulfation(df: pandas.DataFrame) float[source]¶
Sulfation band area (1120–1180 cm⁻¹) – ASTM E2412.
Baseline anchored at the minima in 550–650 cm⁻¹ and 1900–2200 cm⁻¹.
- Parameters:
df (
pd.DataFrame) – Spectrum with columnscm-1andA.- Returns:
Net integrated area (absorbance·cm⁻¹).
- Return type:
- oilftir.astm_utils.area_water(df: pandas.DataFrame) float[source]¶
Water contamination band area (3150–3500 cm⁻¹) – ASTM E2412.
Baseline anchored at the minima in 1900–2200 cm⁻¹ and 3680–4000 cm⁻¹.
- Parameters:
df (
pd.DataFrame) – Spectrum with columnscm-1andA.- Returns:
Net integrated area (absorbance·cm⁻¹).
- Return type:
- oilftir.astm_utils.area_glycol(df: pandas.DataFrame) float[source]¶
Ethylene glycol (coolant) band area (1030–1100 cm⁻¹) – ASTM E2412.
Baseline anchored at the minima in 1010–1030 cm⁻¹ and 1100–1130 cm⁻¹.
- Parameters:
df (
pd.DataFrame) – Spectrum with columnscm-1andA.- Returns:
Net integrated area (absorbance·cm⁻¹).
- Return type:
- oilftir.astm_utils.area_fuel_petrol(df: pandas.DataFrame) float[source]¶
Petrol (gasoline) fuel dilution band area (745–755 cm⁻¹) – ASTM E2412.
Baseline anchored at the minima in 730–750 cm⁻¹ and 760–780 cm⁻¹.
- Parameters:
df (
pd.DataFrame) – Spectrum with columnscm-1andA.- Returns:
Net integrated area (absorbance·cm⁻¹).
- Return type:
- oilftir.astm_utils.area_fuel_diesel(df: pandas.DataFrame) float[source]¶
Diesel fuel dilution band area (805–815 cm⁻¹) – ASTM E2412.
Baseline anchored at the minima in 795–805 cm⁻¹ and 825–835 cm⁻¹.
- Parameters:
df (
pd.DataFrame) – Spectrum with columnscm-1andA.- Returns:
Net integrated area (absorbance·cm⁻¹).
- Return type:
Notes
The raw integrated area is returned. Convert to a concentration using a laboratory-specific calibration curve.
- oilftir.astm_utils.area_antiwear_zddp(df: pandas.DataFrame) float[source]¶
ZDDP antiwear additive band area (960–1025 cm⁻¹) – ASTM E2412.
Baseline anchored at the minima in 550–650 cm⁻¹ and 1900–2200 cm⁻¹.
- Parameters:
df (
pd.DataFrame) – Spectrum with columnscm-1andA.- Returns:
Net integrated area (absorbance·cm⁻¹).
- Return type:
- oilftir.astm_utils.soot_load(df: pandas.DataFrame) float[source]¶
Soot (carbon black) load index – ASTM E2412.
The absorbance at the carbon-black scattering reference point (2000 cm⁻¹) is multiplied by 100 to yield a dimensionless index.
- Parameters:
df (
pd.DataFrame) – Spectrum with columnscm-1andA.- Returns:
Soot index (dimensionless, ≥ 0).
- Return type:
- oilftir.astm_utils.astm_areas(df: pandas.DataFrame) dict[source]¶
Compute all standard ASTM E2412 band areas in a single call.
- Parameters:
df (
pd.DataFrame) – Spectrum with columnscm-1andA.- Returns:
Keys:
oxidation,nitration,sulfation,water,glycol,fuel_petrol,fuel_diesel,antiwear_zddp,soot.- Return type:
- oilftir.astm_utils.area_to_concentration(area: float, calibration_areas: numpy.ndarray, calibration_concentrations: numpy.ndarray, poly_order: int = 3) float[source]¶
Convert a band area to a concentration using a polynomial calibration curve.
Build and apply your own calibration curve by providing known (area, concentration) pairs measured on your instrument.
- Parameters:
- Returns:
Estimated concentration (≥ 0).
- Return type:
Example
>>> # Example: water content calibration >>> cal_areas = np.array([0.0, 70.0, 87.0, 120.0, 144.0]) >>> cal_conc = np.array([0.0, 2.0, 4.0, 5.0, 10.0]) # % v/v >>> conc = area_to_concentration(measured_area, cal_areas, cal_conc)
- oilftir.astm_utils.hqi(x_query: numpy.ndarray, y_query: numpy.ndarray, x_ref: numpy.ndarray, y_ref: numpy.ndarray) float[source]¶
Compute the Hit Quality Index (HQI) between two spectra.
HQI is defined as the squared cosine similarity (0–100 %):
HQI = 100 × (A·B)² / (‖A‖² · ‖B‖²)
The reference is interpolated onto the query’s wavenumber axis using the overlapping region only.
- Parameters:
x_query (
np.ndarray) – Query spectrum (wavenumber, absorbance).y_query (
np.ndarray) – Query spectrum (wavenumber, absorbance).x_ref (
np.ndarray) – Reference spectrum.y_ref (
np.ndarray) – Reference spectrum.
- Returns:
HQI score in percent (0–100).
- Return type:
- oilftir.astm_utils.library_search(query_path: str, library_dir: str, top_n: int = 5, extension: str = '*.sp') list[dict][source]¶
Parallel brute-force HQI library search.
Loads the query spectrum, then compares it against every file matching extension in library_dir (and subdirectories) using the Hit Quality Index.
- Parameters:
- Returns:
All valid results sorted by HQI (descending), each with keys
'file'and'hqi'.- Return type:
list[dict]
- oilftir.astm_utils.plot_spectra(data_dict: dict, title: str = 'FTIR Spectroscopy', xlim: tuple = (4000, 450), ylim_A: tuple = (0, 0.4), ylim_T: tuple = (0, 1), save_path: str | None = None) tuple[source]¶
Plot one or more FTIR spectra (absorbance and transmittance panels).
- Parameters:
data_dict (
dict) –{'Label': {'df': df, 'color': 'black', 'alpha': 1.0, 'linewidth': 2}}Only'df'is required per entry.title (
str) – Figure title.xlim (
(float,float)) – Wavenumber axis limits (default: 4000–450 cm⁻¹).ylim_A (
(float,float)) – Absorbance axis limits.ylim_T (
(float,float)) – Transmittance axis limits.save_path (
strorNone) – If given, the figure is saved to this path (PNG/PDF/SVG).
- Returns:
fig, axes
- Return type:
matplotlib FigureandAxes array