DScribe: turning atomic structures into fixed-size descriptors
DScribe is a python package for creating machine learning descriptors for atomistic systems.
At a glance
- What is it?
- DScribe is a Python package that converts atomic structures into fixed-size numerical fingerprints for machine learning, visualization and similarity analysis. It ships eight descriptor families with derivative support, and the C++ core is what keeps the neighbour-list work out of Python.
- Who is it for?
- Adopt DScribe if you already have structures in ASE and need one of its eight documented descriptors as a plain NumPy or sparse array, with derivatives available when the descriptor supports them. Do not adopt it if your pipeline is built on a different atomistic data model, or if you need a descriptor the table does not list, because the README gives no extension hook for adding one.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 150 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem DScribe solves for atomistic machine learning
Machine learning models want fixed-size vectors. Atomic structures do not come that way. A water molecule and a slab of 200 atoms have different atom counts, different orderings and no natural coordinate system that survives rotation. DScribe exists to close that gap: it transforms an atomic structure into a numerical fingerprint of fixed size, and the README calls those fingerprints descriptors. The package targets materials science and atomistic simulation, and the topic list confirms it: materials-science, atomistic-systems, machine-learning, descriptors. If you are building a regression or classification model over molecules, crystals or surfaces and you need a representation that a scikit-learn or PyTorch model can consume, this is the layer DScribe occupies. It does not train models, and it does not read simulation output for you. It takes a structure object and returns numbers.
The eight descriptors and what the spectrum and derivative columns mean
The README lists eight descriptors in a table with two boolean columns, Spectrum and Derivatives, and all eight rows carry a check mark in both. The set is Coulomb matrix, Sine matrix, Ewald matrix, Atom-centered Symmetry Functions (ACSF), Smooth Overlap of Atomic Positions (SOAP), Many-body Tensor Representation (MBTR), Local Many-body Tensor Representation (LMBTR) and the Valle-Oganov descriptor. The two columns matter more than the list. A check in Spectrum means the descriptor can also be produced as a spectrum, which is the representation used when you want a single global fingerprint rather than a per-atom one. A check in Derivatives means the package can return the gradient of the descriptor with respect to atomic positions, which is what you need if the descriptor feeds a model that is trained on forces or that uses analytic gradients. The README states that derivatives are calculated with respect to atomic positions, and the quick example shows the call: soap_desc.derivatives(samples, return_descriptor=True) returns two values, der and des. Having all eight support both columns is the main structural claim of the library, and it is the claim worth checking against the documentation for your specific descriptor before you build on it.
How the create call and the C++ core fit together
The data flow is short. You construct a descriptor object with its hyperparameters, then call create on one structure or a list of structures. In the README example, SOAP is constructed with species=["C", "H", "O", "N"], r_cut=5, n_max=8, l_max=6 and crossover=True, and CoulombMatrix is constructed with n_atoms_max=3 and permutation="sorted_l2". Those keyword arguments are the descriptor definition: the species list fixes which elements the fingerprint can encode, and r_cut, n_max and l_max fix the spatial and angular resolution of the SOAP expansion. Changing them changes the array width, so the descriptor configuration has to be frozen before training and reused at inference. The create method accepts either a single structure or a list, and the list form is where the parallelism lives: the README shows cm_desc.create(samples, n_jobs=3) and soap_desc.create(samples, oxygen_indices, n_jobs=3). The second positional argument is a list of center indices, one entry per structure, so you can compute a descriptor only around selected atoms. The oxygen_indices line in the example builds exactly that list with np.where(x.get_atomic_numbers() == 8)[0]. The output is a NumPy array or a sparse array. The repository's primary language is C++, which is consistent with the pattern of a thin Python API over a compiled core: the neighbour search and the symmetry-function or SOAP expansion loops run in C++, and Python handles the structure objects and the array plumbing. The practical consequence is that n_jobs parallelises across processes rather than threads, and that a build step is involved when you install from source.
Installation routes and the submodule step
There are three documented installation paths. The pip route is a single command, pip install dscribe. The conda route is conda install -c conda-forge dscribe. The source route is three commands: git clone https://github.com/SINGROUP/dscribe.git, then cd dscribe, then git submodule update --init, then pip install . The submodule step is the one to notice. It means the repository pulls in code that is not stored in the main tree, and skipping it is the obvious way to get a build that fails or a binary that is missing functionality. The README points to the documentation at singroup.github.io/dscribe/latest/install.html for in-depth instructions, which is where you would look for compiler requirements and platform notes, since the README itself does not state them. The quick example imports from ase.build, so ASE is part of the expected workflow even though the README does not present it as a hard dependency. The structures passed to create in the example are ASE Atoms objects, and the get_atomic_numbers method used to build the center index list is an ASE method. If you are not already using ASE, budget for that as an additional piece of your stack.
Where DScribe stops being the right tool
The descriptor table is a closed list. If the representation you need is not one of the eight, the README gives no documented extension point for registering your own descriptor, and no plugin mechanism is described. That is a real boundary, not a temporary gap you can work around with a subclass in a few lines, because the descriptors are backed by compiled code rather than pure Python. The second constraint is the input model. Every example in the README works on ASE Atoms objects, and there is no documented adapter for reading structures from other formats or from other atomistic libraries. If your pipeline already produces structures in a different representation, you are writing the conversion yourself. The third constraint is that descriptor hyperparameters are fixed at construction and determine the output width. A SOAP descriptor built with n_max=8 and l_max=6 produces a wider array than one built with smaller values, and the two are not interchangeable inputs to the same trained model. That is inherent to the approach rather than a defect, but it means the descriptor configuration becomes part of your model artifact and has to be versioned with it. Finally, the README does not state memory behaviour for the sparse output path or give guidance on when sparse is preferable to dense, so that choice has to be made by measurement on your own structures.
How DScribe differs from a general-purpose featurization library
The natural comparison is with a general chemistry featurization toolkit such as RDKit, and the difference is in the unit of representation. RDKit works on molecular graphs: atoms and bonds, with aromaticity, valence and stereochemistry as first-class concepts. Its descriptors are derived from that graph and from 2D or 3D conformer information attached to it. DScribe works on periodic and non-periodic atomistic structures where the positions and the cell are the input, and it builds descriptors from local atomic environments within a cutoff radius. SOAP with r_cut=5 is a statement about a spherical neighbourhood in space, not about a bond list. That distinction decides which one you want. For organic molecules where connectivity and functional groups carry the signal, a graph-based featurizer encodes chemistry that DScribe would have to rediscover from geometry alone. For crystals, surfaces and amorphous systems, where there is no meaningful bond list and periodicity matters, the graph model does not apply and DScribe's geometric descriptors do. The two are not substitutes, and a project working across both regimes would end up using both.
Licence, maintenance and the cost of staying current
DScribe is licensed under Apache-2.0, which permits commercial use and modification and includes an express grant of patent rights from contributors, with the usual requirements around preserving notices and stating changes. That is a permissive licence and it is the reason the package can be embedded in a proprietary training pipeline without the copyleft obligations a GPL would impose. This is a description of the licence text, not legal advice; if the patent clause or the notice requirements matter to your organisation, have counsel read the actual LICENSE file. On maintenance, the repository is not archived and the last push recorded is 2026-04-18, so the project is active. No releases were retrieved for this review, which means the version history and the changelog could not be checked here, and anyone pinning a version should read the release notes directly. The upgrade cost is concentrated in the descriptor definitions. Because hyperparameters such as r_cut, n_max and l_max determine the array width, a change to those values invalidates any model trained on the previous output, and a change to the descriptor implementations themselves could shift the numbers for the same inputs. The README cites two papers, the 2019 Computer Physics Communications article and a later article titled Updates to the DScribe library: New descriptors and derivatives, and the second title is a signal that descriptor behaviour has been extended across versions. Treat the descriptor version as part of your model's reproducibility record.
Editorial conclusion
Adopt DScribe if you already have structures in ASE and need one of its eight documented descriptors as a plain NumPy or sparse array, with derivatives available when the descriptor supports them. Do not adopt it if your pipeline is built on a different atomistic data model, or if you need a descriptor the table does not list, because the README gives no extension hook for adding one. Before committing, verify two things on your own data: that the descriptor you pick produces the array shape your model expects, and that the derivative output matches the layout your training code reads. Both are answered by running the quick example against one of your own structures.
Community notes