Skip to content

Commit 0af89d5

Browse files
committed
fixing vertex attribute reading
1 parent a0b3ec7 commit 0af89d5

3 files changed

Lines changed: 33 additions & 7 deletions

File tree

src/datasource/zarr-vectors/backend.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ export class ZarrVectorsAnnotationSpatialIndexSourceBackend extends WithParamete
270270
attributeNames.map(async (name, i) => {
271271
const url = joinBaseUrlAndPath(
272272
baseUrl,
273-
`attributes/${name}/${chunkKey}/${CHUNK_DATA_FILE}`,
273+
`vertex_attributes/${name}/${chunkKey}/${CHUNK_DATA_FILE}`,
274274
);
275275
const response = await this.sharedKvStoreContext.kvStoreContext.read(
276276
url,

src/datasource/zarr-vectors/base.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export class ZarrVectorsAnnotationSpatialIndexSourceParameters {
6161
baseUrl: string;
6262
rank: number;
6363
// Parallel arrays: attributeNames[i] is the directory name under
64-
// <baseUrl>/attributes/, and attributeDtypes[i] is the numpy dtype of
64+
// <baseUrl>/vertex_attributes/, and attributeDtypes[i] is the numpy dtype of
6565
// the chunk byte blob. Index i in this list corresponds to property
6666
// index i on the parent AnnotationSource.
6767
attributeNames: string[];

src/datasource/zarr-vectors/frontend.ts

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -261,15 +261,15 @@ async function listAttributeNames(
261261
levelUrl: string,
262262
options: Partial<ProgressOptions>,
263263
): Promise<string[]> {
264-
const attributesUrl = joinBaseUrlAndPath(levelUrl, "attributes/");
264+
const attributesUrl = joinBaseUrlAndPath(levelUrl, "vertex_attributes/");
265265
const response = await sharedKvStoreContext.kvStoreContext
266266
.list(attributesUrl, {
267267
responseKeys: "suffix",
268268
...options,
269269
})
270270
.catch(() => undefined);
271271
if (response === undefined) return [];
272-
// Each subdirectory under attributes/ is one property. Strip the
272+
// Each subdirectory under vertex_attributes/ is one property. Strip the
273273
// trailing "/" if present.
274274
return response.directories
275275
.map((d) => (d.endsWith("/") ? d.slice(0, -1) : d))
@@ -338,10 +338,11 @@ async function buildPropertySpecsAndDtypes(
338338

339339
for (const name of orderedNames) {
340340
let dtype: string | undefined;
341+
let arrayMeta: any | undefined;
341342
try {
342-
const arrayMeta = await getJsonResource(
343+
arrayMeta = await getJsonResource(
343344
sharedKvStoreContext,
344-
joinBaseUrlAndPath(levelUrl, `attributes/${name}/zarr.json`),
345+
joinBaseUrlAndPath(levelUrl, `vertex_attributes/${name}/zarr.json`),
345346
`attribute ${JSON.stringify(name)} metadata`,
346347
options,
347348
);
@@ -357,13 +358,38 @@ async function buildPropertySpecsAndDtypes(
357358
attributeNames.push(name);
358359
attributeDtypes.push(dtype as ZarrVectorsAttributeDtype);
359360

361+
// Dictionary-encoded (categorical/enum) attributes: surface as a
362+
// numeric annotation property with enum_values + enum_labels so
363+
// shaders see category names, not raw codes. The on-disk
364+
// convention is documented in zarr-vectors:
365+
// ``encoding: "dictionary"`` + ``categories: [...]`` lives in the
366+
// attribute array's metadata block.
367+
let enumValues: number[] | undefined;
368+
let enumLabels: string[] | undefined;
369+
if (arrayMeta?.attributes?.encoding === "dictionary") {
370+
const categories = arrayMeta.attributes.categories;
371+
if (Array.isArray(categories)) {
372+
enumLabels = categories.map((c: unknown) => String(c));
373+
enumValues = enumLabels.map((_, i) => i);
374+
}
375+
}
376+
360377
const hint = declaredByName.get(name);
361378
if (hint !== undefined) {
362-
rawPropertyJson.push({ ...hint, type: hint.type ?? dtype });
379+
rawPropertyJson.push({
380+
...hint,
381+
type: hint.type ?? dtype,
382+
// Hints win for enum metadata; only fill in from the on-disk
383+
// dictionary when the user didn't already specify it.
384+
enum_values: hint.enum_values ?? enumValues,
385+
enum_labels: hint.enum_labels ?? enumLabels,
386+
});
363387
} else {
364388
rawPropertyJson.push({
365389
id: name,
366390
type: ATTR_DTYPE_TO_NG_TYPE[dtype],
391+
enum_values: enumValues,
392+
enum_labels: enumLabels,
367393
});
368394
}
369395
}

0 commit comments

Comments
 (0)