sn1 / meta2frame.py
steffenc's picture
Fix dataframe construction bug and improve logging/tqdm outputs
08fa697
import glob
import tqdm
import pickle
import os
import datetime
import torch
import bittensor as bt
import pandas as pd
import plotly.express as px
ROOT_DIR = './data/metagraph/'
def load_metagraphs(root_dir, netuid, block_min=0, block_max=3_000_000):
metagraphs = []
match_path = os.path.join(root_dir, str(netuid), '*.pkl')
files = glob.glob(match_path)
print(f'Found {len(files)} metagraphs in {match_path}')
valid_files = [path for path in files if block_min <= int(path.split('/')[-1].split('.')[0]) <= block_max]
pbar = tqdm.tqdm(valid_files, desc=f'Loading {len(valid_files)} metagraph snapshots')
for path in pbar:
with open(path, 'rb') as f:
metagraph = pickle.load(f)
metagraphs.append(metagraph)
return sorted(metagraphs, key=lambda x: x.block)
def get_block_timestamp(block, subtensor):
info = subtensor.substrate.get_block(block_number=int(block))
extrinsic_call = info['extrinsics'][0]['call']
return extrinsic_call.value_serialized['call_args'][0]['value']
def block_to_time(blocks, subtensor=None):
if not isinstance(blocks, pd.Series):
blocks = pd.Series(blocks)
if subtensor is None:
subtensor = bt.subtensor(network='archive')
timestamps = {}
unique_blocks = set(blocks)
for block in tqdm.tqdm(unique_blocks, desc=f'Mapping {len(unique_blocks)} blocks to timestamps'):
timestamps[block] = get_block_timestamp(block, subtensor)
return blocks.map(timestamps).apply(pd.to_datetime, unit='ms')
def make_dataframe(netuid, root_dir=ROOT_DIR, cols=None, block_min=0, block_max=3_000_000, weights=False):
if cols is None:
cols = ['stake','emission','trust','validator_trust','dividends','incentive','R', 'consensus','validator_permit']
frames = []
metagraphs = load_metagraphs(root_dir, netuid, block_min, block_max)
for m in metagraphs:
frame = pd.DataFrame({k: getattr(m, k) for k in cols})
frame['block'] = m.block.item()
frame['netuid'] = netuid
frame['uid'] = range(len(frame))
frame['hotkey'] = [axon.hotkey for axon in m.axons]
frame['coldkey'] = [axon.coldkey for axon in m.axons]
if weights and m.W is not None:
# convert NxN tensor to a list of lists so it fits into the dataframe
frame['weights'] = [w.tolist() for w in m.W]
frames.append(frame)
df = pd.concat(frames)
df['timestamp'] = block_to_time(df['block'])
return df.sort_values(by=['timestamp','block','uid'])