Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Defines the VarKey class"""
2from .small_classes import Count, qty
3from .repr_conventions import ReprMixin
6class VarKey(ReprMixin): # pylint:disable=too-many-instance-attributes
7 """An object to correspond to each 'variable name'.
9 Arguments
10 ---------
11 name : str, VarKey, or Monomial
12 Name of this Variable, or object to derive this Variable from.
14 **descr :
15 Any additional attributes, which become the descr attribute (a dict).
17 Returns
18 -------
19 VarKey with the given name and descr.
20 """
21 unique_id = Count().next
22 subscripts = ("lineage", "idx")
24 def __init__(self, name=None, **descr):
25 # NOTE: Python arg handling guarantees 'name' won't appear in descr
26 self.descr = descr
27 self.descr["name"] = name or "\\fbox{%s}" % VarKey.unique_id()
28 unitrepr = self.unitrepr or self.units
29 if unitrepr in ["", "-", None]: # dimensionless
30 self.descr["units"] = None
31 self.descr["unitrepr"] = "-"
32 else:
33 self.descr["units"] = qty(unitrepr)
34 self.descr["unitrepr"] = unitrepr
36 self.key = self
37 fullstr = self.str_without(["modelnums", "vec"])
38 self.eqstr = fullstr + str(self.lineage) + self.unitrepr
39 self.hashvalue = hash(self.eqstr)
40 self.keys = set((self.name, fullstr))
42 if "idx" in self.descr:
43 if "veckey" not in self.descr:
44 vecdescr = self.descr.copy()
45 del vecdescr["idx"]
46 self.veckey = VarKey(**vecdescr)
47 else:
48 self.keys.add(self.veckey)
49 self.keys.add(self.str_without(["idx", "modelnums"]))
51 def __getstate__(self):
52 "Stores varkey as its metadata dictionary, removing functions"
53 state = self.descr.copy()
54 for key, value in state.items():
55 if getattr(value, "__call__", None):
56 state[key] = "unpickleable function %s" % value
57 return state
59 def __setstate__(self, state):
60 "Restores varkey from its metadata dictionary"
61 self.__init__(**state)
63 def str_without(self, excluded=()):
64 "Returns string without certain fields (such as 'lineage')."
65 name = self.name
66 if ("lineage" not in excluded and self.lineage
67 and ("unnecessary lineage" not in excluded
68 or self.necessarylineage)):
69 name = self.lineagestr("modelnums" not in excluded) + "." + name
70 if "idx" not in excluded:
71 if self.idx:
72 name += "[%s]" % ",".join(map(str, self.idx))
73 elif "vec" not in excluded and self.shape:
74 name += "[:]"
75 return name
77 __repr__ = str_without
79 # pylint: disable=multiple-statements
80 def __hash__(self): return self.hashvalue
81 def __getattr__(self, attr): return self.descr.get(attr, None)
83 @property
84 def models(self):
85 "Returns a tuple of just the names of models in self.lineage"
86 return list(zip(*self.lineage))[0]
88 def latex(self, excluded=()):
89 "Returns latex representation."
90 name = self.name
91 if "vec" not in excluded and "idx" not in excluded and self.shape:
92 name = "\\vec{%s}" % name
93 if "idx" not in excluded and self.idx:
94 name = "{%s}_{%s}" % (name, ",".join(map(str, self.idx)))
95 if ("lineage" not in excluded and self.lineage
96 and ("unnecessary lineage" not in excluded
97 or self.necessarylineage)):
98 name = "{%s}_{%s}" % (name,
99 self.lineagestr("modelnums" not in excluded))
100 return name
102 def __eq__(self, other):
103 if not hasattr(other, "descr"):
104 return False
105 return self.eqstr == other.eqstr