diff --git a/ess/TraceWin.py b/ess/TraceWin.py index baac753345d92a144a764ed50162f5e36ed21272..c3ab57d670563fa8fe00349659c3fc841988a742 100644 --- a/ess/TraceWin.py +++ b/ess/TraceWin.py @@ -1534,12 +1534,24 @@ class project: if vals.count(True) != 1: raise ValueError(f"Did not find {key} to be set correctly") self._dict[key] = o[-1][vals.index(True)] + elif o[1] == "str": + string = self._find_string(hexlist, o[0], o[2]) + self._dict[key] = bytes.fromhex(string).decode("utf-8") else: current = "".join(hexlist[o[0] : o[0] + o[2]]) if o[1] in ["d", "f", "i", "?"]: self._dict[key] = struct.unpack(o[1], b"".fromhex(current))[0] else: raise TypeError(f"Unknown type for {key}: {o[1]}") + self.check_rule(fix_if_possible=True) + + def _find_string(self, hexlist, start, maxlen): + string = "" + i = 0 + while hexlist[start + i] != "00" and i < maxlen: + string += hexlist[start + i] + i += 1 + return string def print_settings(self, settings=None): """ @@ -1605,7 +1617,29 @@ class project: else: print(errmsg) - def check_rule(self, rule=None, fail_on_err=False): + def _check_rule_endswith(self, end, variables, explanation, fail_on_err, fix_if_possible): + + for var in variables: + value = self.get(var) + if not value.endswith(end): + errmsg = f"{var} should end with {end}\nExplanation/logic: {explanation}" + if fail_on_err: + raise ValueError(errmsg) + elif fix_if_possible: + self.set(var, value + end) + else: + print(errmsg) + + def _unset_string_rules(self, variable, value): + for r in self._rules: + if variable in r[1]: + if r[0].split(":")[0] == "endswith": + end = r[0].split(":")[1] + if value.endswith(end): + value = value[: -len(end)] + return value + + def check_rule(self, rule=None, fail_on_err=False, fix_if_possible=False): """ Validate that we still obey the rule if rule is not given, check all rules @@ -1618,6 +1652,8 @@ class project: for r in rules: if r[0] == "same-sign": self._check_rule_same_sign(r[1], r[2], fail_on_err) + elif r[0].split(":")[0] == "endswith": + self._check_rule_endswith(r[0].split(":")[1], r[1], r[2], fail_on_err, fix_if_possible) else: raise TypeError(f"Unknown rule {r[0]}") @@ -1650,6 +1686,12 @@ class project: else: t = False hexlist[i] = struct.pack("?", t).hex() + elif o[1] == "str": + v = self._unset_string_rules(key, v) + h = wrap(v.encode(encoding="utf_8").hex(), 2) + h.append("00") + for i in range(len(h)): + hexlist[o[0] + i] = h[i] else: v = wrap(struct.pack(o[1], v).hex(), 2) for i in range(len(v)): diff --git a/ess/data/tw_project_file_reverse_engineered.json b/ess/data/tw_project_file_reverse_engineered.json index bc4a74a9db5133197d382defcfe9af28108c9340..55d3813551eb36136be27a62523f633a58a5bb35 100644 --- a/ess/data/tw_project_file_reverse_engineered.json +++ b/ess/data/tw_project_file_reverse_engineered.json @@ -1,10 +1,5 @@ [ { - "partran": [ - 109, - "?", - 1 - ], "toutatis": [ 135, "?", @@ -235,6 +230,21 @@ 20248, "?", 1 + ], + "main:lattice_path": [ + 5137, + "str", + 200 + ], + "main:lattice_file": [ + 6137, + "str", + 200 + ], + "main:calc_dir": [ + 7337, + "str", + 200 ] }, [ @@ -245,6 +255,13 @@ "mp:partr_sc_calcstep" ], "per beta/lambda if negative, per metre if positive" + ], + [ + "endswith:.dat", + [ + "main:lattice_file" + ], + "lattice/structure file ends with .dat" ] ] ]