Table Configuration Reference¶
Table configurations define how Tablassert transforms tabular data (Excel, CSV, TSV) into knowledge-graph assertions — author one per source table to declare its source, triple mappings, entity-resolution rules, provenance, and optional edge annotations.
Template vs Sections¶
Table configurations support two patterns:
Pattern 1: Template Only¶
Use when processing a single table with one output.
Pattern 2: Template + Sections¶
Use when processing variations of the same data (different columns, predicates, etc.) while sharing common configuration.
template:
source: {...} # Shared by all sections
provenance: {...} # Shared by all sections
sections:
- statement: # Section 1: Gene-Disease
subject: {method: column, encoding: A}
predicate: associated_with
object: {method: column, encoding: B}
- statement: # Section 2: Gene-Pathway
subject: {method: column, encoding: A}
predicate: participates_in
object: {method: column, encoding: C}
Merge Behavior (fastmerge)¶
Sections inherit from template and override specific fields:
Dictionaries: Recursive merge, section overrides template keys
template:
statement:
subject: {encoding: A}
predicate: related_to
sections:
- statement:
predicate: associated_with # Overrides, subject stays "A"
Lists: Concatenation (extends)
template:
statement:
subject:
prioritize: [Gene]
sections:
- statement:
subject:
prioritize: [Protein] # Result: [Gene, Protein]
Scalars: Section replaces template
template:
statement:
predicate: related_to
sections:
- statement:
predicate: treats # Replaces the template predicate
Configuration Schema¶
Source¶
Defines the data file location and format.
Excel Source¶
| Field | Type | Required | Description |
|---|---|---|---|
kind |
String | No | Source kind. Model default is "excel", but specify it explicitly in configs. |
local |
Path | Yes | Local file path the source is read from. The file must already exist here — Tablassert does not download it. |
url |
URL | Yes | Source URL recorded as provenance (emitted as the edge source_record_urls column and in the RIG). Format-validated only; not fetched. |
sheet |
String | No | Sheet name. Defaults to "Sheet1". |
row_slice |
List[PositiveInt|"auto"] | No | Two-value zero-based crop bounds: [start, stop]. Each value may be a positive integer or "auto". Mutually exclusive with rows. |
rows |
List[PositiveInt] | No | Zero-based row indices to keep after any row_slice crop. Mutually exclusive with row_slice. |
reindex |
List[Reindex] | No | Conditional row filtering |
Example:
source:
kind: excel
local: ./data/mydata.xlsx
url: https://example.com/data.xlsx
sheet: "Sheet1"
row_slice: [1, auto] # Start at the second physical row, read to end
Specify
kindexplicitly. Tablassert selects the reader purely from the declaredkind—excelreads a workbook (sheet),textscans delimited text (delimiter); the file on disk is never inspected to infer its format. Becausekindcarries a default, a source whosekindis omitted or does not match the actual file is still accepted and fed to the wrong reader, surfacing only later as a read error or garbled rows. Statingkindexplicitly makes a mis-declared source fail fast.
Text Source (CSV/TSV)¶
| Field | Type | Required | Description |
|---|---|---|---|
kind |
String | No | Source kind. Model default is "text", but specify it explicitly in configs. |
local |
Path | Yes | Local file path the source is read from. The file must already exist here — Tablassert does not download it. |
url |
URL | Yes | Source URL recorded as provenance (emitted as the edge source_record_urls column and in the RIG). Format-validated only; not fetched. |
delimiter |
String | No | Field delimiter. Defaults to ",". |
row_slice |
List[PositiveInt|"auto"] | No | Two-value zero-based crop bounds: [start, stop]. Each value may be a positive integer or "auto". Mutually exclusive with rows. |
rows |
List[PositiveInt] | No | Zero-based row indices to keep after any row_slice crop. Mutually exclusive with row_slice. |
reindex |
List[Reindex] | No | Conditional filtering |
Example:
source:
kind: text
local: ./data/mydata.tsv
url: https://example.com/data.tsv
delimiter: "\t"
row_slice: [1, auto]
Reindexing (Conditional Filtering)¶
Filter rows based on column values.
| Field | Type | Required | Description |
|---|---|---|---|
column |
String | Yes | Source column letters to evaluate; constrained to ^[A-Z]{1,3}$ (A-ZZZ). |
comparison |
String | No | Operator. Defaults to "ne"; allowed values are "eq", "ne", "lt", "le", "gt", "ge". |
comparator |
String|Int|Float | Yes | Value to compare against. Must be a string for "eq"/"ne", or a number for "lt"/"le"/"gt"/"ge". |
Example:
Statement (Triple Definition)¶
Defines subject-predicate-object relationships.
| Field | Type | Required | Description |
|---|---|---|---|
subject |
NodeEncoding | Yes | Subject entity configuration |
predicate |
String | No | Biolink predicate. Defaults to "related_to". |
object |
NodeEncoding | Yes | Object entity configuration |
qualifiers |
List[Qualifier] | No | Edge qualifiers (context) |
Example:
statement:
subject:
method: column
encoding: A
prioritize: [Gene]
predicate: treats
object:
method: column
encoding: B
prioritize: [Disease]
NodeEncoding¶
Defines how to extract and resolve entities.
| Field | Type | Required | Description |
|---|---|---|---|
method |
String | No | "value" (literal) or "column" (source column letters). Defaults to "value". |
encoding |
String|Int|Float | Yes | Literal value or source column letters, depending on method |
taxon |
PositiveInt | No | NCBI Taxon ID for filtering (e.g., 9606 for human) |
prioritize |
List[String] | No | Preferred Biolink categories (must be valid Categories enum values such as Gene, Protein) |
avoid |
List[String] | No | Excluded Biolink categories (must be valid Categories enum values) |
regex |
List[Regex] | No | Pattern replacements |
fill |
String | No | Null-filling strategy: "forward", "backward", "min", "max", "mean", "zero", "one" |
remove |
List[Int|Float|String] | No | Regex patterns to remove (replaced with empty string) |
prefix |
String | No | Add prefix to values |
suffix |
String | No | Add suffix to values |
explode_by |
String | No | Delimiter to split multi-value cells |
transformations |
List[Math] | No | Mathematical transformations |
Method: Value vs Column¶
method: value - Use a literal value
method: column - Reference a source column (Excel-style letters, since sources are read without headers)
At runtime those letters are converted internally to Polars column names such as column_1, but those internal names are not valid configuration values.
Taxonomic Filtering¶
taxon: int - Filter entities by organism
Common taxon IDs:
- 9606 - Homo sapiens (human)
- 10090 - Mus musculus (mouse)
- 7227 - Drosophila melanogaster (fruit fly)
Category Prioritization¶
prioritize: list[category] - Prefer specific Biolink categories
If "TP53" maps to both Gene and Protein, prefer Gene.
avoid: list[category] - Exclude specific categories
Prevents misclassifying organism names as genes.
Text Transformations¶
regex: list[{pattern: Int|Float|String, replacement: Int|Float|String}] - Pattern-based replacements
subject:
encoding: A
regex:
- {pattern: ".*g__", replacement: ""} # Remove genus prefix
- {pattern: ";s__", replacement: " "} # Replace species separator
Executed in order.
Regex dialect: Patterns are passed directly to Polars
str.replace_all(), which uses the Rustregexcrate. Only features supported by that engine work — in particular, backreferences (\1,\2, …) and lookarounds ((?=...),(?<=...),(?!...),(?<!...)) are not supported and will raise an error at parse time. Plain groups(...)and non-capturing groups(?:...)are supported. Stick to character classes, anchors (^,$), quantifiers, alternation (a|b), and grouping if needed. If a transformation is too complex to express, prefer chaining several simple substitutions or capturing the residual context in amiscellaneous notesannotation instead.
remove: list[regex] - Regex patterns to remove
Each entry is applied as a regex replace-with-empty-string on the cell text in place (rows are not dropped). Same regex constraints apply as the regex field — Polars-compatible patterns only, no backreferences or lookarounds.
prefix / suffix - Add text
Output columns: original_<col> vs <col>_pre_resolution - For every subject/object/qualifier node, the pipeline snapshots the cell value into two columns at different stages:
original_<col>- the pristine source value, captured immediately after the column is read (or the literal is set formethod: value) and before anyfill,explode_by,regex,remove,prefix,suffix, ortransformations. Emitted for bothmethod: valueandmethod: column. Present in final edge output.<col>_pre_resolution- the fully-transformed value, captured after all of the above, i.e. the same text that is then normalized and resolved to a CURIE. Internal only: used by QC (fullmap_audit) and as the node marker incompile_graph; stripped from final edge output.
Example: with method: column, encoding: A, remove: ["^NA "] over a cell "NA BRCA1", original_subject is "NA BRCA1" while subject_pre_resolution is "BRCA1". Annotations never emit either column.
Null Handling¶
fill: string - Fill null values using a strategy
Available strategies:
- "forward" - Fill nulls with previous non-null value
- "backward" - Fill nulls with next non-null value
- "min" - Fill with column minimum
- "max" - Fill with column maximum
- "mean" - Fill with column mean
- "zero" - Fill with 0
- "one" - Fill with 1
annotations:
- annotation: expression_level
method: column
encoding: C
fill: mean # Replace nulls with column average
Multi-Value Handling¶
explode_by: string - Split delimited values into multiple rows
Mathematical Transformations¶
transformations: list[{function, arguments}]
Available functions: copysign, pow
Use the "values" token to reference column values in transformations.
Qualifiers¶
Add context to edges (anatomical location, disease context, etc.).
species_context_qualifier is auto-derived from resolved subject/object taxon
metadata and should not be declared manually.
| Field | Type | Required | Description |
|---|---|---|---|
qualifier |
String | Yes | Biolink qualifier from the Qualifiers enum (e.g., "anatomical_context_qualifier") |
| (inherits NodeEncoding) | All NodeEncoding fields available |
Example:
Provenance¶
Required metadata about data source.
| Field | Type | Required | Description |
|---|---|---|---|
repo |
String | No | Repository. Defaults to "PMC"; allowed values are "PMC", "PMID". |
publication |
String | Yes, unless override is set |
Repository-local identifier emitted as a CURIE. For repo: PMC the value must start with PMC followed by digits (e.g., "PMC11708054", "PMC123") and is emitted under the PMCID: namespace as PMCID:PMC...; for repo: PMID it is emitted as PMID:<publication> (e.g., "11708054" → PMID:11708054). |
knowledge_level |
String | No | Biolink KL/AT knowledge level of produced edges. Defaults to "statistical_association"; allowed values are the KnowledgeLevels enum (e.g., knowledge_assertion, logical_entailment, prediction, statistical_association, text_co_occurrence, observation, not_provided). |
agent_type |
String | No | Biolink KL/AT agent type responsible for produced edges. Defaults to "data_analysis_pipeline"; allowed values are the AgentTypes enum (e.g., manual_agent, automated_agent, data_analysis_pipeline, computational_model, text_mining_agent, image_processing_agent, manual_validation_of_automated_agent, not_provided). |
override |
Object | No | Manual provenance for non-PMC/PMID sources. When set, it replaces repo/publication-derived provenance and publication must be omitted. |
Example:
provenance:
repo: PMC
publication: "PMC11708054"
knowledge_level: statistical_association
agent_type: data_analysis_pipeline
Default provenance trio. When omitted,
repo/knowledge_level/agent_typedefault toPMC/statistical_association/data_analysis_pipeline, so every produced edge is asserted as a statistical association generated by an automated data analysis pipeline under the PubMed Central namespace. That is a sensible default for GWAS/omics tables mined from a pipeline, but it is a claim about your data's semantics: if your rows are manually curated assertions, predictions, or observations, overrideknowledge_levelandagent_type(andrepo/publication) so the emitted Biolink KL/AT provenance is accurate.
Manual provenance override¶
Use provenance.override when a table comes from another knowledge graph or source system whose Translator provenance cannot be derived from a PMC/PMID publication. The override is wired like the other Tablassert model classes and wins over the repo/publication auto-generation for that section's upstream sources, publications, and KL/AT. The edge primary_knowledge_source is not overridable per section — it always derives from the graph-level infores (see Graph); put manual infores CURIEs in upstream_resource_ids.
provenance:
override:
upstream_resource_ids:
- infores:external-source
publications:
- PMCID:PMC1234567
knowledge_level: knowledge_assertion
agent_type: manual_agent
Override fields:
| Field | Type | Required | Description |
|---|---|---|---|
upstream_resource_ids |
List[String] | No | Manual upstream source infores CURIEs replacing the repo-derived PMC/PMID source map — the sanctioned place for manual infores. Each entry must start with infores:. |
publications |
List[String] | No | Manual publication CURIEs. Entries must currently start with PMCID:; PMID compatibility for manual overrides is intentionally deferred. |
knowledge_level |
String | No | Override-specific KL value. Defaults to statistical_association. |
agent_type |
String | No | Override-specific AT value. Defaults to data_analysis_pipeline. |
Tablassert emits the graph-level infores (or infores:<graph-name> when unset) as the Biolink-compatible primary_knowledge_source edge slot — a single-element list such as ["infores:multiomics-kg"], matching the form of upstream_resource_ids. The override cannot set a per-section primary_knowledge_source; manual infores CURIEs belong in upstream_resource_ids. Older resource_id output has been replaced so generated KGX is compatible with the Biolink edge allow-list.
Annotations¶
Optional edge attributes (statistical metadata, notes, etc.).
| Field | Type | Required | Description |
|---|---|---|---|
annotation |
String | Yes | Attribute name (e.g., "p_value", "sample_size"). Lowercased and trimmed of leading/trailing whitespace at parse time; underscores are preserved (use snake_case). |
| (inherits Encoding) | All Encoding fields available (method, encoding, regex, etc.) |
Example:
annotations:
- {annotation: p_value, method: column, encoding: C} # Read from column C
- {annotation: sample_size, method: value, encoding: 450} # Literal value for all edges
- {annotation: multiple_testing_correction_method, method: value, encoding: "Benjamini Hochberg"}
# Descriptive name of your choice — folded into `supporting_text` on output.
- annotation: log2fc_relative_to_vehicle_control
method: value
encoding: "Values are log2 fold-change relative to vehicle control; n=3 biological replicates per arm"
Allow-list and auto-folding¶
Annotation names fall into two groups at build time:
- Biolink-native slots — names matching a Biolink Association slot (e.g.
p_value,sample_size,knowledge_level,primary_knowledge_source,adjusted_p_value,supporting_text,publications, the qualifier slots likeseverity_qualifier/disease_context_qualifier) are written to edges verbatim. - Tablassert pipeline fields —
upstream_resource_ids,source_record_urls.
Any other annotation name is treated as supporting context. At the end of compile_graph, tablassert sweeps the edge columns: for each non-allow-listed name it emits "name: value" entries into the edge's supporting_text (a list[str]), then drops the original column. Behavior worth knowing:
- Pick descriptive names. Whatever string you choose becomes the prefix in
supporting_text, solog2fc_relative_to_vehicle_controlreads as"log2fc_relative_to_vehicle_control: 1.4"on the edge. Avoid generic names likenotesorvalue. - Null and blank cells produce no entry. Whitespace-only values are treated as blank.
- Existing
supporting_textis preserved. If an annotation namedsupporting_textis already on the edge (Biolink-native slot), folded entries are appended to it rather than replacing it. Scalar values are coerced to a single-element list first. - Ordering is stable. Folded entries are sorted alphabetically by column name.
This means nothing in your source data is silently dropped: context that doesn't map to a structured Biolink slot travels along inside supporting_text instead.
In addition to user-declared annotations, every edge automatically carries extracted_from_row_number, a 1-based index into the original source table (matching Excel-style row numbering). It is not declared as an annotation — tablassert emits it internally so each edge always carries its source-row provenance, and it folds into supporting_text like any other non-allow-list column (e.g. "extracted_from_row_number: 42").
Next Steps¶
- Advanced Example - Real-world configuration with complex transformations
- Graph Configuration - How to orchestrate multiple tables
- Tutorial - Step-by-step walkthrough