#!/usr/bin/env python3 """Has anyone tied the magnetic field or solar storms to ecosystem tipping? A search of OpenAlex. Fact-Checked Science, November 2026, for the paper check /biosphere-tipping-warning/ ("Our analysis"). Standard library only. No e-mail address or other personal data is sent. Rule, stated before the run: ten pairings of a magnetic or solar term with a tipping or resilience term, as phrases in titles and abstracts, read in full; then a wider pass, listing only the five most-cited results of each, unread. An empty result says we found none. It doesn't prove there is none: the index misses papers and wordings. Run it: python3 openalex_search.py """ import json import sys import time import urllib.parse import urllib.request sys.stdout.reconfigure(encoding="utf-8") PAIRINGS = ['geomagnetic "tipping point" ecosystem', 'geomagnetic "tipping point" vegetation', '"solar storm" "tipping point" ecosystem', '"geomagnetic storm" vegetation resilience', '"magnetic field" "tipping point" biosphere', '"pole shift" "tipping point" biosphere', '"geomagnetic" "early warning" "critical slowing down" ecosystem', '"space weather" terrestrial ecosystem resilience', '"geomagnetic" forest dieback', '"cosmic ray" "tipping point" ecosystem'] WIDER = ['"geomagnetic" vegetation', '"geomagnetic field" "plant growth"', '"solar activity" NDVI', '"solar cycle" NDVI', '"cosmic ray" vegetation NDVI', '"geomagnetic" ecosystem resilience', '"South Atlantic Anomaly" vegetation'] def run(q, per_page): u = "https://api.openalex.org/works?per-page=%d&sort=cited_by_count:desc&filter=title_and_abstract.search:%s" % (per_page, urllib.parse.quote(q)) with urllib.request.urlopen(urllib.request.Request(u, headers={"User-Agent": "Mozilla/5.0"}), timeout=60) as r: d = json.load(r) print("=== %s | count %s" % (q, d.get("meta", {}).get("count"))) for w in d.get("results", []): print(" %s | %s | %s" % (w.get("publication_year"), (w.get("display_name") or "")[:120], (w.get("doi") or "").replace("https://doi.org/", ""))) time.sleep(0.4) print("TEN PAIRINGS\n") for q in PAIRINGS: run(q, 25) print("\nTHE WIDER PASS (five most-cited of each; unread)\n") for q in WIDER: run(q, 5)