Updates Version 0.1.9.1¶
Topology identification no longer needs Java¶
The Systre call has been replaced by mofstructure.graph_net, a pure-Python
implementation of the Delgado-Friedrichs canonical form. The JVM jar, the
jdk4py dependency and the mofstructure.systre module are gone, and the
wheel is about 1.7 MB smaller.
The replacement was validated before the switch, not after. Given the same quotient graphs it agreed with Systre on 180 of 180 curated MOFs, 30 of 30 COFs and 10 of 10 zeolites, and with CrystalNets - an independent implementation with its own canonical form and archive - on all 111 structures where both named a net. TD10 agrees to the digit Systre prints.
One call from a structure to its net¶
mofstructure.topology joins deconstruction to identification. It accepts a
structure file, an ASE atoms object or a CGD periodic graph, decides whether a
framework is a MOF, a COF or a zeolite, and returns the same record for all
three, so results are comparable across chemistry.
from mofstructure.topology import analyse
analyse("UiO-66.cif")["topology"] # 'fcu'
analyse("ABW.cif")["topology"] # 'sra', a zeolite
analyse("COF-1.cif")["topology"] # 'hcb'
Zeolites, and two more COF linkages¶
method="zeol" takes the tetrahedral atoms as vertices and contracts each
T-O-T bridge into an edge, which is the net the zeolite literature names: ABW
gives sra and EDI gives edi. Until now no method applied to a framework
with no metal cluster to cut at. The hydrazide and ester COF linkages
cover frameworks that previously reported no linkage at all.
A larger archive, and names that say where they came from¶
The lookup table holds 17,454 nets, up from 2,930: the RCSR archive re-keyed,
plus the IZA zeolite framework codes and the EPINET enumeration. Each name is
reported with the archive it came from, so an RCSR symbol is never mistaken for
a position in a systematic enumeration. A zeolite carries both, sra to the
RCSR and ABW to the IZA.
What changed for existing callers¶
topology_hash now digests the canonical key rather than Systre’s relaxed
geometry. The new digest identifies the net: the same framework in a
supercell, with atoms reordered or the origin moved, hashes identically, which
the geometric one did not. Values stored under the old scheme will not match,
and key_version travels with the hash so a stale one is recognisable.
cgd is written from this package’s own embedding, describing the same net
in a primitive rather than conventional cell. Pass refine_cgd=True for an
embedding with near-uniform edge lengths, which is what a builder such as
AuToGraFS wants.
mofstructure_topology is now backed by the Python implementation, and
mofstructure_systre_cgd has been removed.
Updates Version 0.1.9.0¶
This release adds a chemically explicit ligand–cluster topology, stable framework fingerprints and interactive topology drawings. It also makes periodic contracted nets reproducible across equivalent structure files.
Topology and fingerprints¶
method="ligand_cluster" now constructs a periodic incidence graph whose two
vertex classes are complete organic ligands and metal clusters. Every edge is a
distinct periodic coordination incidence. Multiple donor bonds within one
ligand–cluster contact are consolidated, while contacts to different periodic
images remain separate. Ditopic and polytopic ligands stay explicit; use
collapse_ditopic=True when the conventional contracted RCSR net is needed.
Translations for periodic rod and sheet clusters are reduced modulo the component translation lattice. Consequently, contracted topologies no longer depend on atom ordering, cell origin or whether the input is a primitive cell or supercell. Singly coordinated solvent, modulators and dangling ligands are excluded from the Systre net so degree-one collisions do not hide the framework topology.
MOFstructure.get_ligand_cluster_fingerprint() reports ligand and cluster
species, connectivity, denticity, terminal ligands and refinement information
without requiring an RCSR match. Its normalized counts and
fingerprint_hash are stable across atom ordering, origin shifts and
supercell expansion.
topology_hash no longer includes Systre’s input-dependent node labels.
Hashes stored by previous versions will therefore not match values generated by
0.1.9.0. Relaxed coordinates can still differ by the origin selected for the
ideal space group.
Topology visualization¶
MOFstructure.draw_topology() provides an interactive 3D view for sbus,
all_node, single_node and ligand_cluster. Nodes are placed at their
real building-unit centres, connections retain their periodic translations and
optional framework and unit-cell layers show how the net maps onto the crystal.
The method-specific centre-to-centre layer distinguishes SBU/metal centres from
organic/linker centres; the abstract topology can be added with
show_topology=True. Figures can be saved as interactive HTML or static
images using the draw extra.
Periodic self-edges and distinct incidences are now preserved in drawings, zero-length self-edges are removed, and every displayed connection terminates at a visible periodic node image.
Updates Version 0.1.8.9¶
This release corrects two topology bugs, fixes a crash when adding dummy atoms, and removes a redundant option. Deconstruction was already correct in the topology cases; only the net handed to Systre was wrong.
Topology¶
Polytopic linkers were contracted into a clique. Every linker was collapsed
into edges directly between the metals it touched. For a ditopic linker that is
one edge, which is right, but a tritopic linker (BTC and higher) became a
triangle of edges, inflating each metal’s connectivity. HKUST-1, a known
tbo net, came out reo. A polytopic linker is now its own branch-point
node joined to each metal it bridges, so HKUST-1 gives tbo. Ditopic
frameworks are unaffected: UiO-66 stays fcu, MOF-5 and pillared paddlewheels
stay pcu.
Rod SBUs lost their chain connectivity. An infinite metal-oxo rod (MIL-53
and similar) is periodic within itself, but that periodicity was discarded when
the rod was contracted to a node, collapsing the net to a two-dimensional
sql. method="all_node" now splits a rod into its atoms – each metal and
each bridging carboxyl carbon becomes a node – recovering the true net. MIL-53
gives rna (matching CrystalNets AllNodes and mofid), while method="sbus"
keeps the rod as one node (pcu). Discrete SBUs are unchanged (HKUST-1
tbo, UiO-66 fcu).
New ``method=”single_node”``. This is the coarsening CrystalNets calls
SingleNodes: the all-node net with each connected group of organic vertices
merged to one vertex, metals left separate. MIL-53 gives bpq, matching
CrystalNets. mofstructure_topology --method all now records sbus, all_node
and single_node together.
Fixes¶
find_unique_building_units(..., add_dummy=True) crashed with an
IndexError because the helper that locates the far side of a broken bond
only matched the first atom of the pair. Matching is now symmetric, so a dummy
atom is placed at every point of extension.
Command line¶
mofstructure_topology gained --method all, which runs the node
definitions (sbus, all_node, single_node) and records the nets in
one entry per structure. The JSON nests them under a topologies key and the
CSV gives each its own columns, ready to load into a database.
The ligand_cluster method was removed: it duplicated sbus on simple
frameworks and gave non-standard nets on the rest. Use sbus, all_node
or single_node.
The console scripts were made consistent: every script accepts
-v/--verbose, mofstructure_database accepts --method (with
--topology_method kept as an alias), and -o now means output
everywhere. mofstructure_database previously used -o for --oms;
that short form was removed, so use --oms.
Changes¶
The connect_mode argument was removed from build_cgd and the
mofstructure_topology CLI. Linker contraction no longer has a clique/chain
choice: ditopic linkers become edges and polytopic linkers become nodes.
Updates Version 0.1.8.7¶
This release fixes ligand naming, which never resolved before, and stops a crash in the porosity code that could terminate a database run.
IUPAC ligand names now resolve¶
ligand_names previously came back as null for every structure. Two
separate problems had to be fixed before a name could match.
The shipped name database was scraped from PubChem, whose SMILES come from the
CACTVS toolkit. Canonical SMILES are only canonical within one toolkit, so a
CACTVS string never equals the OpenBabel string that compute_smi produces.
A ligand cut out of a framework also carries dangling valences at its points of extension. Terephthalate leaves deconstruction two hydrogens short of the terephthalic acid PubChem stores, so the formula, the SMILES and even the InChIKey connectivity block all differ.
Both sides are now normalised the same way. Open valences are saturated to recover the neutral parent molecule, and every molecule is indexed under its full InChIKey, its canonical SMILES and its InChIKey connectivity block.
get_ligands() returns ASE atoms objects, not names. Look the name up from
the SMILES carried on each fragment:
from mofstructure import structure
from mofstructure.filetyper import load_iupac_names
from mofstructure.mofdeconstructor import lookup_iupac_name
iupac_names = load_iupac_names()
mof = structure.MOFstructure(filename='RUBTAK01.cif')
_, ligands = mof.get_ligands()
for ligand in ligands:
print(lookup_iupac_name(ligand.info['smi'], iupac_names))
# terephthalic acid
The command line tools do this for you and write the result to the
ligand_names field of ligands_data.json, which previously held only
null.
Porosity no longer terminates a run¶
zeo++ calls abort() when its Voronoi decomposition fails an internal volume
check, which raises SIGABRT and cannot be caught by any try/except. A
single awkward framework previously killed the whole process.
zeo_calculation now runs in a child interpreter and returns an empty
dictionary when the child dies, so such structures are recorded as having no
porosity data instead of ending the job.
Topology in the database workflow¶
mofstructure_database accepts -t/--topology, writing
topology_data.json and a CSV summary. At the time it was off by default
because identification then shelled out to Systre.
mofstructure_database cif_folder -t
mofstructure_database cif_folder -t --topology_method all_node
Other fixes¶
The CSV summaries no longer fail when a structure was recorded as
null.mofstructure_generate_cgdpointed at a module that does not exist and failed on every install. It now resolves correctly.Module level documentation across the package, and a docstring for the
MOFstructureclass.
Updates Version 0.1.8.6¶
- Major update in the code structuring with
the inclusion of TopologyExtractor class which makes the entire code more modular and easy to use. In addition, the code can now guess the names of common ligands. Moreover, we have added a new command line tool to compute the topology of MOFs using Systre. This tool is called mofstructure_topology and can be used as follows:
mofstructure_topology cif_folder
mofstructure_topology cif_folder --method all_node
mofstructure_topology cif_folder --method sbus
# Can be directly used on a single CIF file as well
mofstructure_topology cif_file.cif
The topology can also be computing as a library as follows:
from mofstructure.systre import identify_topology
from ase.io import read
# 1) From a CGD file
res = identify_topology("net.cgd", input_is_cgd=True)
print(res.topology)
# 2) From a CIF (generate CGD then run systre)
res = identify_topology("UiO-66.cif", method="all_node")
print(res.topology)
# 3) From ASE Atoms
atoms = read("UiO-66.cif")
res = identify_topology(atoms, method="sbus")
print(res.topology)
It can also be called from structure as follows:
from mofstructure import structure
from ase.io import read
atoms = read("UiO-66.cif")
mofdata = structure.MOFstructure(ase_atoms=atoms)
topology = mofdata.get_topology(method="sbus")
print(topology)
Updates Version 0.1.8.3¶
Major update in the code structuring with the inclusion of MOFstructure class which makes the entire code more modular and easy to use. In addition, the code can now guess the names of common ligands.
Updates Version 0.1.8.2¶
Fixed the python dependency to be compatible with any Python 3.9 and above.
pip install rdkit
Updates Version 0.1.8.1¶
Made rdkit to be an optional dependency so that mofstructure should be compatible with Python 3.12, since there are no recent versions of rdkit that are compatible with Python 3.12. Hence if you wish to use rdkit, you should install it separately.
pip install rdkit
Updates Version 0.1.8¶
1. The main update here is to enable mofstructure to run on Python versions 3.9 to 3.13. We have done the necessary tests but let us know if you have any conflicts or bugs and we will fix it.
Updates Version 0.1.7¶
Implemented a robust CI/CD using Git Actions.
Included add_dummy key to add dummy atoms to points of extension. This is important to effectively control the breaking point. These dummy atoms can then be replaced with hydrogen to fully neutralize the system.
Note
Please don’t use add_dummy when deconstructing to ligands and clusters. The add_dummy argument should be used only for SBUs, e.g.,
connected_components, atoms_indices_at_breaking_point, porpyrin_checker, all_regions = MOF_deconstructor.secondary_building_units(ase_atom)
metal_sbus, organic_sbus, building_unit_regions = MOF_deconstructor.find_unique_building_units(
connected_components,
atoms_indices_at_breaking_point,
ase_atom,
porpyrin_checker,
all_regions,
cheminfo=True,
add_dummy=True
)
metal_sbus[0].write('test1.xyz')
Updates Version 0.1.6¶
Added new command line tools to expedite calculations, especially when working on a large database.
Compute Only Deconstruction¶
If you wish to only compute the deconstruction of MOFs without having to compute their porosity and open metal sites, then simply run the following command:
mofstructure_building_units cif_folder
Compute Only Porosity¶
If you wish to only compute the porosity using default values (i.e., probe radius = 1.86, number of GCMC cycles = 10,000, and default CSD atomic radii), then run the following command:
mofstructure_porosity cif_folder
However, if you wish to use another probe radius (e.g., 1.5) and GCMC cycles of 20,000, alongside custom atomic radii in a file called rad.rad, run the following command:
mofstructure_porosity cif_folder -pr 1.5 -ns 20000 -rf rad.rad
Compute Only Open Metal Sites¶
If you are only interested in computing the open metal sites, then run the following command:
mofstructure_oms cif_folder
Updates Version 0.1.5¶
The new update enables users to include a RAD file when computing porosity using PyZeo. This allows users to specify the type of radii to use. If omitted, the default PyZeo radii will be used, which are covalent radii obtained from the CSD.
Currently, this functionality can only be used when using mofstructure as a library. This can be done as follows:
from mofstructure.porosity import zeo_calculation
from ase.io import read
ase_atom = read(filename)
pore_data = zeo_calculation(ase_atom, rad_file='rad_file_name.rad')
Note
filename is any ASE-readable crystal structure file, ideally a CIF file. Moreover, rad_file_name.rad is a file containing the radii of each element present in the structure file. This should be formatted as follows:
element radii
For example, for an MgO system, your RAD file should look like this:
Mg 0.66
O 1.84
Also, note that if the radii file does not have the .rad extension like rad_file_name.rad, the default radii will be used.
Updates Version 0.1.4¶
The new update enables the computation of open metal sites in CIFs. To use this functionality, run the following on the command line:
mofstructure_database ciffolder --oms
Here, ciffolder corresponds to the directory/folder containing the CIF files.
After computation, the metal information will be found in a JSON file called metal_info.json. This file is located in the output folder that defaults to MOFDb if no other folder is provided.
Note
Computing open metal sites is computationally expensive, especially if you intend to run it on a folder with many CIF files. If you are not interested in computing the open metal sites, simply run the command without the –oms option:
mofstructure_database ciffolder
This command will generate a MOFDb folder without the metal_info.json file, but the code will run much faster.
Also, note that the –oms option is only provided for the mofstructure_database command and is not available for the mofstructure command, which targets a single CIF file. If you have a single CIF file and wish to compute open metal sites, simply put the CIF file in a folder and run the mofstructure_database command on that folder:
mofstructure_database ciffolder --oms