Skip to content

Commit

Permalink
[parameter-sweep] parameter-sweep option does not have an argument an…
Browse files Browse the repository at this point in the history
…ymore
  • Loading branch information
nikohansen committed Dec 30, 2024
1 parent e957355 commit 2e8df12
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 40 deletions.
73 changes: 45 additions & 28 deletions src/cocopp/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,32 +72,41 @@ def _index_after_parameter(name):
def map_indices_to_line_styles(names):
"""helper function for `config_line_styles`.
Check for equal names after a float number (which represents a
parameter value) and map the respective index in names to the index of
first appearence. This is not (directly) used for determining the color.
Map each index of names to the index of the first appearence of the
name, where equality of names is determined starting from after a float
number (which represents a parameter value) using
`_index_after_parameter`.
"""
# names without preceeding float number
nn = [name[_index_after_parameter(name):] for name in names]
res = {k: nn.index(v) for k, v in enumerate(nn)} # index gives the first match
return res

def sorted_line_styles(styles, names, indices):
"""use names up until and including a float as sorting key to rearrange styles"""
"""use the sorting of names up until and including a float to rearrange `styles`.
This assumes that the ``names[indices]`` correspond to
``styles[indices]`` and that ``styles[indices]`` (colormap) are in
increasing order on input. On output, ``sorted_styles`` are in
increasing order w.r.t. the sorting of ``names[indices]``.
"""
sorted_indices = sorted(indices,
key=lambda i: names[i][:_index_after_parameter(names[i])])
# print(names, indices, sorted_indices) # this looks correct
sorted_styles = styles[:]
# the line style of sorted_indices[0] should be the style of indices[0]
# the line style of sorted_indices[k] becomes the style of indices[k]
for i, j in zip(sorted_indices, indices):
sorted_styles[i] = styles[j]
return sorted_styles

def config_line_styles():
'''configure `genericsettings.line_styles` for a parameter sweet.
'''configure `genericsettings.line_styles` for a parameter sweet
The colormap and range can be changed via the ``--parameter_sweep=``
value, the default value is ``'plasma.0.9'``, ``'viridis'`` and
``'gnuplot2.0.85'`` and a comma separated joined sequence thereof are
viable alternatives.
if ``parameter_sweep`` is given on input. The colormap and range can be
changed via the ``--parameter_sweep_colormaps=`` value. The default
value is ``'plasma.0.9'``, viable alternatives are ``'viridis'`` or
``'gnuplot2.0.85'`` or a comma separated joined sequence of any of
these, same color sweeps are 'Greens_r..7', 'Greys_r..7', 'Reds_r..7'.
The sorting of the input arguments up to and including a float value in
the name determines the positioning in the color map.
Expand All @@ -110,49 +119,57 @@ def config_line_styles():
TODO: we may want to keep the original symbol colors?
'''
s = settings.parameter_sweep
if not s or s in (0, '0', None, 'None', False, 'False', 'false', 'off', 'Off', 'OFF'):
if not settings.parameter_sweep:
return
if s in (1, '1', True, 'True', 'true', 't', 'on', 'On', 'ON', 'unsorted'):
if not settings.parameter_sweep_colormaps:
cvals = settings.sequential_colormaps
else:
# check whether s gives a color map
s = settings.parameter_sweep_colormaps
if s.startswith(tuple(mpl.colormaps())):
cvals = s.split(',')
else:
warnings.warn("{0} doesn't conform with any ``matplotlib.colormaps()={1}``"
"Hence we use the default {2}"
.format(settings.parameter_sweep, plt.colormaps(),
settings.sequential_colormaps))
.format(s, plt.colormaps(), settings.sequential_colormaps))
cvals = settings.sequential_colormaps
# map algorithm argument index to first algorithm appearence index
mapping = settings.line_style_mapping or map_indices_to_line_styles(
settings._current_args)
counts = collections.Counter(mapping.values()) # count number of appearences
if settings.verbose >= 0:
print("Found {0} distinct algorithm(s) in {1} arguments"
.format(len(counts), len(mapping)))
try:
color_maps = [_str_to_colormap(cvals[i % len(cvals)], counts[i])
for i in sorted(counts)]
except ValueError as e:
warnings.warn("exception {0} occured while generating color maps".format(e))
settings._default_line_styles = [d.copy() for d in settings.line_styles] # a backup
print("config_line_styles: found {0} distinct algorithm(s) in indices {1} of {2} arguments"
.format(len(counts), sorted(counts), len(mapping)))
# print(mapping, counts)
if settings.line_styles != settings._default_line_styles:
print('config_line_styles: line styles are (already) different from default')
# return
color_maps = {}
for j, i in enumerate(sorted(counts)):
try:
color_maps[i] = _str_to_colormap(cvals[j % len(cvals)], counts[i])
except ValueError as e:
warnings.warn("exception {0} occured while generating color maps".format(e))
_previous_line_styles = [d.copy() for d in settings.line_styles]
# modify color in settings.line_styles and set same line and marker style
for i, j in mapping.items():
# which should be idempotent when applied to line_styles repeatedly
for i, j in sorted(mapping.items()): # sorted w.r.t. input argument order
# _current_args names and indices i must align?
s = settings.line_styles[i]
# s['markeredgecolor'] = s['color'] # doesn't work
s['color'] = next(color_maps[j])
s['color'] = next(color_maps[j]) # CAVEAT: here the order of i matters!?
for key in s.keys():
if key != 'color':
s[key] = settings.line_styles[j][key]
if settings.parameter_sweep.startswith('unsorted'):
if not settings.parameter_sweep_sort:
return
# sort styles for each algorithm
for alg in mapping.values():
indices = sorted([k for k in mapping.keys() if mapping[k] == alg])
for alg in counts:
indices = [k for k in mapping if mapping[k] == alg]
settings.line_styles = sorted_line_styles(
settings.line_styles, settings._current_args, indices)
if settings.verbose >= 0 and settings.line_styles == _previous_line_styles:
print("config_line_styles: didn't change lines styles")

def config(suite_name=None):
"""called from a high level, e.g. rungeneric, to configure the lower level
Expand Down
21 changes: 16 additions & 5 deletions src/cocopp/genericsettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,24 @@
use_recommendations = [False]
'''use only recommendations data (.mdat files) for the respective algorithm
where the last element is recycled for the remaining algorithms'''

parameter_sweep = False
'''may be `True` or `'on'` or color map names to sweep through (versatile interface).
See also `cocopp.config.config_line_styles`.'''
'''configure line styles for a parameter sweep, see also
`cocopp.config.config_line_styles`'''
parameter_sweep_colormaps = None
'''colormap(s) for parameter sweep set from the respective input long_option.
`colormaps` can, for example, be 'plasma.0.9,viridis' indicating the map
names separated by commata and optionally the range for each map.
'''
parameter_sweep_sort = True
'''assign color in sweep by leading float of algorithm name'''
sequential_colormaps = ['plasma..9'] # 'viridis', 'gnuplot2.0.85', 'Greens_r..7', 'Greys_r..7', 'Reds_r..7']
'''default color maps for a parameter sweep'''

line_style_mapping = {}
'''map the input argument position to a line style position, by default the identity.
This could useful to get the same style for several algorithm variants.'''
This could be useful to get the same style for several algorithm variants. Only effective with when ``bool(parameter_sweep) is True``.'''

force_assertions = False # another debug flag for time-consuming assertions
in_a_hurry = 1000 # [0, 1000] lower resolution, no eps, saves 30% time
Expand Down Expand Up @@ -200,10 +212,9 @@
{'color': '#8a52bd', 'linestyle': '-', 'marker': 'o', 'markersize': 7, 'zorder': 2},
{'color': '#8c493c', 'linestyle': '-', 'marker': 'd', 'markersize': 7, 'zorder': 2}]

_default_line_styles = [dict(d) for d in line_styles] # we may modify linestyles and can get back the original
# see old_line_styles for older line styles

sequential_colormaps = ['plasma..9'] # , 'Greens_r..7', 'Greys_r..7', 'Reds_r..7']

figsize = [6.4, 4.8] # == rcParamsDefault['figure.figsize'], used in compall.pprldmany

minmax_algorithm_fontsize = [9, 14] # used in pprldmany, depending on the number of algorithms
Expand Down
21 changes: 14 additions & 7 deletions src/cocopp/rungeneric.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
short_options = "hvo:"
long_options = ["help", "output-dir=", "noisy", "noise-free",
"tab-only", "fig-only",
"parameter-sweep=",
"parameter-sweep",
"parameter-sweep-colormaps=",
"rld-only", "no-rld-single-fcts",
"verbose", "settings=", "conv",
"expensive", "runlength-based",
Expand Down Expand Up @@ -187,12 +188,16 @@ def main(argv=None):
all folder/file arguments are prepended with the given value
which must be a valid path.
--parameter-sweep=colormaps
--parameter-sweep
'on' is a valid value too. Parse the algorithm name for a float
first and use the value to determine the color from a colormap.
`colormaps` can be 'plasma.0.9,viridis' indicating the map names
separated by commata and optionally the range for each map.
if given, parse the algorithm name for a float and use the
value to determine the color order in a colormap.
--parameter-sweep-colormaps=colormaps
`colormaps` can, for example, be ``plasma.0.9,viridis``
indicating (here two) map names separated by commata and
optionally the range for each map.
--in-a-hurry
Expand Down Expand Up @@ -347,7 +352,9 @@ def main(argv=None):
elif o == "--no-interactive":
genericsettings.interactive_mode = False
elif o == "--parameter-sweep":
genericsettings.parameter_sweep = a if a != '' else True
genericsettings.parameter_sweep = True
elif o == "--parameter-sweep-colormaps":
genericsettings.parameter_sweep_colormaps = a
else:
is_assigned = False
if o in longoptlist or o in shortoptlist:
Expand Down

0 comments on commit 2e8df12

Please sign in to comment.