"""Label-preserving dataset normalization and connected-component splitting.""" from collections import defaultdict import hashlib,json LABELS={'positive':1,'negative':0,'unknown':None,'pos':1,'neg':0,'1':1,'0':0} def normalize_snooppi(row): raw=str(row['SNOOPPI_final_label']).lower().strip() if raw not in LABELS:raise ValueError('unrecognized SNOOPPI label: '+raw) return {'label':LABELS[raw],'label_source':raw,'partner_a':row['partner_A_sequence'], 'partner_b':row['partner_B_sequence'],'source':row.get('pubmed_ids',''), 'publication_years':row.get('publication_years',''),'assays':row.get('assays','')} def connected_splits(rows,seed=2027): """Union target clusters, peptide clusters, and publication IDs across rows. Cluster IDs are computed before this function (e.g. MMseqs2). All rows sharing any entity or primary publication receive the same split. """ parent=list(range(len(rows))) def root(i): while parent[i]!=i:parent[i]=parent[parent[i]];i=parent[i] return i def union(i,j): a,b=root(i),root(j) if a!=b:parent[max(a,b)]=min(a,b) seen={} for i,r in enumerate(rows): groups=['target:'+v for v in r['target_clusters']]+['peptide:'+v for v in r['peptide_clusters']]+['source:'+v for v in r['source_ids']] if not groups:raise ValueError('missing split source records') for g in groups: if g in seen:union(i,seen[g]) else:seen[g]=i members=defaultdict(list) for i,r in enumerate(rows):members[root(i)].append(str(r['id'])) labels={} for k,ids in members.items(): h=int(hashlib.sha256((str(seed)+'|'+ '|'.join(sorted(ids))).encode()).hexdigest()[:12],16)/16**12 labels[k]='train' if h<.7 else 'ensemble_fit' if h<.8 else 'calibration' if h<.9 else 'test' return [labels[root(i)] for i in range(len(rows))]