Persons tracking accross historical records.
Project description
BlitzBeaver
BlitzBeaver is a Python package that allows for persons tracking accross historical records. It is desiged to work with noisy and incomplete data.
Getting Started
Prerequisites
- Python 3.10 or higher
- Rust edition 2021
Development Setup
-
Install the Python dependencies:
pip3 install -r requirements.txt
[!NOTE] It is recommended to use a virtual environment for Python dependencies (venv).
-
To compile the Rust code, run:
maturin developOr in release mode:
maturin develop -r
-
To install the blitzbeaver package locally:
pip3 install -e /path/to/blitzbeaver
Records
The historical records given to BlitzBeaver are expected to be in a specific format. The library used to work with the data is polars, it is similar to pandas but has a better integration with Rust (as it is also written in Rust).
Frame
Represents the records at a single point in time (ex: all records from year 1805 if the records are yearly).
Record
Represents a single record (line) in the historical records.
Element
Represents a single value in a record (ex: the name of a person, the birth date, etc.).
import polars as pl
# example of an element
name = "Bob"
# example of a record
record = ["Bob", "Smith", "farmer"]
# example of a frame
frame = pl.DataFrame(
{
"name": ["Bob", "Alice"],
"surname": ["Smith", "Johnson"],
"occupation": ["farmer", "teacher"]
}
)
Record Schema
Represents the schema of a record. It is used to define the structure of the records in the historical records. Each field in the schema corresponds to a column in the frame.
Elements can be of one of two types:
ElementType.String: a single string value (ex:"Bob")ElementType.MultiStrings: a list of strings (ex:["Bob", "Alice"])
import blitzbeaver as bb
record_schema = bb.RecordSchema(
[
bb.FieldSchema("address", bb.ElementType.String),
bb.FieldSchema("firstname", bb.ElementType.String),
bb.FieldSchema("lastname", bb.ElementType.String),
bb.FieldSchema("origin", bb.ElementType.String),
bb.FieldSchema("occupation", bb.ElementType.String),
bb.FieldSchema("children", bb.ElementType.MultiStrings),
]
)
Tracking
The tracking process attempts to match records across different frames, the results of this process are a list of tracking chains. Each tracking chain represents a single entity (person), it is composed of a list of records that are believed to be the same entity at different points in time.
The results of the tracking process is actually not stored as a list of tracking chains, but rather as a graph (TrackingGraph) where each node is a record and each edge represents a link between two records.
Tracker
The tracker is the component responsible for tracking a single entity across the frames, it gradually builds a tracking chain.
The tracker has a memory, it is responsible for producing the most representative values from the records it has seen so far.
import blitzbeaver as bb
# reconstruct a tracking chain from the tracking graph
chain = graph.materialize_tracking_chain(tracker_id, dataframes, record_schema)
# display the tracking chain as a dataframe
chain.as_dataframe()
# outputs:
┌───────────┬─────────┬───────────┬──────────┬────────────┬────────────┬──────────────┐
│ frame_idx ┆ address ┆ firstname ┆ lastname ┆ origin ┆ occupation ┆ children │
╞═══════════╪═════════╪═══════════╪══════════╪════════════╪════════════╪══════════════╡
│ 0 ┆ bourg ┆ clemont ┆ rafford ┆ anglais ┆ lampiste ┆ ["francois"] │
│ 1 ┆ bourg ┆ lement ┆ prafford ┆ null ┆ null ┆ null │
│ 2 ┆ bourg ┆ clement ┆ trafford ┆ anglais ┆ null ┆ ["francois"] │
│ 3 ┆ bourg ┆ clement ┆ prafford ┆ anglais ┆ rentier ┆ ["francois"] │
│ 4 ┆ bourg ┆ rement ┆ grafford ┆ anglais ┆ rentier ┆ ["francois"] │
│ 5 ┆ boulg ┆ clement ┆ rafford ┆ angleterre ┆ rentier ┆ ["francois"] │
└───────────┴─────────┴───────────┴──────────┴────────────┴────────────┴──────────────┘
Configuration
The tracking process takes a configuration that defines all the parameters of the tracking process.
Here is an example of a configuration:
import blitzbeaver as bb
distance_metric_config = bb.DistanceMetricConfig(
metric="lv_substring",
caching_threshold=4,
use_sigmoid=False,
lv_substring_weight=0.5,
)
normal_memory_config = bb.MemoryConfig(
memory_strategy="median",
)
multi_memory_config = bb.MemoryConfig(
memory_strategy="mw-median",
multiword_threshold_match=0.6,
multiword_distance_metric=distance_metric_config,
)
config = bb.config(
record_schema=record_schema,
distance_metric_config=distance_metric_config,
record_scorer_config=bb.RecordScorerConfig(
record_scorer="average",
weights=None,
min_weight_ratio=None
),
resolver_config=bb.ResolverConfig(
resolving_strategy="best-match",
),
memory_config=normal_memory_config,
multistring_memory_config=multi_memory_config,
interest_threshold=0.6,
limit_no_match_streak=3,
num_threads=10,
)
Execution
The tracking process is executed as follows:
import blitzbeaver as bb
tracking_graph = bb.execute_tracking(config, record_schema, dataframes)
Diagnostics
The tracking process also returns some diagnostics information (Diagnostics).
These information provide insights on the tracking process, for example:
- The state of the memory of each tracker for each frame.
- The score of each record of interest for a tracker as well as the distances of each feature.
Beaver file
The tracking graph and diagnostics information can be saved and loaded to/from a .beaver file. The .beaver file is a binary file with a specific format.
import blitzbeaver as bb
path_graph = "./graph.beaver"
# load the graph from a .beaver file
graph = bb.read_beaver(path_graph)
# save the graph to a .beaver file
bb.save_beaver(path_graph, graph)
Normalization
Once computed, the tracking graph can be used to normalize values of the historical records. The idea being to use the link between multiple records of different frames of a tracking chain to correct errors and fill missing values.
# the same tracker as above, with normalized values
chain = graph.materialize_tracking_chain(tracker_id, dataframes, record_schema, normalized_dataframes)
# display the tracking chain as a dataframe
chain.as_dataframe(normalized=True)
# outputs:
┌───────────┬─────────┬───────────┬──────────┬─────────┬────────────┬──────────────┐
│ frame_idx ┆ address ┆ firstname ┆ lastname ┆ origin ┆ occupation ┆ children │
╞═══════════╪═════════╪═══════════╪══════════╪═════════╪════════════╪══════════════╡
│ 0 ┆ bourg ┆ clement ┆ prafford ┆ anglais ┆ rentier ┆ ["francois"] │
│ 1 ┆ bourg ┆ clement ┆ prafford ┆ anglais ┆ rentier ┆ ["francois"] │
│ 2 ┆ bourg ┆ clement ┆ prafford ┆ anglais ┆ rentier ┆ ["francois"] │
│ 3 ┆ bourg ┆ clement ┆ prafford ┆ anglais ┆ rentier ┆ ["francois"] │
│ 4 ┆ bourg ┆ clement ┆ prafford ┆ anglais ┆ rentier ┆ ["francois"] │
│ 5 ┆ bourg ┆ clement ┆ prafford ┆ anglais ┆ rentier ┆ ["francois"] │
└───────────┴─────────┴───────────┴──────────┴─────────┴────────────┴──────────────┘
Configuration
The normalization process takes a configuration:
import blitzbeaver as bb
# the distance metric configuration to use to compute the distances
# between values during clustering
distance_metric_config: bb.DistanceMetricConfig = ...
normalization_config = bb.NormalizationConfig(
threshold_cluster_match=0.5,
min_cluster_size=2,
distance_metric=distance_metric_config,
)
Execution
The normalization process takes as argument the previously computed tracking graph, the historical records (dataframes), record schema and configuration.
It produces a list of dataframes: the normalized historical records.
import blitzbeaver as bb
normalized_dataframes = bb.execute_normalization(
normalization_config,
record_schema,
graph,
dataframes,
)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file blitzbeaver-1.0.0.tar.gz.
File metadata
- Download URL: blitzbeaver-1.0.0.tar.gz
- Upload date:
- Size: 80.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.8.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf43a6ae9e339739985048be0423df5434fc2c81c92538328688b3dbdd16d3ea
|
|
| MD5 |
e69dee7e44dd99c98c30fe47f599f7d4
|
|
| BLAKE2b-256 |
dd1dfa5eeb392a0e1d5d1f3fe0280e04b5361f6f0afc255b57cf2f7c97a6d38c
|
File details
Details for the file blitzbeaver-1.0.0-cp311-cp311-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: blitzbeaver-1.0.0-cp311-cp311-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 5.2 MB
- Tags: CPython 3.11, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.8.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d92b4959b88b5f989370e7bc02d146c139b2a2dcf4fc9e55d62fe570f2c90d7
|
|
| MD5 |
023cf26bd7291f7d85a02eb3e8d23403
|
|
| BLAKE2b-256 |
a5373c9e98ac39b6ae20cf4314b2f62b5cfc5d8192337261b166d4d10745fde0
|