mineral-database

SQLite database of 96 mineral families (68 natural + 15 synthetic + 9 simulant + 4 composite) with 140 CDL expressions, crystal system data, and gemmological properties. Version 1.8.1. Now includes amorphous material support for opal, turquoise, pearl, and more.

pip install gemmology-mineral-database

Core Query Functions

# get_preset(name: str) → dict[str, Any] | None

Get a mineral preset by name (case-insensitive). Returns a dictionary.

from mineral_database import get_preset

preset = get_preset("quartz")
if preset:
    print(preset['name'])         # "Quartz"
    print(preset['cdl'])          # CDL expression string
    print(preset['system'])       # "trigonal"
    print(preset['hardness'])     # "7"
    print(preset['ri'])           # "1.544-1.553"
# get_mineral(name: str) → Mineral | None

Get a Mineral object by name. Returns a typed dataclass instead of a dict.

from mineral_database import get_mineral

mineral = get_mineral("diamond-octahedron")
if mineral:
    print(mineral.name)     # "Diamond"
    print(mineral.cdl)      # "cubic[m3m]:{111}@1.0 + {110}@0.2"
    print(mineral.system)   # "cubic"
    print(mineral.origin)   # "natural"
# list_presets(category: str | None = None) → list[str]

List all available preset names, optionally filtered by crystal system or category.

from mineral_database import list_presets

names = list_presets()
print(len(names))  # 140

# Filter by crystal system
cubic = list_presets("cubic")
print(len(cubic))  # All cubic presets
# search_presets(query: str) → list[str]

Search presets using full-text search across name, chemistry, and description.

from mineral_database import search_presets

results = search_presets("beryl")
print(results)  # ['beryl-prismatic', 'emerald-prismatic', ...]

results = search_presets("SiO2")
print(results)  # Quartz, Amethyst, etc.
# filter_minerals(system=None, min_hardness=None, max_hardness=None, has_twin=False) → list[str]

Filter minerals by various criteria.

from mineral_database import filter_minerals

# Durable gems (hardness 7+)
durable = filter_minerals(min_hardness=7.0)

# Cubic minerals with twins
cubic_twins = filter_minerals(system="cubic", has_twin=True)

RI/SG Lookup

# find_by_ri(ri: float, tolerance: float = 0.01) → list[Mineral]

Find minerals matching a measured refractive index, sorted by closest match.

from mineral_database import find_by_ri

matches = find_by_ri(1.544, tolerance=0.01)
for m in matches:
    print(f"{m.name}: RI {m.ri}")
# find_by_sg(sg: float, tolerance: float = 0.05) → list[Mineral]

Find minerals matching a specific gravity value, sorted by closest match.

Synthetic and Simulant Queries

# list_synthetics(growth_method: str | None = None) → list[str]

List all synthetic mineral family IDs, optionally filtered by growth method.

from mineral_database import list_synthetics

# All synthetics
synths = list_synthetics()
print(synths)  # ['cvd-diamond', 'flame-fusion-ruby', ...]

# Filter by method
flux = list_synthetics(growth_method="flux")
print(flux)  # Flux-grown synthetics only
# list_simulants(target: str | None = None) → list[str]

List all simulant mineral family IDs, optionally filtered by what they imitate.

from mineral_database import list_simulants

# All simulants
sims = list_simulants()
print(sims)  # ['cubic-zirconia', 'moissanite', ...]

# Diamond simulants specifically
diamond_sims = list_simulants(target="diamond")
print(diamond_sims)  # ['cubic-zirconia', 'moissanite', ...]
# get_counterparts(name: str) → dict[str, list[str]]

Get all synthetic and simulant counterparts for a natural mineral.

from mineral_database import get_counterparts

cp = get_counterparts("diamond")
print(cp['synthetics'])  # ['cvd-diamond', 'hpht-diamond']
print(cp['simulants'])   # ['cubic-zirconia', 'moissanite', ...]
# list_by_origin(origin: str) → list[str]

List all mineral family IDs filtered by origin type.

from mineral_database import list_by_origin

naturals = list_by_origin("natural")     # 68 families
synthetics = list_by_origin("synthetic") # 15 families
simulants = list_by_origin("simulant")   # 9 families
composites = list_by_origin("composite") # 4 families
# get_family(name: str) → MineralFamily | None

Get a MineralFamily object by ID, including synthetic-specific fields.

from mineral_database import get_family

family = get_family("cubic-zirconia")
if family:
    print(family.name)                  # "Cubic Zirconia"
    print(family.origin)                # "simulant"
    print(family.natural_counterpart_id) # "diamond"
    print(family.growth_method)          # "skull_melting"

Calculator Utilities

# classify(category: str, value: float) → str | None

Classify a gemmological value based on standard thresholds.

from mineral_database import classify

# Birefringence classification
print(classify("birefringence", 0.009))  # "low"
print(classify("birefringence", 0.045))  # "high"

# Dispersion classification
print(classify("dispersion", 0.044))  # "very_high" (diamond)

# Critical angle classification
print(classify("critical_angle", 24.4))  # "very_small" (diamond)
# list_shape_factors() → list[dict]

Get cut shape factors for carat weight estimation.

# list_heat_treatable() → list[Mineral]

Get minerals with heat treatment temperature data.

Database Configuration

# set_database_path(path: Path) → None

Override the default database path for all queries.

from pathlib import Path
from mineral_database import set_database_path

set_database_path(Path("/path/to/custom/minerals.db"))

Classes

Mineral

Dataclass representing a mineral preset with all gemmological properties.

AttributeTypeDescription
id str Preset ID (e.g., "diamond-octahedron")
name str Display name
cdl str CDL expression
system str Crystal system
point_group str Point group symbol
chemistry str Chemical formula
hardness int | float | str Mohs hardness (may be range like "6-7")
sg float | str | None Specific gravity
ri float | str | None Refractive index
birefringence float | None Maximum birefringence
optical_character str | None Optical character
dispersion float | None Dispersion value
colors list[str] Common colours
cleavage str | None Cleavage description
twin_law str | None Twin law name
origin str Origin: natural, synthetic, simulant, or composite

MineralFamily

Dataclass representing a mineral family (normalized structure). Includes synthetic-specific fields like growth_method, manufacturer, and diagnostic_synthetic_features.

AttributeTypeDescription
id str Family ID (e.g., "diamond")
name str Display name (e.g., "Diamond")
crystal_system str Crystal system
point_group str | None Point group symbol
chemistry str | None Chemical formula
origin str Origin: natural, synthetic, simulant, composite
growth_method str | None Synthesis method (synthetics only)
natural_counterpart_id str | None ID of natural equivalent

Included Data

The database includes 96 mineral families with 140 CDL expressions:

Natural (68)

Diamond, Ruby, Emerald, Quartz, Garnet...

Synthetic (15)

CVD Diamond, Flux Ruby, Hydrothermal Emerald...

Simulant (9)

CZ, Moissanite, YAG, Glass...

Composite (4)

Garnet-Topped Doublet, Opal Triplet...

Amorphous material support

Materials previously without CDL expressions (opal, turquoise, pearl, obsidian, amber, chalcedony) now use the CDL v2.0 amorphous system with shape descriptors. These expressions use subtypes like opalescent, waxy, and glassy instead of crystal systems and point groups.