You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
maybe just as plot.scale("projection")? If the goal is to make it reusable, it doesn't matter if it's an opaque {stream}, and the code is ultra-simple. If we extend the scope and want to get the name back, it's much more difficult.
Exposing projection information would be very useful to Mosaic vgplot. We could then support brushing/filtering over explicitly projected data, at least initially for planar projections and those with separable lon -> x, lat -> y mappings (like unrotated mercator or equirectangular).
I have a working prototype of this locally, which extends Plot's projection.js like so:
return{width: dx,height: dy,offset: [marginLeft+insetLeft,marginTop+insetTop],translate: [tx,ty],scale: k,invert: projection.invert,// may be undefinedstream: (s)=>projection.stream(transform.stream(clip(s)))};
One also needs to first define let k = 1 in the outer scope. I'm exporting dimension information (width, height, offset) to infer the equivalent of scale ranges and to aid setting the boundaries of the brushable region. I use the (translate, scale) data to create my own invert methods (including optimized 1D variants for planar projections). Alternatively, an end-to-end invert method that takes any affine transform into account would work fine.
The only other change is to modify plot.js to expose the projection:
figure.projection=()=>context.projection;
I assume you would want to run this through an exposeProjection method that makes a defensive copy.
Not sure how well something like the above would fit in with your plans and sensibilities, but I can make a PR if it does.
Not to say that we should absolutely support every funky projection out there, but I'm weary of an approach that by design wouldn't allow to work, for example, with polar projections, or maps rotated to include the antimeridian?
Have you thought of going in the opposite direction? If mosaic had only access to the stream — or maybe a convenience method projection(lon, lat) => [x, y] returned by Plot, could it initialize its brushing component by computing all the screen positions (once); these derived dimensions would be added to the datacube, and brushing would work normally. This would make no assumption on what the projection returns.
The drawback of this approach —and I guess that's what you're trying to avoid?— is that you have to compute projected values [x,y] for the whole dataset. But since brushing does not require an extreme precision (that is, a precision of 1 pixel or 0.5 pixel is enough), there might be ways to optimize this even when you have a bazillion data points, by binning or sampling?
Happy to explore this with you in any case—the more maps we can make, the 👍
Yes, there are plenty of non-invertible projections that would be nice to support. As you note, we can compute the projection as a pre-processing step, then rely on the projected (x, y) values. We do this in-database for examples like the Gaia star map and NYC taxis. In the Mosaic context, we need these projected coordinates to reside in-database for scalable and interoperable filtering.
However, all that resides outside of Plot. So for cases where we want to use Plot projections (and their nice defaults, scaling, etc) we currently have a bit of a chicken-and-egg problem. So I've been exploring cases where we can create meaningful selections over lon/lat via projection inversion. If ultimately this proves to be a dead-end, so be it!
In any case it would be nice to be able to access the projection - even if just the stream!
Would also want to use this to enable filtering for data like this: https://jaanli.github.io/new-york-real-estate between Mosaic, Plot, and Protomaps / Maplibre GL types of visualizations like this...
Hi I was watching this issue and I see you want to gather more use cases. Maybe its similar to jhaar's but I want to enable manipulation of the plot in data space.
For that I need to invert a pixel-space delta to a data-space delta. For categorical scales I brute force. I was expecting that for projections I would apply some kind of iterative hill climbing to the well-defined pixel -> data function. I think trying to provide an invert is maybe too opinionated to do because it's an ill defined problem (some projections have multiple solutions for the invert).
Activity
jheer commentedon Mar 21, 2024
Exposing projection information would be very useful to Mosaic vgplot. We could then support brushing/filtering over explicitly projected data, at least initially for planar projections and those with separable lon -> x, lat -> y mappings (like unrotated mercator or equirectangular).
I have a working prototype of this locally, which extends Plot's projection.js like so:
One also needs to first define
let k = 1
in the outer scope. I'm exporting dimension information (width, height, offset) to infer the equivalent of scale ranges and to aid setting the boundaries of the brushable region. I use the (translate, scale) data to create my own invert methods (including optimized 1D variants for planar projections). Alternatively, an end-to-end invert method that takes any affine transform into account would work fine.The only other change is to modify
plot.js
to expose the projection:I assume you would want to run this through an
exposeProjection
method that makes a defensive copy.Not sure how well something like the above would fit in with your plans and sensibilities, but I can make a PR if it does.
Fil commentedon Mar 21, 2024
Not to say that we should absolutely support every funky projection out there, but I'm weary of an approach that by design wouldn't allow to work, for example, with polar projections, or maps rotated to include the antimeridian?
Have you thought of going in the opposite direction? If mosaic had only access to the
stream
— or maybe a convenience methodprojection(lon, lat) => [x, y]
returned by Plot, could it initialize its brushing component by computing all the screen positions (once); these derived dimensions would be added to the datacube, and brushing would work normally. This would make no assumption on what the projection returns.The drawback of this approach —and I guess that's what you're trying to avoid?— is that you have to compute projected values [x,y] for the whole dataset. But since brushing does not require an extreme precision (that is, a precision of 1 pixel or 0.5 pixel is enough), there might be ways to optimize this even when you have a bazillion data points, by binning or sampling?
Happy to explore this with you in any case—the more maps we can make, the 👍
jheer commentedon Mar 21, 2024
Yes, there are plenty of non-invertible projections that would be nice to support. As you note, we can compute the projection as a pre-processing step, then rely on the projected (x, y) values. We do this in-database for examples like the Gaia star map and NYC taxis. In the Mosaic context, we need these projected coordinates to reside in-database for scalable and interoperable filtering.
However, all that resides outside of Plot. So for cases where we want to use Plot projections (and their nice defaults, scaling, etc) we currently have a bit of a chicken-and-egg problem. So I've been exploring cases where we can create meaningful selections over lon/lat via projection inversion. If ultimately this proves to be a dead-end, so be it!
In any case it would be nice to be able to access the projection - even if just the stream!
jaanli commentedon Apr 10, 2024
Fil commentedon Apr 10, 2024
jaanli commentedon Apr 10, 2024
jaanli commentedon Apr 10, 2024
Would also want to use this to enable filtering for data like this: https://jaanli.github.io/new-york-real-estate between Mosaic, Plot, and Protomaps / Maplibre GL types of visualizations like this...
tomlarkworthy commentedon Jan 13, 2025
Is there a workaround to get the [lat, long] => [px, py] transform when there is a projection?
tomlarkworthy commentedon Jan 15, 2025
Hi I was watching this issue and I see you want to gather more use cases. Maybe its similar to jhaar's but I want to enable manipulation of the plot in data space.
https://observablehq.com/@tomlarkworthy/manipulate#plot_location
For that I need to invert a pixel-space delta to a data-space delta. For categorical scales I brute force. I was expecting that for projections I would apply some kind of iterative hill climbing to the well-defined pixel -> data function. I think trying to provide an invert is maybe too opinionated to do because it's an ill defined problem (some projections have multiple solutions for the invert).