question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

pydeck: Extend the support of JavaScript syntaxes that can be used in pydeck.Layer

See original GitHub issue

Target Use case

Extending the support of JavaScript syntaxes that can be used in pydeck.Layer’s argument will help users simplify their code. Users don’t need to make additional columns that are not essentially related to their analysis but are just required for visualization.

Proposed feature

Support JavaScript syntaxes such as ** and Math object among others so that they can be used in pydeck.Layer’s argument. Let me explain the motivation behind this request.

Suppose we have the following pydeck visualization (based on this example in the documentation). As you can see in the keyword argument get_fill_color="entries % 2 === 1 ? [255, 140, 0] : [0, 140, 255]", strings containing a JavaScript expression can be passed. Modulo, strict equality, and ternary operators are obviously accepted.

import pydeck as pdk
import pandas as pd

SCATTERPLOT_LAYER_DATA = "https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/bart-stations.json"
df = pd.read_json(SCATTERPLOT_LAYER_DATA)

# Use pandas to calculate additional data
df["exits_radius"] = df["exits"].pow(0.5)

# Define a layer to display on a map
layer = pdk.Layer(
    "ScatterplotLayer",
    df,
    radius_scale=6,
    get_position="coordinates",
    get_radius="exits_radius",
    get_fill_color="entries % 2 === 1 ? [255, 140, 0] : [0, 140, 255]",
)

# Set the viewport location
view_state = pdk.ViewState(latitude=37.7749295, longitude=-122.4194155, zoom=10, bearing=0, pitch=0)

# Render
r = pdk.Deck(layers=[layer], initial_view_state=view_state)
r.show()
スクリーンショット 2020-09-11 18 34 59

If the following change is applied in order to calculate the radius on the JavaScript end, it won’t work and claims “Error displaying widget”. Exponentiation operator **, which was introduced in ES2016, results in the same error as well.

@@ -4,16 +4,13 @@
 SCATTERPLOT_LAYER_DATA = "https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/bart-stations.json"
 df = pd.read_json(SCATTERPLOT_LAYER_DATA)

-# Use pandas to calculate additional data
-df["exits_radius"] = df["exits"].pow(0.5)
-
 # Define a layer to display on a map
 layer = pdk.Layer(
     "ScatterplotLayer",
     df,
     radius_scale=6,
     get_position="coordinates",
-    get_radius="exits_radius",
+    get_radius="Math.sqrt(exits)",
     get_fill_color="entries % 2 === 1 ? [255, 140, 0] : [0, 140, 255]",
 )

I’d be happy to have these operator and built-in objects available in this context.

To Do List

  • Add label and assign to milestone
  • Coding
  • Doc update
  • What’s new update
  • Test

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:10

github_iconTop GitHub Comments

1reaction
ibgreencommented, Sep 12, 2020

I’ll see if there is any room I can contribute to these 3 packages after familiarizing myself with their codebases.

@yudai-nkt that sounds good, adding support for the exponentiation operator should be done upstream.

However, in the mean-time, if you added support for whitelisting the Math functions, you could always call Math.pow().

To help you get started, maybe you could adapt this pseudo-code, add it to parse-expression-string and make it work?

Note that we’d also want to see a few test cases and some doc updates before landing.

const ALLOWED_FUNCTION_MAP = Math;

function checkASTNode(node, parameters, options) {
  switch (node.type) {
    case 'CallExpression':
      // Only top level functions may be called - never on an object
      const functionCallValid = node.callee.type === 'Identifier' && node.callee.name in ALLOWED_FUNCTION_MAP;
      if (!functionCallValid) {
        let message = `Invalid function call`;
        if (node.callee && node.callee.name) {
           message += ` ${node.callee.name}`;
        }
        throw new Error(message);  
      }
      break;

    case 'ThisExpression':
      throw new Error(`Invalid identifier "this"`);

    case 'MemberExpression':
      throw new Error(`Member function calls not permitted`);

    case 'Identifier':
      const isValid = node.name in parameters;
      if (!isValid) {
        failIdentifierValidation(node.name, parameters, options);
      }
      break;

    default:
  }
}
1reaction
ibgreencommented, Sep 11, 2020

@yudai-nkt Agree that expanding the supported function syntax makes a lot of sense.

Function calling is actually supported under the hood, but there were security concerns with letting the remote app invoke arbitrary javascript functions so it was disabled - permitted functions (e.g Math. ...) should be controlled with a whitelist.

The relevant code is in the @deck.gl/json module: https://github.com/visgl/deck.gl/blob/master/modules/json/src/helpers/parse-expression-string.js

Documentation is here: https://deck.gl/docs/api-reference/json/conversion-reference

@ajduberstein

Read more comments on GitHub >

github_iconTop Results From Across the Web

CustomLayer — pydeck 0.6.1 documentation
... use in pydeck: https://observablehq.com/@pessimistress/deck-gl-custom-layer-tutorial Registering a custom layer requires some knowledge of JavaScript ...
Read more >
What's New - deck.gl
TerrainLayer can now be used with non-geospatial views. ... it can render. pydeck now supports external layer modules via a new custom_libraries setting....
Read more >
Contributing to pydeck - Read the Docs
@deck.gl/json, a Javascript library that converts JSON configurations to deck.gl visualizations; pydeck, the Python wrapper around deck.gl. To contribute to ...
Read more >
pydeck: Unlocking deck.gl for use in Python - Medium
gl's declarative syntax, the ease of use, and ability to render massive data to Python with the beta release of pydeck, a set...
Read more >
docs/whats-new.md · Gitee 极速下载/deck-gl
The JSONConverter class has been generalized and can now be used independently of deck.gl to "hydrate" JavaScript from JSON text specifications. This supports...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found