From ed9d3e4e88e41b3a5cb2626a55152b935208cd61 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 5 Mar 2026 23:03:39 -0600 Subject: [PATCH] scripts: plot[mpl].py: Added -I/--ignore to ignore during xlim/ylim calc This adds -I/--ignore to ignore certain datasets during xlim/ylim calculations. The motivation for this is easier zooming into interesting regions when one or two datasets have gone haywire. I.e. anytime we include yaffs2 in throughput/ram plots. There already exists a couple other options that do similar things, but they're all a bit awkward for one reason or another: 1. -U/--undefine allows omitting specific datasets completely. This is easy to use, but not quite what we want. We usually still want to render the dataset in case it behaves reasonably for a some portion of the plot, but -U/--undefine disables rendering entirely. 2. Explicit -X/--xlim and -Y/--ylim can be used to zoom wherever you want. This works, and is always available if you want more control over zoom. But either requires significant extra scripting, or prior knowledge of the dataset. More often, we don't know exactly what the data will look like, but we know one dataset will probably screw up the axes. But now with -I/--ignore, it's easy to let plot.py/plotmpl.py know we don't really care about the extremes of a dataset. --- scripts/plot.py | 19 +++++++++++++++++-- scripts/plotmpl.py | 19 +++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/scripts/plot.py b/scripts/plot.py index 5c2a17ea..78aa335d 100755 --- a/scripts/plot.py +++ b/scripts/plot.py @@ -1333,6 +1333,7 @@ def main_(ring, csv_paths, *, y=None, defines=[], undefines=[], + ignores=[], sort=None, labels=[], chars=[], @@ -1718,6 +1719,7 @@ def main_(ring, csv_paths, *, y_ = set((y or []) + s.args.get('y', [])) defines_ = defines + s.args.get('defines', []) undefines_ = undefines + s.args.get('undefines', []) + ignores_ = ignores + s.args.get('ignores', []) xlim_ = s.args.get('xlim', xlim) ylim_ = s.args.get('ylim', ylim) xlim_stddev_ = s.args.get('xlim_stddev', xlim_stddev) @@ -1773,11 +1775,17 @@ def main_(ring, csv_paths, *, # find actual xlim/ylim x__ = (lambda: it.chain([0], (x - for dataset in subdatasets.values() + for name, dataset in subdatasets.items() + if not any(all(fnmatch.fnmatchcase(k, g) + for k, g in zip(name, ignore)) + for ignore in ignores_) for x, y in dataset if y is not None))) y__ = (lambda: it.chain([0], (y - for dataset in subdatasets.values() + for name, dataset in subdatasets.items() + if not any(all(fnmatch.fnmatchcase(k, g) + for k, g in zip(name, ignore)) + for ignore in ignores_) for _, y in dataset if y is not None))) xlim_ = ( @@ -2129,6 +2137,13 @@ if __name__ == "__main__": )(*x.split('=', 1)), help="Don't include results where this field is this value. May " "include comma-separated options and globs.") + parser.add_argument( + '-I', '--ignore', + dest='ignores', + action='append', + type=lambda x: tuple(k.strip() for k in x.split(',')), + help="Ignore this group during xlim/ylim calculations, where a " + "group is the comma-separated 'by' fields.") class AppendSort(argparse.Action): def __call__(self, parser, namespace, value, option): if namespace.sort is None: diff --git a/scripts/plotmpl.py b/scripts/plotmpl.py index a6acb3fe..2cdce890 100755 --- a/scripts/plotmpl.py +++ b/scripts/plotmpl.py @@ -894,6 +894,7 @@ def main(csv_paths, output, *, y=None, defines=[], undefines=[], + ignores=[], sort=None, labels=[], colors=[], @@ -1153,6 +1154,7 @@ def main(csv_paths, output, *, y_ = set((y or []) + s.args.get('y', [])) defines_ = defines + s.args.get('defines', []) undefines_ = undefines + s.args.get('undefines', []) + ignores_ = ignores + s.args.get('ignores', []) xlim_ = s.args.get('xlim', xlim) ylim_ = s.args.get('ylim', ylim) xlim_stddev_ = s.args.get('xlim_stddev', xlim_stddev) @@ -1233,11 +1235,17 @@ def main(csv_paths, output, *, ax.yaxis.set_minor_locator(mpl.ticker.NullLocator()) # axes limits x__ = (lambda: it.chain([0], (x - for dataset in subdatasets.values() + for name, dataset in subdatasets.items() + if not any(all(fnmatch.fnmatchcase(k, g) + for k, g in zip(name, ignore)) + for ignore in ignores_) for x, y in dataset if y is not None))) y__ = (lambda: it.chain([0], (y - for dataset in subdatasets.values() + for name, dataset in subdatasets.items() + if not any(all(fnmatch.fnmatchcase(k, g) + for k, g in zip(name, ignore)) + for ignore in ignores_) for _, y in dataset if y is not None))) ax.set_xlim( @@ -1568,6 +1576,13 @@ if __name__ == "__main__": )(*x.split('=', 1)), help="Don't include results where this field is this value. May " "include comma-separated options and globs.") + parser.add_argument( + '-I', '--ignore', + dest='ignores', + action='append', + type=lambda x: tuple(k.strip() for k in x.split(',')), + help="Ignore this group during xlim/ylim calculations, where a " + "group is the comma-separated 'by' fields.") class AppendSort(argparse.Action): def __call__(self, parser, namespace, value, option): if namespace.sort is None: