mantidproject / mantid

Main repository for Mantid code
https://www.mantidproject.org
GNU General Public License v3.0
211 stars 124 forks source link

Bug in autoscale color axis for nonortho view of MDHistoWorkspaces in sliceviewer #33409

Closed RichardWaiteSTFC closed 2 years ago

RichardWaiteSTFC commented 2 years ago

Describe the bug Color axis autoscaling is not working for MDHisto workspaces in nonorthog view in sliceviewer.

Fix for MDEvent workspaces for the 6.3 release was done in #33397, but MDHisto workspaces need to have the color limits determined from the data within the axes extents - see that PR for more info.

To Reproduce Follow the instructions in #33397 - steps 6-7 demonstrates the bug for MDHisto

Expected behavior Autoscaling would work for MDHisto in nonrothog view

RichardWaiteSTFC commented 2 years ago

To avoid duplicating pcolormesh could just add add get_array_clipped_to_bounds as a method QuadMesh like so using setattr

class A:
    def __init__(self, aval):
        self.aval = aval

    def get_aval(self):
        return self.aval

class AA(A): pass

def addmethod(obj, name, func):
    cls = obj.__class__
    # subclass = type(cls.__name__, (cls,), {})  # doesn't change the name
    subclass = type("AA", (cls,), {})
    setattr(subclass, name, func)
    obj.__class__ = subclass

def double_aval(self):
    self.aval *=2
    return self.get_aval()

a = A(1)
print(type(a), a.get_aval())    # <class 'mantidqt.widgets.codeeditor.execution.A'> 1
addmethod(a, "double_aval", double_aval)
print(type(a), a.double_aval()) # <class 'mantidqt.widgets.codeeditor.execution.AA'> 2

But then there is no class def really for the AA class...

RichardWaiteSTFC commented 2 years ago

Or can do this

class QuadMeshMtd(QuadMesh):
    def __init__(self, quad_mesh_to_copy):
        super().__init__(1, 1, np.zeros((2, 2, 2)))  # blank
        self.__dict__ = quad_mesh_to_copy.__dict__.copy()

    def get_array_clipped_to_bound():
        return "pink"

x = np.linspace(-1.5, 1.5, 12)
y = np.linspace(-1.5, 1.5, 24)
xx, yy = np.meshgrid(x, y)

fig, axs = plt.subplots()
mesh = axs.pcolormesh(xx, yy, xx**2 + 4*yy**2, shading='gouraud')
fig.show()

meshMtd = QuadMeshMtd(mesh)
DavidFair commented 2 years ago

Me and Richard discussing (Ab)using Python duck typing / a decorator pattern to avoid copying dict. We don't directly instantiate a QuadMesh so we must wrap the instance instead

from unittest import mock

class QuadMesh:
    def __init__(self):
        self.foo = False

    def get_x_array(self):
        return 1

class Wrapper:
    def __init__(self, wrapped: QuadMesh):
        self._wrapped = wrapped

    def __getattr__(self, item):
        return getattr(self._wrapped, item)

    def get_array(self):
        return 2 + self._wrapped.get_x_array()

    def not_in_parent(self):
        return False

instance = Wrapper(QuadMesh())
print(instance.get_array())
print(instance.not_in_parent())

mocked = mock.create_autospec(instance)
print(mocked.get_array())
mocked.bar()