Skip to main content

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 develop
    

    Or 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

blitzbeaver-1.0.0.tar.gz (80.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

blitzbeaver-1.0.0-cp311-cp311-manylinux_2_28_x86_64.whl (5.2 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

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

Hashes for blitzbeaver-1.0.0.tar.gz
Algorithm Hash digest
SHA256 bf43a6ae9e339739985048be0423df5434fc2c81c92538328688b3dbdd16d3ea
MD5 e69dee7e44dd99c98c30fe47f599f7d4
BLAKE2b-256 dd1dfa5eeb392a0e1d5d1f3fe0280e04b5361f6f0afc255b57cf2f7c97a6d38c

See more details on using hashes here.

File details

Details for the file blitzbeaver-1.0.0-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for blitzbeaver-1.0.0-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 7d92b4959b88b5f989370e7bc02d146c139b2a2dcf4fc9e55d62fe570f2c90d7
MD5 023cf26bd7291f7d85a02eb3e8d23403
BLAKE2b-256 a5373c9e98ac39b6ae20cf4314b2f62b5cfc5d8192337261b166d4d10745fde0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page