Comments (4)
The proposed function above (that renders the entire tree) won't work. It's slow to load a single Landsat 9 TOA image's metadata and, at least in free Colab, won't even render the tree with two images in the collection. Test these data with above function - collection limit set at 2:
data = ee.ImageCollection("LANDSAT/LC09/C02/T1_TOA").limit(2).getInfo()
tree = Tree(animation=0)
tree.add_node(create_tree(data))
tree
from earthengine-jupyter.
Maybe in the current implementation the JSON data can be stored as an added attribute, like add a json
parameter to the Node
class ~e.g.:
class CustomNode(Node):
def __init__(self, name=None, children=None, json=None):
super().__init__(name=name, children=children)
self.json = json
Instead of storing the JSON data as the name
attribute, store it in the new json
attribute and use an empty string or <em>Loading</em>
as the name
attribute. When a person opens a node, fetch the JSON and update the name
.
from earthengine-jupyter.
Here is a potential fix. It adds a Node subclass with an ee_data
attribute for storing the JSON data (MyNode
is not a good name, need to change).
class MyNode(ipytree.Node):
def __init__(self, *args, ee_data=None, **kwargs):
super().__init__(*args, **kwargs)
self.ee_data = ee_data
The StructureTree
class is modified so that the name of "JSON" nodes is Loading and JSON data is stored in the ee_data
attribute.
class StructureTree(ipytree.Tree):
JSON_PREFIX = 'JSON: '
def __init__(self, data, **kwargs):
self.data = data
super().__init__(StructureTree.__ipytreeify(data))
@staticmethod
def __ipytreeify(data) -> tuple:
"""Return a sequence of nodes"""
def is_json(in_str):
'''Determines if a string is JSON.'''
return bool(in_str) and in_str.startswith(StructureTree.JSON_PREFIX)
def inline_style(x, color='#af00db'):
'''Wrap a string with inline HTML styling.'''
return f'<B><SPAN style="color:{color}">{x}</SPAN></B>'
def handle_node_open(change):
if change['new']:
nodes_unpacked = []
for node in change['owner'].nodes:
# If there no subnodes, try to populate the subnodes.
if len(node.nodes) == 0:
if is_json(node.ee_data):
unpacked_json = json.loads(node.ee_data[len(StructureTree.JSON_PREFIX):])
if isinstance(unpacked_json, list):
nodes_unpacked = StructureTree.__ipytreeify(unpacked_json)
elif isinstance(unpacked_json, dict):
nodes_unpacked = StructureTree.__ipytreeify(unpacked_json)
else:
raise
else: # ~is_json(node.name)
nodes_unpacked.append(node)
change['owner'].nodes = nodes_unpacked
if isinstance(data, list):
node_list = []
for count, el in enumerate(data):
if isinstance(el, list):
subnode = MyNode(
name=f'{inline_style("List")} ({len(el)} elements)',
nodes=[MyNode('<em>Loading</em>', ee_data=f'{StructureTree.JSON_PREFIX}{json.dumps(el)}', show_icon=False)],
opened=False,
show_icon=False)
subnode.observe(handle_node_open, names='opened')
elif isinstance(el, dict):
subnode = MyNode(
name=f'{inline_style("Object")} ({len(el)} elements)',
nodes=[MyNode('<em>Loading</em>', ee_data=f'{StructureTree.JSON_PREFIX}{json.dumps(el)}', show_icon=False)],
opened=False,
show_icon=False)
subnode.observe(handle_node_open, names='opened')
else:
subnode = MyNode(f'{el}', show_icon=False)
node_list.append(subnode)
return node_list
elif isinstance(data, dict):
node_list = []
for key, value in data.items():
if isinstance(value, list):
subnode = MyNode(
name=f'{inline_style(key)}: List ({len(value)} elements)',
nodes=[MyNode('<em>Loading</em>', ee_data=f'{StructureTree.JSON_PREFIX}{json.dumps(value)}', show_icon=False)],
opened=False,
show_icon=False)
subnode.observe(handle_node_open, names='opened')
elif isinstance(value, dict):
subnode = MyNode(
name=f'{inline_style(key)}: Object ({len(value)} elements)',
nodes=[MyNode('<em>Loading</em>', ee_data=f'{StructureTree.JSON_PREFIX}{json.dumps(value)}', show_icon=False)],
opened=False,
show_icon=False)
subnode.observe(handle_node_open, names='opened')
else:
subnode = MyNode(f'{inline_style(key)}: {value}', show_icon=False)
node_list.append(subnode)
return node_list
else:
return (data, )
Since ee_data
default is None
, is_json
function needed to add a check for None so that the startswith
string method does not bonk. I tested it with the same Landsat data from above and it works great. It also works for the map inspector demo in the 01_ipyleaflet.ipynb (some other bug seems to crop up when implemented in the map panel - also happens with current implementation, I'll file a separate issue).
from earthengine-jupyter.
Here is a refactored version of StructureTree
from previous comment (still uses badly named MyNode
class).
class MyNode(ipytree.Node):
def __init__(self, *args, ee_data=None, **kwargs):
super().__init__(*args, **kwargs)
self.ee_data = ee_data
class StructureTree(ipytree.Tree):
JSON_PREFIX = 'JSON: '
def __init__(self, data, **kwargs):
self.data = data
super().__init__(StructureTree.__ipytreeify(data))
@staticmethod
def __ipytreeify(data) -> tuple:
"""Return a sequence of nodes"""
def is_json(in_str):
'''Determines if a string is JSON.'''
return bool(in_str) and in_str.startswith(StructureTree.JSON_PREFIX)
def inline_style(x, color='#af00db'):
'''Wrap a string with inline HTML styling.'''
return f'<B><SPAN style="color:{color}">{x}</SPAN></B>'
def handle_node_open(change):
if change['new']:
nodes_unpacked = []
for node in change['owner'].nodes:
if not node.nodes:
if is_json(node.ee_data):
unpacked_json = json.loads(node.ee_data[len(
StructureTree.JSON_PREFIX):])
nodes_unpacked = StructureTree.__ipytreeify(unpacked_json)
else:
nodes_unpacked.append(node)
change['owner'].nodes = nodes_unpacked
NODE_PARAMS = {
'show_icon': False,
'opened': False,
'observe': handle_node_open,
}
def create_loading_node(data):
return MyNode('<em>Loading</em>',
ee_data=f'{StructureTree.JSON_PREFIX}{json.dumps(data)}',
**NODE_PARAMS)
def create_node_name(label, modifer, data):
return f'{inline_style(label)}{modifer} ({len(data)} elements)'
node_list = []
if isinstance(data, list):
for count, el in enumerate(data):
if isinstance(el, (list, dict)):
node_type = 'List' if isinstance(el, list) else 'Object'
subnode = MyNode(
name=create_node_name(node_type, '', el),
nodes=[create_loading_node(el)],
**NODE_PARAMS)
subnode.observe(handle_node_open, names='opened')
else:
subnode = MyNode(f'{el}', **NODE_PARAMS)
node_list.append(subnode)
elif isinstance(data, dict):
for key, value in data.items():
if isinstance(value, (list, dict)):
node_type = ': List' if isinstance(value, list) else ': Object'
subnode = MyNode(
name=create_node_name(key, node_type, value),
nodes=[create_loading_node(value)],
**NODE_PARAMS)
subnode.observe(handle_node_open, names='opened')
else:
subnode = MyNode(f'{inline_style(key)}: {value}', **NODE_PARAMS)
node_list.append(subnode)
else:
node_list.append(MyNode(str(data), show_icon=False))
return tuple(node_list)
from earthengine-jupyter.
Related Issues (20)
- Inspector: load layer statistics asynchronously
- Add colab setup function HOT 1
- Having code in package to install itself doesn't work
- task monitor
- Inspector: Multi-line properties are not handled properly
- Map: add method for specifying center as lon, lat
- Add Map.center_object(eeObject) method
- Map doubleclick results in duplicated Objects folder in the inspector
- Add helper function to set the Colab output cell height
- Fix spelling error "Latitutde" HOT 1
- Module for Charting HOT 2
- Layout: Add tab navigation between the inspector and a console HOT 1
- Make map-inspector layout panels resizable HOT 1
- Panel size slider in MapWithInspector does not work in Colab HOT 1
- Feature Request: pip install eerepr HOT 4
- Turn off EE layer in leaflet doesn't make EE layer disappear HOT 2
- Add functionality for creating a legend for map layers
- addLayer(shown=False) prevents ipyleaflet visibility toggle from working
- Method syncronize_maps not found
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from earthengine-jupyter.