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.1.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.1-py3-none-any.whl (17.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: gemmology_cdl_parser-1.0.1.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.1.tar.gz
Algorithm Hash digest
SHA256 f45599d0821f0738b700a9a72786b4a671e0ef07d740928455097537c8f2c88e
MD5 89f2c950076b31515c2a2592ea00ab0f
BLAKE2b-256 b83f9a488fa1b7515cf2d68a51cec9d12c2a13045a9a44a10902567c00bae0a7

See more details on using hashes here.

Provenance

The following attestation bundles were made for gemmology_cdl_parser-1.0.1.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.1-py3-none-any.whl.

File metadata

File hashes

Hashes for gemmology_cdl_parser-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 23cb10a9e97a40fed5aa974c70531573eb173c187266244e6ee688d9a9de4430
MD5 cbc7b9e341250536b99c41003ed2e853
BLAKE2b-256 41401dd9bf2954b8b88cf3369f17efe6d4384f51f0eb40cad4f4c8d1345e99f3

See more details on using hashes here.

Provenance

The following attestation bundles were made for gemmology_cdl_parser-1.0.1-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