holoviz / holoviz/datashader

Aggregating from non-orthogonal coordinate systems

Open
#719 3 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Python
Stars
3.6k
Forks
376
Avg merge
4h 32m
Merged PRs (30d)
1

Description

## Overview
This issue is to discuss the possibility of supporting 2D non-orthogonal coordinate systems in Datashader.

## Current State
The `Canvas` constructor accepts `x_axis_type` and `y_axis_type` string arguments that may be set to `'linear'` or `'log'`. These strings are then used to lookup predefined axis objects, which are stored as the `x_axis` and `y_axis` properties of the `Canvas` instance:

https://github.com/pyviz/datashader/blob/3171d8869f63214cc161da755e88c30abe8b5098/datashader/core.py#L122-L147

The axis objects are subclasses of the `datashader.core.Axis` class:

https://github.com/pyviz/datashader/blob/3171d8869f63214cc161da755e88c30abe8b5098/datashader/core.py#L21

https://github.com/pyviz/datashader/blob/3171d8869f63214cc161da755e88c30abe8b5098/datashader/core.py#L90

https://github.com/pyviz/datashader/blob/3171d8869f63214cc161da755e88c30abe8b5098/datashader/core.py#L103

These classes have `mapper` and `inverse_mapper` methods that apply and reverse the 1D axis transform. e.g.:

https://github.com/pyviz/datashader/blob/3171d8869f63214cc161da755e88c30abe8b5098/datashader/core.py#L103-L114

These `mapper` and `inverse_mapper` methods must be numba jit compiled because they are called by the inner loops in the Glyph aggregation pathways. e.g.

https://github.com/pyviz/datashader/blob/3171d8869f63214cc161da755e88c30abe8b5098/datashader/glyphs.py#L158-L175

## Current Limitations
1. It is not currently possible for a user to specify a custom axis type and pass that to the canvas constructor.
2. Because the `Axis` `mapper` and `inverse_mapper` interface only accepts a single value to map, these axes are fundamentally 1D. In other words, a transformed `x` value may depend only on the original `x` and it may not depend on original `y` value. This limitation precludes support for non-orthogonal 2D coordinate systems. e.g. polar, affine, barycentric, curvalinear, map projections etc.

## Potential Enhancements
1. To allow users to customize the axis transformations, the `datashader.core.Axis` interface could be documented and the `Canvas` constructor could accept `Axis` sub-class instances as the `x_axis_type` and `y_axis_type` arguments.
2. To support non-orthogonal coordinate systems, I think it would be enough to update the `mapper` and `inverse_mapper` methods to accept two arguments.

```python
def mapper(coord, other_coord):
...

def inverse_mapper(coord, other_coord):
...
```

Orthogonal transforms, like the current `LinearAxis` and `LogAxis` could ignore the second argument. Non-orthogonal transforms could make use of both arguments. Here's what a polar transform might look like.

```python
class PolarRadiusToX(Axis):
def mapper(r, theta):
return r*np.cos(theta)

def inverse_mapper(x, y):
return np.sqrt(x**2 + y**2)

class PolarThetaToY(Axis)
def mapper(theta, r):
return r*np.sin(theta)

def inverse_mapper(y, x):
return np.atan2(y, x)

canvas = Canvas(..., x_axis_type=PolarRadiusToX(), y_axis_type=PolarThetaToY())
rs = ...
thetas = ...
canvas.points(x=rs, y=thetas)
```

## Impact
This would require tracking down every use of `Canvas.x_axis` and `Canvas.y_axis` and adding the second argument, but I don't foresee it requiring any significant refactoring. This assumes that there won't be any performance degradation from adding the second argument to the `Linear` and `Log` axis mapping methods.

cc @jbednar @philippjfr

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the Axis and Canvas implementation in datashader/core.py, then trace mapper and inverse_mapper calls in datashader/glyphs.py. Review every use of Canvas.x_axis and Canvas.y_axis before defining a supported interface for custom and non-orthogonal transforms. Done means the project has an agreed implementation that supports the proposed two-coordinate mappings without degrading existing linear and log behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
numpy, python
Domain
data-visualization
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.