pymoo 0.6.1.6__cp312-cp312-macosx_10_13_universal2.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pymoo/__init__.py +3 -0
- pymoo/algorithms/__init__.py +0 -0
- pymoo/algorithms/base/__init__.py +0 -0
- pymoo/algorithms/base/bracket.py +38 -0
- pymoo/algorithms/base/genetic.py +110 -0
- pymoo/algorithms/base/line.py +62 -0
- pymoo/algorithms/base/local.py +39 -0
- pymoo/algorithms/base/meta.py +79 -0
- pymoo/algorithms/hyperparameters.py +91 -0
- pymoo/algorithms/moo/__init__.py +0 -0
- pymoo/algorithms/moo/age.py +310 -0
- pymoo/algorithms/moo/age2.py +194 -0
- pymoo/algorithms/moo/cmopso.py +239 -0
- pymoo/algorithms/moo/ctaea.py +305 -0
- pymoo/algorithms/moo/dnsga2.py +80 -0
- pymoo/algorithms/moo/kgb.py +450 -0
- pymoo/algorithms/moo/moead.py +183 -0
- pymoo/algorithms/moo/mopso_cd.py +309 -0
- pymoo/algorithms/moo/nsga2.py +113 -0
- pymoo/algorithms/moo/nsga3.py +361 -0
- pymoo/algorithms/moo/pinsga2.py +370 -0
- pymoo/algorithms/moo/rnsga2.py +188 -0
- pymoo/algorithms/moo/rnsga3.py +246 -0
- pymoo/algorithms/moo/rvea.py +214 -0
- pymoo/algorithms/moo/sms.py +196 -0
- pymoo/algorithms/moo/spea2.py +191 -0
- pymoo/algorithms/moo/unsga3.py +49 -0
- pymoo/algorithms/soo/__init__.py +0 -0
- pymoo/algorithms/soo/convex/__init__.py +0 -0
- pymoo/algorithms/soo/nonconvex/__init__.py +0 -0
- pymoo/algorithms/soo/nonconvex/brkga.py +162 -0
- pymoo/algorithms/soo/nonconvex/cmaes.py +556 -0
- pymoo/algorithms/soo/nonconvex/de.py +283 -0
- pymoo/algorithms/soo/nonconvex/direct.py +148 -0
- pymoo/algorithms/soo/nonconvex/es.py +213 -0
- pymoo/algorithms/soo/nonconvex/g3pcx.py +94 -0
- pymoo/algorithms/soo/nonconvex/ga.py +95 -0
- pymoo/algorithms/soo/nonconvex/ga_niching.py +223 -0
- pymoo/algorithms/soo/nonconvex/isres.py +74 -0
- pymoo/algorithms/soo/nonconvex/nelder.py +251 -0
- pymoo/algorithms/soo/nonconvex/nrbo.py +191 -0
- pymoo/algorithms/soo/nonconvex/optuna.py +80 -0
- pymoo/algorithms/soo/nonconvex/pattern.py +185 -0
- pymoo/algorithms/soo/nonconvex/pso.py +337 -0
- pymoo/algorithms/soo/nonconvex/pso_ep.py +307 -0
- pymoo/algorithms/soo/nonconvex/random_search.py +25 -0
- pymoo/algorithms/soo/nonconvex/sres.py +56 -0
- pymoo/algorithms/soo/univariate/__init__.py +0 -0
- pymoo/algorithms/soo/univariate/exp.py +46 -0
- pymoo/algorithms/soo/univariate/golden.py +65 -0
- pymoo/algorithms/soo/univariate/quadr_interp.py +81 -0
- pymoo/algorithms/soo/univariate/wolfe.py +163 -0
- pymoo/config.py +33 -0
- pymoo/constraints/__init__.py +3 -0
- pymoo/constraints/adaptive.py +66 -0
- pymoo/constraints/as_obj.py +56 -0
- pymoo/constraints/as_penalty.py +41 -0
- pymoo/constraints/eps.py +34 -0
- pymoo/constraints/from_bounds.py +36 -0
- pymoo/core/__init__.py +0 -0
- pymoo/core/algorithm.py +408 -0
- pymoo/core/callback.py +38 -0
- pymoo/core/crossover.py +79 -0
- pymoo/core/decision_making.py +102 -0
- pymoo/core/decomposition.py +76 -0
- pymoo/core/duplicate.py +163 -0
- pymoo/core/evaluator.py +116 -0
- pymoo/core/indicator.py +34 -0
- pymoo/core/individual.py +784 -0
- pymoo/core/infill.py +65 -0
- pymoo/core/initialization.py +44 -0
- pymoo/core/mating.py +39 -0
- pymoo/core/meta.py +21 -0
- pymoo/core/mixed.py +164 -0
- pymoo/core/mutation.py +44 -0
- pymoo/core/operator.py +46 -0
- pymoo/core/parameters.py +134 -0
- pymoo/core/plot.py +208 -0
- pymoo/core/population.py +180 -0
- pymoo/core/problem.py +373 -0
- pymoo/core/recorder.py +99 -0
- pymoo/core/repair.py +23 -0
- pymoo/core/replacement.py +96 -0
- pymoo/core/result.py +52 -0
- pymoo/core/sampling.py +45 -0
- pymoo/core/selection.py +61 -0
- pymoo/core/solution.py +10 -0
- pymoo/core/survival.py +107 -0
- pymoo/core/termination.py +70 -0
- pymoo/core/variable.py +415 -0
- pymoo/decomposition/__init__.py +0 -0
- pymoo/decomposition/aasf.py +24 -0
- pymoo/decomposition/asf.py +10 -0
- pymoo/decomposition/pbi.py +13 -0
- pymoo/decomposition/perp_dist.py +13 -0
- pymoo/decomposition/tchebicheff.py +11 -0
- pymoo/decomposition/util.py +13 -0
- pymoo/decomposition/weighted_sum.py +8 -0
- pymoo/docs.py +187 -0
- pymoo/experimental/__init__.py +0 -0
- pymoo/experimental/algorithms/__init__.py +0 -0
- pymoo/experimental/algorithms/gde3.py +57 -0
- pymoo/functions/__init__.py +135 -0
- pymoo/functions/compiled/__init__.py +0 -0
- pymoo/functions/compiled/calc_perpendicular_distance.cpp +27464 -0
- pymoo/functions/compiled/calc_perpendicular_distance.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/decomposition.cpp +28853 -0
- pymoo/functions/compiled/decomposition.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/info.cpp +7058 -0
- pymoo/functions/compiled/info.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/mnn.cpp +30095 -0
- pymoo/functions/compiled/mnn.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/non_dominated_sorting.cpp +35692 -0
- pymoo/functions/compiled/non_dominated_sorting.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/pruning_cd.cpp +29248 -0
- pymoo/functions/compiled/pruning_cd.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/stochastic_ranking.cpp +28042 -0
- pymoo/functions/compiled/stochastic_ranking.cpython-312-darwin.so +0 -0
- pymoo/functions/standard/__init__.py +1 -0
- pymoo/functions/standard/calc_perpendicular_distance.py +20 -0
- pymoo/functions/standard/decomposition.py +18 -0
- pymoo/functions/standard/hv.py +5 -0
- pymoo/functions/standard/mnn.py +78 -0
- pymoo/functions/standard/non_dominated_sorting.py +474 -0
- pymoo/functions/standard/pruning_cd.py +93 -0
- pymoo/functions/standard/stochastic_ranking.py +42 -0
- pymoo/gradient/__init__.py +24 -0
- pymoo/gradient/automatic.py +85 -0
- pymoo/gradient/grad_autograd.py +105 -0
- pymoo/gradient/grad_complex.py +35 -0
- pymoo/gradient/grad_jax.py +51 -0
- pymoo/gradient/numpy.py +22 -0
- pymoo/gradient/toolbox/__init__.py +19 -0
- pymoo/indicators/__init__.py +0 -0
- pymoo/indicators/distance_indicator.py +55 -0
- pymoo/indicators/gd.py +7 -0
- pymoo/indicators/gd_plus.py +7 -0
- pymoo/indicators/hv/__init__.py +59 -0
- pymoo/indicators/hv/approximate.py +105 -0
- pymoo/indicators/hv/exact.py +68 -0
- pymoo/indicators/hv/exact_2d.py +102 -0
- pymoo/indicators/igd.py +7 -0
- pymoo/indicators/igd_plus.py +7 -0
- pymoo/indicators/kktpm.py +151 -0
- pymoo/indicators/migd.py +55 -0
- pymoo/indicators/rmetric.py +203 -0
- pymoo/indicators/spacing.py +52 -0
- pymoo/mcdm/__init__.py +0 -0
- pymoo/mcdm/compromise_programming.py +19 -0
- pymoo/mcdm/high_tradeoff.py +40 -0
- pymoo/mcdm/pseudo_weights.py +32 -0
- pymoo/operators/__init__.py +0 -0
- pymoo/operators/control.py +190 -0
- pymoo/operators/crossover/__init__.py +0 -0
- pymoo/operators/crossover/binx.py +47 -0
- pymoo/operators/crossover/dex.py +125 -0
- pymoo/operators/crossover/erx.py +164 -0
- pymoo/operators/crossover/expx.py +53 -0
- pymoo/operators/crossover/hux.py +37 -0
- pymoo/operators/crossover/nox.py +25 -0
- pymoo/operators/crossover/ox.py +88 -0
- pymoo/operators/crossover/pcx.py +84 -0
- pymoo/operators/crossover/pntx.py +49 -0
- pymoo/operators/crossover/sbx.py +137 -0
- pymoo/operators/crossover/spx.py +5 -0
- pymoo/operators/crossover/ux.py +20 -0
- pymoo/operators/mutation/__init__.py +0 -0
- pymoo/operators/mutation/bitflip.py +17 -0
- pymoo/operators/mutation/gauss.py +60 -0
- pymoo/operators/mutation/inversion.py +42 -0
- pymoo/operators/mutation/nom.py +7 -0
- pymoo/operators/mutation/pm.py +96 -0
- pymoo/operators/mutation/rm.py +23 -0
- pymoo/operators/repair/__init__.py +0 -0
- pymoo/operators/repair/bounce_back.py +32 -0
- pymoo/operators/repair/bounds_repair.py +97 -0
- pymoo/operators/repair/inverse_penalty.py +91 -0
- pymoo/operators/repair/rounding.py +18 -0
- pymoo/operators/repair/to_bound.py +31 -0
- pymoo/operators/repair/vtype.py +11 -0
- pymoo/operators/sampling/__init__.py +0 -0
- pymoo/operators/sampling/lhs.py +76 -0
- pymoo/operators/sampling/rnd.py +52 -0
- pymoo/operators/selection/__init__.py +0 -0
- pymoo/operators/selection/rnd.py +75 -0
- pymoo/operators/selection/tournament.py +78 -0
- pymoo/operators/survival/__init__.py +0 -0
- pymoo/operators/survival/rank_and_crowding/__init__.py +1 -0
- pymoo/operators/survival/rank_and_crowding/classes.py +212 -0
- pymoo/operators/survival/rank_and_crowding/metrics.py +208 -0
- pymoo/optimize.py +72 -0
- pymoo/parallelization/__init__.py +15 -0
- pymoo/parallelization/dask.py +25 -0
- pymoo/parallelization/joblib.py +28 -0
- pymoo/parallelization/ray.py +31 -0
- pymoo/parallelization/starmap.py +24 -0
- pymoo/problems/__init__.py +157 -0
- pymoo/problems/dyn.py +47 -0
- pymoo/problems/dynamic/__init__.py +0 -0
- pymoo/problems/dynamic/cec2015.py +108 -0
- pymoo/problems/dynamic/df.py +451 -0
- pymoo/problems/dynamic/misc.py +167 -0
- pymoo/problems/functional.py +48 -0
- pymoo/problems/many/__init__.py +5 -0
- pymoo/problems/many/cdtlz.py +159 -0
- pymoo/problems/many/dcdtlz.py +88 -0
- pymoo/problems/many/dtlz.py +264 -0
- pymoo/problems/many/wfg.py +553 -0
- pymoo/problems/multi/__init__.py +14 -0
- pymoo/problems/multi/bnh.py +34 -0
- pymoo/problems/multi/carside.py +48 -0
- pymoo/problems/multi/clutch.py +104 -0
- pymoo/problems/multi/csi.py +55 -0
- pymoo/problems/multi/ctp.py +198 -0
- pymoo/problems/multi/dascmop.py +213 -0
- pymoo/problems/multi/kursawe.py +25 -0
- pymoo/problems/multi/modact.py +68 -0
- pymoo/problems/multi/mw.py +400 -0
- pymoo/problems/multi/omnitest.py +48 -0
- pymoo/problems/multi/osy.py +32 -0
- pymoo/problems/multi/srn.py +28 -0
- pymoo/problems/multi/sympart.py +94 -0
- pymoo/problems/multi/tnk.py +24 -0
- pymoo/problems/multi/truss2d.py +83 -0
- pymoo/problems/multi/welded_beam.py +41 -0
- pymoo/problems/multi/wrm.py +36 -0
- pymoo/problems/multi/zdt.py +151 -0
- pymoo/problems/multi_to_single.py +22 -0
- pymoo/problems/single/__init__.py +12 -0
- pymoo/problems/single/ackley.py +24 -0
- pymoo/problems/single/cantilevered_beam.py +34 -0
- pymoo/problems/single/flowshop_scheduling.py +113 -0
- pymoo/problems/single/g.py +874 -0
- pymoo/problems/single/griewank.py +18 -0
- pymoo/problems/single/himmelblau.py +15 -0
- pymoo/problems/single/knapsack.py +49 -0
- pymoo/problems/single/mopta08.py +26 -0
- pymoo/problems/single/multimodal.py +20 -0
- pymoo/problems/single/pressure_vessel.py +30 -0
- pymoo/problems/single/rastrigin.py +20 -0
- pymoo/problems/single/rosenbrock.py +22 -0
- pymoo/problems/single/schwefel.py +18 -0
- pymoo/problems/single/simple.py +13 -0
- pymoo/problems/single/sphere.py +19 -0
- pymoo/problems/single/traveling_salesman.py +79 -0
- pymoo/problems/single/zakharov.py +19 -0
- pymoo/problems/static.py +14 -0
- pymoo/problems/util.py +42 -0
- pymoo/problems/zero_to_one.py +27 -0
- pymoo/termination/__init__.py +23 -0
- pymoo/termination/collection.py +12 -0
- pymoo/termination/cv.py +48 -0
- pymoo/termination/default.py +45 -0
- pymoo/termination/delta.py +64 -0
- pymoo/termination/fmin.py +16 -0
- pymoo/termination/ftol.py +144 -0
- pymoo/termination/indicator.py +49 -0
- pymoo/termination/max_eval.py +14 -0
- pymoo/termination/max_gen.py +15 -0
- pymoo/termination/max_time.py +20 -0
- pymoo/termination/robust.py +34 -0
- pymoo/termination/xtol.py +33 -0
- pymoo/util/__init__.py +33 -0
- pymoo/util/archive.py +152 -0
- pymoo/util/cache.py +29 -0
- pymoo/util/clearing.py +82 -0
- pymoo/util/display/__init__.py +0 -0
- pymoo/util/display/column.py +52 -0
- pymoo/util/display/display.py +34 -0
- pymoo/util/display/multi.py +100 -0
- pymoo/util/display/output.py +53 -0
- pymoo/util/display/progress.py +54 -0
- pymoo/util/display/single.py +67 -0
- pymoo/util/dominator.py +67 -0
- pymoo/util/hv.py +21 -0
- pymoo/util/matlab_engine.py +39 -0
- pymoo/util/misc.py +447 -0
- pymoo/util/nds/__init__.py +0 -0
- pymoo/util/nds/dominance_degree_non_dominated_sort.py +159 -0
- pymoo/util/nds/efficient_non_dominated_sort.py +152 -0
- pymoo/util/nds/fast_non_dominated_sort.py +70 -0
- pymoo/util/nds/find_non_dominated.py +54 -0
- pymoo/util/nds/naive_non_dominated_sort.py +36 -0
- pymoo/util/nds/non_dominated_sorting.py +94 -0
- pymoo/util/nds/tree_based_non_dominated_sort.py +133 -0
- pymoo/util/normalization.py +312 -0
- pymoo/util/optimum.py +42 -0
- pymoo/util/randomized_argsort.py +63 -0
- pymoo/util/ref_dirs/__init__.py +24 -0
- pymoo/util/ref_dirs/construction.py +89 -0
- pymoo/util/ref_dirs/das_dennis.py +52 -0
- pymoo/util/ref_dirs/energy.py +317 -0
- pymoo/util/ref_dirs/energy_layer.py +119 -0
- pymoo/util/ref_dirs/genetic_algorithm.py +64 -0
- pymoo/util/ref_dirs/incremental.py +69 -0
- pymoo/util/ref_dirs/misc.py +128 -0
- pymoo/util/ref_dirs/optimizer.py +59 -0
- pymoo/util/ref_dirs/performance.py +162 -0
- pymoo/util/ref_dirs/reduction.py +85 -0
- pymoo/util/ref_dirs/sample_and_map.py +24 -0
- pymoo/util/reference_direction.py +258 -0
- pymoo/util/remote.py +55 -0
- pymoo/util/roulette.py +29 -0
- pymoo/util/running_metric.py +128 -0
- pymoo/util/sliding_window.py +25 -0
- pymoo/util/value_functions.py +720 -0
- pymoo/util/vectors.py +40 -0
- pymoo/util/vf_dominator.py +102 -0
- pymoo/vendor/__init__.py +0 -0
- pymoo/vendor/cec2018.py +398 -0
- pymoo/vendor/gta.py +617 -0
- pymoo/vendor/vendor_cmaes.py +421 -0
- pymoo/vendor/vendor_coco.py +81 -0
- pymoo/vendor/vendor_scipy.py +232 -0
- pymoo/version.py +1 -0
- pymoo/visualization/__init__.py +21 -0
- pymoo/visualization/app/__init__.py +0 -0
- pymoo/visualization/app/pso.py +61 -0
- pymoo/visualization/fitness_landscape.py +128 -0
- pymoo/visualization/heatmap.py +123 -0
- pymoo/visualization/matplotlib.py +61 -0
- pymoo/visualization/pcp.py +121 -0
- pymoo/visualization/petal.py +91 -0
- pymoo/visualization/radar.py +108 -0
- pymoo/visualization/radviz.py +68 -0
- pymoo/visualization/scatter.py +150 -0
- pymoo/visualization/star_coordinate.py +75 -0
- pymoo/visualization/util.py +296 -0
- pymoo/visualization/video/__init__.py +0 -0
- pymoo/visualization/video/callback_video.py +82 -0
- pymoo/visualization/video/one_var_one_obj.py +57 -0
- pymoo/visualization/video/two_var_one_obj.py +62 -0
- pymoo-0.6.1.6.dist-info/METADATA +209 -0
- pymoo-0.6.1.6.dist-info/RECORD +337 -0
- pymoo-0.6.1.6.dist-info/WHEEL +6 -0
- pymoo-0.6.1.6.dist-info/licenses/LICENSE +191 -0
- pymoo-0.6.1.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.docs import parse_doc_string
|
|
4
|
+
from pymoo.core.plot import Plot
|
|
5
|
+
from pymoo.util.misc import set_if_none, set_if_none_from_tuples
|
|
6
|
+
from pymoo.visualization.util import parse_bounds, normalize
|
|
7
|
+
from pymoo.visualization.matplotlib import plt
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class PCP(Plot):
|
|
11
|
+
|
|
12
|
+
def __init__(self,
|
|
13
|
+
bounds=None,
|
|
14
|
+
show_bounds=True,
|
|
15
|
+
n_ticks=5,
|
|
16
|
+
normalize_each_axis=True,
|
|
17
|
+
bbox=False,
|
|
18
|
+
**kwargs):
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
Parallel Coordinate Plot
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
|
|
27
|
+
bounds : {bounds}
|
|
28
|
+
|
|
29
|
+
axis_style : {axis_style}
|
|
30
|
+
|
|
31
|
+
labels : {labels}
|
|
32
|
+
|
|
33
|
+
n_ticks : int
|
|
34
|
+
Number of ticks to be shown on each parallel axis.
|
|
35
|
+
|
|
36
|
+
show_bounds : bool
|
|
37
|
+
Whether the value of the boundaries are shown in the plot or not.
|
|
38
|
+
|
|
39
|
+
normalize_each_axis : bool
|
|
40
|
+
Whether the values should be normalized either by bounds or implicitly.
|
|
41
|
+
|
|
42
|
+
Other Parameters
|
|
43
|
+
----------------
|
|
44
|
+
|
|
45
|
+
figsize : {figsize}
|
|
46
|
+
title : {title}
|
|
47
|
+
legend : {legend}
|
|
48
|
+
tight_layout : {tight_layout}
|
|
49
|
+
cmap : {cmap}
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
super().__init__(bounds=bounds, **kwargs)
|
|
54
|
+
self.show_bounds = show_bounds
|
|
55
|
+
self.n_ticks = n_ticks
|
|
56
|
+
self.bbox = bbox
|
|
57
|
+
self.normalize_each_axis = normalize_each_axis
|
|
58
|
+
|
|
59
|
+
set_if_none_from_tuples(self.axis_style, ("color", "red"), ("linewidth", 2), ("alpha", 0.75))
|
|
60
|
+
|
|
61
|
+
def _do(self):
|
|
62
|
+
|
|
63
|
+
# initial a figure with a single plot
|
|
64
|
+
self.init_figure()
|
|
65
|
+
|
|
66
|
+
# if no normalization of each axis the bounds are based on the overall min and max
|
|
67
|
+
if not self.normalize_each_axis and self.bounds is None:
|
|
68
|
+
_F = np.vstack([e[0] for e in self.to_plot])
|
|
69
|
+
self.bounds = [_F.min(), _F.max()]
|
|
70
|
+
|
|
71
|
+
# normalize the input
|
|
72
|
+
bounds = parse_bounds(self.bounds, self.n_dim)
|
|
73
|
+
to_plot_norm, bounds = normalize(self.to_plot, bounds, return_bounds=True)
|
|
74
|
+
|
|
75
|
+
# plot for each set the lines
|
|
76
|
+
for k, (F, kwargs) in enumerate(to_plot_norm):
|
|
77
|
+
|
|
78
|
+
_kwargs = kwargs.copy()
|
|
79
|
+
set_if_none(_kwargs, "color", self.colors[k % len(self.colors)])
|
|
80
|
+
|
|
81
|
+
for i in range(len(F)):
|
|
82
|
+
plt.plot(np.arange(F.shape[1]), F[i, :], **_kwargs)
|
|
83
|
+
|
|
84
|
+
# Plot the parallel coordinate axes
|
|
85
|
+
for i in range(self.n_dim):
|
|
86
|
+
self.ax.axvline(i, **self.axis_style)
|
|
87
|
+
|
|
88
|
+
bottom, top = -0.1, 1.075
|
|
89
|
+
margin_left = 0.08
|
|
90
|
+
|
|
91
|
+
if self.show_bounds:
|
|
92
|
+
lower = self.ax.text(i - margin_left, bottom, self.func_number_to_text(bounds[0][i]))
|
|
93
|
+
upper = self.ax.text(i - margin_left, top, self.func_number_to_text(bounds[1][i]))
|
|
94
|
+
|
|
95
|
+
if self.bbox:
|
|
96
|
+
lower.set_bbox(dict(facecolor='white', alpha=0.8))
|
|
97
|
+
upper.set_bbox(dict(facecolor='white', alpha=0.8))
|
|
98
|
+
|
|
99
|
+
if self.n_ticks is not None:
|
|
100
|
+
n_length = 0.03
|
|
101
|
+
for y in np.linspace(0, 1, self.n_ticks):
|
|
102
|
+
self.ax.hlines(y, i - n_length, i + n_length, **self.axis_style)
|
|
103
|
+
|
|
104
|
+
# if bounds are shown, then move them to the bottom
|
|
105
|
+
if self.show_bounds:
|
|
106
|
+
self.ax.tick_params(axis='x', which='major', pad=25)
|
|
107
|
+
|
|
108
|
+
self.ax.spines['right'].set_visible(False)
|
|
109
|
+
self.ax.spines['left'].set_visible(False)
|
|
110
|
+
|
|
111
|
+
self.ax.set_yticklabels([])
|
|
112
|
+
self.ax.set_yticks([])
|
|
113
|
+
self.ax.set_ylim((-0.05, 1.05))
|
|
114
|
+
|
|
115
|
+
self.ax.set_xticks(np.arange(self.n_dim))
|
|
116
|
+
self.ax.set_xticklabels(self.get_labels())
|
|
117
|
+
|
|
118
|
+
return self
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
parse_doc_string(PCP.__init__)
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.docs import parse_doc_string
|
|
4
|
+
from pymoo.core.plot import Plot
|
|
5
|
+
from pymoo.util.misc import set_if_none
|
|
6
|
+
from pymoo.visualization.util import get_circle_points, plot_axes_lines, \
|
|
7
|
+
plot_axis_labels, plot_circle, plot_polygon, parse_bounds, normalize, equal_axis, no_ticks
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Petal(Plot):
|
|
11
|
+
|
|
12
|
+
def __init__(self,
|
|
13
|
+
bounds=None,
|
|
14
|
+
**kwargs):
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
Petal Diagram
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
bounds : tuple
|
|
23
|
+
The boundaries for each objective. Necessary to be provided for this plot!
|
|
24
|
+
axis_style : {axis_style}
|
|
25
|
+
reverse : bool
|
|
26
|
+
Default false. Otherwise, larger area means smaller value.
|
|
27
|
+
|
|
28
|
+
Other Parameters
|
|
29
|
+
----------------
|
|
30
|
+
|
|
31
|
+
figsize : {figsize}
|
|
32
|
+
title : {title}
|
|
33
|
+
legend : {legend}
|
|
34
|
+
tight_layout : {tight_layout}
|
|
35
|
+
cmap : {cmap}
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
super().__init__(bounds=bounds, **kwargs)
|
|
40
|
+
|
|
41
|
+
if bounds is None:
|
|
42
|
+
raise Exception("Boundaries must be provided for Petal Width. Otherwise, no trade-offs can be calculated.")
|
|
43
|
+
|
|
44
|
+
set_if_none(self.axis_style, "color", "black")
|
|
45
|
+
set_if_none(self.axis_style, "linewidth", 2)
|
|
46
|
+
set_if_none(self.axis_style, "alpha", 0.5)
|
|
47
|
+
|
|
48
|
+
def _plot(self, ax, F):
|
|
49
|
+
|
|
50
|
+
# equal axis length and no ticks
|
|
51
|
+
equal_axis(ax)
|
|
52
|
+
no_ticks(ax)
|
|
53
|
+
|
|
54
|
+
V = get_circle_points(len(F))
|
|
55
|
+
|
|
56
|
+
# sections to plot
|
|
57
|
+
sections = np.linspace(0, 2 * np.pi, self.n_dim + 1)
|
|
58
|
+
|
|
59
|
+
t = [(sections[i] + sections[i + 1]) / 2 for i in range(len(sections) - 1)]
|
|
60
|
+
endpoints = np.column_stack([np.cos(t), np.sin(t)])
|
|
61
|
+
plot_axis_labels(ax, endpoints, self.get_labels(), **self.axis_label_style)
|
|
62
|
+
|
|
63
|
+
center = np.zeros(2)
|
|
64
|
+
|
|
65
|
+
for i in range(len(sections) - 1):
|
|
66
|
+
t = np.linspace(sections[i], sections[i + 1], 100)
|
|
67
|
+
v = np.column_stack([np.cos(t), np.sin(t)])
|
|
68
|
+
|
|
69
|
+
P = np.vstack([center, F[i] * v])
|
|
70
|
+
plot_polygon(ax, P, color=self.colors[i])
|
|
71
|
+
|
|
72
|
+
# draw the outer circle
|
|
73
|
+
plot_circle(ax, **self.axis_style)
|
|
74
|
+
plot_axes_lines(ax, V, **self.axis_style)
|
|
75
|
+
|
|
76
|
+
def _do(self):
|
|
77
|
+
|
|
78
|
+
n_rows = len(self.to_plot)
|
|
79
|
+
n_cols = max([len(e[0]) for e in self.to_plot])
|
|
80
|
+
self.init_figure(n_rows=n_rows, n_cols=n_cols, force_axes_as_matrix=True)
|
|
81
|
+
|
|
82
|
+
# normalize the input
|
|
83
|
+
bounds = parse_bounds(self.bounds, self.n_dim)
|
|
84
|
+
to_plot_norm = normalize(self.to_plot, bounds, reverse=self.reverse)
|
|
85
|
+
|
|
86
|
+
for k, (F, kwargs) in enumerate(to_plot_norm):
|
|
87
|
+
for j, _F in enumerate(F):
|
|
88
|
+
self._plot(self.ax[k, j], _F)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
parse_doc_string(Petal.__init__)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.docs import parse_doc_string
|
|
4
|
+
from pymoo.core.plot import Plot
|
|
5
|
+
from pymoo.util.misc import set_if_none_from_tuples
|
|
6
|
+
from pymoo.visualization.util import plot_axes_lines, plot_axis_labels, plot_polygon, get_circle_points, \
|
|
7
|
+
plot_radar_line, equal_axis, no_ticks, parse_bounds, normalize
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Radar(Plot):
|
|
11
|
+
|
|
12
|
+
def __init__(self,
|
|
13
|
+
normalize_each_objective=True,
|
|
14
|
+
n_partitions=3,
|
|
15
|
+
point_style={},
|
|
16
|
+
**kwargs):
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
Radar Plot
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
normalize_each_objective : bool
|
|
24
|
+
Whether each objective is normalized. Otherwise, the inner and outer bound is plotted.
|
|
25
|
+
point_style : dict
|
|
26
|
+
The style being used to visualize the points
|
|
27
|
+
n_partitions : int
|
|
28
|
+
Number of partitions to show in the radar.
|
|
29
|
+
reverse : {reverse}
|
|
30
|
+
axis_style : {axis_style}
|
|
31
|
+
labels : {labels}
|
|
32
|
+
|
|
33
|
+
Other Parameters
|
|
34
|
+
----------------
|
|
35
|
+
figsize : {figsize}
|
|
36
|
+
title : {title}
|
|
37
|
+
legend : {legend}
|
|
38
|
+
tight_layout : {tight_layout}
|
|
39
|
+
cmap : {cmap}
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
super().__init__(**kwargs)
|
|
43
|
+
self.normalize_each_objective = normalize_each_objective
|
|
44
|
+
self.n_partitions = n_partitions
|
|
45
|
+
|
|
46
|
+
self.point_style = point_style
|
|
47
|
+
set_if_none_from_tuples(self.point_style, ("s", 15))
|
|
48
|
+
|
|
49
|
+
set_if_none_from_tuples(self.axis_style, ("color", "black"), ("linewidth", 0.5), ("alpha", 0.75))
|
|
50
|
+
|
|
51
|
+
def _plot(self, ax, _F, inner, outer, kwargs):
|
|
52
|
+
|
|
53
|
+
set_if_none_from_tuples(kwargs, ("alpha", 0.5))
|
|
54
|
+
|
|
55
|
+
# equal axis length and no ticks
|
|
56
|
+
equal_axis(ax)
|
|
57
|
+
no_ticks(ax)
|
|
58
|
+
|
|
59
|
+
# draw the axis lines and labels
|
|
60
|
+
plot_axes_lines(ax, outer, extend_factor=1.0, **self.axis_style)
|
|
61
|
+
plot_axis_labels(ax, outer, self.get_labels(), margin=0.015, **self.axis_label_style)
|
|
62
|
+
|
|
63
|
+
# plot the outer radar line and the inner polygon
|
|
64
|
+
plot_radar_line(ax, outer, **self.axis_style)
|
|
65
|
+
plot_polygon(ax, inner)
|
|
66
|
+
|
|
67
|
+
# find the corresponding point
|
|
68
|
+
_F = inner + _F[:, None] * (outer - inner)
|
|
69
|
+
|
|
70
|
+
# plot the points and no polygon
|
|
71
|
+
ax.scatter(_F[:, 0], _F[:, 1], **self.point_style)
|
|
72
|
+
plot_polygon(ax, _F, **kwargs)
|
|
73
|
+
|
|
74
|
+
def _do(self):
|
|
75
|
+
|
|
76
|
+
if self.bounds is None:
|
|
77
|
+
raise Exception("The boundaries must be provided.")
|
|
78
|
+
|
|
79
|
+
_F = np.vstack([e[0] for e in self.to_plot])
|
|
80
|
+
if np.any(_F < self.bounds[0]) or np.any(_F > self.bounds[1]):
|
|
81
|
+
raise Exception(
|
|
82
|
+
"Points out of the boundaries exist! Please make sure the boundaries are indeed boundaries.")
|
|
83
|
+
|
|
84
|
+
n_rows = len(self.to_plot)
|
|
85
|
+
n_cols = max([len(e[0]) for e in self.to_plot])
|
|
86
|
+
self.init_figure(n_rows=n_rows, n_cols=n_cols, force_axes_as_matrix=True)
|
|
87
|
+
|
|
88
|
+
# normalize the input
|
|
89
|
+
bounds = parse_bounds(self.bounds, self.n_dim)
|
|
90
|
+
to_plot_norm = normalize(self.to_plot, bounds, reverse=self.reverse)
|
|
91
|
+
|
|
92
|
+
# get the endpoints of circle
|
|
93
|
+
V = get_circle_points(self.n_dim)
|
|
94
|
+
|
|
95
|
+
if self.normalize_each_objective:
|
|
96
|
+
inner = np.zeros((self.n_dim, 1)) * V
|
|
97
|
+
outer = np.ones((self.n_dim, 1)) * V
|
|
98
|
+
else:
|
|
99
|
+
inner = bounds[[0]].T * V
|
|
100
|
+
outer = (bounds[[1]].T * V) / bounds[1].max()
|
|
101
|
+
|
|
102
|
+
for k, (F, kwargs) in enumerate(to_plot_norm):
|
|
103
|
+
|
|
104
|
+
for j, _F in enumerate(F):
|
|
105
|
+
self._plot(self.ax[k, j], _F, inner, outer, kwargs)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
parse_doc_string(Radar.__init__)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from pymoo.docs import parse_doc_string
|
|
2
|
+
from pymoo.core.plot import Plot
|
|
3
|
+
from pymoo.util.misc import set_if_none_from_tuples
|
|
4
|
+
from pymoo.visualization.util import plot_circle, plot_radar_line, plot_axis_labels, equal_axis, no_ticks, \
|
|
5
|
+
get_uniform_points_around_circle
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Radviz(Plot):
|
|
9
|
+
|
|
10
|
+
def __init__(self, endpoint_style={}, **kwargs):
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
Radviz Plot
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
|
|
18
|
+
axis_style : {axis_style}
|
|
19
|
+
endpoint_style : dict
|
|
20
|
+
Endpoints are drawn at each extreme point of an objective. This style can be modified.
|
|
21
|
+
labels : {labels}
|
|
22
|
+
|
|
23
|
+
Other Parameters
|
|
24
|
+
----------------
|
|
25
|
+
|
|
26
|
+
figsize : {figsize}
|
|
27
|
+
title : {title}
|
|
28
|
+
legend : {legend}
|
|
29
|
+
tight_layout : {tight_layout}
|
|
30
|
+
cmap : {cmap}
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
super().__init__(**kwargs)
|
|
35
|
+
|
|
36
|
+
# set the default axis style
|
|
37
|
+
set_if_none_from_tuples(self.axis_style, ("color", "black"), ("linewidth", 1), ("alpha", 0.75))
|
|
38
|
+
|
|
39
|
+
self.endpoint_style = endpoint_style
|
|
40
|
+
set_if_none_from_tuples(self.endpoint_style, ("color", "black"), ("s", 70), ("alpha", 0.3))
|
|
41
|
+
|
|
42
|
+
def _do(self):
|
|
43
|
+
|
|
44
|
+
# initial a figure with a single plot
|
|
45
|
+
self.init_figure()
|
|
46
|
+
|
|
47
|
+
# equal axis length and no ticks
|
|
48
|
+
equal_axis(self.ax)
|
|
49
|
+
no_ticks(self.ax)
|
|
50
|
+
|
|
51
|
+
V = get_uniform_points_around_circle(self.n_dim)
|
|
52
|
+
plot_axis_labels(self.ax, V, self.get_labels(), **self.axis_label_style)
|
|
53
|
+
|
|
54
|
+
# draw the outer circle and radar lines
|
|
55
|
+
plot_circle(self.ax, **self.axis_style)
|
|
56
|
+
plot_radar_line(self.ax, V, **self.axis_style)
|
|
57
|
+
|
|
58
|
+
# draw the endpoints of each objective
|
|
59
|
+
if self.endpoint_style:
|
|
60
|
+
self.ax.scatter(V[:, 0], V[:, 1], **self.endpoint_style)
|
|
61
|
+
|
|
62
|
+
# plot all the points
|
|
63
|
+
for k, (F, kwargs) in enumerate(self.to_plot):
|
|
64
|
+
N = (F[..., None] * V).sum(axis=1) / F.sum(axis=1)[:, None]
|
|
65
|
+
self.ax.scatter(N[:, 0], N[:, 1], **kwargs)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
parse_doc_string(Radviz.__init__)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.plot import Plot
|
|
4
|
+
from pymoo.docs import parse_doc_string
|
|
5
|
+
from pymoo.util.misc import set_if_none
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def plot_1d(sc):
|
|
9
|
+
sc.init_figure()
|
|
10
|
+
labels = sc.get_labels()
|
|
11
|
+
ax = sc.ax
|
|
12
|
+
|
|
13
|
+
for k, (F, kwargs) in enumerate(sc.to_plot):
|
|
14
|
+
func = getattr(ax, kwargs.pop("mode"))
|
|
15
|
+
func(F, np.zeros_like(F), **kwargs)
|
|
16
|
+
ax.set_xlabel(labels[0])
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def plot_2d(sc):
|
|
20
|
+
sc.init_figure()
|
|
21
|
+
labels = sc.get_labels()
|
|
22
|
+
ax = sc.ax
|
|
23
|
+
|
|
24
|
+
for k, (F, kwargs) in enumerate(sc.to_plot):
|
|
25
|
+
func = getattr(ax, kwargs.pop("mode"))
|
|
26
|
+
func(F[:, 0], F[:, 1], **kwargs)
|
|
27
|
+
ax.set_xlabel(labels[0])
|
|
28
|
+
ax.set_ylabel(labels[1])
|
|
29
|
+
|
|
30
|
+
return sc
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def plot_3d(sc, angle):
|
|
34
|
+
sc.init_figure(plot_3D=True)
|
|
35
|
+
labels = sc.get_labels()
|
|
36
|
+
ax = sc.ax
|
|
37
|
+
|
|
38
|
+
for k, (F, kwargs) in enumerate(sc.to_plot):
|
|
39
|
+
|
|
40
|
+
# here alo `plot_trisurf` is allowed
|
|
41
|
+
func = getattr(ax, kwargs.pop("mode"))
|
|
42
|
+
func(F[:, 0], F[:, 1], F[:, 2], **kwargs)
|
|
43
|
+
|
|
44
|
+
ax.xaxis.pane.fill = False
|
|
45
|
+
ax.yaxis.pane.fill = False
|
|
46
|
+
ax.zaxis.pane.fill = False
|
|
47
|
+
|
|
48
|
+
ax.set_xlabel(labels[0])
|
|
49
|
+
ax.set_ylabel(labels[1])
|
|
50
|
+
ax.set_zlabel(labels[2])
|
|
51
|
+
|
|
52
|
+
if sc.angle is not None:
|
|
53
|
+
ax.view_init(*angle)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def plot_pairwise(sc):
|
|
57
|
+
sc.init_figure(n_rows=sc.n_dim, n_cols=sc.n_dim)
|
|
58
|
+
labels = sc.get_labels()
|
|
59
|
+
|
|
60
|
+
for k, (F, kwargs) in enumerate(sc.to_plot):
|
|
61
|
+
|
|
62
|
+
assert F.shape[1] >= 2, "A pairwise sc plot needs at least two dimensions."
|
|
63
|
+
mode = kwargs.pop("mode")
|
|
64
|
+
|
|
65
|
+
for i in range(sc.n_dim):
|
|
66
|
+
for j in range(sc.n_dim):
|
|
67
|
+
|
|
68
|
+
ax = sc.ax[i, j]
|
|
69
|
+
func = getattr(ax, mode)
|
|
70
|
+
|
|
71
|
+
if i != j:
|
|
72
|
+
func(F[:, i], F[:, j], **kwargs)
|
|
73
|
+
ax.set_xlabel(labels[i])
|
|
74
|
+
ax.set_ylabel(labels[j])
|
|
75
|
+
else:
|
|
76
|
+
func(0, 0, s=1, color="white")
|
|
77
|
+
ax.set_xticks([])
|
|
78
|
+
ax.set_yticks([])
|
|
79
|
+
ax.text(0, 0, labels[i], ha='center', va='center', fontsize=20)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class Scatter(Plot):
|
|
83
|
+
|
|
84
|
+
def __init__(self,
|
|
85
|
+
plot_3d=True,
|
|
86
|
+
angle=(45, 45),
|
|
87
|
+
**kwargs):
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
Scatter Plot
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
|
|
95
|
+
axis_style : {axis_style}
|
|
96
|
+
labels : {labels}
|
|
97
|
+
|
|
98
|
+
Other Parameters
|
|
99
|
+
----------------
|
|
100
|
+
|
|
101
|
+
figsize : {figsize}
|
|
102
|
+
title : {title}
|
|
103
|
+
legend : {legend}
|
|
104
|
+
tight_layout : {tight_layout}
|
|
105
|
+
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
super().__init__(**kwargs)
|
|
109
|
+
self.angle = angle
|
|
110
|
+
self.plot_3d = plot_3d
|
|
111
|
+
|
|
112
|
+
def _do(self):
|
|
113
|
+
|
|
114
|
+
# set some default values
|
|
115
|
+
to_plot = []
|
|
116
|
+
for k, (F, v) in enumerate(self.to_plot):
|
|
117
|
+
v = dict(v)
|
|
118
|
+
set_if_none(v, "color", self.colors[k % len(self.colors)])
|
|
119
|
+
set_if_none(v, "alpha", 1.0)
|
|
120
|
+
|
|
121
|
+
# this is added to have compatibility to an old version
|
|
122
|
+
# should be removed when the documentation is updated
|
|
123
|
+
if "plot_type" in v:
|
|
124
|
+
name = v.pop("plot_type")
|
|
125
|
+
|
|
126
|
+
if name == "line":
|
|
127
|
+
name = "plot"
|
|
128
|
+
elif name == "surface":
|
|
129
|
+
name = "plot_trisurf"
|
|
130
|
+
|
|
131
|
+
v["mode"] = name
|
|
132
|
+
set_if_none(v, "mode", "scatter")
|
|
133
|
+
|
|
134
|
+
to_plot.append([F, v])
|
|
135
|
+
|
|
136
|
+
self.to_plot = to_plot
|
|
137
|
+
|
|
138
|
+
if self.n_dim == 1:
|
|
139
|
+
plot_1d(self)
|
|
140
|
+
elif self.n_dim == 2:
|
|
141
|
+
plot_2d(self)
|
|
142
|
+
elif self.n_dim == 3 and self.plot_3d:
|
|
143
|
+
plot_3d(self, self.angle)
|
|
144
|
+
else:
|
|
145
|
+
plot_pairwise(self)
|
|
146
|
+
|
|
147
|
+
return self
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
parse_doc_string(Scatter.__init__)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.visualization.util import plot_axes_arrow, plot_axis_labels, equal_axis, no_ticks, parse_bounds, \
|
|
4
|
+
normalize, get_uniform_points_around_circle
|
|
5
|
+
from pymoo.docs import parse_doc_string
|
|
6
|
+
from pymoo.core.plot import Plot
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class StarCoordinate(Plot):
|
|
10
|
+
|
|
11
|
+
def __init__(self,
|
|
12
|
+
axis_extension=1.03,
|
|
13
|
+
**kwargs):
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
Star Coordinate Plot
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
|
|
21
|
+
axis_style : {axis_style}
|
|
22
|
+
labels : {labels}
|
|
23
|
+
endpoint_style : dict
|
|
24
|
+
Endpoints are drawn at each extreme point of an objective. This style can be modified.
|
|
25
|
+
|
|
26
|
+
Other Parameters
|
|
27
|
+
----------------
|
|
28
|
+
|
|
29
|
+
figsize : {figsize}
|
|
30
|
+
title : {title}
|
|
31
|
+
legend : {legend}
|
|
32
|
+
tight_layout : {tight_layout}
|
|
33
|
+
cmap : {cmap}
|
|
34
|
+
|
|
35
|
+
"""
|
|
36
|
+
super().__init__(**kwargs)
|
|
37
|
+
|
|
38
|
+
self.axis_extension = axis_extension
|
|
39
|
+
|
|
40
|
+
if "arrow_style" not in kwargs:
|
|
41
|
+
self.arrow_style = {
|
|
42
|
+
"head_width": 0.02,
|
|
43
|
+
"head_length": 0.01
|
|
44
|
+
}
|
|
45
|
+
else:
|
|
46
|
+
self.arrow_style = kwargs["arrow_style"]
|
|
47
|
+
|
|
48
|
+
def _do(self):
|
|
49
|
+
|
|
50
|
+
# initial a figure with a single plot
|
|
51
|
+
self.init_figure()
|
|
52
|
+
|
|
53
|
+
# equal axis length and no ticks
|
|
54
|
+
equal_axis(self.ax)
|
|
55
|
+
no_ticks(self.ax)
|
|
56
|
+
|
|
57
|
+
# determine the overall scale of points
|
|
58
|
+
_F = np.vstack([e[0] for e in self.to_plot])
|
|
59
|
+
_min, _max = _F.min(axis=0), _F.max(axis=0)
|
|
60
|
+
|
|
61
|
+
V = get_uniform_points_around_circle(self.n_dim)
|
|
62
|
+
|
|
63
|
+
plot_axes_arrow(self.ax, V, extend_factor=self.axis_extension, **{**self.axis_style, **self.arrow_style})
|
|
64
|
+
plot_axis_labels(self.ax, V, self.get_labels(), **self.axis_label_style)
|
|
65
|
+
|
|
66
|
+
# normalize in range for this plot - here no implicit normalization as in radviz
|
|
67
|
+
bounds = parse_bounds(self.bounds, self.n_dim)
|
|
68
|
+
to_plot_norm = normalize(self.to_plot, bounds)
|
|
69
|
+
|
|
70
|
+
for k, (F, kwargs) in enumerate(to_plot_norm):
|
|
71
|
+
N = (F[..., None] * V).sum(axis=1)
|
|
72
|
+
self.ax.scatter(N[:, 0], N[:, 1], **kwargs)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
parse_doc_string(StarCoordinate.__init__)
|