Skip to content

Repository files navigation

cdl-parser

PyPI versionPythonLicense: MIT

Crystal Description Language (CDL) Parser - A Python library for parsing compact string notation describing crystal morphology for gemmological and mineralogical visualization. CDL v2.0 adds support for amorphous materials, nested growth, and crystal aggregates.

Part of the Gemmology Project.

Installation

pip install cdl-parser

Quick Start

fromcdl_parserimportparse_cdl# Parse a simple octahedrondesc=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 specificationdesc=parse_cdl("cubic[m3m]:{111} | twin(spinel)")
print(desc.twin.law) # 'spinel'# Parse an amorphous material (v2.0)desc=parse_cdl("amorphous[opalescent]:{botryoidal}")
print(desc.system) # 'amorphous'print(desc.subtype) # 'opalescent'# Parse nested growth (v2.0)desc=parse_cdl("trigonal[32]:({10-10}@1.0 + {10-11}@0.8) > ({10-10}@0.5 + {10-11}@0.4)")
# Parse an aggregate (v2.0)desc=parse_cdl("trigonal[32]:{10-10}@1.0 + {10-11}@0.8 ~ cluster[12]")

CDL Specification

Syntax Overview

# Crystalline materials
system[point_group]:{form}@scale + {form}@scale | modification | twin(law)
# Amorphous materials (v2.0)
amorphous[subtype]:{shape1, shape2}[features] | phenomenon[type]
# Nested growth (v2.0)
system[point_group]:(forms) > (overgrowth_forms)
# Aggregates (v2.0)
system[point_group]:forms ~ arrangement[count]

Crystal Systems

All 7 crystal systems are supported with their standard point groups, plus amorphous materials:

SystemDefault Point GroupAll Point Groups
cubicm3mm3m, 432, -43m, m-3, 23
hexagonal6/mmm6/mmm, 622, 6mm, -6m2, 6/m, -6, 6
trigonal-3m-3m, 32, 3m, -3, 3
tetragonal4/mmm4/mmm, 422, 4mm, -42m, 4/m, -4, 4
orthorhombicmmmmmm, 222, mm2
monoclinic2/m2/m, m, 2
triclinic-1-1, 1
amorphousnone(n/a)

Amorphous Materials (v2.0)

Materials without crystalline structure use the amorphous keyword instead of a crystal system:

# Syntax: amorphous[subtype]:{shape1, shape2}[features]"amorphous[opalescent]:{botryoidal}""amorphous[cryptocrystalline]:{massive, nodular}[colour:blue]""amorphous[waxy]:{mammillary}[banding:concentric]"

Subtypes:opalescent, glassy, waxy, resinous, cryptocrystalline

Shapes:massive, botryoidal, reniform, stalactitic, mammillary, nodular, conchoidal

Nested Growth (v2.0)

The > operator describes overgrowth relationships (base > overgrowth), where an outer crystal grows on an inner one. Right-associative: a > b > c = a > (b > c).

# Scepter quartz — enlarged head on thin stem"trigonal[32]:({10-10}@1.0 + {10-11}@0.8) > ({10-10}@0.5 + {10-11}@0.4)"# Diamond phantom"cubic[m3m]:{111}@1.0 > {111}@1.0"

Aggregates (v2.0)

The ~ operator describes crystal aggregates — multiple copies of a form arranged in a spatial pattern:

# Syntax: forms ~ arrangement[count]"trigonal[32]:{10-10}@1.0 + {10-11}@0.8 ~ cluster[12]"# Quartz cluster"trigonal[32]:{10-10}@1.0 + {10-11}@0.8 ~ druse[50]"# Amethyst geode"cubic[m3m]:{100} ~ cluster[5]"# Pyrite cluster"trigonal[-3m]:rhombohedron ~ parallel[3]"# Calcite parallel growth

Arrangements:parallel, random, radial, epitaxial, druse, cluster

Orientations (optional): aligned, random, planar, spherical

Group-Level Twins (v2.0)

Twin specifications can be applied to form groups, allowing twinning of composite morphologies:

# Twin a group of forms"cubic[m3m]:({111}@1.0 + {100}@0.3) | twin(spinel)"

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}"# Opal — amorphous with play of color (v2.0)"amorphous[opalescent]:{botryoidal} | phenomenon[play_of_color:intense]"# Turquoise — cryptocrystalline massive (v2.0)"amorphous[cryptocrystalline]:{massive, nodular}[colour:blue]"# Scepter quartz — nested growth (v2.0)"trigonal[32]:({10-10}@1.0 + {10-11}@0.8) > ({10-10}@0.5 + {10-11}@0.4)"# Quartz cluster aggregate (v2.0)"trigonal[32]:{10-10}@1.0 + {10-11}@0.8 ~ cluster[12]"# Amethyst geode druse (v2.0)"trigonal[32]:{10-10}@1.0 + {10-11}@0.8 ~ druse[50]"

API Reference

Core Functions

parse_cdl(text: str) -> CrystalDescription | AmorphousDescription

Parse a CDL string into a structured description. Returns CrystalDescription for crystalline materials or AmorphousDescription for amorphous materials.

fromcdl_parserimportparse_cdl# Crystalline — returns CrystalDescriptiondesc=parse_cdl("cubic[m3m]:{111}@1.0 + {100}@1.3")
# Amorphous — returns AmorphousDescription (v2.0)desc=parse_cdl("amorphous[opalescent]:{botryoidal}")

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

Validate a CDL string without parsing.

fromcdl_parserimportvalidate_cdlis_valid, error=validate_cdl("cubic[m3m]:{111}")
ifnotis_valid:
print(f"Error: {error}")

Data Classes

CrystalDescription

Main output of CDL parsing for crystalline materials.

@dataclassclassCrystalDescription:
system: str# Crystal systempoint_group: str# Point group symbolforms: list[FormNode] # Form tree (CrystalForm | FormGroup | NestedGrowth | AggregateSpec)modifications: list[Modification] # Morphological modstwin: TwinSpec|None# Twin specificationphenomenon: PhenomenonSpec|None# Optical phenomenondoc_comments: list[str] |None# Doc comments (#!)definitions: list[Definition] |None# Named definitions (@name = ...)defflat_forms(self) ->list[CrystalForm]:
"""Flatten form tree into a list of CrystalForm leaves."""

AmorphousDescription (v2.0)

Output of CDL parsing for amorphous (non-crystalline) materials.

@dataclassclassAmorphousDescription:
subtype: str# 'opalescent', 'glassy', 'waxy', etc.shapes: list[str] # 'massive', 'botryoidal', etc.features: list[Feature] |None# Feature annotationsphenomenon: PhenomenonSpec|None# Optical phenomenondoc_comments: list[str] |None# Doc comments (#!)definitions: list[Definition] |None# Named definitions@propertydefsystem(self) ->str: # Always returns 'amorphous'

NestedGrowth (v2.0)

Represents a base crystal with an overgrowth (the > operator).

@dataclassclassNestedGrowth:
base: FormNode# Base form nodeovergrowth: FormNode# Overgrowth form node

AggregateSpec (v2.0)

Represents a crystal aggregate (the ~ operator).

@dataclassclassAggregateSpec:
form: FormNode# Form to aggregatearrangement: str# 'parallel', 'random', 'radial', etc.count: int# Number of individualsspacing: str|None# Optional spacing valueorientation: str|None# Optional orientation modeorientation_param: float|None# Optional orientation parameter

MillerIndex

Miller index representation.

@dataclassclassMillerIndex:
h: intk: intl: inti: Optional[int] =None# For 4-index notationdefas_tuple(self) ->tuple[int, ...]
defas_3index(self) ->tuple[int, int, int]

CrystalForm

A crystal form with scale.

@dataclassclassCrystalForm:
miller: MillerIndexscale: float=1.0name: Optional[str] =None

Constants

fromcdl_parserimport (
CRYSTAL_SYSTEMS, # Set of system namesPOINT_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 namesAMORPHOUS_SUBTYPES, # Set: opalescent, glassy, waxy, resinous, cryptocrystallineAMORPHOUS_SHAPES, # Set: massive, botryoidal, reniform, stalactitic, ...AGGREGATE_ARRANGEMENTS, # Set: parallel, random, radial, epitaxial, druse, clusterAGGREGATE_ORIENTATIONS, # Set: aligned, random, planar, spherical
)

Exceptions

fromcdl_parserimportParseError, ValidationErrortry:
desc=parse_cdl("invalid{{{")
exceptParseErrorase:
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:

fromcdl_parserimportparse_cdlfromcrystal_geometryimportcdl_to_geometryfromcrystal_rendererimportgenerate_cdl_svg, generate_geometry_svg# Option 1: Direct CDL string to SVGcdl="cubic[m3m]:{111}@1.0 + {100}@1.3"generate_cdl_svg(cdl, "crystal.svg")
# Option 2: Parse, then generate geometry for custom processingdesc=parse_cdl(cdl)
geometry=cdl_to_geometry(desc)
# Render geometry directlygenerate_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

About

Crystal Description Language parser and validator

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages