The problem
The two most-used tier names describe opposite axes, and each one names the axis the other actually means:
Manual names the writer ("a person"), but the tier means the origin (data from outside the pipeline).
Imported names the origin ("from elsewhere"), but the tier means the writer (the table's own make()).
The docs are consistent and correct about what the tiers mean. It is the class names that cross over, and a reader who reasons from the names alone will land in the wrong place.
The docs already explain Manual in different words than its name
- Table Declaration §1.2 —
Manual is "Data inserted at runtime from outside the pipeline (users, instruments, ingestion scripts)". Two of the three examples are automated.
- Computation Model — "Manual and Lookup tables are not auto-populated; they are the entry points where a pipeline's data originates."
- Fan-Out Ingestion — "inserts into several entry-point tables (
Manual or Imported)".
So the concept is already named "entry point" throughout the prose. Only the class is called Manual.
The failure mode this produces
A designer building an automated feed reasons, reasonably: "this table isn't filled manually — a sync script fills it — so it isn't Manual. It comes from outside, so it's Imported." They declare dj.Imported.
But Imported is defined as "populated by make()", and this table has no make() — it's filled by insert from elsewhere. So the insert is refused, and the fix that presents itself is allow_direct_insert=True rather than a corrected tier.
The result is a recognizable and diagnosable shape:
- an
Imported table with no make(), which reads to every later reader as a table whose make() was forgotten;
populate() on it silently doing nothing rather than erroring;
- a permanent
allow_direct_insert=True suppressing a guard that was reporting a real problem;
- the pipeline's actual boundary with the outside world drawn one table away from where it is.
Every step of that reasoning is sound except the premise that "manual" means "by hand."
Suggested docs changes (the near-term ask)
- State the axis explicitly, once, where tiers are introduced: the tier says how rows arrive, not who causes them to arrive. Rows inserted from outside the table →
Manual; rows produced by the table's own make() → Imported (reads an external source) or Computed (derives from other tables).
- Say plainly that "manual" means external-origin, not hand-entered — an automated ingestion script inserts into a
Manual table. The reference table hints at this with "ingestion scripts"; it deserves a sentence, not a parenthetical.
- Add the failure mode as a short "common mistake" callout — an
Imported table with no make(), and allow_direct_insert as its tell. It is cheap to check and hard to spot by eye.
- Consider a small 2×2 (origin: external / derived × writer: inserted /
make()) — it makes Lookup and Part sit naturally alongside the other three and shows why only four of the cells are populated.
Forward-looking: a better name
dj.Entry would name the thing itself — a table where data enters the pipeline, by whatever hand — and it matches the vocabulary the explanation pages already use. It carries no implication about who or what does the writing, which is the whole source of the confusion.
That is a datajoint-python change, not a docs change, so it needs a decision there. Filing it here because the explanation is the fix available now and the naming question follows from it. If it were taken up, the obvious shape is dj.Entry as the primary name with dj.Manual kept permanently as a backward-compatible alias — no deprecation, no migration, existing pipelines and tutorials keep working, and new material can teach the clearer name. Renaming Imported is a harder call and probably not worth it; once the axis is stated, Imported reads correctly as "imported by this table."
Happy to open a PR for items 1–3 if the framing looks right.
The problem
The two most-used tier names describe opposite axes, and each one names the axis the other actually means:
Manualnames the writer ("a person"), but the tier means the origin (data from outside the pipeline).Importednames the origin ("from elsewhere"), but the tier means the writer (the table's ownmake()).The docs are consistent and correct about what the tiers mean. It is the class names that cross over, and a reader who reasons from the names alone will land in the wrong place.
The docs already explain
Manualin different words than its nameManualis "Data inserted at runtime from outside the pipeline (users, instruments, ingestion scripts)". Two of the three examples are automated.ManualorImported)".So the concept is already named "entry point" throughout the prose. Only the class is called
Manual.The failure mode this produces
A designer building an automated feed reasons, reasonably: "this table isn't filled manually — a sync script fills it — so it isn't
Manual. It comes from outside, so it'sImported." They declaredj.Imported.But
Importedis defined as "populated bymake()", and this table has nomake()— it's filled by insert from elsewhere. So the insert is refused, and the fix that presents itself isallow_direct_insert=Truerather than a corrected tier.The result is a recognizable and diagnosable shape:
Importedtable with nomake(), which reads to every later reader as a table whosemake()was forgotten;populate()on it silently doing nothing rather than erroring;allow_direct_insert=Truesuppressing a guard that was reporting a real problem;Every step of that reasoning is sound except the premise that "manual" means "by hand."
Suggested docs changes (the near-term ask)
Manual; rows produced by the table's ownmake()→Imported(reads an external source) orComputed(derives from other tables).Manualtable. The reference table hints at this with "ingestion scripts"; it deserves a sentence, not a parenthetical.Importedtable with nomake(), andallow_direct_insertas its tell. It is cheap to check and hard to spot by eye.make()) — it makesLookupandPartsit naturally alongside the other three and shows why only four of the cells are populated.Forward-looking: a better name
dj.Entrywould name the thing itself — a table where data enters the pipeline, by whatever hand — and it matches the vocabulary the explanation pages already use. It carries no implication about who or what does the writing, which is the whole source of the confusion.That is a
datajoint-pythonchange, not a docs change, so it needs a decision there. Filing it here because the explanation is the fix available now and the naming question follows from it. If it were taken up, the obvious shape isdj.Entryas the primary name withdj.Manualkept permanently as a backward-compatible alias — no deprecation, no migration, existing pipelines and tutorials keep working, and new material can teach the clearer name. RenamingImportedis a harder call and probably not worth it; once the axis is stated,Importedreads correctly as "imported by this table."Happy to open a PR for items 1–3 if the framing looks right.