jfoster17 / glue-jupyter Goto Github PK
View Code? Open in Web Editor NEWThis project forked from glue-viz/glue-jupyter
Glue front-end for the Jupyter ecosystem
Home Page: https://glue-jupyter.readthedocs.io/en/latest/
License: Other
This project forked from glue-viz/glue-jupyter
Glue front-end for the Jupyter ecosystem
Home Page: https://glue-jupyter.readthedocs.io/en/latest/
License: Other
Currently this Tool only works on the lowest (glue) layer on a map. In theory, we probably want it to work on the top-most layer of type "region" -- the user is then responsible for making sure that the appropriate layer is available on top (we could provide some feedback on which layer is on top, which is especially important in the case where different region files cover substantially different portions of the earth).
If a rectangular region starts to cover too many (?) points, performance gets bad. This is because we apply the subset live as we drag the rectangle and this is slow. Notably, most other viewers don't enforce really live brushing, so we probably just drop this (although it is really useful feedback for regions where it is otherwise not clear what is going on).
I'm not sure how well GeoRegionData works with non-polygons. Specifically, we can probably make life simpler to turn GeoPandas objects composed only of points into simple table attributes. We should also consider what to do about lines.
Parts of this modification are easy to make as a generic glue plug-in, but how do we add the new commands to app.py?
A GeoRegionData object calculates centroids (really, representative points which are like centroids but guaranteed to be inside a region), stores them as centroid_component_ids, and uses these centroids to determine whether a region lies inside a ROI. The Map viewer defaults to place these centroids as lon_att and lat_att, but the GeoRegionData object plots just fine if the user changes these because it does not, in fact, rely on these attributes to plot the data.
We should either DISABLE the ability to change these attributes (a bit inconsistent with glue more broadly) OR make the viewer not display the GeoRegionData unless the centroid_component_ids are selected (and display a warning in this case).
Probably by doing something like this:
https://www.tutorialguruji.com/python/how-to-add-an-ipyleaflet-map-to-a-pyqt5-application/
Sometimes we get an IncompatibleAttribute
error from
return get_mask_with_key_joins(self, self._key_joins, subset_state, view=view)
as we are trying to do:
gdf = trans.to_object(self.layer)
`---------------------------------------------------------------------------
IncompatibleAttribute Traceback (most recent call last)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/data.py:1385, in Data.get_mask(self, subset_state, view)
1384 try:
-> 1385 return subset_state.to_mask(self, view=view)
1386 except IncompatibleAttribute:
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/subset.py:773, in RangeSubsetState.to_mask(self, data, view)
771 @contract(data='isinstance(Data)', view='array_view')
772 def to_mask(self, data, view=None):
--> 773 x = data[self.att, view]
774 result = (x >= self.lo) & (x <= self.hi)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/data.py:571, in BaseCartesianData.getitem(self, key)
569 raise IncompatibleAttribute(_k)
--> 571 return self.get_data(key, view=view)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/data.py:1361, in Data.get_data(self, cid, view)
1360 else:
-> 1361 raise IncompatibleAttribute(cid)
1363 if view is not None:
IncompatibleAttribute: state
During handling of the above exception, another exception occurred:
IncompatibleAttribute Traceback (most recent call last)
File ~/python-repos/glue-jupyter/glue_jupyter/bqplot/common/viewer.py:198, in BqplotBaseView.apply_roi(self, roi, use_current)
194 subset_state = self._roi_to_subset_state(roi)
195 cmd = ApplySubsetState(data_collection=self._data,
196 subset_state=subset_state,
197 override_mode=use_current)
--> 198 self._session.command_stack.do(cmd)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/command.py:125, in CommandStack.do(self, cmd)
123 logging.getLogger(name).debug("Do %s", cmd)
124 self._command_stack.append(cmd)
--> 125 result = cmd.do(self._session)
126 self._command_stack = self._command_stack[-MAX_UNDO:]
127 self._undo_stack = []
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/command.py:308, in ApplySubsetState.do(self, session)
305 if len(mode._edit_subset) == 0:
306 override_mode = ReplaceMode
--> 308 mode.update(self.data_collection, self.subset_state, override_mode=override_mode)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/edit_subset_mode.py:100, in EditSubsetMode.update(self, d, new_state, focus_data, override_mode)
97 logging.getLogger(name).debug("Update subset for %s", d)
99 if isinstance(d, (Data, DataCollection)):
--> 100 self._combine_data(new_state, override_mode=override_mode)
101 else:
102 raise TypeError("input must be a Data or DataCollection: %s" %
103 type(d))
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/edit_subset_mode.py:74, in EditSubsetMode._combine_data(self, new_state, override_mode)
72 subs = self._edit_subset
73 for s in as_list(subs):
---> 74 mode(s, new_state)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/edit_subset_mode.py:115, in ReplaceMode(edit_subset, new_state)
113 """ Replaces edit_subset.subset_state with new_state """
114 logging.getLogger(name).debug("Replace %s", edit_subset)
--> 115 edit_subset.subset_state = new_state.copy()
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/subset_group.py:177, in SubsetGroup.setattr(self, attr, value)
175 object.setattr(self, attr, value)
176 if attr in ['subset_state', 'label', 'style']:
--> 177 self.broadcast(attr)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/subset_group.py:168, in SubsetGroup.broadcast(self, item)
165 @contract(item='string')
166 def broadcast(self, item):
167 for s in self.subsets:
--> 168 s.broadcast(item)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/subset.py:215, in Subset.broadcast(self, attribute)
213 if self._broadcasting and self.data.hub:
214 msg = SubsetUpdateMessage(self, attribute=attribute)
--> 215 self.data.hub.broadcast(msg)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/hub.py:215, in Hub.broadcast(self, message)
213 logging.getLogger(name).info("Broadcasting %s", message)
214 for subscriber, handler in self._find_handlers(message):
--> 215 handler(message)
File ~/python-repos/glue-jupyter/glue_jupyter/view.py:146, in IPyWidgetView._update_subset(self, message)
144 pass
145 else:
--> 146 layer_artist.update()
147 self.redraw()
File ~/python-repos/glue-jupyter/glue_jupyter/ipyleaflet/map/layer_artist.py:238, in IPyLeafletMapLayerArtist.update(self)
236 """Req: Update appearance of the layer before redrawing. Called when a subset is changed."""
237 #print(f"Update called for {self}")
--> 238 self._on_attribute_change()
239 self.redraw()
File ~/python-repos/glue-jupyter/glue_jupyter/ipyleaflet/map/layer_artist.py:146, in IPyLeafletMapLayerArtist._on_attribute_change(self, value)
141 if self.state.layer_type == 'regions':
142
143 # XX TODO XX -- We need to verify that we should be plotting this
144 # i.e. that the lat/lon attributes are appropriately linked/set
145 trans = GeoPandasTranslator()
--> 146 gdf = trans.to_object(self.layer)
148 if isinstance(self.layer, Subset):
149 new_layer_artist = ipyleaflet.GeoJSON(data=json.loads(gdf.to_json()),
150 style={'fillOpacity': 0.5,
151 'dashArray': '0',
(...)
154 hover_style={'fillOpacity': 0.95},
155 )
File ~/python-repos/glue-jupyter/glue_jupyter/ipyleaflet/data.py:90, in GeoPandasTranslator.to_object(self, data_or_subset, attribute)
88 gdf[cid.label] = g
89 else:
---> 90 gdf[cid.label] = data_or_subset[cid]
91 gdf.set_geometry("geometry",inplace=True)
92 gdf.crs = crs
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/subset.py:288, in Subset.getitem(self, view)
283 """ Retrieve the elements from a data view within the subset
284
285 :param view: View of the data. See data.getitem for detils
286 """
287 c, v = split_component_view(view)
--> 288 ma = self.to_mask(v)
289 return self.data[view][ma]
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/subset.py:182, in Subset.to_mask(self, view)
169 @contract(view='array_view', returns='array')
170 def to_mask(self, view=None):
171 """
172 Convert the current subset to a mask.
173
(...)
180
181 """
--> 182 return self.data.get_mask(self.subset_state, view=view)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/data.py:1387, in Data.get_mask(self, subset_state, view)
1385 return subset_state.to_mask(self, view=view)
1386 except IncompatibleAttribute:
-> 1387 return get_mask_with_key_joins(self, self._key_joins, subset_state, view=view)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/joins.py:105, in get_mask_with_key_joins(data, key_joins, subset_state, view)
99 else:
101 raise Exception("Either the number of components in the key join sets "
102 "should match, or one of the component sets should ",
103 "contain a single component.")
--> 105 raise IncompatibleAttribute
IncompatibleAttribute Traceback (most recent call last)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/data.py:1385, in Data.get_mask(self, subset_state, view)
1384 try:
-> 1385 return subset_state.to_mask(self, view=view)
1386 except IncompatibleAttribute:
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/subset.py:773, in RangeSubsetState.to_mask(self, data, view)
771 @contract(data='isinstance(Data)', view='array_view')
772 def to_mask(self, data, view=None):
--> 773 x = data[self.att, view]
774 result = (x >= self.lo) & (x <= self.hi)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/data.py:571, in BaseCartesianData.getitem(self, key)
569 raise IncompatibleAttribute(_k)
--> 571 return self.get_data(key, view=view)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/data.py:1361, in Data.get_data(self, cid, view)
1360 else:
-> 1361 raise IncompatibleAttribute(cid)
1363 if view is not None:
IncompatibleAttribute: state
During handling of the above exception, another exception occurred:
IncompatibleAttribute Traceback (most recent call last)
File ~/python-repos/glue-jupyter/glue_jupyter/bqplot/common/viewer.py:198, in BqplotBaseView.apply_roi(self, roi, use_current)
194 subset_state = self._roi_to_subset_state(roi)
195 cmd = ApplySubsetState(data_collection=self._data,
196 subset_state=subset_state,
197 override_mode=use_current)
--> 198 self._session.command_stack.do(cmd)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/command.py:125, in CommandStack.do(self, cmd)
123 logging.getLogger(name).debug("Do %s", cmd)
124 self._command_stack.append(cmd)
--> 125 result = cmd.do(self._session)
126 self._command_stack = self._command_stack[-MAX_UNDO:]
127 self._undo_stack = []
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/command.py:308, in ApplySubsetState.do(self, session)
305 if len(mode._edit_subset) == 0:
306 override_mode = ReplaceMode
--> 308 mode.update(self.data_collection, self.subset_state, override_mode=override_mode)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/edit_subset_mode.py:100, in EditSubsetMode.update(self, d, new_state, focus_data, override_mode)
97 logging.getLogger(name).debug("Update subset for %s", d)
99 if isinstance(d, (Data, DataCollection)):
--> 100 self._combine_data(new_state, override_mode=override_mode)
101 else:
102 raise TypeError("input must be a Data or DataCollection: %s" %
103 type(d))
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/edit_subset_mode.py:74, in EditSubsetMode._combine_data(self, new_state, override_mode)
72 subs = self._edit_subset
73 for s in as_list(subs):
---> 74 mode(s, new_state)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/edit_subset_mode.py:115, in ReplaceMode(edit_subset, new_state)
113 """ Replaces edit_subset.subset_state with new_state """
114 logging.getLogger(name).debug("Replace %s", edit_subset)
--> 115 edit_subset.subset_state = new_state.copy()
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/subset_group.py:177, in SubsetGroup.setattr(self, attr, value)
175 object.setattr(self, attr, value)
176 if attr in ['subset_state', 'label', 'style']:
--> 177 self.broadcast(attr)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/subset_group.py:168, in SubsetGroup.broadcast(self, item)
165 @contract(item='string')
166 def broadcast(self, item):
167 for s in self.subsets:
--> 168 s.broadcast(item)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/subset.py:215, in Subset.broadcast(self, attribute)
213 if self._broadcasting and self.data.hub:
214 msg = SubsetUpdateMessage(self, attribute=attribute)
--> 215 self.data.hub.broadcast(msg)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/hub.py:215, in Hub.broadcast(self, message)
213 logging.getLogger(name).info("Broadcasting %s", message)
214 for subscriber, handler in self._find_handlers(message):
--> 215 handler(message)
File ~/python-repos/glue-jupyter/glue_jupyter/view.py:146, in IPyWidgetView._update_subset(self, message)
144 pass
145 else:
--> 146 layer_artist.update()
147 self.redraw()
File ~/python-repos/glue-jupyter/glue_jupyter/ipyleaflet/map/layer_artist.py:238, in IPyLeafletMapLayerArtist.update(self)
236 """Req: Update appearance of the layer before redrawing. Called when a subset is changed."""
237 #print(f"Update called for {self}")
--> 238 self._on_attribute_change()
239 self.redraw()
File ~/python-repos/glue-jupyter/glue_jupyter/ipyleaflet/map/layer_artist.py:146, in IPyLeafletMapLayerArtist._on_attribute_change(self, value)
141 if self.state.layer_type == 'regions':
142
143 # XX TODO XX -- We need to verify that we should be plotting this
144 # i.e. that the lat/lon attributes are appropriately linked/set
145 trans = GeoPandasTranslator()
--> 146 gdf = trans.to_object(self.layer)
148 if isinstance(self.layer, Subset):
149 new_layer_artist = ipyleaflet.GeoJSON(data=json.loads(gdf.to_json()),
150 style={'fillOpacity': 0.5,
151 'dashArray': '0',
(...)
154 hover_style={'fillOpacity': 0.95},
155 )
File ~/python-repos/glue-jupyter/glue_jupyter/ipyleaflet/data.py:90, in GeoPandasTranslator.to_object(self, data_or_subset, attribute)
88 gdf[cid.label] = g
89 else:
---> 90 gdf[cid.label] = data_or_subset[cid]
91 gdf.set_geometry("geometry",inplace=True)
92 gdf.crs = crs
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/subset.py:288, in Subset.getitem(self, view)
283 """ Retrieve the elements from a data view within the subset
284
285 :param view: View of the data. See data.getitem for detils
286 """
287 c, v = split_component_view(view)
--> 288 ma = self.to_mask(v)
289 return self.data[view][ma]
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/subset.py:182, in Subset.to_mask(self, view)
169 @contract(view='array_view', returns='array')
170 def to_mask(self, view=None):
171 """
172 Convert the current subset to a mask.
173
(...)
180
181 """
--> 182 return self.data.get_mask(self.subset_state, view=view)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/data.py:1387, in Data.get_mask(self, subset_state, view)
1385 return subset_state.to_mask(self, view=view)
1386 except IncompatibleAttribute:
-> 1387 return get_mask_with_key_joins(self, self._key_joins, subset_state, view=view)
File ~/opt/anaconda3/envs/geo_env/lib/python3.10/site-packages/glue/core/joins.py:105, in get_mask_with_key_joins(data, key_joins, subset_state, view)
99 else:
101 raise Exception("Either the number of components in the key join sets "
102 "should match, or one of the component sets should ",
103 "contain a single component.")
--> 105 raise IncompatibleAttribute
IncompatibleAttribute:
Output View
`
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.