Skip to main content

Crystal Description Language (CDL) parser for crystallographic visualization

Project description

cdl-parser

PyPI version Python License: MIT

Crystal Description Language (CDL) Parser - A Python library for parsing compact string notation describing crystal morphology for gemmological and mineralogical visualization.

Part of the Gemmology Project.

Installation

pip install cdl-parser

Quick Start

from cdl_parser import parse_cdl

# Parse a simple octahedron
desc = parse_cdl("cubic[m3m]:{111}")
print(desc.system)      # 'cubic'
print(desc.point_group) # 'm3m'

# Parse a truncated octahedron (diamond-like)
desc = parse_cdl("cubic[m3m]:{111}@1.0 + {100}@1.3")
print(len(desc.forms))  # 2

# Parse with twin specification
desc = parse_cdl("cubic[m3m]:{111} | twin(spinel)")
print(desc.twin.law)    # 'spinel'

CDL Specification

Syntax Overview

system[point_group]:{form}@scale + {form}@scale | modification | twin(law)

Crystal Systems

All 7 crystal systems are supported with their standard point groups:

System Default Point Group All Point Groups
cubic m3m m3m, 432, -43m, m-3, 23
hexagonal 6/mmm 6/mmm, 622, 6mm, -6m2, 6/m, -6, 6
trigonal -3m -3m, 32, 3m, -3, 3
tetragonal 4/mmm 4/mmm, 422, 4mm, -42m, 4/m, -4, 4
orthorhombic mmm mmm, 222, mm2
monoclinic 2/m 2/m, m, 2
triclinic -1 -1, 1

Miller Indices

Forms are specified using Miller indices in curly braces:

# 3-index notation (hkl)
"{111}"   # Octahedron face
"{100}"   # Cube face
"{110}"   # Dodecahedron face

# 4-index notation for hexagonal/trigonal (hkil where i = -(h+k))
"{10-10}" # Hexagonal prism
"{10-11}" # Rhombohedron
"{0001}"  # Basal pinacoid

Named Forms

Common forms can be referenced by name:

# Cubic named forms
"octahedron"      # → {111}
"cube"            # → {100}
"dodecahedron"    # → {110}
"trapezohedron"   # → {211}

# Hexagonal/Trigonal named forms
"prism"           # → {10-10}
"basal"           # → {0001}
"rhombohedron"    # → {10-11}

Scale Values

The @scale parameter controls the relative prominence of forms:

# Larger scale = form appears more (more truncation)
"{111}@1.0 + {100}@1.3"  # Cube truncates the octahedron
"{111}@1.0 + {100}@0.3"  # Octahedron with small cube facets

Twin Laws

Named twin laws for common crystal twins:

# Contact twins
"twin(spinel)"      # Spinel law (111) twin
"twin(brazil)"      # Brazil law quartz twin
"twin(japan)"       # Japan law quartz twin

# Penetration twins
"twin(fluorite)"    # Fluorite interpenetration twin
"twin(iron_cross)"  # Iron cross pyrite twin

# Cyclic twins
"twin(trilling,3)"  # Three-fold cyclic twin

Complete Examples

# Diamond (octahedron with cube truncation)
"cubic[m3m]:{111}@1.0 + {100}@0.3"

# Quartz prism with rhombohedron termination
"trigonal[-3m]:{10-10}@1.0 + {10-11}@0.8"

# Garnet (dodecahedron + trapezohedron)
"cubic[m3m]:{110}@1.0 + {211}@0.6"

# Spinel-law twinned octahedron
"cubic[m3m]:{111} | twin(spinel)"

# Fluorite cube
"cubic[m3m]:{100}"

API Reference

Core Functions

parse_cdl(text: str) -> CrystalDescription

Parse a CDL string into a structured description.

from cdl_parser import parse_cdl

desc = parse_cdl("cubic[m3m]:{111}@1.0 + {100}@1.3")

validate_cdl(text: str) -> tuple[bool, str | None]

Validate a CDL string without parsing.

from cdl_parser import validate_cdl

is_valid, error = validate_cdl("cubic[m3m]:{111}")
if not is_valid:
    print(f"Error: {error}")

Data Classes

CrystalDescription

Main output of CDL parsing.

@dataclass
class CrystalDescription:
    system: str                          # Crystal system
    point_group: str                     # Point group symbol
    forms: List[CrystalForm]             # Crystal forms
    modifications: List[Modification]    # Morphological mods
    twin: Optional[TwinSpec]             # Twin specification

MillerIndex

Miller index representation.

@dataclass
class MillerIndex:
    h: int
    k: int
    l: int
    i: Optional[int] = None  # For 4-index notation

    def as_tuple(self) -> tuple[int, ...]
    def as_3index(self) -> tuple[int, int, int]

CrystalForm

A crystal form with scale.

@dataclass
class CrystalForm:
    miller: MillerIndex
    scale: float = 1.0
    name: Optional[str] = None

Constants

from cdl_parser import (
    CRYSTAL_SYSTEMS,      # Set of system names
    POINT_GROUPS,         # Dict[system, Set[groups]]
    DEFAULT_POINT_GROUPS, # Dict[system, default_group]
    NAMED_FORMS,          # Dict[name, (h, k, l)]
    TWIN_LAWS,            # Set of twin law names
)

Exceptions

from cdl_parser import ParseError, ValidationError

try:
    desc = parse_cdl("invalid{{{")
except ParseError as e:
    print(f"Syntax error at position {e.position}: {e.message}")

CLI Usage

# Parse and display
cdl parse "cubic[m3m]:{111}@1.0 + {100}@1.3"

# Validate
cdl validate "cubic[m3m]:{111}"

# Output as JSON
cdl parse "cubic[m3m]:{111}" --json

# List available options
cdl --list-systems
cdl --list-point-groups
cdl --list-forms
cdl --list-twins

Integration with Other Packages

cdl-parser is designed to work with the Gemmology Project ecosystem:

from cdl_parser import parse_cdl
from crystal_geometry import cdl_to_geometry
from crystal_renderer import generate_cdl_svg, generate_geometry_svg

# Option 1: Direct CDL string to SVG
cdl = "cubic[m3m]:{111}@1.0 + {100}@1.3"
generate_cdl_svg(cdl, "crystal.svg")

# Option 2: Parse, then generate geometry for custom processing
desc = parse_cdl(cdl)
geometry = cdl_to_geometry(desc)

# Render geometry directly
generate_geometry_svg(geometry.vertices, geometry.faces, "geometry.svg")

Development

# Clone the repository
git clone https://github.com/gemmology-dev/cdl-parser.git
cd cdl-parser

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Type checking
mypy src/cdl_parser

# Linting
ruff check src/cdl_parser

Documentation

Full documentation is available at cdl-parser.gemmology.dev.

License

MIT License - see LICENSE for details.

Related Projects

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gemmology_cdl_parser-1.0.0.tar.gz (21.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gemmology_cdl_parser-1.0.0-py3-none-any.whl (17.4 kB view details)

Uploaded Python 3

File details

Details for the file gemmology_cdl_parser-1.0.0.tar.gz.

File metadata

  • Download URL: gemmology_cdl_parser-1.0.0.tar.gz
  • Upload date:
  • Size: 21.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for gemmology_cdl_parser-1.0.0.tar.gz
Algorithm Hash digest
SHA256 e8d7559f206e0552583d70028f78cf91bd2414e10cd4f7ebc600a6873c664458
MD5 4e6f22218d526b7fa36edc03005adb6c
BLAKE2b-256 6b17dd001d49419e2e18bdc5194ed076a4109078c30b98bd8b8f42f5f4c50e41

See more details on using hashes here.

Provenance

The following attestation bundles were made for gemmology_cdl_parser-1.0.0.tar.gz:

Publisher: pypi-publish.yml on gemmology-dev/cdl-parser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gemmology_cdl_parser-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for gemmology_cdl_parser-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1b4ffed2a9075ad74d297ec3cdf12a9b1857ad50c0a94991f2476eaa536d7f48
MD5 d62809b1b6c24a786c3374a5163d96f7
BLAKE2b-256 dab4cfca842c423af6981dc731f4957607e78bd5a4607f7d5a6783ebeeb1ab09

See more details on using hashes here.

Provenance

The following attestation bundles were made for gemmology_cdl_parser-1.0.0-py3-none-any.whl:

Publisher: pypi-publish.yml on gemmology-dev/cdl-parser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page