Coverage for /builds/ase/ase/ase/io/sdf.py: 100.00%
17 statements
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
1# fmt: off
3"""Reads chemical data in SDF format (wraps the molfile format).
5See https://en.wikipedia.org/wiki/Chemical_table_file#SDF
6"""
7from typing import TextIO
9from ase.atoms import Atoms
10from ase.utils import reader
13def get_num_atoms_sdf_v2000(first_line: str) -> int:
14 """Parse the first line extracting the number of atoms.
16 The V2000 dialect uses a fixed field length of 3, which means there
17 won't be space between the numbers if there are 100+ atoms, and
18 the format doesn't support 1000+ atoms at all.
20 http://biotech.fyicenter.com/1000024_SDF_File_Format_Specification.html
21 """
22 return int(first_line[0:3]) # first three characters
25@reader
26def read_sdf(file_obj: TextIO) -> Atoms:
27 """Read the sdf data and compose the corresponding Atoms object."""
28 lines = file_obj.readlines()
29 # first three lines header
30 del lines[:3]
32 num_atoms = get_num_atoms_sdf_v2000(lines.pop(0))
33 positions = []
34 symbols = []
35 for line in lines[:num_atoms]:
36 x, y, z, symbol = line.split()[:4]
37 symbols.append(symbol)
38 positions.append((float(x), float(y), float(z)))
39 return Atoms(symbols=symbols, positions=positions)