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"] = 'methylation'
model.metadata["species"] = 'Homo sapiens'
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.1 (2020): 56."
model.metadata["doi"] = "https://doi.org/10.1186/s13073-020-00752-3"
model.metadata["research_only"] = None
model.metadata["notes"] = "Epigenetic mitotic-like clock estimating the cumulative number of stem-cell divisions in a tissue from hypermethylation at Polycomb/PRC2-target CpGs, a variant formulation of the EpiTOC2 mitotic-age estimator developed for cancer-risk prediction from tissue and blood methylation."
model.metadata["tissue"] = 'Whole blood (656 Hannum samples used for parameter calibration); validated across multiple normal adult tissue types and TCGA cancers; fetal/cord-blood samples used only to select…'
model.metadata["predicts"] = 'Mitotic age: total number of stem-cell divisions per stem cell (TNSC), and, when normalized by chronological age, the intrinsic stem-cell division rate (IR) of a tissue — used as a…'
model.metadata["unit"] = 'years'
model.metadata["model_type"] = 'Mitotic model'
model.metadata["platform"] = 'Illumina 450K/EPIC'
model.metadata["population"] = 'Adults, pan-tissue (parameters calibrated in adult whole blood, applied across normal adult tissues and cancers)'
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