Spaces:
Sleeping
Sleeping
File size: 5,310 Bytes
58e6885 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | """
Dry-run: for every template, count how many JSON files in one or more
data directories are compatible (per the same check used by
infographics_generator).
Usage:
# default (read pools from config.data_resource_dirs)
python scripts/match_templates_to_data.py --out scripts/_template_match.csv
# explicit pools
python scripts/match_templates_to_data.py \
--data /data/liduan/resources/claude_data_v2 /data/liduan/resources/claude_new \
--out scripts/_template_match.csv
"""
import argparse
import csv
import json
import os
import sys
from pathlib import Path
from collections import defaultdict
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
from config import data_resource_dirs as CFG_DATA_DIRS
from modules.chart_engine.template.template_registry import scan_templates
from modules.infographics_generator.template_utils import (
analyze_templates,
check_template_compatibility,
)
def parse_args():
p = argparse.ArgumentParser()
p.add_argument("--data", nargs="+", default=None,
help="One or more directories of input JSONs "
"(default: config.data_resource_dirs)")
p.add_argument("--out", default="scripts/_template_match.csv", help="CSV report path")
p.add_argument("--engines", nargs="+",
default=["d3-js", "echarts-js", "echarts_py"],
help="Which engines to consider")
p.add_argument("--sample", type=int, default=0,
help="If >0, randomly subsample this many files (per --seed)")
p.add_argument("--seed", type=int, default=42)
return p.parse_args()
def main():
args = parse_args()
data_dirs = [Path(p) for p in (args.data or CFG_DATA_DIRS)]
for d in data_dirs:
if not d.is_dir():
raise SystemExit(f"--data path is not a directory: {d}")
json_files = []
for d in data_dirs:
files = sorted(d.glob("*.json"))
json_files.extend(files)
print(f" {d}: {len(files)} json files")
print(f"Total: {len(json_files)} json files across {len(data_dirs)} dir(s)")
if args.sample and args.sample < len(json_files):
import random
random.Random(args.seed).shuffle(json_files)
json_files = json_files[:args.sample]
print(f"Sub-sampled to {len(json_files)} files (seed={args.seed})")
datas = []
for f in json_files:
with open(f, "r") as fh:
d = json.load(fh)
d["name"] = str(f)
# Disambiguate filenames when the same basename exists in both pools:
# use "<dir-name>/<filename>" so picker / driver can map back uniquely.
rel = f"{f.parent.name}/{f.name}"
datas.append((rel, d))
templates = scan_templates()
_, template_requirements = analyze_templates(templates)
# Enumerate ALL templates (engine/chart_type/chart_name) keys
all_template_keys = []
for engine, t_dict in templates.items():
if engine not in args.engines:
continue
for chart_type, c_dict in t_dict.items():
for chart_name in c_dict:
if "base" in chart_name:
continue
all_template_keys.append((engine, chart_type, chart_name))
print(f"Total templates (engines={args.engines}): {len(all_template_keys)}")
# For each data, compute compatible templates ONCE (it returns the full list)
# then we tally per template.
counter = defaultdict(int)
matched_files = defaultdict(list)
for name, data in datas:
compat = check_template_compatibility(data, templates, None)
for tpl_key, _ordered_fields in compat:
counter[tpl_key] += 1
matched_files[tpl_key].append(name)
os.makedirs(os.path.dirname(args.out) or ".", exist_ok=True)
with open(args.out, "w", newline="") as fh:
w = csv.writer(fh)
w.writerow(["engine", "chart_type", "chart_name", "num_compatible_data"])
for engine, chart_type, chart_name in all_template_keys:
tpl_key = f"{engine}/{chart_type}/{chart_name}"
w.writerow([engine, chart_type, chart_name, counter.get(tpl_key, 0)])
print(f"Wrote {args.out}")
# Distribution histogram
buckets = [0, 1, 5, 10, 20, 30, 50, 100, 10**9]
bucket_labels = ["0", "1-4", "5-9", "10-19", "20-29", "30-49", "50-99", "100+"]
bucket_counts = [0] * len(bucket_labels)
for engine, chart_type, chart_name in all_template_keys:
n = counter.get(f"{engine}/{chart_type}/{chart_name}", 0)
for i in range(len(bucket_labels)):
if buckets[i] <= n < buckets[i + 1]:
bucket_counts[i] += 1
break
print()
print("Templates by number of compatible data files in",
", ".join(str(d) for d in data_dirs))
for lab, c in zip(bucket_labels, bucket_counts):
print(f" {lab:>8s}: {c}")
n_geq_20 = sum(1 for k in all_template_keys
if counter.get("/".join(k), 0) >= 20)
n_geq_5 = sum(1 for k in all_template_keys
if counter.get("/".join(k), 0) >= 5)
print()
print(f"Templates with >= 20 compatible data: {n_geq_20}")
print(f"Templates with >= 5 compatible data: {n_geq_5}")
if __name__ == "__main__":
main()
|