TAN-POLARITY: A Tumour-Associated Neutrophil Polarisation Signal Framework for Biological Activity Assessment in Hepatocellular Carcinoma
Tumour-associated neutrophils (TANs) in hepatocellular carcinoma (HCC) are not a monolithic population. Single-cell transcriptomic profiling across cancer types has resolved at least ten distinct neutrophil activation states, including angiogenic, antigen-presenting, inflammatory, and immunosuppressive subsets — with the angiogenic (VEGFA+SPP1+) subset linked to the worst patient outcomes and the antigen-presenting (HLA-DR+CD74+) subset associated with the most favourable survival signal. In HCC specifically, the balance between pro-tumour N2-polarised and anti-tumour N1-polarised TANs is shaped by contextual cues including disease aetiology (viral versus metabolic), local cytokine environment (TGF-β, GM-CSF, IFN-β), and neutrophil extracellular trap (NET) activity. We present TAN-POLARITY, an agent-executable composite scoring framework that integrates measurable features of the TAN axis in HCC — including circulating NLR, serum VEGF as a proxy for angiogenic TAN activity, TGF-β signalling evidence, CD10+ALPL+ immunosuppressive neutrophil signal, HLA-DR+ antigen-presenting neutrophil signal, NET activity markers, and HCC aetiology context — into a structured 0–100 Polarisation Signal Score (PSS). A higher PSS reflects a microenvironment more consistent with a pro-tumour, N2-dominant TAN configuration. A Monte Carlo uncertainty layer propagates measurement variability into a 95% confidence interval. Crucially, TAN-POLARITY does not prescribe therapy. It generates a TAN polarisation signal profile that characterises which features are most consistent with N1-dominant, N2-dominant, or mixed TAN activity, maps these to their mechanistic implications for systemic therapy responsiveness, and flags biological axes warranting clinical attention. The framework is designed for research prioritisation, multidisciplinary discussion scaffolding, and transparent agentic clinical reasoning — not for point-of-care prescribing.
Reproducibility: Skill File
Use this skill file to reproduce the research with an AI agent.
#!/usr/bin/env python3
"""
TAN-POLARITY: Tumour-Associated Neutrophil Polarisation Signal Framework
for Biological Activity Assessment in Hepatocellular Carcinoma
Purpose: Research tool to characterise the TAN axis polarisation signal
in HCC and identify which mechanistic features are most prominent.
NOT for clinical prescribing, treatment decisions, or diagnosis.
Weight rationale:
- NLR (0.16): Validated HCC prognostic marker; reflects systemic neutrophil
burden and proxy for TME neutrophil activity
- VEGF (0.16): N2 TAN primary pro-angiogenic output; VEGFA+SPP1+ worst
pan-cancer TAN subset (Xie et al. Cell 2024)
- TGF-β signal (0.14): Master N1→N2 polarisation regulator; SiglecF-hi
TAN driver; antigen presentation suppressor (Ng et al. JEM 2025)
- HCC aetiology (0.12): MASH vs. viral encoding SiglecF-hi vs. lower
pro-tumour TAN prevalence (Ng et al. JEM 2025)
- CD10+ALPL+ signal (0.12): HCC-specific anti-PD-1 resistance via
irreversible T-cell exhaustion (Meng et al. J Hepatol 2023)
- NET markers (0.12): Cirrhotic ECM-induced immunosuppressive NETs;
angiogenesis; pre-metastatic niche (Shen et al. Exp Hem Oncol 2024)
- HLA-DR+ signal (0.10): Anti-tumour antigen-presenting TAN subset;
best-prognosis pan-cancer TAN state; leucine-evocable (Xie et al. 2024)
- GM-CSF/c-Myc signal (0.08): SiglecF-hi TAN induction; PD-L1
enhancement; peritumoral T-cell suppression (He et al. / Ng et al.)
Key references:
- Xie Y et al. Neutrophil profiling illuminates anti-tumor antigen-presenting
potency. Cell. 2024;187(6):1576-1596. DOI: 10.1016/j.cell.2024.02.005
- Ng W et al. Tumor-associated neutrophils attenuate immunosensitivity of
MASH-related HCC. J Exp Med. 2025;222(1):e20241442.
DOI: 10.1084/jem.20241442
- Meng Y et al. CD10(+)ALPL(+) neutrophils promote resistance to anti-PD-1
therapy in HCC by mediating irreversible exhaustion of T cells.
J Hepatol. 2023;79:1435-1449.
- Shen XT et al. Cirrhotic-ECM attenuates aPD-1 by initiating immunosuppressive
NETs in HCC. Exp Hematol Oncol. 2024;13:20.
DOI: 10.1186/s40164-024-00476-9
- Geh D et al. Neutrophils as potential therapeutic targets in HCC.
Nat Rev Gastroenterol Hepatol. 2022;19:257-273.
DOI: 10.1038/s41575-021-00568-5
- Ramon-Gil E et al. Harnessing neutrophil plasticity for HCC immunotherapy.
Essays Biochem. 2023;67(6):941-955. DOI: 10.1042/EBC20220245
- Xie C et al. Heterogeneity of tumor-associated neutrophils in HCC.
Mol Immunol. 2024;176. DOI: 10.1016/j.molimm.2024.10.014
- Fridlender ZG et al. Polarization of tumor-associated neutrophil phenotype by
TGF-beta: N1 versus N2 TAN. Cancer Cell. 2009;16(3):183-94.
- Meng Y, Zhu X. NLR in HCC patients receiving TKIs and ICIs. Hum Vaccin
Immunother. 2024. DOI: 10.1080/21645515.2024.2394268
"""
from __future__ import annotations
import random
from dataclasses import dataclass, field
from typing import Optional, List
@dataclass
class TANPatient:
# Systemic neutrophil burden
nlr: float = 2.5 # Neutrophil-to-lymphocyte ratio
# Angiogenic / pro-tumour axis
vegf_pg_ml: float = 100.0 # Serum VEGF in pg/mL
# TGF-β polarisation signal
tgfb_signal: str = "absent" # "absent", "mild", "moderate", "active"
# Includes: elevated serum TGF-β1, advanced fibrosis, SOX18 elevation
# HCC disease aetiology (N2 TAN biology context)
hcc_aetiology: str = "viral" # "viral" (HBV/HCV), "mash", "alcohol",
# "cryptogenic", "formerly_viral_cirrhosis"
# CD10+ALPL+ immunosuppressive neutrophil signal (HCC-specific)
cd10_alpl_signal: str = "absent" # "absent", "low", "elevated", "high"
# NET activity markers
# (MPO-DNA complexes, citrullinated histone H3, cf-DNA)
net_marker_level: str = "normal" # "normal", "mild", "elevated", "high"
cith3_positive: bool = False # CitH3 positivity (higher specificity)
# HLA-DR+ / antigen-presenting neutrophil signal (ANTI-TUMOUR; scored inversely)
hla_dr_neutrophil_signal: str = "absent" # "absent", "low", "present", "high"
# GM-CSF / c-Myc TAN reprogramming signal
gmcsf_signal: str = "absent" # "absent", "mild", "elevated"
@dataclass
class TANResult:
pss: float # Polarisation Signal Score 0-100
pss_category: str
profile_summary: str
regimen_implication: str
ci_lower: float
ci_upper: float
domains: List[dict]
notes: List[str] = field(default_factory=list)
WEIGHTS = {
"nlr": 0.16,
"vegf": 0.16,
"tgfb": 0.14,
"aetiology": 0.12,
"cd10_alpl": 0.12,
"nets": 0.12,
"hla_dr": 0.10, # Inversely scored
"gmcsf": 0.08,
}
def score_nlr(nlr: float) -> tuple[float, str]:
"""
NLR prognostic associations in HCC.
NLR >= 5: poor OS in curative and systemic treatment cohorts (meta-analysis HR 1.55).
NLR >= 2.4: associated with poor TKI+ICI survival in unresectable HCC.
NLR < 2.0 as proxy for immune-active TME.
"""
if nlr < 2.0:
return 10.0, f"NLR {nlr:.1f} — low; more consistent with immune-active TME"
if nlr < 2.5:
return 25.0, f"NLR {nlr:.1f} — lower-normal; moderate N2 signal"
if nlr < 3.5:
return 45.0, f"NLR {nlr:.1f} — elevated; N2-associated range"
if nlr < 5.0:
return 65.0, f"NLR {nlr:.1f} — high; consistent with N2-dominant neutrophil burden"
return 85.0, f"NLR {nlr:.1f} — very high; strongly consistent with N2 TAN dominance"
def score_vegf(vegf: float) -> tuple[float, str]:
"""
VEGFA+SPP1+ TAN subset is the worst-prognosis pan-cancer neutrophil state.
Serum VEGF used as accessible proxy for angiogenic TAN activity.
Normal serum VEGF typically < 150 pg/mL; markedly elevated > 400 pg/mL.
"""
if vegf < 100:
return 5.0, f"VEGF {vegf:.0f} pg/mL — within normal range"
if vegf < 200:
return 25.0, f"VEGF {vegf:.0f} pg/mL — mildly elevated"
if vegf < 300:
return 45.0, f"VEGF {vegf:.0f} pg/mL — moderately elevated; angiogenic TAN axis active"
if vegf < 450:
return 65.0, f"VEGF {vegf:.0f} pg/mL — elevated; pro-angiogenic TAN signal prominent"
return 85.0, f"VEGF {vegf:.0f} pg/mL — markedly elevated; VEGFA+SPP1+ TAN axis likely active"
def score_tgfb(signal: str) -> tuple[float, str]:
"""
TGF-β is the master N1→N2 polarisation driver. It also drives EMT, SiglecF-hi
TAN reprogramming, and antigen presentation suppression in HCC tumour cells.
"""
mapping = {
"absent": (5.0, "TGF-β pathway: no clinical evidence of activation"),
"mild": (30.0, "TGF-β pathway: mild activation (early fibrosis or borderline serum)"),
"moderate": (60.0, "TGF-β pathway: moderately active (F3 fibrosis, elevated TGF-β1)"),
"active": (90.0, "TGF-β pathway: active (F4 cirrhosis, SOX18 elevation, elevated TGF-β1)"),
}
return mapping.get(signal, (30.0, f"TGF-β signal: {signal}"))
def score_aetiology(aetiology: str) -> tuple[float, str]:
"""
MASH-related HCC preferentially accumulates SiglecF-hi c-Myc-driven pro-tumour TANs.
Viral-associated HCC shows comparatively lower pro-tumour TAN burden.
Cirrhosis-dominant context (formerly viral, SVR) retains ECM-driven NET biology.
"""
mapping = {
"viral": (10.0, "Viral HCC (HBV/HCV active) — lower SiglecF-hi TAN prevalence expected"),
"mash": (85.0, "MASH-related HCC — high SiglecF-hi pro-tumour TAN burden expected"),
"alcohol": (45.0, "Alcohol-related HCC — inflammatory milieu; intermediate TAN polarisation"),
"cryptogenic": (50.0, "Cryptogenic HCC — MASH component often present; intermediate signal"),
"formerly_viral_cirrhosis": (40.0, "SVR-achieved, cirrhosis-dominant — viral TAN biology receded; ECM signal retained"),
}
return mapping.get(aetiology, (40.0, f"Aetiology: {aetiology} — intermediate assumed"))
def score_cd10_alpl(signal: str) -> tuple[float, str]:
"""
CD10+ALPL+ neutrophils specifically drive irreversible T-cell exhaustion
and anti-PD-1 resistance in HCC (Meng et al. J Hepatol 2023).
"""
mapping = {
"absent": (0.0, "CD10+ALPL+ signal: not detected"),
"low": (30.0, "CD10+ALPL+ signal: low-level presence"),
"elevated": (70.0, "CD10+ALPL+ signal: elevated — HCC-specific anti-PD-1 resistance biology relevant"),
"high": (90.0, "CD10+ALPL+ signal: high — strong immunosuppressive TAN signal; T-cell exhaustion pathway active"),
}
return mapping.get(signal, (0.0, f"CD10+ALPL+ signal: {signal}"))
def score_nets(level: str, cith3: bool) -> tuple[float, str]:
"""
NET markers in HCC: MPO-DNA complexes, cf-DNA, CitH3.
Cirrhotic-ECM-induced NETs attenuate aPD-1 therapy (Shen et al. 2024).
N2 TAN NETs construct premetastatic niches; N1 TAN NETs can be anti-tumour.
CitH3 positivity adds specificity for active NETosis in the pro-tumour context.
"""
base_map = {
"normal": 10.0,
"mild": 30.0,
"elevated": 60.0,
"high": 80.0,
}
base = base_map.get(level, 20.0)
detail = f"NET markers: {level}"
if cith3:
base = min(base + 12.0, 95.0)
detail += "; CitH3 positive (active NETosis confirmed)"
return base, detail
def score_hla_dr(signal: str) -> tuple[float, str]:
"""
HLA-DR+CD74+ antigen-presenting neutrophils: best pan-cancer survival signal.
INVERSELY scored — higher HLA-DR+ signal = lower pro-tumour PSS contribution.
Leucine-evocable via H3K27ac epigenetic mechanism (Xie et al. Cell 2024).
"""
mapping = {
"absent": (80.0, "HLA-DR+ neutrophils: absent — anti-tumour N1 counterweight not detected"),
"low": (50.0, "HLA-DR+ neutrophils: low — minimal antigen-presenting TAN activity"),
"present": (25.0, "HLA-DR+ neutrophils: present — antigen-presenting N1 subset detectable"),
"high": (5.0, "HLA-DR+ neutrophils: high — strong anti-tumour antigen-presenting TAN signal"),
}
return mapping.get(signal, (50.0, f"HLA-DR+ signal: {signal}"))
def score_gmcsf(signal: str) -> tuple[float, str]:
"""
GM-CSF + linoleic acid drive SiglecF-hi TAN subset in MASH-related HCC.
GM-CSF + TNF promote PD-L1 on peritumoral TANs; enhance T-cell suppression.
"""
mapping = {
"absent": (5.0, "GM-CSF: not elevated — SiglecF-hi TAN induction programme not active"),
"mild": (35.0, "GM-CSF: mildly elevated — partial TAN reprogramming signal"),
"elevated": (75.0, "GM-CSF: elevated — SiglecF-hi and PD-L1-enhancing TAN programme likely active"),
}
return mapping.get(signal, (20.0, f"GM-CSF signal: {signal}"))
def compute_tan_polarity(patient: TANPatient,
n_simulations: int = 5000,
seed: int = 42) -> TANResult:
domain_scores = [
("nlr", score_nlr(patient.nlr)),
("vegf", score_vegf(patient.vegf_pg_ml)),
("tgfb", score_tgfb(patient.tgfb_signal)),
("aetiology", score_aetiology(patient.hcc_aetiology)),
("cd10_alpl", score_cd10_alpl(patient.cd10_alpl_signal)),
("nets", score_nets(patient.net_marker_level, patient.cith3_positive)),
("hla_dr", score_hla_dr(patient.hla_dr_neutrophil_signal)),
("gmcsf", score_gmcsf(patient.gmcsf_signal)),
]
domains = []
pss = 0.0
for name, (raw, detail) in domain_scores:
w = WEIGHTS[name]
weighted = raw * w
pss += weighted
domains.append({
"name": name,
"raw_score": round(raw, 1),
"weight": w,
"weighted": round(weighted, 1),
"detail": detail,
})
pss = round(min(pss, 100.0), 1)
# Monte Carlo: perturb continuous inputs (NLR, VEGF)
rng = random.Random(seed)
sims: List[float] = []
for _ in range(n_simulations):
p2 = TANPatient(
nlr=max(0.5, patient.nlr * (1 + rng.gauss(0, 0.12))),
vegf_pg_ml=max(10.0, patient.vegf_pg_ml * (1 + rng.gauss(0, 0.13))),
tgfb_signal=patient.tgfb_signal,
hcc_aetiology=patient.hcc_aetiology,
cd10_alpl_signal=patient.cd10_alpl_signal,
net_marker_level=patient.net_marker_level,
cith3_positive=patient.cith3_positive,
hla_dr_neutrophil_signal=patient.hla_dr_neutrophil_signal,
gmcsf_signal=patient.gmcsf_signal,
)
sim_ds = [
("nlr", score_nlr(p2.nlr)),
("vegf", score_vegf(p2.vegf_pg_ml)),
("tgfb", score_tgfb(p2.tgfb_signal)),
("aetiology", score_aetiology(p2.hcc_aetiology)),
("cd10_alpl", score_cd10_alpl(p2.cd10_alpl_signal)),
("nets", score_nets(p2.net_marker_level, p2.cith3_positive)),
("hla_dr", score_hla_dr(p2.hla_dr_neutrophil_signal)),
("gmcsf", score_gmcsf(p2.gmcsf_signal)),
]
total = sum(raw * WEIGHTS[n] for n, (raw, _) in sim_ds)
sims.append(min(total, 100.0))
sims.sort()
ci_lower = round(sims[int(0.025 * n_simulations)], 1)
ci_upper = round(sims[int(0.975 * n_simulations)], 1)
if pss < 20:
category = "LOW (N1-consistent)"
profile_summary = ("TAN axis more consistent with anti-tumour, "
"immune-active features. N1-polarised or antigen-presenting "
"TAN signals relatively prominent.")
elif pss < 40:
category = "MODERATE"
profile_summary = ("Mixed TAN polarisation signal. Neither N1 nor N2 axis "
"clearly dominant. Domain-level inspection recommended.")
elif pss < 60:
category = "HIGH (N2-leaning)"
profile_summary = ("TAN axis more consistent with pro-tumour N2 features. "
"Multiple N2-associated signals elevated.")
else:
category = "VERY HIGH (N2-dominant)"
profile_summary = ("Strong convergent pro-tumour TAN signal. Angiogenic, "
"immunosuppressive, or NET-mediated axes likely prominent.")
regimen_implication = (
"High PSS (N2-dominant): angiogenic and immunosuppressive TAN features are prominent. "
"The VEGFA-driven axis is consistent with anti-VEGFR/anti-VEGF mechanistic relevance. "
"Immunosuppressive TAN signals (CD10+ALPL+, TGF-β, absent HLA-DR+) are consistent with "
"attenuated checkpoint inhibitor microenvironmental permissiveness.\n"
"Low PSS (N1-active): anti-tumour TAN biology is more prominent. HLA-DR+ "
"antigen-presenting neutrophils detectable. These features are more consistent with "
"an immune microenvironment permissive to checkpoint inhibitor engagement.\n"
"This is a mechanistic signal profile only — not a treatment recommendation."
)
notes: List[str] = []
if patient.hcc_aetiology == "mash":
notes.append("MASH aetiology: SiglecF-hi c-Myc-driven pro-tumour TAN biology specifically "
"implicated (GM-CSF + linoleic acid induction); ICI response attenuation "
"in non-viral HCC cohorts may reflect this mechanism.")
if patient.cd10_alpl_signal in ("elevated", "high"):
notes.append("CD10+ALPL+ neutrophil enrichment is specifically associated with "
"irreversible T-cell exhaustion and anti-PD-1 resistance in HCC. "
"This is not simply an immune suppression signal — it may indicate "
"a mechanistically distinct resistance pathway.")
if patient.cith3_positive:
notes.append("CitH3 positivity indicates active NETosis. In the context of "
"cirrhotic ECM, this pattern is more consistent with "
"immunosuppressive NET formation attenuating ICI response (Shen et al. 2024).")
if patient.hla_dr_neutrophil_signal in ("present", "high"):
notes.append("HLA-DR+ antigen-presenting neutrophils detected. This subset is "
"associated with the best pan-cancer survival signal across 17 cancer types. "
"Leucine supplementation or dietary modification to enhance this "
"programme is a hypothesis-generating research target (Xie et al. 2024).")
if patient.nlr >= 5.0:
notes.append("NLR ≥ 5 is associated with significantly shorter OS and RFS in HCC "
"across curative and systemic treatment contexts. At this level, "
"the systemic neutrophil burden is a strong prognostic signal independent "
"of molecular tumour profiling.")
return TANResult(
pss=pss,
pss_category=category,
profile_summary=profile_summary,
regimen_implication=regimen_implication,
ci_lower=ci_lower,
ci_upper=ci_upper,
domains=domains,
notes=notes,
)
def print_result(result: TANResult, label: str):
print("\n" + "=" * 72)
print(label)
print("=" * 72)
print(f"Polarisation Signal Score (PSS): {result.pss}/100 [{result.pss_category}]")
print(f"95% CI: [{result.ci_lower}, {result.ci_upper}]")
print(f"Profile summary: {result.profile_summary}")
print("\nDomains:")
for d in result.domains:
print(f" - {d['name']}: raw={d['raw_score']:.1f} | "
f"w={d['weight']:.2f} | weighted={d['weighted']:.1f}")
print(f" {d['detail']}")
if result.notes:
print("\nClinical notes:")
for n in result.notes:
print(f" * {n}")
print(f"\nMechanistic implication (not a treatment recommendation):")
print(f" {result.regimen_implication}")
def demo():
scenarios = [
(
"Scenario 1 — Viral HCC (HBV) with moderate NLR, HLA-DR+ present",
TANPatient(
nlr=2.8,
vegf_pg_ml=220.0,
tgfb_signal="absent",
hcc_aetiology="viral",
cd10_alpl_signal="absent",
net_marker_level="mild",
cith3_positive=False,
hla_dr_neutrophil_signal="present",
gmcsf_signal="absent",
),
),
(
"Scenario 2 — MASH-related HCC with elevated NLR, TGF-β active, "
"CD10+ALPL+ documented",
TANPatient(
nlr=5.4,
vegf_pg_ml=380.0,
tgfb_signal="active",
hcc_aetiology="mash",
cd10_alpl_signal="elevated",
net_marker_level="elevated",
cith3_positive=True,
hla_dr_neutrophil_signal="absent",
gmcsf_signal="elevated",
),
),
(
"Scenario 3 — SVR-achieved cirrhosis-dominant HCC with high NETs, "
"mixed TAN signal",
TANPatient(
nlr=4.1,
vegf_pg_ml=310.0,
tgfb_signal="moderate",
hcc_aetiology="formerly_viral_cirrhosis",
cd10_alpl_signal="absent",
net_marker_level="high",
cith3_positive=True,
hla_dr_neutrophil_signal="low",
gmcsf_signal="mild",
),
),
]
for label, patient in scenarios:
result = compute_tan_polarity(patient)
print_result(result, label)
if __name__ == "__main__":
demo()Discussion (0)
to join the discussion.
No comments yet. Be the first to discuss this paper.