Coverage for gpkit/interactive/references.py: 95%
61 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-07 22:13 -0500
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-07 22:13 -0500
1"Code to make variable references plots"
3import os
4import shutil
5import webbrowser
6from collections import defaultdict
9# pylint:disable=too-many-locals,too-many-branches,consider-using-f-string
10def referencesplot(model, *, openimmediately=True):
11 """Makes a references plot.
13 1) Creates the JSON file for a d3 references plot
14 2) Places it and the corresponding HTML file in the working directory
15 3) (optionally) opens that HTML file up immediately in a web browser
17 """
18 imports = {}
19 totalv_ss = defaultdict(dict)
20 for constraint in model.flat():
21 for varkey in constraint.vks:
22 vlineage = varkey.lineagestr()
23 clineage = constraint.lineagestr()
24 if not vlineage:
25 vlineage = f"{varkey} [{varkey.unitstr()}]"
26 for lin in (clineage, vlineage):
27 if lin not in imports:
28 imports[lin] = set()
29 if vlineage != clineage:
30 imports[clineage].add(vlineage)
31 if constraint.v_ss:
32 totalv_ss[clineage] += constraint.v_ss
34 def clean_lineage(lineage, clusterdepth=2):
35 prelineage = ".".join(lineage.split(".")[:clusterdepth])
36 last = "0".join(lineage.split(".")[clusterdepth:])
37 return "model."+prelineage + "." + last
39 lines = ['jsondata = [']
40 for lineage, limports in imports.items():
41 name, short = clean_lineage(lineage), lineage.split(".")[-1]
42 limports = map(clean_lineage, limports)
43 lines.append(
44 ' {"name":"%s","fullname":"%s","shortname":"%s","imports":%s},'
45 % (name, lineage, short, repr(list(limports)).replace("'", '"')))
46 lines[-1] = lines[-1][:-1]
47 lines.append("]")
49 if totalv_ss:
50 def get_total_senss(clineage, vlineage, normalize=False):
51 v_ss = totalv_ss[clineage]
52 num = sum(abs(ss) for vk, ss in v_ss.items()
53 if vk.lineagestr() == vlineage)
54 if not normalize:
55 return num
56 return num/sum(abs(ss) for ss in v_ss.values())
57 lines.append("globalsenss = {")
58 for clineage, limports in imports.items():
59 if not limports:
60 continue
61 limports = {vl: get_total_senss(clineage, vl) for vl in limports}
62 lines.append(' "%s": %s,' %
63 (clineage, repr(limports).replace("'", '"')))
64 lines[-1] = lines[-1][:-1]
65 lines.append("}")
66 lines.append("normalizedsenss = {")
67 for clineage, limports in imports.items():
68 if not limports:
69 continue
70 limports = {vl: get_total_senss(clineage, vl, normalize=True)
71 for vl in limports}
72 lines.append(' "%s": %s,' %
73 (clineage, repr(limports).replace("'", '"')))
74 lines[-1] = lines[-1][:-1]
75 lines.append("}")
77 with open("referencesplot.json", "w", encoding="UTF-8") as f:
78 f.write("\n".join(lines))
80 htmlfile = "referencesplot.html"
81 if not os.path.isfile(htmlfile):
82 shutil.copy(os.path.join(os.path.dirname(__file__), htmlfile), htmlfile)
84 if openimmediately:
85 webbrowser.open("file://" + os.path.join(os.getcwd(), htmlfile),
86 autoraise=True)