Import/Export of JCAMP-DX files
JCAMP-DX is an open format initially developed for IR data and extended to other spectroscopies. At present, the JCAMP-DX reader implemented in SpectroChemPy is limited to IR data and AFFN encoding (see [McDonald and Paul A. Wilks, 1988].
The JCAMP-DX reader of SpectroChemPy has been essentially written to read JCAMP-DX files exported by the SpectroChemPy write_jdx() writer.
[1]:
import spectrochempy as scp
X = scp.read_omnic("irdata//CO@Mo_Al2O3.SPG")
S0 = X[0]
S0
[1]:
NDDataset [CO@Mo_Al2O3] — float64, shape: (y:1, x:3112), a.u.
Omnic filename: /home/runner/.spectrochempy/testdata/irdata/CO@Mo_Al2O3.SPG
2026-08-16 03:11:15+00:00> Sorted by date
2026-08-16 03:11:15+00:00> Slice extracted: (0)
Data
Dimension `x`
Dimension `y`
[ *Résultat de Soustraction:04_Mo_Al2O3_calc_0.003torr_LT_after sulf_Oct 18 15:46:42 2016 (GMT+02:00)]]
[2]:
S0.write_jcamp("CO@Mo_Al2O3_0.jdx", confirm=False)
[2]:
PosixPath('/home/runner/work/spectrochempy/tempdirs/scp_yf458zyp/docs/sources/userguide/importexport/CO@Mo_Al2O3_0.jdx')
The namespace API is also available for writing:
[3]:
scp.jcamp.write(S0, "CO@Mo_Al2O3_0.jdx", confirm=False, overwrite=True)
[3]:
PosixPath('/home/runner/work/spectrochempy/tempdirs/scp_yf458zyp/docs/sources/userguide/importexport/CO@Mo_Al2O3_0.jdx')
Then used (and maybe changed) by a 3rd party software, and re-imported in spectrochempy:
[4]:
newS0 = scp.read_jcamp("CO@Mo_Al2O3_0.jdx")
newS0
[4]:
NDDataset [CO@Mo_Al2O3] — float64, shape: (y:1, x:3112), a.u.
Data
Dimension `x`
Dimension `y`
The namespace API works identically:
[5]:
newS0 = scp.jcamp.read("CO@Mo_Al2O3_0.jdx")
newS0
[5]:
NDDataset [CO@Mo_Al2O3] — float64, shape: (y:1, x:3112), a.u.
Data
Dimension `x`
Dimension `y`
It is important to note here that the conversion to JCAMP-DX changes the last digits of absorbance and wavenumbers:
The writer preserves the numeric values it writes. It does not silently convert wavelength to wavenumber or transmittance to absorbance. Current export support is therefore limited to exact-scale JCAMP mappings:
x:
cm^-1,um,nm, or no unit (ARBITRARY UNITS);y:
absorbance,transmittance, or no unit (ARBITRARY UNITS).
Other merely convertible or named arbitrary units are rejected until you convert them explicitly before export.
[6]:
from spectrochempy.utils.compare import difference
[7]:
max_error, max_rel_error = difference(S0, newS0)
print(f"Max absolute difference in absorbance: {max_error:.3g}")
print(f"Max relative difference in absorbance: {max_rel_error:.3g}")
Max absolute difference in absorbance: 1.12e-08
Max relative difference in absorbance: 0.863
[8]:
max_error, max_rel_error = difference(S0.x, newS0.x)
print(f"Max absolute difference in wavenumber: {max_error:.3g}")
print(f"Max relative difference in wavenumber: {max_rel_error:.3g}")
Max absolute difference in wavenumber: 0
Max relative difference in wavenumber: 0
But this is much beyond the experimental accuracy of the data.