Debugging non-compliant tree sequences#
If you’re working on an application that writes out tree sequences (or more properly, the underlying table collections), you may find yourself in the situation where you’re writing out files that tskit cannot read because of violations of the Data model. How to see what’s going on?
First, try loading the TableCollection directly (skipping
the convert-to-tree-sequence step that involves additional validation).
This will work if you have errors like a mutation that references a
non-extant node, for instance.
To do this, you simply run:
import tskit
tables = tskit.TableCollection.load("data/basic_tree_seq.trees")
print(tables)
TableCollection
Sequence Length: 10000.0
Time units: generations
Metadata: b''
Individuals
╔══╤═════╤════════╤═══════╤════════╗
║id│flags│location│parents│metadata║
╠══╪═════╪════════╪═══════╪════════╣
║0 │ 0│ │ │ ║
║1 │ 0│ │ │ ║
║2 │ 0│ │ │ ║
╚══╧═════╧════════╧═══════╧════════╝
Nodes
╔══╤═════╤═════╤══════════╤══════════╤════════╗
║id│time │flags│population│individual│metadata║
╠══╪═════╪═════╪══════════╪══════════╪════════╣
║0 │ 0│ 1│ 0│ 0│ ║
║1 │ 0│ 1│ 0│ 0│ ║
║2 │ 0│ 1│ 0│ 1│ ║
║3 │ 0│ 1│ 0│ 1│ ║
║4 │ 0│ 1│ 0│ 2│ ║
║5 │ 0│ 1│ 0│ 2│ ║
║6 │ 100│ 0│ 0│ -1│ ║
║7 │ 335│ 0│ 0│ -1│ ║
║8 │ 420│ 0│ 0│ -1│ ║
║9 │ 593│ 0│ 0│ -1│ ║
║10│ 853│ 0│ 0│ -1│ ║
║11│ 958│ 0│ 0│ -1│ ║
║12│1,125│ 0│ 0│ -1│ ║
║13│1,479│ 0│ 0│ -1│ ║
╚══╧═════╧═════╧══════════╧══════════╧════════╝
Edges
╔══╤═════╤══════╤══════╤═════╤════════╗
║id│left │right │parent│child│metadata║
╠══╪═════╪══════╪══════╪═════╪════════╣
║0 │ 0│10,000│ 6│ 1│ ║
║1 │ 0│10,000│ 6│ 3│ ║
║2 │ 0│ 3,834│ 7│ 2│ ║
║3 │ 0│ 3,834│ 7│ 6│ ║
║4 │3,834│10,000│ 8│ 2│ ║
║5 │3,834│10,000│ 8│ 4│ ║
║6 │ 310│10,000│ 9│ 5│ ║
║7 │3,834│10,000│ 9│ 6│ ║
║8 │ 310│ 3,834│ 9│ 7│ ║
║9 │ 0│ 3,834│ 10│ 4│ ║
║10│ 0│ 310│ 10│ 5│ ║
║11│3,834│ 7,977│ 10│ 8│ ║
║12│ 310│ 7,977│ 10│ 9│ ║
║13│ 0│10,000│ 11│ 0│ ║
║14│7,977│10,000│ 11│ 9│ ║
║15│ 0│ 7,977│ 11│ 10│ ║
║16│ 0│ 310│ 12│ 7│ ║
║17│ 0│ 310│ 12│ 11│ ║
║18│7,977│10,000│ 13│ 8│ ║
║19│7,977│10,000│ 13│ 11│ ║
╚══╧═════╧══════╧══════╧═════╧════════╝
Sites
╔══╤════════╤═══════════════╤════════╗
║id│position│ancestral_state│metadata║
╠══╪════════╪═══════════════╪════════╣
║0 │ 536│ A│ ║
║1 │ 2,447│ G│ ║
║2 │ 6,947│ C│ ║
║3 │ 7,868│ C│ ║
║4 │ 8,268│ C│ ║
╚══╧════════╧═══════════════╧════════╝
Mutations
╔══╤════╤════╤════════════╤═════════════╤══════╤════════╗
║id│site│node│time │derived_state│parent│metadata║
╠══╪════╪════╪════════════╪═════════════╪══════╪════════╣
║0 │ 0│ 4│334.47624226│ G│ -1│ ║
║1 │ 1│ 0│ 57.17142646│ C│ -1│ ║
║2 │ 2│ 0│381.32639237│ G│ -1│ ║
║3 │ 3│ 5│581.59317086│ T│ -1│ ║
║4 │ 4│ 4│302.17696763│ T│ -1│ ║
╚══╧════╧════╧════════════╧═════════════╧══════╧════════╝
Migrations
╔══╤════╤═════╤════╤══════╤════╤════╤════════╗
║id│left│right│node│source│dest│time│metadata║
╠══╪════╪═════╪════╪══════╪════╪════╪════════╣
╚══╧════╧═════╧════╧══════╧════╧════╧════════╝
Populations
╔══╤════════════════════════════════════╗
║id│metadata ║
╠══╪════════════════════════════════════╣
║0 │{'description': '', 'name': 'pop_0'}║
╚══╧════════════════════════════════════╝
Provenances
╔══╤═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╤══════════════════════════╗
║id│record │timestamp ║
╠══╪═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╪══════════════════════════╣
║0 │{"schema_version": "1.0.0", "software": {"name": "msprime", "version": "1.2.0"}, "parameters": {"command": "sim_ancestry", "samples": 3, "demography": null, "sequence_length": 10000.0, "discrete_genome": null, "recombination_rate": 1e-07, "gene_conversion_rate": null, "gene_conversion_tract_length": null, "population_size": 1000, "ploidy": null, "model": "dtwf", "initial_state": null, "start_time": null, "end_time": null, "record_migrations": null, "record_full_arg": null, "num_labels": null, "random_seed": 665, "replicate_index": 0}, "environment": {"os": {"system": "Darwin", "node": "Yans-New-Air", "release": "20.6.0", "version": "Darwin Kernel Version 20.6.0: Tue Feb 22 21:10:41 PST 2022; root:xnu-7195.141.26~1/RELEASE_X86_64", "machine": "x86_64"}, "python": {"implementation": "CPython", "version": "3.9.10"}, "libraries": {"kastore": {"version": "2.1.1"}, "tskit": {"version": "0.5.1"}, "gsl": {"version": "2.7"}}}}│2022-07-14T21:51:11.443571║
║1 │ {"schema_version": "1.0.0", "software": {"name": "msprime", "version": "1.2.0"}, "parameters": {"command": "sim_mutations", "tree_sequence": {"__constant__": "__current_ts__"}, "rate": 2e-07, "model": null, "start_time": null, "end_time": null, "discrete_genome": null, "keep": null, "random_seed": 123}, "environment": {"os": {"system": "Darwin", "node": "Yans-New-Air", "release": "20.6.0", "version": "Darwin Kernel Version 20.6.0: Tue Feb 22 21:10:41 PST 2022; root:xnu-7195.141.26~1/RELEASE_X86_64", "machine": "x86_64"}, "python": {"implementation": "CPython", "version": "3.9.10"}, "libraries": {"kastore": {"version": "2.1.1"}, "tskit": {"version": "0.5.1"}, "gsl": {"version": "2.7"}}}}│2022-07-14T21:51:11.445208║
╚══╧═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╧══════════════════════════╝
Then, the tables can be inspected.
Sometimes the error makes it so the tables cannot even be loaded
as a TableCollection: for instance, if something went wrong
with the ragged columns.
Under the hood, data is stored on disk
with kastore,
so we can use kastore directly:
import kastore
ka = kastore.load("data/basic_tree_seq.trees")
print(ka)
<kastore.store.Store object at 0x7f77c8576ff0>
The kastore has (by design!) very minimal functionality: we can ask what keys it has, and retrieve the associated values. So, this one has these keys:
list(ka.keys())
['edges/child',
'edges/left',
'edges/metadata',
'edges/metadata_offset',
'edges/metadata_schema',
'edges/parent',
'edges/right',
'format/name',
'format/version',
'indexes/edge_insertion_order',
'indexes/edge_removal_order',
'individuals/flags',
'individuals/location',
'individuals/location_offset',
'individuals/metadata',
'individuals/metadata_offset',
'individuals/metadata_schema',
'individuals/parents',
'individuals/parents_offset',
'metadata',
'metadata_schema',
'migrations/dest',
'migrations/left',
'migrations/metadata',
'migrations/metadata_offset',
'migrations/metadata_schema',
'migrations/node',
'migrations/right',
'migrations/source',
'migrations/time',
'mutations/derived_state',
'mutations/derived_state_offset',
'mutations/metadata',
'mutations/metadata_offset',
'mutations/metadata_schema',
'mutations/node',
'mutations/parent',
'mutations/site',
'mutations/time',
'nodes/flags',
'nodes/individual',
'nodes/metadata',
'nodes/metadata_offset',
'nodes/metadata_schema',
'nodes/population',
'nodes/time',
'populations/metadata',
'populations/metadata_offset',
'populations/metadata_schema',
'provenances/record',
'provenances/record_offset',
'provenances/timestamp',
'provenances/timestamp_offset',
'sequence_length',
'sites/ancestral_state',
'sites/ancestral_state_offset',
'sites/metadata',
'sites/metadata_offset',
'sites/metadata_schema',
'sites/position',
'time_units',
'uuid']
The names are self-explanatory. For instance, we can look at the array of child nodes associated with each edge:
ka.get("edges/child")
array([ 1, 3, 2, 6, 2, 4, 5, 6, 7, 4, 5, 8, 9, 0, 9, 10, 7,
11, 8, 11], dtype=int32)
Good luck!