EpiTOC3#

Index#

  1. Instantiate model class

  2. Define clock metadata

  3. Download clock dependencies

  4. Load features

  5. Load weights into base model

  6. Load reference values

  7. Load preprocess and postprocess objects

  8. Check all clock parameters

  9. Basic test

  10. Save torch model

  11. Clear directory

Let’s first import some packages:

[1]:
import os
import inspect
import shutil
import json
import torch
import pandas as pd
import pyaging as pya

Instantiate model class#

[2]:
def print_entire_class(cls):
    source = inspect.getsource(cls)
    print(source)

print_entire_class(pya.models.EpiTOC3)
class EpiTOC3(epiTOC2):
    pass

[3]:
model = pya.models.EpiTOC3()

Define clock metadata#

[4]:
model.metadata["clock_name"] = "epitoc3"
model.metadata["data_type"] = "DNA methylation"  # Paper: The study constructs clocks from DNA methylation measurements.
model.metadata["species"] = "Homo sapiens"  # Paper: The analyzed samples and clock are human.
model.metadata["year"] = 2020
model.metadata["approved_by_author"] = "⌛"
model.metadata["citation"] = "Teschendorff, Andrew E. \"A comparison of epigenetic mitotic-like clocks for cancer risk prediction.\" Genome Medicine 12 (2020): 56."
model.metadata["doi"] = "https://doi.org/10.1186/s13073-020-00752-3"
model.metadata["notes"] = "Code-defined 170-CpG extension of the dynamic mitotic model. Official EpiMitClocks data show that all 170 sites are a subset of the 371 stemTOC vivo-mitCpGs derived from fetal/neonatal references, six normal proliferating cell lines, and three adult whole-blood cohorts. The assigned 2020 dynamic-model paper does not name or define epiTOC3."
model.metadata["research_only"] = None
model.metadata["tissue"] = ["cultured primary human cells", "whole blood", "multi-tissue", "cord blood"]  # Paper: epiTOC3 uses 170 unmethylated population-doubling-associated CpGs.
model.metadata["predicts"] = ["mitotic age"]  # Paper: The function directly estimates cumulative stem-cell divisions in a tissue.
model.metadata["training_target"] = ["population doublings"]  # Paper: The epiTOC3 signature comprises population-doubling-associated CpGs.
model.metadata["unit"] = ["cell divisions per stem cell"]  # Paper: The returned TNSC is cumulative stem-cell divisions.
model.metadata["model_type"] = "dynamic methylation transmission model"  # Paper: The function describes epiTOC3 as building on a dynamic DNA methylation-gain model.
model.metadata["platform"] = ["Illumina 450K", "Illumina EPIC"]  # Paper: Input is an Illumina 450k/EPIC DNAm beta matrix.
model.metadata["population"] = "all ages"  # Paper: The derivation uses fetal/neonatal reference tissues, six normal cell lines, and adult whole-blood cohorts.
model.metadata["journal"] = "Genome Medicine"
model.metadata["last_author"] = "Andrew E. Teschendorff"
model.metadata["n_features"] = 170
model.metadata["citations"] = 155
model.metadata["citations_date"] = "2026-07-05"

Download clock dependencies#

[5]:
supplementary_url = "https://raw.githubusercontent.com/Duzhaozhen/OmniAge/c10fbe8cb92957520fbff1d55ae1def0691252e5/OmniAgePy/src/omniage/data/epiTOC3.csv"
supplementary_file_name = "coefficients.csv"
os.system(f"curl -sL -o {supplementary_file_name} {supplementary_url}")
[5]:
0

Load features#

[6]:
df = pd.read_csv('coefficients.csv')
model.features = df['probe'].astype(str).tolist()

Load weights into base model#

[7]:
model.delta = torch.tensor(df['delta'].values, dtype=torch.float32).unsqueeze(0)
model.beta0 = torch.tensor(df['beta0'].values, dtype=torch.float32).unsqueeze(0)
[8]:
model.base_model = None

Load reference values#

[9]:
model.reference_values = [-1]*len(model.features)

Load preprocess and postprocess objects#

[10]:
model.preprocess_name = "nan_to_zero"
model.preprocess_dependencies = None
[11]:
model.postprocess_name = None
model.postprocess_dependencies = None

Check all clock parameters#

[12]:
pya.utils.print_model_details(model)

%==================================== Model Details ====================================%
Model Attributes:

training: True
metadata: {'approved_by_author': '⌛',
 'citation': 'Teschendorff, Andrew E. "A comparison of epigenetic mitotic-like '
             'clocks for cancer risk prediction." Genome Medicine 12.1 (2020): '
             '56.',
 'clock_name': 'epitoc3',
 'data_type': 'methylation',
 'doi': 'https://doi.org/10.1186/s13073-020-00752-3',
 'notes': None,
 'research_only': None,
 'species': 'Homo sapiens',
 'version': None,
 'year': 2020}
reference_values: [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]... [Total elements: 170]
preprocess_name: 'nan_to_zero'
preprocess_dependencies: None
postprocess_name: None
postprocess_dependencies: None
features: ['cg23062112', 'cg18560328', 'cg21229268', 'cg11250773', 'cg12892303', 'cg12781700', 'cg12065366', 'cg17712694', 'cg12799781', 'cg01718742', 'cg10263370', 'cg16491617', 'cg11832210', 'cg07686635', 'cg26510017', 'cg15745900', 'cg15402399', 'cg05009934', 'cg10094616', 'cg06010588', 'cg23847712', 'cg17370163', 'cg13428480', 'cg22620221', 'cg16437728', 'cg25984671', 'cg07882671', 'cg04342955', 'cg14482313', 'cg14537533']... [Total elements: 170]
base_model_features: None
base_model: None
delta: [9.999999747378752e-05, 9.999999747378752e-05, 9.999999747378752e-05, 0.0002500000118743628, 9.999999747378752e-05, 9.999999747378752e-05, 9.999999747378752e-05, 9.999999747378752e-05, 4.999999873689376e-05, 0.0002500000118743628, 0.0002500000118743628, 9.999999747378752e-05, 9.999999747378752e-06, 9.999999747378752e-06, 4.999999873689376e-05, 4.999999873689376e-05, 9.999999747378752e-06, 4.999999873689376e-05, 4.999999873689376e-05, 0.0002500000118743628, 0.0002500000118743628, 0.0002500000118743628, 4.999999873689376e-05, 0.0002500000118743628, 9.999999747378752e-05, 9.999999747378752e-05, 9.999999747378752e-05, 4.999999873689376e-05, 0.0002500000118743628, 9.999999747378752e-05]... [Tensor of shape torch.Size([1, 170])]
beta0: [0.05000000074505806, 0.019999999552965164, 0.029999999329447746, 0.0, 0.03999999910593033, 0.03999999910593033, 0.05000000074505806, 0.05000000074505806, 0.029999999329447746, 0.009999999776482582, 0.019999999552965164, 0.029999999329447746, 0.03999999910593033, 0.05000000074505806, 0.019999999552965164, 0.03999999910593033, 0.05000000074505806, 0.03999999910593033, 0.05000000074505806, 0.05000000074505806, 0.05000000074505806, 0.05000000074505806, 0.03999999910593033, 0.05000000074505806, 0.05000000074505806, 0.05000000074505806, 0.019999999552965164, 0.05000000074505806, 0.0, 0.019999999552965164]... [Tensor of shape torch.Size([1, 170])]

%==================================== Model Details ====================================%
Model Structure:


%==================================== Model Details ====================================%
Model Parameters and Weights:


%==================================== Model Details ====================================%

Basic test#

[13]:
torch.manual_seed(42)
input = torch.randn(10, len(model.features), dtype=float)
model.eval()
model.to(float)
pred = model(input)
pred
[13]:
tensor([[ 1921.6122],
        [-4698.6198],
        [ 1365.4274],
        [-4247.0676],
        [  -35.5126],
        [  116.7216],
        [ 7356.7134],
        [-3367.8507],
        [ 7780.6034],
        [-7170.8200]], dtype=torch.float64)

Save torch model#

[14]:
torch.save(model, f"../weights/{model.metadata['clock_name']}.pt")

Clear directory#

[15]:
# Function to remove a folder and all its contents
def remove_folder(path):
    try:
        shutil.rmtree(path)
        print(f"Deleted folder: {path}")
    except Exception as e:
        print(f"Error deleting folder {path}: {e}")

# Get a list of all files and folders in the current directory
all_items = os.listdir('.')

# Loop through the items
for item in all_items:
    # Check if it's a file and does not end with .ipynb
    if os.path.isfile(item) and not item.endswith('.ipynb'):
        os.remove(item)
        print(f"Deleted file: {item}")
    # Check if it's a folder
    elif os.path.isdir(item):
        remove_folder(item)
Deleted file: coefficients.csv