Skip to content

Commit 3eafd5c

Browse files
docs: name a table's grain (level of detail) alongside schema dimension (#242)
1 parent cbd6a36 commit 3eafd5c

3 files changed

Lines changed: 28 additions & 0 deletions

File tree

src/explanation/entity-integrity.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,30 @@ The rule applies whether the table has only new attributes or also inherits
223223
attributes through foreign keys. A new primary-key attribute means a new
224224
dimension.
225225

226+
### Grain
227+
228+
A dimension is a *single* axis of variation; a table's **grain** is the *whole
229+
combination* of axes at which each row is recorded or computed — its full primary
230+
key. Grain is the answer to this guide's leading question, *"what is one row of
231+
this table?"*
232+
233+
> **The grain of a table is the level of detail at which its data is recorded or
234+
> computed: what one row represents, given by the combination of dimensions in its
235+
> primary key.**
236+
237+
- `Session`, keyed `(subject_id, session_idx)`, has grain **(subject × session)**
238+
one row per session of a subject.
239+
- Adding a dimension makes the grain **finer**: a part table that adds `blob_idx`
240+
(`Detection.Blob` below) has grain **(… × blob)** — one row per blob of a
241+
detection.
242+
- A computed table's grain is the combination of dimensions at which its `make()`
243+
produces rows — its
244+
[`key_source`](../reference/specs/autopopulate.md). *A computation operates at
245+
its grain.*
246+
247+
"Grain" is the established term in dimensional modeling for what a single row
248+
represents; DataJoint generalizes it from recorded fact rows to *computed* rows.
249+
226250
### Tables that introduce dimensions
227251

228252
```python

src/reference/specs/autopopulate.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ class Analysis(dj.Computed):
8282

8383
The `key_source` property defines which entries should exist in the table—the complete set of primary keys that `make()` should be called with.
8484

85+
This set is the table's **grain**—the combination of dimensions at which the computation is done. `make()` runs once per key, so a computed table operates at the grain of its `key_source`.
86+
8587
### 2.2 Automatic Key Source
8688

8789
By default, DataJoint automatically calculates `key_source` as the join of all tables referenced by foreign keys in the primary key:

src/reference/specs/query-algebra.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,8 @@ result = A.aggr(B, ..., exclude_nonmatching=True) # Only rows with matches
407407

408408
**B must contain all primary key attributes of A.** This enables grouping B's rows by A's primary key.
409409

410+
Geometrically, aggregation **reduces the grain**: it projects the finer grain of `B` onto the coarser grain of `A` it contains, folding each group of B-rows into summary values. Requiring `B` to contain all of A's primary key is exactly what makes every B-row fall into one A-group. Note that `.proj` does *not* reduce the grain—it always retains the primary key (§3.2)—so aggregation, not projection, is the grain-reducing operator.
411+
410412
### 5.4 Aggregate Functions
411413

412414
```python

0 commit comments

Comments
 (0)