# Buggy code
def plot_diagram(diagram, homology_dimensions=None, **input_layout):
    """Plot a single persistence diagram.

    Parameters
    ----------
    diagram : ndarray of shape (n_points, 3)
        The persistence diagram to plot, where the third dimension along axis 1
        contains homology dimensions, and the first two contain (birth, death)
        pairs to be used as coordinates in the two-dimensional plot.

    homology_dimensions : list of int or None, optional, default: ``None``
        Homology dimensions which will appear on the plot. If ``None``, all
        homology dimensions which appear in `diagram` will be plotted.

    """
    from ..diagrams._utils import _subdiagrams  # To avoid circular imports

    # TODO: increase the marker size
    if homology_dimensions is None:
        homology_dimensions = np.unique(diagram[:, 2])

    max_filt_param = np.where(np.isinf(diagram), -np.inf, diagram).max()

    layout = dict(
        width=500,
        height=500,
        xaxis1=dict(
            title="Birth",
            side="bottom",
            type="linear",
            range=[0, 1.1 * max_filt_param],
            ticks="outside",
            anchor="y1",
            showline=True,
            zeroline=True,
            showexponent="all",
            exponentformat="e",
        ),
        yaxis1=dict(
            title="Death",
            side="left",
            type="linear",
            range=[0, 1.1 * max_filt_param],
            ticks="outside",
            anchor="x1",
            showline=True,
            zeroline=True,
            showexponent="all",
            exponentformat="e",
        ),
        plot_bgcolor="white",
    )

    layout.update(input_layout)

    fig = gobj.Figure(layout=layout)
    fig.update_xaxes(zeroline=True, linewidth=1, linecolor="black", mirror=False)
    fig.update_yaxes(zeroline=True, linewidth=1, linecolor="black", mirror=False)

    fig.add_trace(
        gobj.Scatter(
            x=np.array([-100 * max_filt_param, 100 * max_filt_param]),
            y=np.array([-100 * max_filt_param, 100 * max_filt_param]),
            mode="lines",
            line=dict(dash="dash", width=1, color="black"),
            showlegend=False,
            hoverinfo="none",
        )
    )

    for dim in homology_dimensions:
        name = f"H{int(dim)}" if dim != np.inf else "Any homology dimension"
        subdiagram = _subdiagrams(np.asarray([diagram]), [dim], remove_dim=True)[0]
        diff = subdiagram[:, 1] != subdiagram[:, 0]
        subdiagram = subdiagram[diff]
        fig.add_trace(
            gobj.Scatter(
                x=subdiagram[:, 0], y=subdiagram[:, 1], mode="markers", name=name
            )
        )

    fig.show()


# Traceback (ValueError)
---------------------------------------------------------------------------
_RemoteTraceback                          Traceback (most recent call last)
_RemoteTraceback: 
"""
Traceback (most recent call last):
  File "C:\Users\nicho\Anaconda3\lib\site-packages\joblib\externals\loky\process_executor.py", line 418, in _process_worker
    r = call_item()
  File "C:\Users\nicho\Anaconda3\lib\site-packages\joblib\externals\loky\process_executor.py", line 272, in __call__
    return self.fn(*self.args, **self.kwargs)
  File "C:\Users\nicho\Anaconda3\lib\site-packages\joblib\_parallel_backends.py", line 567, in __call__
    return self.func(*args, **kwargs)
  File "C:\Users\nicho\Anaconda3\lib\site-packages\joblib\parallel.py", line 225, in __call__
    for func, args, kwargs in self.items]
  File "C:\Users\nicho\Anaconda3\lib\site-packages\joblib\parallel.py", line 225, in <listcomp>
    for func, args, kwargs in self.items]
  File "C:\Users\nicho\Anaconda3\lib\site-packages\gtda\diagrams\_metrics.py", line 86, in heats
    diagrams[diagrams < sampling[0, 0]] = sampling[0, 0]
ValueError: assignment destination is read-only
"""

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
<ipython-input-132-73d0b2c011fe> in <module>
      7 hk = HeatKernel(sigma=1, n_bins=n_bins, n_jobs=2)
      8 num_dimensions = 1
----> 9 x_t = hk.fit_transform(diagrams)

~\Anaconda3\lib\site-packages\gtda\utils\_docs.py in fit_transform_wrapper(*args, **kwargs)
    104         @wraps(original_fit_transform)
    105         def fit_transform_wrapper(*args, **kwargs):
--> 106             return original_fit_transform(*args, **kwargs)
    107         fit_transform_wrapper.__doc__ = \
    108             make_fit_transform_docs(fit_docs, transform_docs)

~\Anaconda3\lib\site-packages\sklearn\base.py in fit_transform(self, X, y, **fit_params)
    569         if y is None:
    570             # fit method of arity 1 (unsupervised transformation)
--> 571             return self.fit(X, **fit_params).transform(X)
    572         else:
    573             # fit method of arity 2 (supervised transformation)

~\Anaconda3\lib\site-packages\gtda\diagrams\representations.py in transform(self, X, y)
    591             heats)(_subdiagrams(X, [dim], remove_dim=True)[s],
    592                    self._samplings[dim], self._step_size[dim], self.sigma)
--> 593             for dim in self.homology_dimensions_
    594             for s in gen_even_slices(X.shape[0],
    595                                      effective_n_jobs(self.n_jobs)))

~\Anaconda3\lib\site-packages\joblib\parallel.py in __call__(self, iterable)
    932 
    933             with self._backend.retrieval_context():
--> 934                 self.retrieve()
    935             # Make sure that we get a last message telling us we are done
    936             elapsed_time = time.time() - self._start_time

~\Anaconda3\lib\site-packages\joblib\parallel.py in retrieve(self)
    831             try:
    832                 if getattr(self._backend, 'supports_timeout', False):
--> 833                     self._output.extend(job.get(timeout=self.timeout))
    834                 else:
    835                     self._output.extend(job.get())

~\Anaconda3\lib\site-packages\joblib\_parallel_backends.py in wrap_future_result(future, timeout)
    519         AsyncResults.get from multiprocessing."""
    520         try:
--> 521             return future.result(timeout=timeout)
    522         except LokyTimeoutError:
    523             raise TimeoutError()

~\Anaconda3\lib\concurrent\futures\_base.py in result(self, timeout)
    430                 raise CancelledError()
    431             elif self._state == FINISHED:
--> 432                 return self.__get_result()
    433             else:
    434                 raise TimeoutError()

~\Anaconda3\lib\concurrent\futures\_base.py in __get_result(self)
    382     def __get_result(self):
    383         if self._exception:
--> 384             raise self._exception
    385         else:
    386             return self._result

ValueError: assignment destination is read-only

# Fixed code
def plot_diagram(diagram, homology_dimensions=None, **input_layout):
    """Plot a single persistence diagram.

    Parameters
    ----------
    diagram : ndarray of shape (n_points, 3)
        The persistence diagram to plot, where the third dimension along axis 1
        contains homology dimensions, and the first two contain (birth, death)
        pairs to be used as coordinates in the two-dimensional plot.

    homology_dimensions : list of int or None, optional, default: ``None``
        Homology dimensions which will appear on the plot. If ``None``, all
        homology dimensions which appear in `diagram` will be plotted.

    """

    # TODO: increase the marker size
    if homology_dimensions is None:
        homology_dimensions = np.unique(diagram[:, 2])

    max_filt_param = np.where(np.isinf(diagram), -np.inf, diagram).max()

    layout = dict(
        width=500,
        height=500,
        xaxis1=dict(
            title="Birth",
            side="bottom",
            type="linear",
            range=[0, 1.1 * max_filt_param],
            ticks="outside",
            anchor="y1",
            showline=True,
            zeroline=True,
            showexponent="all",
            exponentformat="e",
        ),
        yaxis1=dict(
            title="Death",
            side="left",
            type="linear",
            range=[0, 1.1 * max_filt_param],
            ticks="outside",
            anchor="x1",
            showline=True,
            zeroline=True,
            showexponent="all",
            exponentformat="e",
        ),
        plot_bgcolor="white",
    )

    layout.update(input_layout)

    fig = gobj.Figure(layout=layout)
    fig.update_xaxes(zeroline=True, linewidth=1, linecolor="black", mirror=False)
    fig.update_yaxes(zeroline=True, linewidth=1, linecolor="black", mirror=False)

    fig.add_trace(
        gobj.Scatter(
            x=np.array([-100 * max_filt_param, 100 * max_filt_param]),
            y=np.array([-100 * max_filt_param, 100 * max_filt_param]),
            mode="lines",
            line=dict(dash="dash", width=1, color="black"),
            showlegend=False,
            hoverinfo="none",
        )
    )

    for dim in homology_dimensions:
        name = f"H{int(dim)}" if dim != np.inf else "Any homology dimension"
        subdiagram = diagram[diagram[:, 2] == dim]
        diff = subdiagram[:, 1] != subdiagram[:, 0]
        subdiagram = subdiagram[diff]
        fig.add_trace(
            gobj.Scatter(
                x=subdiagram[:, 0], y=subdiagram[:, 1], mode="markers", name=name
            )
        )

    fig.show()