prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  vispy.plot.image fails on float64 textures
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `vispy/visuals/image.py`
  Content:
  ```
  1 # -*- coding: utf-8 -*-
  2 # Copyright (c) 2014, Vispy Development Team.
  3 # Distributed under the (new) BSD License. See LICENSE.txt for more info.
  4 
  5 from __future__ import division
  6 
  7 import numpy as np
  8 
  9 from .. import gloo
  10 from .transforms import STTransform, NullTransform
  11 from .modular_mesh import ModularMesh
  12 from .components import (TextureComponent, VertexTextureCoordinateComponent,
  13                          TextureCoordinateComponent)
  14 
  15 
  16 class ImageVisual(ModularMesh):
  17     """Visual subclass displaying an image.
  18 
  19     Parameters
  20     ----------
  21     data : (height, width, 4) ubyte array
  22         ImageVisual data.
  23     method : str
  24         Selects method of rendering image in case of non-linear transforms.
  25         Each method produces similar results, but may trade efficiency
  26         and accuracy. If the transform is linear, this parameter is ignored
  27         and a single quad is drawn around the area of the image.
  28 
  29             * 'subdivide': ImageVisual is represented as a grid of triangles
  30               with texture coordinates linearly mapped.
  31             * 'impostor': ImageVisual is represented as a quad covering the 
  32               entire view, with texture coordinates determined by the 
  33               transform. This produces the best transformation results, but may
  34               be slow.
  35 
  36     grid: tuple (rows, cols)
  37         If method='subdivide', this tuple determines the number of rows and
  38         columns in the image grid.
  39     """
  40     def __init__(self, data, method='subdivide', grid=(10, 10), **kwargs):
  41         super(ImageVisual, self).__init__(**kwargs)
  42 
  43         self._data = None
  44 
  45         # maps from quad coordinates to texture coordinates
  46         self._tex_transform = STTransform()
  47 
  48         self._texture = None
  49         self._interpolation = 'nearest'
  50         self.set_data(data)
  51         self.set_gl_options(cull_face=('front_and_back',))
  52 
  53         self.method = method
  54         self.grid = grid
  55 
  56     def set_data(self, image=None, **kwds):
  57         if image is not None:
  58             self._data = image
  59             self._texture = None
  60         super(ImageVisual, self).set_data(**kwds)
  61 
  62     @property
  63     def interpolation(self):
  64         return self._interpolation
  65 
  66     @interpolation.setter
  67     def interpolation(self, interp):
  68         self._interpolation = interp
  69         self.update()
  70 
  71     @property
  72     def size(self):
  73         return self._data.shape[:2][::-1]
  74 
  75     def _build_data(self, transforms):
  76         # Construct complete data array with position and optionally color
  77         if transforms.get_full_transform().Linear:
  78             method = 'subdivide'
  79             grid = (1, 1)
  80         else:
  81             method = self.method
  82             grid = self.grid
  83 
  84         # TODO: subdivision and impostor modes should be handled by new
  85         # components?
  86         if method == 'subdivide':
  87             # quads cover area of image as closely as possible
  88             w = 1.0 / grid[1]
  89             h = 1.0 / grid[0]
  90 
  91             quad = np.array([[0, 0, 0], [w, 0, 0], [w, h, 0],
  92                              [0, 0, 0], [w, h, 0], [0, h, 0]],
  93                             dtype=np.float32)
  94             quads = np.empty((grid[1], grid[0], 6, 3), dtype=np.float32)
  95             quads[:] = quad
  96 
  97             mgrid = np.mgrid[0.:grid[1], 0.:grid[0]].transpose(1, 2, 0)
  98             mgrid = mgrid[:, :, np.newaxis, :]
  99             mgrid[..., 0] *= w
  100             mgrid[..., 1] *= h
  101 
  102             quads[..., :2] += mgrid
  103             tex_coords = quads.reshape(grid[1]*grid[0]*6, 3)
  104             vertices = tex_coords.copy()
  105             vertices[..., 0] *= self._data.shape[1]
  106             vertices[..., 1] *= self._data.shape[0]
  107             ModularMesh.set_data(self, pos=vertices)
  108             coords = np.ascontiguousarray(tex_coords[:, :2])
  109             tex_coord_comp = TextureCoordinateComponent(coords)
  110         elif method == 'impostor':
  111             # quad covers entire view; frag. shader will deal with image shape
  112             quad = np.array([[-1, -1, 0], [1, -1, 0], [1, 1, 0],
  113                              [-1, -1, 0], [1, 1, 0], [-1, 1, 0]],
  114                             dtype=np.float32)
  115             ModularMesh.set_data(self, pos=quad)
  116 
  117             self._tex_transform.scale = (1./self._data.shape[0],
  118                                          1./self._data.shape[1])
  119             ctr = transforms.get_full_transform().inverse
  120             total_transform = self._tex_transform * ctr
  121             tex_coord_comp = VertexTextureCoordinateComponent(total_transform)
  122             tr = NullTransform()
  123             self._program.vert['map_local_to_nd'] = tr
  124         else:
  125             raise ValueError("Unknown image draw method '%s'" % method)
  126 
  127         data = self._data
  128         self._texture = gloo.Texture2D(data)
  129         self._texture.interpolation = self._interpolation
  130 
  131         self.color_components = [TextureComponent(self._texture,
  132                                                   tex_coord_comp)]
  133 
  134     def _activate_transform(self, transforms=None):
  135         # this is handled in _build_data instead.
  136         pass
  137 
  138     def bounds(self, mode, axis):
  139         if axis > 1:
  140             return (0, 0)
  141         else:
  142             return (0, self.size[axis])
  143 
  144     def draw(self, transforms):
  145         if self._data is None:
  146             return
  147 
  148         if transforms.get_full_transform().Linear:
  149             method = 'subdivide'
  150         else:
  151             method = self.method
  152 
  153         # always have to rebuild for impostor, only first for subdivide
  154         if self._texture is None:
  155             self._build_data(transforms)
  156         if method == 'subdivide':
  157             tr = transforms.get_full_transform()
  158             self._program.vert['map_local_to_nd'] = tr
  159 
  160         super(ImageVisual, self).draw(transforms)
  161
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/vispy/visuals/image.py b/vispy/visuals/image.py
  --- a/vispy/visuals/image.py
  +++ b/vispy/visuals/image.py
  @@ -28,8 +28,8 @@
   
               * 'subdivide': ImageVisual is represented as a grid of triangles
                 with texture coordinates linearly mapped.
  -            * 'impostor': ImageVisual is represented as a quad covering the 
  -              entire view, with texture coordinates determined by the 
  +            * 'impostor': ImageVisual is represented as a quad covering the
  +              entire view, with texture coordinates determined by the
                 transform. This produces the best transformation results, but may
                 be slow.
   
  @@ -55,6 +55,9 @@
   
       def set_data(self, image=None, **kwds):
           if image is not None:
  +            image = np.array(image, copy=False)
  +            if image.dtype == np.float64:
  +                image = image.astype(np.float32)
               self._data = image
               self._texture = None
           super(ImageVisual, self).set_data(**kwds)
  
verification_info: {"golden_diff": "diff --git a/vispy/visuals/image.py b/vispy/visuals/image.py\n--- a/vispy/visuals/image.py\n+++ b/vispy/visuals/image.py\n@@ -28,8 +28,8 @@\n \n             * 'subdivide': ImageVisual is represented as a grid of triangles\n               with texture coordinates linearly mapped.\n-            * 'impostor': ImageVisual is represented as a quad covering the \n-              entire view, with texture coordinates determined by the \n+            * 'impostor': ImageVisual is represented as a quad covering the\n+              entire view, with texture coordinates determined by the\n               transform. This produces the best transformation results, but may\n               be slow.\n \n@@ -55,6 +55,9 @@\n \n     def set_data(self, image=None, **kwds):\n         if image is not None:\n+            image = np.array(image, copy=False)\n+            if image.dtype == np.float64:\n+                image = image.astype(np.float32)\n             self._data = image\n             self._texture = None\n         super(ImageVisual, self).set_data(**kwds)\n", "issue": "vispy.plot.image fails on float64 textures\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2014, Vispy Development Team.\n# Distributed under the (new) BSD License. See LICENSE.txt for more info.\n\nfrom __future__ import division\n\nimport numpy as np\n\nfrom .. import gloo\nfrom .transforms import STTransform, NullTransform\nfrom .modular_mesh import ModularMesh\nfrom .components import (TextureComponent, VertexTextureCoordinateComponent,\n                         TextureCoordinateComponent)\n\n\nclass ImageVisual(ModularMesh):\n    \"\"\"Visual subclass displaying an image.\n\n    Parameters\n    ----------\n    data : (height, width, 4) ubyte array\n        ImageVisual data.\n    method : str\n        Selects method of rendering image in case of non-linear transforms.\n        Each method produces similar results, but may trade efficiency\n        and accuracy. If the transform is linear, this parameter is ignored\n        and a single quad is drawn around the area of the image.\n\n            * 'subdivide': ImageVisual is represented as a grid of triangles\n              with texture coordinates linearly mapped.\n            * 'impostor': ImageVisual is represented as a quad covering the \n              entire view, with texture coordinates determined by the \n              transform. This produces the best transformation results, but may\n              be slow.\n\n    grid: tuple (rows, cols)\n        If method='subdivide', this tuple determines the number of rows and\n        columns in the image grid.\n    \"\"\"\n    def __init__(self, data, method='subdivide', grid=(10, 10), **kwargs):\n        super(ImageVisual, self).__init__(**kwargs)\n\n        self._data = None\n\n        # maps from quad coordinates to texture coordinates\n        self._tex_transform = STTransform()\n\n        self._texture = None\n        self._interpolation = 'nearest'\n        self.set_data(data)\n        self.set_gl_options(cull_face=('front_and_back',))\n\n        self.method = method\n        self.grid = grid\n\n    def set_data(self, image=None, **kwds):\n        if image is not None:\n            self._data = image\n            self._texture = None\n        super(ImageVisual, self).set_data(**kwds)\n\n    @property\n    def interpolation(self):\n        return self._interpolation\n\n    @interpolation.setter\n    def interpolation(self, interp):\n        self._interpolation = interp\n        self.update()\n\n    @property\n    def size(self):\n        return self._data.shape[:2][::-1]\n\n    def _build_data(self, transforms):\n        # Construct complete data array with position and optionally color\n        if transforms.get_full_transform().Linear:\n            method = 'subdivide'\n            grid = (1, 1)\n        else:\n            method = self.method\n            grid = self.grid\n\n        # TODO: subdivision and impostor modes should be handled by new\n        # components?\n        if method == 'subdivide':\n            # quads cover area of image as closely as possible\n            w = 1.0 / grid[1]\n            h = 1.0 / grid[0]\n\n            quad = np.array([[0, 0, 0], [w, 0, 0], [w, h, 0],\n                             [0, 0, 0], [w, h, 0], [0, h, 0]],\n                            dtype=np.float32)\n            quads = np.empty((grid[1], grid[0], 6, 3), dtype=np.float32)\n            quads[:] = quad\n\n            mgrid = np.mgrid[0.:grid[1], 0.:grid[0]].transpose(1, 2, 0)\n            mgrid = mgrid[:, :, np.newaxis, :]\n            mgrid[..., 0] *= w\n            mgrid[..., 1] *= h\n\n            quads[..., :2] += mgrid\n            tex_coords = quads.reshape(grid[1]*grid[0]*6, 3)\n            vertices = tex_coords.copy()\n            vertices[..., 0] *= self._data.shape[1]\n            vertices[..., 1] *= self._data.shape[0]\n            ModularMesh.set_data(self, pos=vertices)\n            coords = np.ascontiguousarray(tex_coords[:, :2])\n            tex_coord_comp = TextureCoordinateComponent(coords)\n        elif method == 'impostor':\n            # quad covers entire view; frag. shader will deal with image shape\n            quad = np.array([[-1, -1, 0], [1, -1, 0], [1, 1, 0],\n                             [-1, -1, 0], [1, 1, 0], [-1, 1, 0]],\n                            dtype=np.float32)\n            ModularMesh.set_data(self, pos=quad)\n\n            self._tex_transform.scale = (1./self._data.shape[0],\n                                         1./self._data.shape[1])\n            ctr = transforms.get_full_transform().inverse\n            total_transform = self._tex_transform * ctr\n            tex_coord_comp = VertexTextureCoordinateComponent(total_transform)\n            tr = NullTransform()\n            self._program.vert['map_local_to_nd'] = tr\n        else:\n            raise ValueError(\"Unknown image draw method '%s'\" % method)\n\n        data = self._data\n        self._texture = gloo.Texture2D(data)\n        self._texture.interpolation = self._interpolation\n\n        self.color_components = [TextureComponent(self._texture,\n                                                  tex_coord_comp)]\n\n    def _activate_transform(self, transforms=None):\n        # this is handled in _build_data instead.\n        pass\n\n    def bounds(self, mode, axis):\n        if axis > 1:\n            return (0, 0)\n        else:\n            return (0, self.size[axis])\n\n    def draw(self, transforms):\n        if self._data is None:\n            return\n\n        if transforms.get_full_transform().Linear:\n            method = 'subdivide'\n        else:\n            method = self.method\n\n        # always have to rebuild for impostor, only first for subdivide\n        if self._texture is None:\n            self._build_data(transforms)\n        if method == 'subdivide':\n            tr = transforms.get_full_transform()\n            self._program.vert['map_local_to_nd'] = tr\n\n        super(ImageVisual, self).draw(transforms)\n", "path": "vispy/visuals/image.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2014, Vispy Development Team.\n# Distributed under the (new) BSD License. See LICENSE.txt for more info.\n\nfrom __future__ import division\n\nimport numpy as np\n\nfrom .. import gloo\nfrom .transforms import STTransform, NullTransform\nfrom .modular_mesh import ModularMesh\nfrom .components import (TextureComponent, VertexTextureCoordinateComponent,\n                         TextureCoordinateComponent)\n\n\nclass ImageVisual(ModularMesh):\n    \"\"\"Visual subclass displaying an image.\n\n    Parameters\n    ----------\n    data : (height, width, 4) ubyte array\n        ImageVisual data.\n    method : str\n        Selects method of rendering image in case of non-linear transforms.\n        Each method produces similar results, but may trade efficiency\n        and accuracy. If the transform is linear, this parameter is ignored\n        and a single quad is drawn around the area of the image.\n\n            * 'subdivide': ImageVisual is represented as a grid of triangles\n              with texture coordinates linearly mapped.\n            * 'impostor': ImageVisual is represented as a quad covering the\n              entire view, with texture coordinates determined by the\n              transform. This produces the best transformation results, but may\n              be slow.\n\n    grid: tuple (rows, cols)\n        If method='subdivide', this tuple determines the number of rows and\n        columns in the image grid.\n    \"\"\"\n    def __init__(self, data, method='subdivide', grid=(10, 10), **kwargs):\n        super(ImageVisual, self).__init__(**kwargs)\n\n        self._data = None\n\n        # maps from quad coordinates to texture coordinates\n        self._tex_transform = STTransform()\n\n        self._texture = None\n        self._interpolation = 'nearest'\n        self.set_data(data)\n        self.set_gl_options(cull_face=('front_and_back',))\n\n        self.method = method\n        self.grid = grid\n\n    def set_data(self, image=None, **kwds):\n        if image is not None:\n            image = np.array(image, copy=False)\n            if image.dtype == np.float64:\n                image = image.astype(np.float32)\n            self._data = image\n            self._texture = None\n        super(ImageVisual, self).set_data(**kwds)\n\n    @property\n    def interpolation(self):\n        return self._interpolation\n\n    @interpolation.setter\n    def interpolation(self, interp):\n        self._interpolation = interp\n        self.update()\n\n    @property\n    def size(self):\n        return self._data.shape[:2][::-1]\n\n    def _build_data(self, transforms):\n        # Construct complete data array with position and optionally color\n        if transforms.get_full_transform().Linear:\n            method = 'subdivide'\n            grid = (1, 1)\n        else:\n            method = self.method\n            grid = self.grid\n\n        # TODO: subdivision and impostor modes should be handled by new\n        # components?\n        if method == 'subdivide':\n            # quads cover area of image as closely as possible\n            w = 1.0 / grid[1]\n            h = 1.0 / grid[0]\n\n            quad = np.array([[0, 0, 0], [w, 0, 0], [w, h, 0],\n                             [0, 0, 0], [w, h, 0], [0, h, 0]],\n                            dtype=np.float32)\n            quads = np.empty((grid[1], grid[0], 6, 3), dtype=np.float32)\n            quads[:] = quad\n\n            mgrid = np.mgrid[0.:grid[1], 0.:grid[0]].transpose(1, 2, 0)\n            mgrid = mgrid[:, :, np.newaxis, :]\n            mgrid[..., 0] *= w\n            mgrid[..., 1] *= h\n\n            quads[..., :2] += mgrid\n            tex_coords = quads.reshape(grid[1]*grid[0]*6, 3)\n            vertices = tex_coords.copy()\n            vertices[..., 0] *= self._data.shape[1]\n            vertices[..., 1] *= self._data.shape[0]\n            ModularMesh.set_data(self, pos=vertices)\n            coords = np.ascontiguousarray(tex_coords[:, :2])\n            tex_coord_comp = TextureCoordinateComponent(coords)\n        elif method == 'impostor':\n            # quad covers entire view; frag. shader will deal with image shape\n            quad = np.array([[-1, -1, 0], [1, -1, 0], [1, 1, 0],\n                             [-1, -1, 0], [1, 1, 0], [-1, 1, 0]],\n                            dtype=np.float32)\n            ModularMesh.set_data(self, pos=quad)\n\n            self._tex_transform.scale = (1./self._data.shape[0],\n                                         1./self._data.shape[1])\n            ctr = transforms.get_full_transform().inverse\n            total_transform = self._tex_transform * ctr\n            tex_coord_comp = VertexTextureCoordinateComponent(total_transform)\n            tr = NullTransform()\n            self._program.vert['map_local_to_nd'] = tr\n        else:\n            raise ValueError(\"Unknown image draw method '%s'\" % method)\n\n        data = self._data\n        self._texture = gloo.Texture2D(data)\n        self._texture.interpolation = self._interpolation\n\n        self.color_components = [TextureComponent(self._texture,\n                                                  tex_coord_comp)]\n\n    def _activate_transform(self, transforms=None):\n        # this is handled in _build_data instead.\n        pass\n\n    def bounds(self, mode, axis):\n        if axis > 1:\n            return (0, 0)\n        else:\n            return (0, self.size[axis])\n\n    def draw(self, transforms):\n        if self._data is None:\n            return\n\n        if transforms.get_full_transform().Linear:\n            method = 'subdivide'\n        else:\n            method = self.method\n\n        # always have to rebuild for impostor, only first for subdivide\n        if self._texture is None:\n            self._build_data(transforms)\n        if method == 'subdivide':\n            tr = transforms.get_full_transform()\n            self._program.vert['map_local_to_nd'] = tr\n\n        super(ImageVisual, self).draw(transforms)\n", "path": "vispy/visuals/image.py"}]}