Canonicalize takes an array of values as input and reorients
        and transposes it to match the canonical format expected by
        plotting functions. In certain cases the dimensions defined
        via the kdims of an Element may not match the dimensions of
        the underlying data. A set of data_coords may be passed in to
        define the dimensionality of the data, which can then be used
        to np.squeeze the data to remove any constant dimensions. If
        the data is also irregular, i.e. contains multi-dimensional
        coordinates, a set of virtual_coords can be supplied, required
        by some interfaces (e.g. xarray) to index irregular datasets
        with a virtual integer index. This ensures these coordinates
        are not simply dropped.

def canonicalize(cls, dataset, data, data_coords=None, virtual_coords=[]):
        """
        Canonicalize takes an array of values as input and reorients
        and transposes it to match the canonical format expected by
        plotting functions. In certain cases the dimensions defined
        via the kdims of an Element may not match the dimensions of
        the underlying data. A set of data_coords may be passed in to
        define the dimensionality of the data, which can then be used
        to np.squeeze the data to remove any constant dimensions. If
        the data is also irregular, i.e. contains multi-dimensional
        coordinates, a set of virtual_coords can be supplied, required
        by some interfaces (e.g. xarray) to index irregular datasets
        with a virtual integer index. This ensures these coordinates
        are not simply dropped.
        """
        if data_coords is None:
            data_coords = dataset.dimensions('key', label='name')[::-1]

        # Transpose data
        dims = [name for name in data_coords
                if isinstance(cls.coords(dataset, name), get_array_types())]
        dropped = [dims.index(d) for d in dims
                   if d not in dataset.kdims+virtual_coords]
        if dropped:
            data = np.squeeze(data, axis=tuple(dropped))

        if not any(cls.irregular(dataset, d) for d in dataset.kdims):
            inds = [dims.index(kd.name) for kd in dataset.kdims]
            inds = [i - sum([1 for d in dropped if i>=d]) for i in inds]
            if inds:
                data = data.transpose(inds[::-1])

        # Reorient data
        invert = False
        slices = []
        for d in dataset.kdims[::-1]:
            coords = cls.coords(dataset, d)
            if np.all(coords[1:] < coords[:-1]) and not coords.ndim > 1:
                slices.append(slice(None, None, -1))
                invert = True
            else:
                slices.append(slice(None))
        data = data[tuple(slices)] if invert else data

        # Allow lower dimensional views into data
        if len(dataset.kdims) < 2:
            data = data.flatten()
        return data