EnsembleAgeStatic#
Index#
Let’s first import some packages:
[16]:
import os
import inspect
import shutil
import json
import torch
import pandas as pd
import pyaging as pya
Instantiate model class#
[17]:
def print_entire_class(cls):
source = inspect.getsource(cls)
print(source)
print_entire_class(pya.models.EnsembleAgeStatic)
class EnsembleAgeStatic(pyagingModel):
def __init__(self):
super().__init__()
def preprocess(self, x):
return x
def postprocess(self, x):
return x
[18]:
model = pya.models.EnsembleAgeStatic()
Define clock metadata#
[19]:
model.metadata["clock_name"] = 'ensembleagestatic'
model.metadata["data_type"] = 'methylation'
model.metadata["species"] = 'Mus musculus'
model.metadata["year"] = 2025
model.metadata["approved_by_author"] = '⌛'
model.metadata["citation"] = "Haghani, A., Lu, A.T., Yan, Q. et al. EnsembleAge: enhancing epigenetic age assessment with a multi-clock framework. GeroScience (2025)"
model.metadata["doi"] = 'https://doi.org/10.1007/s11357-025-01808-1'
model.metadata["research_only"] = None
model.metadata["notes"] = None
Download clock dependencies#
Download directly with curl#
[20]:
supplementary_url = "https://static-content.springer.com/esm/art%3A10.1007%2Fs11357-025-01808-1/MediaObjects/11357_2025_1808_MOESM1_ESM.xlsx"
supplementary_file_name = "coefficients.xlsx"
os.system(f"curl -o {supplementary_file_name} {supplementary_url}")
[20]:
0
Load features#
From Excel file#
[21]:
df = pd.read_excel('coefficients.xlsx', sheet_name='Table S3. Ensemble.Static')
df = df[df['EnsembleAge.Static_ElasticNoAgeTraf'] != 0]
model.features = df['CGid'][1:].tolist()
Load weights into base model#
[22]:
weights = torch.tensor(df['EnsembleAge.Static_ElasticNoAgeTraf'][1:].tolist()).unsqueeze(0).float()
intercept = torch.tensor([df['EnsembleAge.Static_ElasticNoAgeTraf'][0]]).float()
Linear model#
[23]:
base_model = pya.models.LinearModel(input_dim=len(model.features))
base_model.linear.weight.data = weights.float()
base_model.linear.bias.data = intercept.float()
model.base_model = base_model
Load reference values#
[24]:
model.reference_values = None
Load preprocess and postprocess objects#
[25]:
model.preprocess_name = None
model.preprocess_dependencies = None
[26]:
model.postprocess_name = None
model.postprocess_dependencies = None
Check all clock parameters#
[27]:
pya.utils.print_model_details(model)
%==================================== Model Details ====================================%
Model Attributes:
training: True
metadata: {'approved_by_author': '⌛',
'citation': 'Haghani, A., Lu, A.T., Yan, Q. et al. EnsembleAge: enhancing '
'epigenetic age assessment with a multi-clock framework. '
'GeroScience (2025)',
'clock_name': 'ensembleagestatic',
'data_type': 'methylation',
'doi': 'https://doi.org/10.1007/s11357-025-01808-1',
'notes': None,
'research_only': None,
'species': 'Mus musculus',
'version': None,
'year': 2025}
reference_values: None
preprocess_name: None
preprocess_dependencies: None
postprocess_name: None
postprocess_dependencies: None
features: ['cg00045149', 'cg00073543', 'cg00196544', 'cg00208586', 'cg00225449', 'cg00258262', 'cg00398876', 'cg00407148', 'cg00436746', 'cg00482994', 'cg00519323', 'cg00585163', 'cg00587168', 'cg00823476', 'cg00929113', 'cg00957561', 'cg00987824', 'cg01000173', 'cg01061575', 'cg01292864', 'cg01374344', 'cg01431336', 'cg01574836', 'cg01579428', 'cg01831882', 'cg01851187', 'cg01955745', 'cg02028344', 'cg02040024', 'cg02055614']... [Total elements: 288]
base_model_features: None
%==================================== Model Details ====================================%
Model Structure:
base_model: LinearModel(
(linear): Linear(in_features=288, out_features=1, bias=True)
)
%==================================== Model Details ====================================%
Model Parameters and Weights:
base_model.linear.weight: [0.0637185126543045, -0.11446300148963928, -0.0020393782760947943, 0.008083564229309559, 0.059383004903793335, 0.04884342849254608, -0.1297401338815689, 0.35425910353660583, -0.011381455697119236, -0.03423526883125305, 0.02570508047938347, 3.577101233531721e-05, 0.08512508124113083, -0.2595727741718292, -0.3420218229293823, -0.16915351152420044, -0.032312169671058655, -0.005041784606873989, 0.7813555598258972, 0.1747809797525406, 0.0031973698642104864, 0.03488273546099663, -0.016142716631293297, -0.0022294276859611273, 0.0005290567642077804, -0.41029852628707886, -0.21743696928024292, 0.0026450669392943382, 0.010644305497407913, 0.05568145588040352]... [Tensor of shape torch.Size([1, 288])]
base_model.linear.bias: tensor([2.0136])
%==================================== Model Details ====================================%
Basic test#
[28]:
torch.manual_seed(42)
input = torch.randn(10, len(model.features), dtype=float)
model.eval()
model.to(float)
pred = model(input)
pred
[28]:
tensor([[-8.9517],
[ 3.8102],
[-5.1303],
[-0.1851],
[-2.7117],
[ 1.7973],
[ 1.8472],
[ 5.4340],
[10.4711],
[-1.7131]], dtype=torch.float64, grad_fn=<AddmmBackward0>)
Save torch model#
[29]:
torch.save(model, f"../weights/{model.metadata['clock_name']}.pt")
Clear directory#
[30]:
# 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.xlsx