Quick Start Guide

This Quick Start Guide provides simple examples to help you begin using mofstructure for working with metal-organic frameworks (MOFs). We’ll cover basic command-line usage and how to use mofstructure as a Python library.

Running on the Command Line

Example 1: Deconstructing a MOF into Building Units

To deconstruct a MOF from a CIF file into its building units, run the following command:

mofstructure example_mof.cif

This command processes the example_mof.cif file and saves the output in a folder named MOF_building_units within the current directory.

Example 2: Specifying an Output Directory

If you want to save the deconstructed MOF in a specific folder, use this command:

mofstructure example_mof.cif /path/to/output_folder

Replace /path/to/output_folder with your desired output directory.

Example 3: Creating a Database from Multiple CIF Files

To create a database from a folder containing multiple CIF files, use the following command:

mofstructure_database /path/to/cif_folder

The database will be saved in a folder named MOFstructureDB in the current directory.

Using mofstructure as a Library

Example 1: Importing the Module and Reading a CIF File

Start by importing the necessary modules and reading a CIF file using ASE:

from mofstructure import mofdeconstructor
from ase.io import read

ase_atom = read('example_mof.cif')

Example 2: Removing Unbound Guest Molecules

To remove unbound guest molecules from the structure, use:

no_guest_indices = mofdeconstructor.remove_unbound_guest(ase_atom)
no_guest_atom = ase_atom[no_guest_indices]

Example 3: Computing Porosity

To compute the porosity of the MOF, run:

from mofstructure import porosity

pores = porosity.zeo_calculation(ase_atom, probe_radius=1.86)
print(pores)

The record always holds the same keys - av_volume_fraction, av_a3, asa_a2, asa_m2_per_cm3, number_of_channels, lcd_a, pld_a, lfpd_a and porosity_status. A structure zeo++ cannot handle, or one that runs past timeout seconds, comes back with None in place of each number and the reason in porosity_status, so a batch never stalls and a table never acquires holes.

Example 4: Deconstructing MOFs into SBUs and linkers

To identify and extract SBUs and linkers from the MOF:

connected_components, atoms_indices_at_breaking_point, porpyrin_checker, all_regions, breaking_pairs = MOF_deconstructor.secondary_building_units(ase_atom)

 metal_sbus, organic_sbus, _ = MOF_deconstructor.find_unique_building_units(
             connected_components,
             atoms_indices_at_breaking_point,
             ase_atom, porpyrin_checker,
             all_regions,
             cheminfo=True,
             add_dummy=True

         )

This code will output the SBUs and linkers along with their cheminformatic information.

Example 6: Determining the Topology of a MOF

To determine the topology of a framework. The kind of framework is worked out from the structure, so MOFs, COFs and zeolites can be passed alike:

from ase.io import read
from mofstructure.topology import analyse, analyse_methods

# 1) From a CGD periodic graph
print(analyse("net.cgd")["topology"])

# 2) From a CIF, naming the deconstruction
print(analyse("UiO-66.cif", method="all_node")["topology"])

# 3) From ASE Atoms, letting it choose
print(analyse(read("UiO-66.cif"))["topology"])

# 4) A MOF has more than one defensible net; report them all
for method, record in analyse_methods("UiO-66.cif").items():
    print(method, record["topology"])

The record also carries key, the canonical key. It is unique to the net and unchanged by supercell, atom order or origin, so two structures with the same key have the same topology whether or not any archive names it.

Example 7: Computing topology from the command line

To compute the topology of a MOF from the command line, run:

mofstructure_topology cif_folder

This computes the topology of every CIF file in the folder and appends the records to MOFstructureDB/Structure_Data/topology_data.json - the same file mofstructure_database writes to, so one folder holds one structure database however it was built. A topology_data.csv summary is written beside it, one row per structure. Use -s to name a different directory, --json to write the full records to a file of your choosing, and --no-save to print without writing.

A single file, several files or a folder may be named. Each structure is printed as it finishes and a tally closes the run; --quiet keeps the tally only, and -v reports each deconstruction as it is built.

A MOF admits more than one node definition. Pass --method to pick one of sbus, all_node, single_node or ligand_cluster, or --all-methods to record each of them under <structure>:<method>.

Example 8: Writing the net as a CGD file

mofstructure_generate_cgd writes the net itself as a CGD PERIODIC_GRAPH. --method takes the same node definitions, and auto reads the material from the structure:

mofstructure_generate_cgd HKUST-1.cif
mofstructure_generate_cgd zeolite.cif --method zeol -o zeolite.cgd

--embedding chooses the geometry written for the net. deconstruction, the default, writes the crystal’s own coordinates and needs no identification. ideal writes the canonical barycentric placement, with the cell fixed by the symmetry of the net alone; it is reproducible to the digit and carries the canonical key, so an unnamed net stays identifiable from its own file. refined relaxes that towards edges of equal length, which is what a tool building on the net needs.

mofstructure_generate_cgd HKUST-1.cif --embedding ideal
mofstructure_generate_cgd UiO-66.cif --embedding refined

The barycentric placement minimises the sum of squared edge lengths, so real nets emerge with the longest edge two or three times the shortest. Refining typically brings that spread from 2.2 down to 1.0, but its result depends on the optimiser and is not reproducible to the last digit, so every file records which embedding it holds. Where refining cannot beat the exact placement, the exact one is written and the command says so.