Odontogram & Periodontics
v0.1.0Interactive 5-surface anatomical tooth charting, morphological validation rules, and 6-point periodontal probing matrix.
Interactive Odontogram & Periodontics
The Odontogram & Periodontics bounded context provides anatomical dental charting, multi-system tooth notation, surface-level condition mapping, and full-mouth 6-point periodontal disease diagnostics.
Tooth Notation Systems & Dentition
Obelawium Dental natively supports international standard dental notation schemes:
use Obelaw\Ium\Dental\Enums\ToothNotationSystem;
use Obelaw\Ium\Dental\Enums\DentitionType;
enum ToothNotationSystem: string
{
case UNIVERSAL = 'universal'; // 1-32, A-T (American Standard)
case FDI = 'fdi'; // Two-digit ISO 3950 (11-48, 51-85)
case PALMER = 'palmer'; // Quadrant grid notation
}
enum DentitionType: string
{
case PERMANENT = 'permanent'; // 32 adult teeth
case DECIDUOUS = 'deciduous'; // 20 primary / pediatric teeth
}
The ToothNumber Value Object
The ToothNumber value object guarantees strict typing and automatic bidirectional conversion across notation standards:
use Obelaw\Ium\Dental\ValueObjects\ToothNumber;
// Instantiate from Universal number
$molar = ToothNumber::fromUniversal(14); // Upper Left First Molar
echo $molar->value; // 14
echo $molar->toFdi(); // 26 (FDI Quadrant 2, Tooth 6)
echo $molar->isAnterior(); // false (Posterior Molar)
echo $molar->isMaxillary(); // true (Upper Arch)
// Instantiate from FDI Two-Digit (ISO 3950)
$canine = ToothNumber::fromFdi(13); // Upper Right Canine
echo $canine->toUniversal(); // 6
echo $canine->isAnterior(); // true
5-Surface Functional Anatomical Charting
Restorations, active carious lesions, and sealants are charted across five anatomical surfaces:
- Mesial (
M): The surface facing toward the dental midline. - Distal (
D): The surface facing away from the midline. - Occlusal (
O): The chewing surface of posterior teeth (molars and premolars). - Incisal (
I): The cutting biting edge of anterior teeth (incisors and canines). - Buccal / Facial (
B/F): The surface facing the cheek or lips. - Lingual / Palatal (
L/P): The surface facing the tongue or palate.
use Obelaw\Ium\Dental\ValueObjects\SurfaceSet;
use Obelaw\Ium\Dental\Enums\ToothSurface;
$surfaces = SurfaceSet::from([
ToothSurface::MESIAL->value,
ToothSurface::OCCLUSAL->value,
ToothSurface::DISTAL->value,
]); // MOD restoration set
Morphological Surface Invariant
To preserve clinical accuracy, the domain enforces strict anatomical morphology rules through $surfaces->validateForTooth($tooth):
[Tooth Morphology Validation]
|
Is the tooth Anterior or Posterior?
|
+-------------------+-------------------+
| |
[Anterior] [Posterior]
(Incisors / Canines) (Premolars / Molars)
| |
Cannot have 'O' Cannot have 'I'
(Occlusal surface) (Incisal edge)
| |
If 'O' present: If 'I' present:
THROWS InvalidToothMorphologyException THROWS InvalidToothMorphologyException
use Obelaw\Ium\Dental\Exceptions\InvalidToothMorphologyException;
// Example: Incisor cannot have an Occlusal surface
$centralIncisor = ToothNumber::fromUniversal(8); // Upper Right Central Incisor
$invalidSurfaces = SurfaceSet::from([ToothSurface::OCCLUSAL->value]);
// Throws InvalidToothMorphologyException: Tooth 8 is anterior and cannot have an occlusal surface.
$invalidSurfaces->validateForTooth($centralIncisor);
Tooth Clinical Conditions
The condition of each tooth or surface is tracked via ToothCondition:
use Obelaw\Ium\Dental\Enums\ToothCondition;
enum ToothCondition: string
{
case HEALTHY = 'healthy';
case CARIES = 'caries';
case RESTORATION = 'restoration';
case CROWN = 'crown';
case ENDO = 'endo'; // Root Canal Treatment
case IMPLANT = 'implant'; // Titanium osteointegrated implant
case MISSING = 'missing'; // Congenitally absent
case EXTRACTED = 'extracted'; // Surgically removed
case FRACTURED = 'fractured';
case IMPACTED = 'impacted'; // Third molar impaction
}
6-Point Periodontal Probing Matrix
Periodontal examinations evaluate periodontal pocket depth (PPD), gingival recession, bleeding, furcation involvement, and tooth mobility across six anatomical sites per tooth:
- MB: Mesiobuccal
- B: Buccal / Mid-buccal
- DB: Distobuccal
- ML: Mesiolingual
- L: Lingual / Mid-lingual
- DL: Distolingual
Clinical Attachment Level (CAL) Computation
The domain automatically computes the true Clinical Attachment Level (CAL):
$$\text{CAL} = \text{Probing Pocket Depth (PPD)} + \text{Gingival Recession}$$
If PPD is 5mm and Gingival Recession is 2mm, the resulting CAL is 7mm, indicating severe clinical periodontal attachment loss.
use Obelaw\Ium\Dental\ValueObjects\PeriodontalProbingMatrix;
use Obelaw\Ium\Dental\Enums\ProbingPoint;
$matrix = new PeriodontalProbingMatrix(
depths: [
ProbingPoint::MESIOBUCCAL->value => 4,
ProbingPoint::BUCCAL->value => 3,
ProbingPoint::DISTOBUCCAL->value => 5,
ProbingPoint::MESIOLINGUAL->value => 3,
ProbingPoint::LINGUAL->value => 2,
ProbingPoint::DISTOLINGUAL->value => 4,
],
bleeding: [
ProbingPoint::MESIOBUCCAL->value => true, // Bleeding on probing (BOP)
ProbingPoint::DISTOBUCCAL->value => true,
]
);
Fluent Service Operations
All charting operations are performed via ium()->dental()->odontograms():
1. Creating a New Odontogram Chart
use Obelaw\Ium\Dental\Enums\ToothNotationSystem;
use Obelaw\Ium\Dental\Enums\DentitionType;
$chart = ium()->dental()->odontograms()->createChart(
patientId: $patient->id,
system: ToothNotationSystem::UNIVERSAL,
type: DentitionType::PERMANENT
);
2. Charting Tooth Conditions & Surfaces
use Obelaw\Ium\Dental\ValueObjects\ToothNumber;
use Obelaw\Ium\Dental\ValueObjects\SurfaceSet;
use Obelaw\Ium\Dental\Enums\ToothCondition;
use Obelaw\Ium\Dental\Enums\ToothSurface;
$molar = ToothNumber::fromUniversal(19); // Lower Left First Molar
$surfaces = SurfaceSet::from([
ToothSurface::MESIAL->value,
ToothSurface::OCCLUSAL->value,
]);
$chartedTooth = ium()->dental()->odontograms()->markSurface(
chartId: $chart->id,
tooth: $molar,
surfaces: $surfaces,
condition: ToothCondition::CARIES,
notes: 'Incipient dentin caries on MO margin.'
);
3. Recording Periodontal Probing
use Obelaw\Ium\Dental\ValueObjects\ToothNumber;
use Obelaw\Ium\Dental\ValueObjects\PeriodontalProbingMatrix;
$tooth = ToothNumber::fromUniversal(30); // Lower Right First Molar
$perioPoint = ium()->dental()->odontograms()->recordProbing(
chartId: $chart->id,
tooth: $tooth,
matrix: $matrix,
recession: ['MB' => 1, 'B' => 1, 'DB' => 2, 'ML' => 0, 'L' => 0, 'DL' => 1],
furcation: 1, // Class I furcation
mobility: 1, // Grade 1 mobility
notes: 'Subgingival calculus noted on mesial root.'
);
4. Fetching the Latest Patient Chart
$latestChart = ium()->dental()->odontograms()->getLatestChart($patient->id);
$teeth = $latestChart->teeth; // Collection of OdontogramTooth records
Emitted Domain Events
| Event Class | Trigger | Payload |
|---|---|---|
ToothCharted | Dispatched after tooth conditions or surfaces are updated. | OdontogramTooth $tooth |
PerioExamRecorded | Dispatched when a periodontal point or exam is recorded. | PeriodontalPoint $point |