1010from .norm import Normalizer
1111from .utils import find_limits , fix_empty_range
1212
13- SHADER_LIBRARY = {
13+ # Custom vertex shader for variable size and color
14+ VERTEX_SHADER = """
15+ attribute float size;
16+ attribute vec3 customColor;
17+ varying vec3 vColor;
18+
19+ void main() {
20+ vColor = customColor;
21+ vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
22+ gl_PointSize = size;
23+ gl_Position = projectionMatrix * mvPosition;
24+ }
25+ """
26+
27+ # Custom fragment shaders for different markers
28+ FRAGMENT_SHADERS = {
1429 "o" : """
1530varying vec3 vColor;
1631
@@ -62,29 +77,31 @@ def __init__(
6277 zorder = 0 ,
6378 cmap = "viridis" ,
6479 norm : str = "linear" ,
80+ xscale = "linear" ,
81+ yscale = "linear" ,
6582 ) -> None :
6683 self .axes = None
6784 self ._x = np .asarray (x )
6885 self ._y = np .asarray (y )
69- self ._xscale = "linear"
70- self ._yscale = "linear"
86+ self ._xscale = xscale
87+ self ._yscale = yscale
7188 self ._zorder = zorder
7289
90+ self ._geometry = p3 .BufferGeometry (
91+ attributes = {"position" : p3 .BufferAttribute (array = self ._make_positions ())}
92+ )
93+
7394 if not isinstance (c , str ) or not np .isscalar (s ) or marker != "s" :
7495 if isinstance (c , str ):
7596 self ._c = np .ones_like (self ._x )
7697 self ._norm = Normalizer (vmin = 1 , vmax = 1 )
7798 self ._cmap = cm .LinearSegmentedColormap .from_list ("tmp" , [c , c ])
78- # (
79- # np.ones_like(self._x)
80- # )
8199 else :
82100 self ._c = np .asarray (c )
83101 self ._norm = Normalizer (
84102 vmin = np .min (self ._c ), vmax = np .max (self ._c ), norm = norm
85103 )
86104 self ._cmap = mpl .colormaps [cmap ].copy ()
87- # rgba = self.cmap(self.norm(self._c))
88105
89106 colors = self ._make_colors ()
90107
@@ -93,103 +110,77 @@ def __init__(
93110 else :
94111 sizes = np .asarray (s , dtype = np .float32 )
95112
96- # Custom vertex shader for variable size and color
97- vertex_shader = """
98- attribute float size;
99- attribute vec3 customColor;
100- varying vec3 vColor;
101-
102- void main() {
103- vColor = customColor;
104- vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
105- gl_PointSize = size;
106- gl_Position = projectionMatrix * mvPosition;
107- }
108- """
109-
110- self ._geometry = p3 .BufferGeometry (
111- attributes = {
112- "position" : p3 .BufferAttribute (
113- array = np .array (
114- [self ._x , self ._y , np .full_like (self ._x , self ._zorder )],
115- dtype = "float32" ,
116- ).T
117- ),
113+ self ._geometry .attributes .update (
114+ {
118115 "customColor" : p3 .BufferAttribute (array = colors ),
119116 "size" : p3 .BufferAttribute (array = sizes ),
120117 }
121118 )
122119 # Create ShaderMaterial with custom shaders
123120 self ._material = p3 .ShaderMaterial (
124- vertexShader = vertex_shader ,
125- fragmentShader = SHADER_LIBRARY [marker ],
121+ vertexShader = VERTEX_SHADER ,
122+ fragmentShader = FRAGMENT_SHADERS [marker ],
126123 transparent = True ,
127124 )
128125 else :
129- self ._geometry = p3 .BufferGeometry (
130- attributes = {
131- "position" : p3 .BufferAttribute (
132- array = np .array (
133- [self ._x , self ._y , np .full_like (self ._x , self ._zorder )],
134- dtype = "float32" ,
135- ).T
136- ),
137- }
138- )
139-
140126 self ._material = p3 .PointsMaterial (color = cm .to_hex (c ), size = s )
141127
142128 self ._points = p3 .Points (geometry = self ._geometry , material = self ._material )
143129
130+ def _make_positions (self ) -> np .ndarray :
131+ with warnings .catch_warnings (category = RuntimeWarning , action = "ignore" ):
132+ xx = self ._x if self ._xscale == "linear" else np .log10 (self ._x )
133+ yy = self ._y if self ._yscale == "linear" else np .log10 (self ._y )
134+ return np .array ([xx , yy , np .full_like (xx , self ._zorder )], dtype = "float32" ).T
135+
144136 def _make_colors (self ) -> np .ndarray :
145137 return self ._cmap (self .norm (self ._c ))[..., :3 ].astype ("float32" )
146138
147139 def _update_colors (self ) -> None :
148140 self ._geometry .attributes ["customColor" ].array = self ._make_colors ()
149141
142+ def _update_positions (self ):
143+ self ._geometry .attributes ["position" ].array = self ._make_positions ()
144+
150145 def get_bbox (self ):
151146 pad = 0.03
152147 left , right = fix_empty_range (find_limits (self ._x , scale = self ._xscale , pad = pad ))
153148 bottom , top = fix_empty_range (find_limits (self ._y , scale = self ._yscale , pad = pad ))
154149 return {"left" : left , "right" : right , "bottom" : bottom , "top" : top }
155150
156- def _update (self ):
157- with warnings .catch_warnings (category = RuntimeWarning , action = "ignore" ):
158- xx = self ._x if self ._xscale == "linear" else np .log10 (self ._x )
159- yy = self ._y if self ._yscale == "linear" else np .log10 (self ._y )
160- self ._geometry .attributes ["position" ].array = np .array (
161- [xx , yy , np .full_like (xx , self ._zorder )], dtype = "float32"
162- ).T
163-
164- def get (self ):
151+ def _as_object3d (self ) -> p3 .Object3D :
165152 return self ._points
166153
167154 def get_xdata (self ) -> np .ndarray :
168155 return self ._x
169156
170157 def set_xdata (self , x ):
171158 self ._x = np .asarray (x )
172- self ._update ()
159+ self ._update_positions ()
173160
174161 def get_ydata (self ) -> np .ndarray :
175162 return self ._y
176163
177164 def set_ydata (self , y ):
178165 self ._y = np .asarray (y )
179- self ._update ()
166+ self ._update_positions ()
180167
181168 def set_data (self , xy ):
182169 self ._x = np .asarray (xy [:, 0 ])
183170 self ._y = np .asarray (xy [:, 1 ])
184- self ._update ()
171+ self ._update_positions ()
185172
186173 def _set_xscale (self , scale ):
187174 self ._xscale = scale
188- self ._update ()
175+ self ._update_positions ()
189176
190177 def _set_yscale (self , scale ):
191178 self ._yscale = scale
192- self ._update ()
179+ self ._update_positions ()
180+
181+ def set_array (self , c : np .ndarray ):
182+ self ._c = np .asarray (c )
183+ self ._update_colors ()
193184
194185 def set_cmap (self , cmap : str ) -> None :
195186 self ._cmap = mpl .colormaps [cmap ].copy ()
0 commit comments