Skip to main content

cg-pytools

A small library for analysing crystal morphology from CrystoGen (formerly CrystalGrower) - crystal growth simulations: shape characterisation (Zingg ratios, aspect ratios, surface area / volume), Wulff and surface processing, energy-network parsing, and plotting utilities. It also ships example SGE / SLURM job scripts for running CrystoGen + OCC workflows (solvent screens, growth rates, growth modifiers, …) on HPC clusters.

For a full, GUI-driven workflow, see CGAspects — CrystoGen's official (PySide6) data-analysis tool for CrystoGen output. cg-pytools is a stripped-down, lightweight alternative: a scriptable library and command-line utilities for the same kind of analysis, without the GUI. It is currently limited in scope, and may in future grow to contain the core of CGAspects.

Installation

pip install cg-pytools

Or, for local development:

git clone https://github.com/CrystoGenLtd/cg-pytools.git
cd cg-pytools
pip install -e .

Usage

Shape analysis

CrystalShape reads .xyz (multi-frame), .txt, and mesh files (.stl, .ply, .glb); ShapeAnalyser turns those coordinates into morphology metrics (bounding-box or SVD/PCA lengths, Zingg aspect ratios, surface area, volume, surface-area-to-volume ratio, and a shape class).

from cgpytools import CrystalShape, ShapeAnalyser

crystal = CrystalShape.from_file("crystal.xyz")

analyser = ShapeAnalyser(zingg_method="svd")
analyser.analyse_crystal(crystal)          # all frames; pass frame_idx for one
metrics = analyser.get_all_frame_metrics()  # {frame_idx: ShapeMetrics}

first = metrics[0]
print(first.aspect1, first.aspect2, first.shape, first.surface_area_to_volume_ratio)

Wulff shapes from surface energies

CrystalWulff loads the crystallographic information (lattice matrices, symmetry operations, surface cuts and their energies) from a CrystoGen surface energies JSON file, expands the facets by symmetry, and builds the Wulff shape.

from cgpytools.analysis.surfaces import CrystalWulff

wulff = CrystalWulff.from_json("cg_results.json")
print(wulff.n_surfaces, wulff.n_molecules)

# Wulff shape from the stored energies, written to disk as a mesh
mesh = wulff.to_mesh(name="wulff", savedir="shapes", suffix=".stl", solvation="solvated")
print(mesh.volume)

# Spherical harmonic coefficients instead of a mesh
coeffs = wulff.to_mesh(solvation="vacuum", save=False, to_return="sph", l_max=20)

# Point cloud (xyz) reconstructed from the harmonic expansion
wulff.to_xyz(name="wulff", savedir="shapes", index=0, l_max=20)

# Lowest-energy cut per unique Miller index
reduced = wulff.reduced_surface_energies(context="solvated")

Facets and energies from elsewhere (e.g. a CrystoGen size file) can be fed in directly:

import numpy as np
from cgpytools.analysis.surfaces import (
    CrystalWulff,
    generate_wulff_shapes_from_size_file,
    parse_size_file_headers,
)

wulff = CrystalWulff.from_json("cg_results.json")

facets = parse_size_file_headers("size.csv")     # Miller indices from the headers
energies = np.array([...])                        # one energy per facet
mesh = wulff.calculate_wulff_shape(facets, energies, expand_symmetry=True)

# Or sweep a whole simulation: a shape every n time steps, written to size.csv's
# parent directory under shapes/
results = generate_wulff_shapes_from_size_file(wulff, "size.csv", n_steps=10, file_format="stl")

Energy networks

CGNet parses a CrystoGen .net interaction-energy file into molecules and interactions, and can group equivalent interactions or swap the energies out.

from cgpytools import CGNet

net = CGNet("crystal.net")
net.parse()

print(net.n_energies, net.n_unique_energies)
print(net.unique_energies)          # {molecule_label: array of energies}

net.group_net("r")                  # group by distance ("r", "mol_type" or "energy")
net.write("grouped.net")

Plotting and logging

from cgpytools.plot.plot import setup_global_style
from cgpytools.io.log import setup_logging

log = setup_logging(basic_level="DEBUG", console_level="INFO")
setup_global_style("publication")   # "modern", "classic", "minimal", "dark", "publication"

setup_logging attaches a console handler plus console.log and report.log file handlers to the root logger. The library logs rather than prints, so results such as the info summary below only reach the console once logging is configured. Note that cgpytools.analysis.surfaces calls setup_logging at import time (which is why its CLI prints without extra setup, and why importing it creates the two log files); cgpytools.io.net does not, so configure logging yourself to see its messages.

Command line

Installing the package provides two commands:

Command Module Purpose
cg-surfaces cgpytools.analysis.surfaces Wulff shapes and surface energies from an OCC results JSON
cg-screen cgpytools.analysis.screen Batch crystal-shape analysis and plotting (general / solvent / size / movie / CDA modes)

cg-surfaces takes the *_cg_results.json file that OCC writes when run with --surface-energies <n>; without that flag the JSON has no surface cuts, and only info will work.

cg-surfaces

# Summary of the crystal, its surface cuts and the lowest-energy cut per hkl,
# with a column for each of the vacuum and solvated energies
cg-surfaces cg_results.json info

# Restrict both tables to one context, and pick the lowest-energy cuts on it
cg-surfaces cg_results.json info --context vacuum

# Export the Wulff shape as a mesh, using only the lowest-energy cuts
cg-surfaces cg_results.json mesh \
    -o shapes --name wulff --suffix .stl --solvation solvated --reduced

# Export the Wulff shape as an xyz point cloud
cg-surfaces cg_results.json xyz \
    -o shapes --name wulff --index 0 --l-max 20

# Generate shapes from one or more size files, every 10 time steps
cg-surfaces cg_results.json size size.csv \
    -o results -n 10 --format stl

cg-screen

Walks an input directory, discovers the relevant CrystoGen outputs and writes CSV summaries plus Zingg / heatmap / line plots. See docs/screen.md for the full guide.

# Morphology of every shape file under ./crystals
cg-screen -i ./crystals --general

# Solvent screen, including OCC solubilities and net-file energies
cg-screen -i ./solvent_screen --solvent -s solvents.json --occ --energies

# Growth dynamics from size.csv files, a Wulff shape every 10 steps
cg-screen -i ./growth_data --size -c example_cg_results.json --wulff-interval 10

net remains runnable as a module:

# Group a net file by interaction distance
python -m cgpytools.io.net -i crystal.net -o grouped.net --group -k r

Modules

Module Purpose
cgpytools.io.crystal Read crystal shapes / frames (CrystalShape, Frame, Frames)
cgpytools.analysis.shape_analysis Morphology metrics, Zingg classification (ShapeAnalyser)
cgpytools.analysis.surfaces Wulff construction and surface/size-file processing (CrystalWulff); cg-surfaces CLI
cgpytools.analysis.screen Batch shape-analysis pipeline and plots (CrystalShapeAnalysisPipeline); cg-screen CLI
cgpytools.io.net Interaction-energy network parsing (CGNet)
cgpytools.plot.plot Shared plotting theme and styling helpers (setup_global_style)
cgpytools.io.log Logging configuration (setup_logging)

CrystalShape, ShapeAnalyser and CGNet are re-exported from the top-level cgpytools package; everything else is imported from its module.

Scripts

Standalone scripts live in scripts/python/:

Script Depends on Description
growth_kinetics.py numpy, pandas, matplotlib, scipy Time-evolution plots of size data from simulation subfolders.
growth_rates.py numpy, pandas, matplotlib Growth-rate-vs-supersaturation summaries from size.csv files.

Both are single-file and have no dependency on cgpytools — they can be copied and run on their own. The screening tool that used to live here is now part of the package, installed as the cg-screen command (see docs/screen.md).

HPC job scripts

Example SGE and SLURM job scripts for the CrystoGen + OCC workflows live under scripts/HPC/ organised by use case (solvent screens, growth rates, etc.). Each folder has a README.txt describing the inputs it needs.

Copy the scripts to a folder containing a CIF or other inputs, depending on which job type is to be submitted.

Acknowledgements

The Wulff construction and spherical harmonic tools in surfaces are built on chmpy by Peter Spackman. chmpy provides WulffConstruction (the dual-space Wulff construction, its mesh and spherical harmonic transform) and reconstruct (point clouds from spherical harmonic coefficients).

Parts of cgpytools.analysis.surfaces were also written by Peter Spackman, or adapted from chmpy — in particular the symmetry expansion and unique-direction reduction of Miller indices — and are used here with his permission. Those sections are marked in the source.

License

Copyright © 2026 Alvin Jenner W and contributors.

cg-pytools is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version — the same licence as CGAspects.

It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

See COPYING.LESSER (LGPLv3) and COPYING (GPLv3).

cg-pytools depends on chmpy, which is distributed under the GPL-3.0-or-later licence. chmpy is a dependency rather than vendored code, but note that a distributed work combining the two is covered by the GPL.

Metadata

Release files for cg-pytools 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cg-pytools 0.2.0
File Size Uploaded
cg_pytools-0.2.0.tar.gz 69.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cg-pytools 0.2.0
File Interpreter ABI Platform
cg_pytools-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 141.1 kB

Release files / cg_pytools-0.2.0.tar.gz

Download URL cg_pytools-0.2.0.tar.gz
Size 69.0 kB
Tags Source
SHA-256 checksum
How to use checksums
c48b1776ab899f4f82117c2e2a40f8db874ebeb366a06519d265b6c99a4a79f9
BLAKE2b-256 checksum
How to use checksums
82266e67ffb4284b3771b36509cdb50e26a928e51b725e70a32b904d06b39945
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 3, 2026.

Transparency log

Release files / cg_pytools-0.2.0-py3-none-any.whl

Download URL cg_pytools-0.2.0-py3-none-any.whl
Size 72.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
72e99299f50078f726a6e724f158e612879ae7bad9cab78dc2182dbcd52f683a
BLAKE2b-256 checksum
How to use checksums
ddf523a23677e4e9a01d5f6eeaf42581815fa7d8a071b173f507af2336a19960
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 3, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.2

2 release files

0.2.1

2 release files

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page