codecov[bot]: # [Codecov](https://codecov.io/gh/N-Wouda/ALNS/pull/21?src=pr&el=h1) Report
> Merging [#21](https://codecov.io/gh/N-Wouda/ALNS/pull/21?src=pr&el=desc) into [master](https://codecov.io/gh/N-Wouda/ALNS/commit/c669e907808fa02138a55a68877d02021272af30&el=desc) will **not change** coverage by `%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/N-Wouda/ALNS/pull/21/graphs/tree.svg?width=650&height=150&src=pr&token=xtNEr42uZZ)](https://codecov.io/gh/N-Wouda/ALNS/pull/21?src=pr&el=tree)

```diff
@@            Coverage Diff            @@
##            master       #21   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           16        16           
  Lines          287       271   -16     
=========================================
- Hits           287       271   -16     
```


| [Impacted Files](https://codecov.io/gh/N-Wouda/ALNS/pull/21?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [alns/ALNS.py](https://codecov.io/gh/N-Wouda/ALNS/pull/21/diff?src=pr&el=tree#diff-YWxucy9BTE5TLnB5) | `100.00% <0.00%> (ø)` | :arrow_up: |
| [alns/Result.py](https://codecov.io/gh/N-Wouda/ALNS/pull/21/diff?src=pr&el=tree#diff-YWxucy9SZXN1bHQucHk=) | `100.00% <0.00%> (ø)` | :arrow_up: |
| [alns/Statistics.py](https://codecov.io/gh/N-Wouda/ALNS/pull/21/diff?src=pr&el=tree#diff-YWxucy9TdGF0aXN0aWNzLnB5) | `100.00% <0.00%> (ø)` | :arrow_up: |
| [alns/criteria/SimulatedAnnealing.py](https://codecov.io/gh/N-Wouda/ALNS/pull/21/diff?src=pr&el=tree#diff-YWxucy9jcml0ZXJpYS9TaW11bGF0ZWRBbm5lYWxpbmcucHk=) | `100.00% <0.00%> (ø)` | :arrow_up: |
| [alns/criteria/RecordToRecordTravel.py](https://codecov.io/gh/N-Wouda/ALNS/pull/21/diff?src=pr&el=tree#diff-YWxucy9jcml0ZXJpYS9SZWNvcmRUb1JlY29yZFRyYXZlbC5weQ==) | `100.00% <0.00%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/N-Wouda/ALNS/pull/21?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/N-Wouda/ALNS/pull/21?src=pr&el=footer). Last update [c669e90...b3d5084](https://codecov.io/gh/N-Wouda/ALNS/pull/21?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

diff --git a/alns/Result.py b/alns/Result.py
index a788279..beec688 100644
--- a/alns/Result.py
+++ b/alns/Result.py
@@ -165,9 +165,9 @@ class Result:
         operator_names = list(operator_counts.keys())
 
         operator_counts = np.array(list(operator_counts.values()))
-        cumulative_counts = operator_counts.cumsum(axis=1)
+        cumulative_counts = operator_counts[:, :num_types].cumsum(axis=1)
 
-        ax.set_xlim(right=np.sum(operator_counts, axis=1).max())
+        ax.set_xlim(right=cumulative_counts[:, -1].max())
 
         for idx in range(num_types):
             widths = operator_counts[:, idx]
diff --git a/setup.py b/setup.py
index 7c2d8cb..adb3f2b 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@ import setuptools
 
 MAJOR = 1
 MINOR = 2
-MAINTENANCE = 0
+MAINTENANCE = 1
 MODIFIER = ""
 
 VERSION = "{0}.{1}.{2}{3}".format(MAJOR, MINOR, MAINTENANCE, MODIFIER)

Fix Result.plot_operator_counts plot looking 'weird'
E.g. when not plotting all possible outcome types, the axes are still fixed as if one did. Like so:

![image](https://user-images.githubusercontent.com/16272507/74932339-d684dd00-53e1-11ea-8fb2-8c6a08e098ea.png)

diff --git a/alns/tests/test_result.py b/alns/tests/test_result.py
index 7f309f2..bc7c663 100644
--- a/alns/tests/test_result.py
+++ b/alns/tests/test_result.py
@@ -13,7 +13,7 @@ from .states import Sentinel
 try:
     from matplotlib.testing.decorators import check_figures_equal
 except ImportError:
-    def check_figures_equal(*args, **kwargs):       # placeholder
+    def check_figures_equal(*args, **kwargs):  # placeholder
         return check_figures_equal
 
 
@@ -69,19 +69,21 @@ def get_objective_plot(ax, *args, **kwargs):
     ax.set_xlabel("Iteration (#)")
 
 
-def get_operator_plot(figure, destroy, repair, title=None, **kwargs):
+def get_operator_plot(figure, destroy, repair, legend=None, suptitle=None,
+                      **kwargs):
     """
     Helper method.
     """
-    def _helper(ax, operator_counts, title, **kwargs):
+
+    def _helper(ax, operator_counts, title):
         operator_names = list(operator_counts.keys())
 
         operator_counts = np.array(list(operator_counts.values()))
-        cumulative_counts = operator_counts.cumsum(axis=1)
+        cumulative_counts = operator_counts[:, :len(legend)].cumsum(axis=1)
 
-        ax.set_xlim(right=np.sum(operator_counts, axis=1).max())
+        ax.set_xlim(right=cumulative_counts[:, -1].max())
 
-        for idx in range(4):
+        for idx in range(len(legend)):
             widths = operator_counts[:, idx]
             starts = cumulative_counts[:, idx] - widths
 
@@ -94,16 +96,19 @@ def get_operator_plot(figure, destroy, repair, title=None, **kwargs):
         ax.set_xlabel("Iterations where operator resulted in this outcome (#)")
         ax.set_ylabel("Operator")
 
-    if title is not None:
-        figure.suptitle(title)
+    if suptitle is not None:
+        figure.suptitle(suptitle)
+
+    if legend is None:
+        legend = ["Best", "Better", "Accepted", "Rejected"]
 
     d_ax, r_ax = figure.subplots(nrows=2)
 
-    _helper(d_ax, destroy, "Destroy operators", **kwargs)
-    _helper(r_ax, repair, "Repair operators", **kwargs)
+    _helper(d_ax, destroy, "Destroy operators")
+    _helper(r_ax, repair, "Repair operators")
 
-    figure.legend(["Best", "Better", "Accepted", "Rejected"],
-                  ncol=4,
+    figure.legend(legend,
+                  ncol=len(legend),
                   loc="lower center")
 
 
@@ -161,7 +166,7 @@ def test_plot_objectives_kwargs(fig_test, fig_ref):
     correctly passed to the ``plot`` method.
     """
     result = get_result(Sentinel())
-    kwargs = dict(lw=5, marker='*', title="Test title")
+    kwargs = dict(lw=5, marker='*')
 
     # Tested plot
     result.plot_objectives(fig_test.subplots(), **kwargs)
@@ -241,7 +246,7 @@ def test_plot_operator_counts_title(fig_test, fig_ref):
     get_operator_plot(fig_ref,
                       result.statistics.destroy_operator_counts,
                       result.statistics.repair_operator_counts,
-                      title="A random test title")
+                      suptitle="A random test title")
 
 
 @pytest.mark.matplotlib
@@ -278,3 +283,24 @@ def test_plot_operator_counts_kwargs(fig_test, fig_ref):
                       result.statistics.destroy_operator_counts,
                       result.statistics.repair_operator_counts,
                       **kwargs)
+
+
+@pytest.mark.matplotlib
+@pytest.mark.skipif(sys.version_info < (3, 5),
+                    reason="Plot testing is not reliably available for Py3.4")
+@check_figures_equal(extensions=['png'])
+def test_plot_operator_counts_legend_length(fig_test, fig_ref):
+    """
+    Tests if the length of the passed-in legend is used to determine which
+    counts to show.
+    """
+    result = get_result(Sentinel())
+
+    # Tested plot
+    result.plot_operator_counts(fig_test, legend=["Best"])
+
+    # Reference plot
+    get_operator_plot(fig_ref,
+                      result.statistics.destroy_operator_counts,
+                      result.statistics.repair_operator_counts,
+                      legend=["Best"])

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.7
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
-e git+https://github.com/N-Wouda/ALNS.git@c669e907808fa02138a55a68877d02021272af30#egg=alns
certifi @ file:///croot/certifi_1671487769961/work/certifi
charset-normalizer==3.4.1
click==8.1.8
codecov==2.1.13
coverage==7.2.7
cycler==0.11.0
Deprecated==1.2.18
exceptiongroup==1.2.2
fonttools==4.38.0
idna==3.10
importlib-metadata==6.7.0
iniconfig==2.0.0
kiwisolver==1.4.5
matplotlib==3.5.3
mypy==1.4.1
mypy-extensions==1.0.0
networkx==2.6.3
numpy==1.21.6
packaging==24.0
Pillow==9.5.0
pluggy==1.2.0
pyparsing==3.1.4
pytest==7.4.4
pytest-cov==4.1.0
python-dateutil==2.9.0.post0
requests==2.31.0
six==1.17.0
tabulate==0.8.10
tomli==2.0.1
tsplib95==0.7.1
typed-ast==1.5.5
typing_extensions==4.7.1
urllib3==2.0.7
wrapt==1.16.0
zipp==3.15.0

name: ALNS
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - charset-normalizer==3.4.1
      - click==8.1.8
      - codecov==2.1.13
      - coverage==7.2.7
      - cycler==0.11.0
      - deprecated==1.2.18
      - exceptiongroup==1.2.2
      - fonttools==4.38.0
      - idna==3.10
      - importlib-metadata==6.7.0
      - iniconfig==2.0.0
      - kiwisolver==1.4.5
      - matplotlib==3.5.3
      - mypy==1.4.1
      - mypy-extensions==1.0.0
      - networkx==2.6.3
      - numpy==1.21.6
      - packaging==24.0
      - pillow==9.5.0
      - pluggy==1.2.0
      - pyparsing==3.1.4
      - pytest==7.4.4
      - pytest-cov==4.1.0
      - python-dateutil==2.9.0.post0
      - requests==2.31.0
      - six==1.17.0
      - tabulate==0.8.10
      - tomli==2.0.1
      - tsplib95==0.7.1
      - typed-ast==1.5.5
      - typing-extensions==4.7.1
      - urllib3==2.0.7
      - wrapt==1.16.0
      - zipp==3.15.0
prefix: /opt/conda/envs/ALNS

alns/tests/test_result.py::test_plot_operator_counts_legend_length[png]
alns/tests/test_result.py::test_result_state alns/tests/test_result.py::test_raises_missing_statistics alns/tests/test_result.py::test_plot_objectives[png] alns/tests/test_result.py::test_plot_objectives_kwargs[png] alns/tests/test_result.py::test_plot_objectives_default_axes alns/tests/test_result.py::test_plot_operator_counts[png] alns/tests/test_result.py::test_plot_operator_counts_raises_legend alns/tests/test_result.py::test_plot_operator_counts_title[png] alns/tests/test_result.py::test_plot_operator_counts_default_figure alns/tests/test_result.py::test_plot_operator_counts_kwargs[png]
setup.py alns/Result.py
setup.py alns/Result.py