@ 碳平面图/ sarr- slayer
自定义层,用于在 MapLibre 或 Mapbox GL 中渲染 Zarr 数据集, 启发( 并借用重要代码和概念)
沙尔格勒, (中文(简体) ), zar, (中文(简体) ), @碳计划/地图,以及 甲板-gl-鼠标用途 自定义 Layer 界面 直接向地图提供数据,并支持向地球和交易者提供MapLibre和Mapbox的预测。 Mapbox的其他预测(Albers, Equal Earth等)不会使自定义地层产生,因此地层没有被画入其中. 在 MapLibre 上,该图层还在自定义地图中制作已注册的预测 addProjection实验性(见 自定义地图预测) (中文(简体) ). 在苍蝇上重新预测输入数据.
演示
见 演示 快速巡视能力。 演示的代码在 /demo 文件夹.
数据要求
支持 v2 和 v3 sarr 商店通过 萨里塔. 任意CRS支持 proj4 数据 重新预测.
自定义商店
一个带沙雷的商店 proj 财务报告和审定财务报表 spatial 常规不需要配置:层直接从元数据中读出其CRS、范围、取向和轴名,完全不读出坐标阵列.
| 属性 | 什么解决 |
|---|---|
proj:code | 以标识符表示的中央RS: EPSG:4326, (中文(简体) ), EPSG:3857, (中文(简体) ), OGC:CRS84, WGS84 UTM 区(EPSG:326xx编号 :EPSG:327xx),或登记在 proj4.defs。 。 。 . |
proj:wkt2 编号 : proj:projjson | 密码proj4不载运 不需要检查表. |
spatial:transform | 0号线的高度和边缘位置. |
spatial:bbox | 程度,胜过变身的 当两者宣布. |
spatial:registration | 声明的坐标是否落在单元格边缘上( E)pixel,默认值)或单元格中心(node) (中文(简体) ). |
spatial:dimensions | 哪些数组维度是y和x, 对于没有命名可识别的轴 . |
spatial:shape | 每个金字塔的大小,上 multiscales.layout 条目,保留每个关卡打开的数组. |
被宣布的属性是权威的. 如果一家商店发布它们,它们被作为-即用,而不是对照它的坐标数组进行检查,因此,一个其属性与自己的数据不一致的商店会使错误发生而不是被悄悄地纠正.
构造器选项总是赢得商店声明的内容 : crs, (中文(简体) ), proj4, (中文(简体) ), bounds, (中文(简体) ), latIsAscending 财务报告和审定财务报表 spatialDimensions 每一个都覆盖相应的属性.
对于一个商店宣布 proj:code proj4不知道,没有 proj:wkt2 或者说 proj:projjson,层层会发出警告,并留下CRS未解决. 通过定义为 proj4 prop,或用proj4注册代码,以获得商店自己的声明解析(参见 登记计算机登记系统) (中文(简体) ).
当这些属性不存在时,地层会回到它总是所做的:读取坐标阵列的大小和取向,将维度名称与一个常见别名列表相匹配,从界限的大小推断出CRS. 一个CF grid_mapping 变量读取为 crs_wkt 否时 proj: 属性存在.
多比例
高分辨率数据集需要多尺度. 支持沙尔 多重规模公约 遗产 nd 输出,并尝试解释其他多尺度格式。 见 顶点 用于查看如何创建这些数据集.
Chunks根据取景口相接处加载,级别与屏幕分辨率相匹配. 在 MapLibre 上,一个投放的视图的相距部分会加载相机数据.
当所查看的块会超过层的内存预算时(maxCacheMB),从相近的地平面上从中心负载相去去. 没有收发器级的数据,如单分辨率阵列,满载不计其数,可以在广视中使用大量的内存.
Chunk读取了网络出错导致的故障,超时,429或5xx被后退重审. 其他的 HTTP 错误会留下块空白, 直到选择器改变或级别重新加载 .
全球渲染和极地覆盖
Web Mercator 渲染片段位于相距±85°附近,在地球预测上留下了明显的"波子孔". EPSG:4326和 proj4 数据集 :
地图Libre - 完全覆盖极地,不需要配置,但地形允许,柱子显示有孔(见 地形) (中文(简体) ).
映射框 - 设定 renderPoles: true 以覆盖柱子(实验). 要求数 mapbox-gl >= 3.32;在更古老的版本上,它没有效果,并且警告过一次. 它依赖于无证的Mapbox行为,在版本之间可能会有变化. 极地孔在从地到地的过渡期间仍然显示,而且地形已启用.
new ZarrLayer({
// ...
renderPoles: true, // Mapbox only — MapLibre always renders to the poles
})
地形
层帘在两个提供者的3D地形上,不需要配置: 启用地图上的地形(map.setTerrain(...)),地层跟随地表. 在MapLibre上,这依赖于paplibre-gl 6.13或以后的实验性API;在更古老的版本上,地层画平. 在地形允许的情况下,杆会显示通常的Web Mercator洞.
自定义地图预测
在 MapLibre (地图- gl 6. 15 或稍后) 上,该图层在 Planar 地图中生成在 MapLibre 上注册的预测 addProjection,例如南极极地立体(EPSG:3031). API和这种支持都是实验性的,可能会改变微量释放. 将同样的投影对象传递到层中 addProjection。 。 。 .
import proj4 from 'proj4'
import { addProjection, type CRS } from 'maplibre-gl'
const antarctic: CRS = {
name: 'EPSG:3031',
projection: proj4(
'EPSG:4326',
'+proj=stere +lat_0=-90 +lat_ts=-71 +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs'
),
tileMatrixSet: { origin: [-4194304, 4194304], extentAtZoom0: 8388608 },
}
addProjection(antarctic)
map.setProjection({ type: 'EPSG:3031' })
const layer = new ZarrLayer({ ...options, mapProjections: [antarctic] })
在任何CRS中,层读取的数据被重新投射到地图的投影中. 已注册投影中的地图绘制出一个没有副本的单一世界,其底图和地平板必须在同一投影中被剪去. 地图在未列出的已登记投影中 mapProjections,该图层被隐藏并记录一个警告。 该演示包括几个极地和等地的例子.
安装
npm install @carbonplan/zarr-layer
本地建设
npm install
npm run build
使用量
import maplibregl from 'maplibre-gl' // or mapbox
import { ZarrLayer } from '@carbonplan/zarr-layer'
const map = new maplibregl.Map({container: 'map'})
const layer = new ZarrLayer({
id: 'zarr-layer',
source: 'https://example.com/my.zarr',
variable: 'temperature',
clim: [270, 310],
colormap: ['#000000', '#ffffff', ...],
selector: { month: 1 },
})
map.on('load', () => {
map.addLayer(layer)
// optionally add before id to slot data into map layer stack.
// map.addLayer(layer, 'beforeID')
})
选项
要求 :
| 选项 | 类型 | 说明 |
|---|---|---|
| 编号 | 字符串 | 独特的层标识符 |
| 来源 | 字符串 | Zarr 存储 URL( 除非 store (已提供) |
| 变量 | 字符串 | 要渲染的可变名称 |
| 颜色映射 | 数组 | 六进制字符串或 [r,g,b] 数值 |
| 高潮 | [min,最大] | 颜色比例限制 |
可选 :
| 选项 | 类型 | 默认 | 说明 |
|---|---|---|---|
| 存储 | 可读 | - 说吧 | 自定义 sarrita相容商店(如 Icechunk Store). 提供时, source 成为可选的. |
| 选择器 | 对象 | {} | 尺寸选择器( 未指定默认为索引 0) |
| 透明度 | 编号 | 1 | 层不透明 (0-1) |
| 沙尔维森语Name | 2 | 3 | 自动 | Zarr 格式版本( 先为 tries v3, 倒回 v2) |
| 分钟 | 编号 | 0 | 渲染最小缩放级别 |
| 最大范围 | 编号 | Infinity | 渲染的最大缩放级别 |
| 填入数值 | 编号 | 自动 | 将存储值视为无数据,取而代之 fill_value。与原始数值相比,在 scale_factor编号 :add_offset已清除 setVariable |
| 最大区域图 | 编号 | 16 | 区域一次在飞行中取取;其余在队列中等待,最接近取景中心. 为许多小而快的区域的取景点升起 |
| 最大缓存 | 编号 | 512 | 该层可能缓存的兆字节数据, 加上解码块的一半。 将它放入内存受约束的设备; 在视图中块装入甚至过它 |
| 最小区域大小 | 编号 | 一块 | 最小的区域,以每轴像素为单位,加载并绘制为单位. 区域是整块块的, 所以这些小块分成更少,更大的区域。 每轴2048px的生长停止 |
| 空间差异 | 对象 | 自动 | 自定义 { lat, lon } 淡化名称 |
| 曲线 | 字符串 | 自动 | CRS标识符. 无需 EPSG:4326编号 :EPSG:3857 数据(自动发现)。 Proj4编码界定(除其他外,WGS84 UTM区)或登记在 proj4.defs 无工作 proj4 绳子. |
| proj4 数据 | 字符串 | - 说吧 | 用于 CRS 重排的 Proj4 定义字符串 (bounds 建议,其他来源于坐标) |
| 边框 | 数组 | 自动 | [xMin, yMin, xMax, yMax] 在源 CRS 单元(EPSG:4326的度,EPSG:3857的米)中. 这些被解释为边缘界限(不是中到中线) |
| 升迁 | 布尔 | 自动 | 纬度方向 |
| 渲染模式 | '2d' | '3d' | '3d' | 自定义图层渲染模式 |
| 自定义标签 | 字符串 | - 说吧 | 自定义碎片阴影器 |
| 制服 | 对象 | - 说吧 | 阴影统一值、数字或数字数组(需要) customFrag(中文(简体) ) |
| 连接状态变化 | 函数 | - 说吧 | 正在装入状态回调 |
| 转换请求 | 函数 | - 说吧 | 转换请求 URL并添加信头/证书(参见 认证(中文(简体) ) |
| 错误 | 函数 | - 说吧 | 当签名请求过期时, 使用 HTTP 状态调用( 见 认证(中文(简体) ) |
| 制作Poles | 布尔 | false | 在 Mapbox Global 为 EPSG 启用极地覆盖: 4326/proj4 数据集(参见 全球渲染) (中文(简体) ). 对EPSG:3857数据无影响. MapLibre 总是在杆上做. |
| 映射图 | 地图预测 [] | [] | 在MapLibre实验中登记的预测 addProjection 该图层生成的(见 自定义地图预测(中文(简体) ) |
方法
layer.setOpacity(0.8)
layer.setClim([0, 100])
layer.setColormap(['#000', '#fff'])
layer.setSelector({ time: 5 })
layer.setVariable('precipitation') // async - reloads metadata
layer.setUniforms({ u_weight: 1.5 }) // no-op unless layer has customFrag
快速选择器变化
setSelector 是同步的,每通电话都会接一个 对于UIs, 快速火速更新( 例如拖取时间滑动器) , 在将它交给地层之前, 在您侧面卸出值, 这样您就不会发射一次取消的获取 .
选择器
选择器指定您要渲染的多维数据的哪一片块 。 未指定索引 0 的尺寸默认值。 钥匙是商店自己的非空间维度名称,准确匹配. 无尺寸名称的密钥是列出有效名称的错误 。 它会浮出水面 onLoadingStateChange 以图层选择者为代表 queryData。 。 。 .
基本语法 :
// Simple value - matches exact value in coordinate array
{ time: 5 }
{ time: '2024-01-15' }
// Explicit index - uses array index directly (no coordinate lookup)
{ time: { selected: 5, type: 'index' } }
// Explicit value - same as simple syntax, matches exact value
{ time: { selected: 5, type: 'value' } }
多波段选择( 用于自定义阴影) :
// String values use the string directly as the shader variable name
{ band: ['tavg', 'prec'] }
// exposes as: tavg, prec
// Numeric values are prefixed with the dimension key (required for valid GLSL identifiers)
{ month: [1, 2, 3] }
// exposes as: month_1, month_2, month_3
// Index selectors use dimension-prefixed shader variable names
{ band: { selected: [0, 1, 2], type: 'index' } }
// exposes as: band_0, band_1, band_2; update shader references accordingly
// Mix with other dimensions
{ band: ['red', 'green', 'blue'], time: 0 }
查询特定选择器 :
// Array of values for time series queries
const result = await layer.queryData(
{ type: 'Point', coordinates: [lng, lat] },
{ time: [0, 1, 2, 3, 4] } // returns data for all 5 time steps
)
非空数组值通过标签将结果嵌入,无论长度如何: { time: [3] } 返回时 { 3: number[] }。重复的值崩溃成一个序列。 单值返回平方 number[],而选择器中留下的空数组或维数,在索引 0 中都读取.
类型选项 :
| 类型 | 行为 |
|---|---|
'value' (默认) | 匹配坐标阵列中的确切值( 如果找不到则推出) |
'index' | 直接使用值作为数组索引 |
定制遮阳和制服
自定义片段阴影让您在数据上做数学来改变其显示方式. 这对诸如日志缩放,组合波段,或者在一个时间窗口中汇总数据等事物可能有用. 带可以横跨单独的块-每个带被平行地取出并结合进行渲染. 对波段计数没有实际限制,因此一个阴影器可以读取几十个(如64维嵌入). 你可以过去 uniforms 允许用户交互影响自定义的阴影码.
带名被自动分解为有效的GLSL标识符:任何不是字母,数字,或下划线的字符被替换为下划线,从数字开始的名字被前缀为下划线. 譬如说, s2med_harvest:B02 变成 s2med_harvest_B02 财务报告和审定财务报表 123band 变成 _123band。 。 。 .
层与预多倍相混合的α混合功能相融合,所以 customFrag 必须输出多倍色。 将RGB乘以您最终的α(例如. fragColor = vec4(c.rgb * opacity, opacity)) (中文(简体) ). 直视 vec4(c.rgb, opacity) 只有完全不透明时才正确.
带值随 scale_factor编号 :add_offset 已经应用.
当a customFrag 提供, 它拥有丢弃。缺少/填充像素时显示为 NaN 而不是被自动投放,所以可以将部分覆盖(例如,一个平均覆盖不同覆盖的波段),而不只是它们的相交点加以汇总. 请注意: NaN 通过算术传播(甚至) NaN * 0.0 实值 NaN),因此在相乘或相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相. isnan(x) ? 0.0 : x添加您自己的 discard 您想要降下像素 :
new ZarrLayer({
// ...
customFrag: `
uniform float u_weight;
if (isnan(band_a)) {
discard;
}
float val = band_a * u_weight;
float norm = (val - clim.x) / (clim.y - clim.x);
vec4 c = texture(colormap, vec2(clamp(norm, 0.0, 1.0), 0.5));
fragColor = vec4(c.rgb * opacity, opacity);
`,
uniforms: { u_weight: 1.0 },
})
制服也可以是数字阵列(或 Float32Array以荫为受 float 相同长度的数组。 这适合作为向量而出现的值,例如比较嵌入带的查询:
const layer = new ZarrLayer({
// ...
selector: { band: ['A00', 'A01', 'A02'] },
customFrag: `
float similarity = A00 * u_query[0] + A01 * u_query[1] + A02 * u_query[2];
vec4 c = texture(colormap, vec2(clamp(similarity, 0.0, 1.0), 0.5));
fragColor = vec4(c.rgb * opacity, opacity);
`,
uniforms: { u_query: [0.2, 0.5, 0.3] },
})
layer.setUniforms({ u_query: [0.1, 0.1, 0.8] })
更新一个数组的值是便宜的;改变它的长度会重新编译出阴影器,所以保持长度固定(纸上未使用的条目). 每个元素都使用设备的一个碎片统一向量(WebGL2中至少224个,与层自制服共享),因此一个非常长的阵列可以超过设备的极限而无法编译. 该地层本身使用约45个向量,因此预算长阵列与其余的相对.
NDVI 实例
以下是使用自定义阴影来计算 NDVI (Normalized Difference Vegetation Index) 的例子 :
new ZarrLayer({
source: 'https://example.com/sentinel2.zarr',
variable: 'data',
colormap: [
/* gradient */
],
selector: { band: ['B08', 'B04'], time: 0 },
clim: [-1, 1],
customFrag: `
if (isnan(B08) || isnan(B04)) {
discard;
}
float ndvi = (B08 - B04) / (B08 + B04);
float norm = (ndvi - clim.x) / (clim.y - clim.x);
vec4 c = texture(colormap, vec2(clamp(norm, 0.0, 1.0), 0.5));
fragColor = vec4(c.rgb * opacity, opacity);
`,
})
自定义预测
EPSG:4326或EPSG:3857中的数据集不需要CRS配置. 其他任何物品(如:Lambert Conflect Concion,UTM),设置 crs 密码。 如果 proj4 定义了这个代码, 或者您自己注册了它, 它将不进行进一步的配置 proj4 定义字符串与它并列,或者渲染器会发出警告并返回到推断的 CRS 。 指定 bounds 在源 CRS 单元中推荐性能(其他方法来自坐标阵列).
这些都不需要 商店携带 proj 财务报告和审定财务报表 spatial 公约(见 自定义仓库) (中文(简体) ).
new ZarrLayer({
// ...
spatialDimensions: {
lat: 'projection_y_coordinate',
lon: 'projection_x_coordinate',
},
proj4:
'+proj=lcc +lat_1=38.5 +lat_2=38.5 +lat_0=38.5 +lon_0=-97.5 +x_0=0 +y_0=0 +R=6371229 +units=m +no_defs',
bounds: [-2697520, -1587306, 2697480, 1586694], // recommended: edge bounds [xMin, yMin, xMax, yMax] in source CRS units
})
数据将重新预测到Web Mercator, 使用由 GPU 加速的 mesh 重新预测的电源显示 @ 开发种子/ raster- project查找 proj4 字符串 eps.io 数据 或者在您的数据集的元数据.
登记计算机登记系统
proj4 定义了框外的一小组代码 : EPSG:4326, (中文(简体) ), EPSG:4269, (中文(简体) ), EPSG:3857 (带有其别名), EPSG:5041, (中文(简体) ), EPSG:5042,以及120个WGS84 UTM区(EPSG:32601- 说吧EPSG:32660 北边, EPSG:32701- 说吧EPSG:32760 (原始内容存档于2018-09-21). South. 所有其它东西都需要你的定义 包括国家电网 EPSG:27700 财务报告和审定财务报表 EPSG:2154,而其他数据上的UTM区,看起来是内置的,但不是:NAD83(EPSG:269xx)和ETRS89号卫星(EPSG:258xx)是与其WGS84对应的相隔代码.
传之为道 proj4 道具,它优先于 crs 以及店里公布的任何东西 或者在创建层之前用 proj4 注册它, 它让一个商店自己的 proj:code 解析时没有每层配置 :
import proj4 from 'proj4'
proj4.defs('EPSG:25833', '+proj=utm +zone=33 +ellps=GRS80 +units=m +no_defs')
注册只有在不知道哪个商店是CRS提前到来时才会支付;否则道具更简单. proj4.defs 还接受WKT2和PROJJSON. 请注意,Zarr-layer进口proj4 而不是捆绑自己的副本,所以你 proj4 导入是它读取的注册簿,只要您的捆绑者将两者解决为一份.
商店声明 proj:wkt2 或者说 proj:projjson 拥有自己的定义,不需要这些.
查询
支助 Point, (中文(简体) ), LineString, (中文(简体) ), Polygon,以及 MultiPolygon 以 Geojson 格式绘制的相片 。 你可以选择通过一个 selector,它覆盖层 selector 键。 询问留下的维度 留在图层显示的切片上 所以 { time: [0, 1, 2] } 显示一个乐队返回那个乐队的时间序列.
// Point query
const result = await layer.queryData(
{ type: 'Point', coordinates: [lng, lat] },
// optional selector override (useful for e.g. time series creation)
{ time: [0, 1, 2] }
)
// Polygon query
const result = await layer.queryData({
type: 'Polygon',
coordinates: [[...]],
})
// Returns:
// {
// [variable]: number[],
// dimensions: ['<store-y-axis>', '<store-x-axis>'],
// coordinates: { '<store-y-axis>': number[], '<store-x-axis>': number[] }
// }
空间查询结果在数据集的源 CRS 中返回,在商店自己的空间轴名下. 一个 EPSG:3857 数据集为 y编号 :x 轴返回下方的 Web Mercator 仪表 y编号 :x; 一个 EPSG:4326 数据集为 latitude编号 :longitude 轴返回下方的度 latitude编号 :longitude;一个自定义-proj4数据集返回其源-CRS值,无论商店称它为什么。 输入几何仍作为GeoJSON lon/lat提供,无论来源CRS.
你可以通过第三个 options 用于控制查询行为的参数 :
const result = await layer.queryData(geometry, selector, {
signal: abortController.signal, // cancel in-flight query
includeSpatialCoordinates: false, // omit per-pixel coordinates for slimmer results
level: 'finest', // read the highest-resolution level instead of the drawn one
distanceKey: 'along', // LineString only: result key for distance, default 'distance'
})
其他钥匙都在里面 coordinates 是商店的维度名称。 A 类 LineString 查询一个名为大小的商店 distance 扔出,这样维度值就不会被覆盖。 换个 distanceKey 来查询它.
说明: 查询结果匹配已提供值( E)scale_factor编号 :add_offset 适用, fillValue/NaN被过滤). 结果中忽略了没有数据的单元格.
多值选择器, 如 { time: [0, 1, 2] },当一个单元格拥有至少一个序列的数据时,该单元格被保留,而该序列没有数据 NaN 在那个位置。 因此,每个系列都有相同的长度和索引 i 指在所有单元格和坐标数组中相同的单元格,当 includeSpatialCoordinates 实值 false组合时跳过非无限值. JSON.stringify 写入 NaN 作为 null。 。 。 .
线条配置
A 类 LineString 查询返回一个配置文件:该行经过的每个网格单元格一个样本,按路径顺序.
const profile = await layer.queryData({
type: 'LineString',
coordinates: [[lng0, lat0], [lng1, lat1], ...],
})
// Returns the same shape as other queries, plus `distance`:
// {
// [variable]: number[],
// dimensions: ['<store-y-axis>', '<store-x-axis>'],
// coordinates: {
// '<store-y-axis>': number[],
// '<store-x-axis>': number[],
// distance: number[], // meters along the line, one per sample
// }
// }
- 相去相远.
distance[i]从开始到进入样本细胞的距离i。对照它绘制真实的相距轴而不是样本索引. - 密度. 采样跟随读取的关卡,所以缩放相近的剖面. 过
level: 'finest'对于不依赖于缩放的配置文件. - 价值. 样本是被存储的细胞值,不是在细胞间插出.
- 差距. 没有数据的单元格被忽略,跳入
distance显示空白。 光栅外的线路部分也一样. - 复说. 一个细胞每通过一次采样,所以一条线会再次将它反向采样. 一条线穿过一个精确的细胞角,走向对角,而不取样它只接触那里的细胞.
- 时间序列沿一行. 通过一个多值选择器, 如
{ time: [0, 1, 2] }每个步骤获得一个对齐的配置文件. - 安提弥陀. 其经度均位于±180的行被字面读取. 要穿越时空,继续通过它,例如从
170改为190。 。 。 . - 入入入限相. 坐标必须是有限度的,纬度在±90以内,经度在±720以内,或者查询会发出一个
RangeError。 。 。 .
查询分辨率
默认情况下,一个查询会读取当前地图所绘制的关卡,所以结果与用户所看到的一致并缩放出相近的关卡. 过 level: 'finest' 总是读取商店中最高分辨率的级别,这就是当答案不应该依赖于相机时你想要的——例如采样点特征.
'finest' 读取渲染器可能没有的关卡,所以它会取出冷,而不是重用已缓存的渲染路径。 一个点成本大约是一块左右;一条线沿其路径读取一串小窗口,所以其成本随着长度以像素为单位而增长;一个多边形在更细的层次上覆盖了四倍多的像素,因此在低缩放的深金字塔上可以读取更多. 它不打扰渲染:查询读取了自己的关卡,留下了所画的关卡. 对单层商店没有影响.
查询准备
queryData 等待元数据及承诺的解析级别,以便在之后立即调用 map.addLayer(layer) 之间没有交接 也没有投票 准备性失败——初始化失败、没有加载一个关卡、从地图上删除,或者在加载层前进行查询——拒绝 ZarrLayerNotReadyError 而不是空地返回。 初始化和水平负载出错 .cause。 。 。 .
失败读取也拒绝, 所以空结果意味着几何没有找到数据 .
layer.ready 暴露与承诺相同的等待,用于询问以外的用途:
map.addLayer(layer)
await layer.ready // metadata loaded and a resolution level committed
信号与 onLoadingStateChange,这是一个自旋器:它像块载荷一样翻转,没有报告关卡,所以 loading: false 可以在层仍无平分时释放。 内容 error 字段报告初始化和水平负载失败及返回到 null 在负载恢复或选择器改变后.
认证
使用 transformRequest 在请求中添加标题或证书。 该函数接收每个请求的已完全解析的URL,可以像预先签名的S3 URL一样进行per-path认证. 支持任意 获取选项。 。 。 .
// Static auth (same headers for all requests)
transformRequest: (url) => ({
url,
headers: { Authorization: `Bearer ${token}` },
})
// Presigned URLs (path-specific signatures)
transformRequest: async (url) => ({
url: await getPresignedUrl(url),
})
过期的全权证书
签署为请求的全权证书在会中过期。 这些失败本来是看不见的,因为这一层将一个被否决的读取视为缺失块并造成一个孔. onAuthError 显示状态, 以便刷新和重新添加层 :
onAuthError: async (status) => {
await refreshCredentials()
map.removeLayer(layer.id)
map.addLayer(newLayerWithFreshCredentials())
}
它只向400和401发火,最多每家店开一次火, 所以同时发生的一团故障 触发了单一的新鲜。 包括400人是因为过期的AWS临时证书返回 ExpiredToken编号 :InvalidToken 作为400个,在头部探测器或CORS指定的反应上往往没有可读的身体. 403被排除在外:S3和CloudFront将它交还给真正缺失的块,这些块是稀有的金字塔经常被击中. 没有处理器,400 宣传是一个错误,而不是被读取为缺失块.
自定义存储
高级用例如 冰块,可以直接通过自定义相容的 sarrita 商店. 当使用自定义商店时, source 成为可选 :
import { IcechunkStore } from 'icechunk-js'
const store = await IcechunkStore.open(...)
new ZarrLayer({
id: 'icechunk-layer',
store,
variable: 'temperature',
colormap: [...],
clim: [0, 100],
})
商店必须执行Zarrita Readable 与至少 a 的接口 get(key: string) 方法.
代码
图书馆使用 萨里塔 用于Zarr数据访问。 Zarrita 包括用于 bytes, (中文(简体) ), zlib, (中文(简体) ), gzip, (中文(简体) ), blosc, (中文(简体) ), lz4, (中文(简体) ), zstd, (中文(简体) ), transpose, (中文(简体) ), crc32c,以及 bitround。如果需要,可以添加更多内容!
添加自定义解码器
可使用虚拟化的NetCDF数据 numcodecs.*- 前缀的编码名称(例如, numcodecs.zlib, (中文(简体) ), numcodecs.shuffle萨里塔默认不承认 使用 codecRegistry 在创建图层前注册:
import { codecRegistry } from '@carbonplan/zarr-layer'
// Alias numcodecs.zlib → zarrita's built-in zlib
const zlibFactory = codecRegistry.get('zlib')
if (zlibFactory) codecRegistry.set('numcodecs.zlib', zlibFactory)
// numcodecs.shuffle — byte un-shuffle by element size
codecRegistry.set('numcodecs.shuffle', async () => ({
fromConfig(config: { elementsize?: number }) {
const elementsize = config?.elementsize ?? 1
return {
kind: 'bytes_to_bytes',
decode(bytes: Uint8Array): Uint8Array {
if (elementsize <= 1) return bytes
const n = bytes.length
const count = Math.floor(n / elementsize)
const out = new Uint8Array(n)
for (let i = 0; i < count; i++) {
for (let j = 0; j < elementsize; j++) {
out[i * elementsize + j] = bytes[j * count + i]
}
}
for (let i = count * elementsize; i < n; i++) {
out[i] = bytes[i]
}
return out
},
}
},
}))
谢谢
这个实验只有在这个空间中其他工作的脚步上才有可能进行. 沙尔格勒 显示自定义层是一个可行的渲染选项 zar 显示网络渲染有多灵活 。 我们从两者中借用代码和概念。 这个图书馆还依靠我们以前的工作 @碳计划/地图 对于它的许多模式。 自定义投影支持用途 @ 开发种子/ raster- project 为适应性网格生成。 数位的 LLMs 帮助了此库的编码和调试 .
许可证
此寄存器的所有代码是 麻省理工学院- 持有许可证,但如果重新使用我们的任何数字内容(图片、标志、文章等),请提供归属.
关于我们
碳计划是一个利用数据和科学进行气候行动的非营利组织. 我们的目标是通过开放数据和工具,提高气候解决方案的透明度和科学完整性。 找到更多的东西 碳平面图.org 或联系方式 打开一个问题 或者说 发送电子邮件。 。 。 .