mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
200 lines
7.5 KiB
Python
200 lines
7.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Semantic Scholar batch fetcher.
|
|
100 requests per 5 minutes = 1 request per 3 seconds.
|
|
Fills verification table with real peer-reviewed paper references.
|
|
Uses /dev/shm for fast WAL-mode SQLite.
|
|
"""
|
|
|
|
import sqlite3
|
|
import urllib.request
|
|
import urllib.parse
|
|
import json
|
|
import time
|
|
import os
|
|
import sys
|
|
|
|
SRC = "/home/allaun/physics_equations.db"
|
|
TMP = "/dev/shm/physics_equations.db"
|
|
|
|
if os.path.exists(TMP):
|
|
os.remove(TMP)
|
|
os.system(f"cp {SRC} {TMP}")
|
|
|
|
conn = sqlite3.connect(TMP)
|
|
conn.execute("PRAGMA journal_mode=WAL")
|
|
conn.execute("PRAGMA synchronous=OFF")
|
|
conn.execute("PRAGMA cache_size=-2000000")
|
|
cur = conn.cursor()
|
|
|
|
# Get all domain info
|
|
cur.execute("SELECT id, name FROM domains WHERE id IN (SELECT DISTINCT domain_id FROM equations WHERE domain_id IS NOT NULL) ORDER BY id")
|
|
domains = {r[0]: r[1] for r in cur.fetchall()}
|
|
|
|
# Get all equations grouped by domain
|
|
cur.execute("SELECT domain_id, id FROM equations WHERE domain_id IS NOT NULL")
|
|
domain_eqs = {}
|
|
for d, e in cur.fetchall():
|
|
domain_eqs.setdefault(d, []).append(e)
|
|
|
|
# ================================================================
|
|
# Semantic Scholar search queries per domain
|
|
# ================================================================
|
|
DOMAIN_SEARCHES = [
|
|
(1, "Newton laws motion"),
|
|
(2, "universal gravitation inverse square"),
|
|
(3, "Maxwell equations experimental verification"),
|
|
(4, "second law thermodynamics entropy"),
|
|
(5, "Schrodinger equation quantum mechanics"),
|
|
(6, "Einstein field equations general relativity test"),
|
|
(7, "Standard Model electroweak precision"),
|
|
(8, "Hubble constant cosmological parameters"),
|
|
(9, "Navier-Stokes turbulence Kolmogorov"),
|
|
(10, "Snell law refraction optics"),
|
|
(11, "speed of sound acoustic measurement"),
|
|
(12, "BCS superconductivity Cooper pairs"),
|
|
(13, "neutrino oscillation flavor mixing"),
|
|
(14, "Chandrasekhar limit white dwarf mass"),
|
|
(15, "Debye length plasma physics"),
|
|
(16, "Noether theorem symmetry conservation"),
|
|
(17, "fluctuation theorem statistical mechanics"),
|
|
(18, "Hooke law elasticity modulus"),
|
|
(19, "Landauer principle information thermodynamics"),
|
|
(20, "Planck constant Kibble balance kilogram"),
|
|
(21, "Hall-Petch grain size strengthening"),
|
|
(22, "Bragg diffraction crystal structure"),
|
|
(23, "Shockley diode semiconductor pn junction"),
|
|
(24, "Flory-Huggins polymer solution theory"),
|
|
(25, "Langmuir adsorption isotherm"),
|
|
(28, "Gutenberg-Richter earthquake magnitude"),
|
|
(29, "geostrophic wind atmospheric dynamics"),
|
|
(30, "ocean wave dispersion gravity wave"),
|
|
(31, "Darcy law groundwater flow porous media"),
|
|
(32, "Hodgkin-Huxley action potential neuron"),
|
|
(33, "Marcus electron transfer reaction rate"),
|
|
(34, "optical frequency comb laser spectroscopy"),
|
|
(35, "Zeeman effect magnetic field splitting"),
|
|
(36, "non-Newtonian fluid power-law rheology"),
|
|
(37, "Archard wear law tribology"),
|
|
(38, "Janssen effect granular silo pressure"),
|
|
(39, "Coulomb blockade single-electron transistor"),
|
|
(40, "Bell inequality entanglement quantum"),
|
|
(41, "Lorenz attractor deterministic chaos"),
|
|
(42, "MRI Bloch equation imaging contrast"),
|
|
(43, "Bethe-Bloch stopping power charged particle"),
|
|
(44, "Shockley-Queisser solar cell efficiency limit"),
|
|
(45, "Parker spiral solar wind magnetic field"),
|
|
(46, "Chapman-Jouguet detonation velocity"),
|
|
(47, "negative refractive index metamaterial"),
|
|
(48, "sonar equation underwater acoustics"),
|
|
(49, "PID control feedback engineering"),
|
|
]
|
|
|
|
# ================================================================
|
|
# Semantic Scholar API
|
|
# ================================================================
|
|
def s2_search(query, limit=5):
|
|
"""
|
|
Search Semantic Scholar for papers matching query.
|
|
Returns list of dicts: {title, year, doi, journal, citations}
|
|
Rate limit: 100 requests per 5 minutes.
|
|
"""
|
|
papers = []
|
|
try:
|
|
url = "https://api.semanticscholar.org/graph/v1/paper/search"
|
|
params = {
|
|
"query": query,
|
|
"limit": limit,
|
|
"fields": "title,year,externalIds,journal,publicationDate,citationCount",
|
|
}
|
|
full_url = url + "?" + urllib.parse.urlencode(params)
|
|
req = urllib.request.Request(full_url, headers={"User-Agent": "PhysicsDB/1.0"})
|
|
with urllib.request.urlopen(req, timeout=20) as resp:
|
|
data = json.loads(resp.read().decode())
|
|
|
|
for paper in data.get("data", []):
|
|
ext = paper.get("externalIds", {}) or {}
|
|
journal_info = paper.get("journal", {}) or {}
|
|
papers.append({
|
|
"paperId": paper.get("paperId", ""),
|
|
"title": paper.get("title", "")[:250],
|
|
"year": paper.get("year") or 0,
|
|
"doi": ext.get("DOI", ""),
|
|
"journal": journal_info.get("name", "") if journal_info else "",
|
|
"citations": paper.get("citationCount", 0),
|
|
"query": query,
|
|
})
|
|
except Exception as e:
|
|
print(f" S2 error [{query[:40]}]: {e}", flush=True)
|
|
return papers
|
|
|
|
|
|
# ================================================================
|
|
# Fetch all domains (serial, rate-limited)
|
|
# ================================================================
|
|
total_papers = 0
|
|
insert_rows = []
|
|
start_time = time.time()
|
|
|
|
print(f"Fetching Semantic Scholar for {len(DOMAIN_SEARCHES)} domains...")
|
|
print("(Rate limit: 100 req / 5 min = 1 per 3 seconds)\n")
|
|
|
|
for dom_id, query in DOMAIN_SEARCHES:
|
|
papers = s2_search(query, limit=5)
|
|
name = domains.get(dom_id, f"domain_{dom_id}")
|
|
eqs = domain_eqs.get(dom_id, [None])
|
|
|
|
for i, p in enumerate(papers):
|
|
eq_id = eqs[i % len(eqs)] if eqs else None
|
|
experiment_text = f"Semantic Scholar: {p['journal']}" if p['journal'] else f"S2 [{query}]"
|
|
insert_rows.append((
|
|
eq_id,
|
|
p["title"],
|
|
experiment_text,
|
|
p["year"],
|
|
p["doi"] if p["doi"] else f"S2:{p['paperId'][:20]}",
|
|
"Peer-reviewed (S2)",
|
|
))
|
|
total_papers += 1
|
|
|
|
print(f" {name:30s} → {len(papers):2d} papers | total: {total_papers:3d} | {time.time()-start_time:.0f}s", flush=True)
|
|
time.sleep(3.1) # Respect rate limit
|
|
|
|
# ================================================================
|
|
# Insert into database
|
|
# ================================================================
|
|
print(f"\nBatch inserting {len(insert_rows)} records into {TMP}...")
|
|
cur.executemany(
|
|
"""INSERT INTO verifications (equation_id, test_name, experiment, year, precision_level, status)
|
|
VALUES (?, ?, ?, ?, ?, ?)""",
|
|
insert_rows,
|
|
)
|
|
conn.commit()
|
|
|
|
# Stats
|
|
cur.execute("SELECT COUNT(*) FROM verifications")
|
|
total_ver = cur.fetchone()[0]
|
|
cur.execute("SELECT status, COUNT(*) FROM verifications GROUP BY status ORDER BY COUNT(*) DESC")
|
|
print("\nVerification status breakdown:")
|
|
for row in cur.fetchall():
|
|
print(f" {row[0]:30s} : {row[1]:6d}")
|
|
|
|
cur.execute("""
|
|
SELECT d.name, COUNT(v.id) as n
|
|
FROM verifications v
|
|
JOIN equations e ON v.equation_id = e.id
|
|
JOIN domains d ON e.domain_id = d.id
|
|
WHERE v.status = 'Peer-reviewed (S2)'
|
|
GROUP BY d.id ORDER BY n DESC LIMIT 20
|
|
""")
|
|
print("\nTop domains by Semantic Scholar papers:")
|
|
for row in cur.fetchall():
|
|
print(f" {row[0]:30s} : {row[1]:5d}")
|
|
|
|
conn.close()
|
|
|
|
# Copy back
|
|
os.system(f"cp {TMP} {SRC}")
|
|
elapsed = time.time() - start_time
|
|
print(f"\nDone — {total_ver} total verifications ({total_papers} new from Semantic Scholar) in {elapsed:.0f}s")
|
|
print(f"Database: {SRC} ({os.path.getsize(SRC)} bytes)")
|