Aggregating from non-orthogonal coordinate systems
- 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