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.
This commit is contained in:
Christopher Haster
2026-03-05 23:03:39 -06:00
parent 233525db0e
commit ed9d3e4e88
2 changed files with 34 additions and 4 deletions
+17 -2
View File
@@ -1333,6 +1333,7 @@ def main_(ring, csv_paths, *,
y=None, y=None,
defines=[], defines=[],
undefines=[], undefines=[],
ignores=[],
sort=None, sort=None,
labels=[], labels=[],
chars=[], chars=[],
@@ -1718,6 +1719,7 @@ def main_(ring, csv_paths, *,
y_ = set((y or []) + s.args.get('y', [])) y_ = set((y or []) + s.args.get('y', []))
defines_ = defines + s.args.get('defines', []) defines_ = defines + s.args.get('defines', [])
undefines_ = undefines + s.args.get('undefines', []) undefines_ = undefines + s.args.get('undefines', [])
ignores_ = ignores + s.args.get('ignores', [])
xlim_ = s.args.get('xlim', xlim) xlim_ = s.args.get('xlim', xlim)
ylim_ = s.args.get('ylim', ylim) ylim_ = s.args.get('ylim', ylim)
xlim_stddev_ = s.args.get('xlim_stddev', xlim_stddev) xlim_stddev_ = s.args.get('xlim_stddev', xlim_stddev)
@@ -1773,11 +1775,17 @@ def main_(ring, csv_paths, *,
# find actual xlim/ylim # find actual xlim/ylim
x__ = (lambda: it.chain([0], (x 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 for x, y in dataset
if y is not None))) if y is not None)))
y__ = (lambda: it.chain([0], (y 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 for _, y in dataset
if y is not None))) if y is not None)))
xlim_ = ( xlim_ = (
@@ -2129,6 +2137,13 @@ if __name__ == "__main__":
)(*x.split('=', 1)), )(*x.split('=', 1)),
help="Don't include results where this field is this value. May " help="Don't include results where this field is this value. May "
"include comma-separated options and globs.") "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): class AppendSort(argparse.Action):
def __call__(self, parser, namespace, value, option): def __call__(self, parser, namespace, value, option):
if namespace.sort is None: if namespace.sort is None:
+17 -2
View File
@@ -894,6 +894,7 @@ def main(csv_paths, output, *,
y=None, y=None,
defines=[], defines=[],
undefines=[], undefines=[],
ignores=[],
sort=None, sort=None,
labels=[], labels=[],
colors=[], colors=[],
@@ -1153,6 +1154,7 @@ def main(csv_paths, output, *,
y_ = set((y or []) + s.args.get('y', [])) y_ = set((y or []) + s.args.get('y', []))
defines_ = defines + s.args.get('defines', []) defines_ = defines + s.args.get('defines', [])
undefines_ = undefines + s.args.get('undefines', []) undefines_ = undefines + s.args.get('undefines', [])
ignores_ = ignores + s.args.get('ignores', [])
xlim_ = s.args.get('xlim', xlim) xlim_ = s.args.get('xlim', xlim)
ylim_ = s.args.get('ylim', ylim) ylim_ = s.args.get('ylim', ylim)
xlim_stddev_ = s.args.get('xlim_stddev', xlim_stddev) 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()) ax.yaxis.set_minor_locator(mpl.ticker.NullLocator())
# axes limits # axes limits
x__ = (lambda: it.chain([0], (x 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 for x, y in dataset
if y is not None))) if y is not None)))
y__ = (lambda: it.chain([0], (y 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 for _, y in dataset
if y is not None))) if y is not None)))
ax.set_xlim( ax.set_xlim(
@@ -1568,6 +1576,13 @@ if __name__ == "__main__":
)(*x.split('=', 1)), )(*x.split('=', 1)),
help="Don't include results where this field is this value. May " help="Don't include results where this field is this value. May "
"include comma-separated options and globs.") "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): class AppendSort(argparse.Action):
def __call__(self, parser, namespace, value, option): def __call__(self, parser, namespace, value, option):
if namespace.sort is None: if namespace.sort is None: