<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://taylor-ccb-group.github.io/SpatialData.js/blog</id>
    <title>SpatialData.js Blog</title>
    <updated>2026-08-24T16:08:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://taylor-ccb-group.github.io/SpatialData.js/blog"/>
    <subtitle>SpatialData.js Blog</subtitle>
    <icon>https://taylor-ccb-group.github.io/SpatialData.js/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[@zarrita/storage build issue]]></title>
        <id>https://taylor-ccb-group.github.io/SpatialData.js/blog/build_glitch</id>
        <link href="https://taylor-ccb-group.github.io/SpatialData.js/blog/build_glitch"/>
        <updated>2026-08-24T16:08:00.000Z</updated>
        <summary type="html"><![CDATA[While copying Vitessce code across, I had initially disabled use of ZipFileStore because I had a memory of it being problematic for me in earlier prototypes - and marked 'experimental' in the zarrita documentation.]]></summary>
        <content type="html"><![CDATA[<p>While copying Vitessce code across, I had initially disabled use of <code>ZipFileStore</code> because I had a memory of it being problematic for me in earlier prototypes - and marked 'experimental' in the zarrita documentation.</p>
<p>At some point I thought that I was satisfied it was in fact working ok - but now I notice that there is in fact a related issues showing up, even without <code>ZipFileStore</code>, but perhaps more generally with <code>'@zarrita/storage'</code>?</p>
<!-- -->
<div class="language-text codeBlockContainer_ghgD theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_gZt6"><pre tabindex="0" class="prism-code language-text codeBlock_fGlX thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_P0KV"><div class="token-line" style="color:#393A34"><span class="token plain">error during build:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│ ../../node_modules/.pnpm/@zarrita+storage@0.1.3/node_modules/@zarrita/storage/dist/src/fs.js (1:9): "Buffer" is not exported by "__vite-browser-external", imported by "..…</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│ file: /Users/ptodd/code/www/SpatialData.ts/node_modules/.pnpm/@zarrita+storage@0.1.3/node_modules/@zarrita/storage/dist/src/fs.js:1:9</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│ 1: import { Buffer } from "node:buffer";</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│             ^</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│ 2: import * as fs from "node:fs";</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│ 3: import * as path from "node:path";</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">....</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">└─ Failed in 940ms at /Users/ptodd/code/www/SpatialData.ts/packages/core</span><br></div></code></pre></div></div>
<p>I had previously added a <a href="https://www.npmjs.com/package/vite-plugin-node-polyfills" target="_blank" rel="noopener noreferrer" class="">vite-plugin-node-polyfills</a> to MDV which meant that it was working in the Vite dev-server... but then I realised that the actual build script was broken, and in the brief time I spent looking at it, I couldn't seem to make both dev and build work - so I attributed it to the experimental nature of <code>ZipFileStore</code> and moved on (we've yet to make use of <code>zarrita</code> in mainline MDV, but at least everything seemed ok without that being used).</p>
<p>I don't entirely know what I've done to cause <code>...@zarrita/storage/dist/src/fs.js</code> to be included in the build - <code>fs.js</code> sounds like something that shouldn't be invoked in front-end code (unless I suppose it's using emscripten filesystem or something, which come to think of it could make sense). Anyway, it seems like a zarrita bug, but I'm still not entirely sure - I'll try to make a minimal repro at some point.</p>
<p>Now - clearly the code used in Vitessce is building ok there, and glancing at their vite config I can't see anything obviously in place that is supposed to mitigate this particular issue. I'm not sure what is so different about how our builds are configured that would cause it to be different.</p>
<p>Looking at the places where <code>'@zarrita/storage'</code> is used, I think we can refactor such that the <code>DataSourceParams</code> needed by things in the file currently named <code>VZarrDataSource.ts</code> always use the store that other SpatialData.js code is already creating. I would like to be able to support <code>ZipFileStore</code>, and in future we'll need more careful consideration around writeable-stores etc etc, but for now I think we can remove some of the code previously copied from vitessce and it at least builds ok.</p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[How minimal should the core dependencies be?]]></title>
        <id>https://taylor-ccb-group.github.io/SpatialData.js/blog/core_dependencies</id>
        <link href="https://taylor-ccb-group.github.io/SpatialData.js/blog/core_dependencies"/>
        <updated>2026-08-24T16:08:00.000Z</updated>
        <summary type="html"><![CDATA[Given that the idea is to have something analogous to the Python library, that would mean that each type of SpatialElement would return something somewhat equivalent to the corresponding library in Python - to characterise the dependencies of that package as 'minimalist', even without the batteries-included [extras], seems disingenious... Perhaps the philosophy is not so much that these will be minimal, but they should avoid needless bloat and especially any likelihood of tricky conflicts to manage (deck.gl).]]></summary>
        <content type="html"><![CDATA[<p>Given that the idea is to have something analogous to the Python library, that would mean that each type of <code>SpatialElement</code> would return something somewhat equivalent to the corresponding library in Python - to characterise the dependencies of that package as 'minimalist', even without the batteries-included <code>[extras]</code>, seems disingenious... Perhaps the philosophy is not so much that these will be minimal, but they should avoid needless bloat and especially any likelihood of tricky conflicts to manage (<em><code>&lt;cough&gt;deck.gl&lt;/cough&gt;</code></em>).</p>
<!-- -->
<p>Here is an approximate summary of the ways in which these are typed in Python:</p>
<div class="language-python codeBlockContainer_ghgD theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_gZt6"><pre tabindex="0" class="prism-code language-python codeBlock_fGlX thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_P0KV"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">Elements</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">UserDict</span><span class="token punctuation" style="color:#393A34">[</span><span class="token builtin">str</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> T</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">Images</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Elements</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">DataArray </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> DataTree</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">Labels</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Elements</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">DataArray </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> DataTree</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">Tables</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Elements</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">AnnData</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">Shapes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Elements</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">GeoDataFrame</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">Points</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Elements</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">DaskDataFrame</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_oJ_Z" id="images--labels-dataarray--datatree">Images / Labels (<code>DataArray | DataTree</code>)<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/core_dependencies#images--labels-dataarray--datatree" class="hash-link" aria-label="Direct link to images--labels-dataarray--datatree" title="Direct link to images--labels-dataarray--datatree" translate="no">​</a></h2>
<p>It is probably reasonably fair to assume that - at least in the immediate term - the priority for these raster elements is that they will primarily be used for visualisation. For viewing images in viv/MDV, it is already possible just by passing the correct path to <code>viv</code>. More work will be required in order to be able to correctly use transformations, with multiple layers etc... but that doesn't necessarily entail the need in the immediate term to have any very particularly special method for loading these parts of the stores in <code>@spatialdata/core</code>.</p>
<p>It may be that we are likely to use <a href="https://loaders.gl/" target="_blank" rel="noopener noreferrer" class="">loaders.gl</a> for integration into other parts of the ecosystem - perhaps contributing where relevant if there exist gaps.</p>
<p>It would be nice to have well-formed and typed ergonomic definitions for this - we may use the <a href="https://github.com/ome/ngff" target="_blank" rel="noopener noreferrer" class="">OME-NGFF schema</a> with <code>zod</code> to validate and provide de-facto accurate types for this data.</p>
<p>We should at least have simple canonical ways of querying various aspects of the metadata, shape etc sooner rather than later, along with working examples of using this to view images.</p>
<h2 class="anchor anchorTargetStickyNavbar_oJ_Z" id="tables-anndata">Tables (<code>AnnData</code>)<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/core_dependencies#tables-anndata" class="hash-link" aria-label="Direct link to tables-anndata" title="Direct link to tables-anndata" translate="no">​</a></h2>
<p>We have added <a href="https://github.com/ilan-gold/anndata.js" target="_blank" rel="noopener noreferrer" class="">AnnData.js</a> for this purpose. Some parts of it don't feel entirely ergonomic - but we can always make suggestions/contributions if appropriate (and that feeling may be at least partly of my not having done enough to familiarise myself with it).</p>
<p>The Vitessce <code>SpatialDataTableSource</code> is also relevant to look at particularly given that it is the parent for their implementations of Shapes and Points are based on it.</p>
<blockquote>
<p>because when a table annotates points and shapes, it can be helpful to have all of the required functionality to load the table data and the parquet data.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_oJ_Z" id="shapes-geodataframe">Shapes (<code>GeoDataFrame</code>)<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/core_dependencies#shapes-geodataframe" class="hash-link" aria-label="Direct link to shapes-geodataframe" title="Direct link to shapes-geodataframe" translate="no">​</a></h2>
<p>This is an instance where it probably makes most sense to use a similar implementation to Vitessce's <a href="https://github.com/vitessce/vitessce/blob/main/packages/file-types/spatial-zarr/src/SpatialDataShapesSource.js" target="_blank" rel="noopener noreferrer" class=""><code>SpatialDataShapesSource</code></a>, with Arrow tables.</p>
<p>If we do that - that means that the code we need to borrow/port from vitessce leaks significantly. As of this writing, I'm in the process of copying <code>SpatialDataShapesSource</code> from there, and following through the imports to port whatever else is necessary... for now, I'm naming files with a <code>V</code> at the start, like <code>VShapesSource</code> corresponds to <code>SpatialDataShapesSource</code> - the <code>SpatialData</code> part seems redundant here.</p>
<p>It is likely that we may end up with something similar to essentially having a version of their <code>file-types/(spatial-)zarr</code> package(s).</p>
<p>If we do continue to make use of this code, we should also make sure that equivalent tests are also ported etc.</p>
<h2 class="anchor anchorTargetStickyNavbar_oJ_Z" id="points-daskdataframe">Points (<code>DaskDataFrame</code>)<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/core_dependencies#points-daskdataframe" class="hash-link" aria-label="Direct link to points-daskdataframe" title="Direct link to points-daskdataframe" translate="no">​</a></h2>
<p>There is some discussion about potential different ways in which point transcript data may be represented - we think that we may want to propose new evolutions of the spec in order to facilitate the kind of interactive web-based visualisation we do in Vitessce/MDV.</p>
<p>In terms of a direct JS-analog to <code>Dask</code> in Python - this is something we need to think about more. Again, the reference-point for initial implementation is Vitessce's <a href="https://github.com/vitessce/vitessce/blob/main/packages/file-types/spatial-zarr/src/SpatialDataPointsSource.js" target="_blank" rel="noopener noreferrer" class=""><code>SpatialDataPointsSource</code></a></p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Initial Design Notes]]></title>
        <id>https://taylor-ccb-group.github.io/SpatialData.js/blog/initial_design_notes</id>
        <link href="https://taylor-ccb-group.github.io/SpatialData.js/blog/initial_design_notes"/>
        <updated>2026-08-24T16:08:00.000Z</updated>
        <summary type="html"><![CDATA[This project is a TypeScript implementation of the SpatialData library.]]></summary>
        <content type="html"><![CDATA[<p>This project is a TypeScript implementation of the <a href="https://spatialdata.scverse.org/en/stable/" target="_blank" rel="noopener noreferrer" class="">SpatialData</a> library.</p>
<p>It is a collaborative effort by the <a href="https://github.com/Taylor-CCB-Group" target="_blank" rel="noopener noreferrer" class="">Taylor CCB Group</a> at the Center for Human Genetics, Oxford University and the Gihlenborg Group at the Harvard Medical School - Department of Biomedical Informatics.</p>
<!-- -->
<p>The approach taken to the design is to follow the structure of the original Python library, adapting it to TypeScript with the intention that it should be familiar to users of the original library and aligned with best practices in frontend development. It should be usable in a server-side environment as well, and some consideration will be given to this, but it is not the primary focus of the project and at this stage isn't something that is anticipated to be a priority.</p>
<p>Once it has reached a state in which a useful subset of the functionality has been implemented, it will be released in an 'alpha' state as a package on npm.</p>
<p>The aim is to do this soon, such that <a href="https://mdv.ndm.ox.ac.uk/" target="_blank" rel="noopener noreferrer" class="">MDV</a> can have a new type of <code>DataLoader</code> based on this. Actually, without getting too derailed into MDV-specifics, it may be that the first use of the library will be for accessing and rendering things like <code>Points</code> transcripts, in a way that sits-beside the main data at least for the time-being.</p>
<p>There is a lot of overlap between MDV and <a href="https://vitessce.io/" target="_blank" rel="noopener noreferrer" class="">vitessce</a>. It is anticipated that substantial portions of this codebase will be based on existing implementations in vitessce. We had discussed approaches to refactoring their code such that the data-loading functionality could be exposed as something to be exposed as a separate package - I wasn't quite clear how we'd adapt each-others idioms about what kind of common interface we'd use that would allow our MDV idioms to map to theirs.</p>
<p>The intention is that as this becomes mature, both projects will make use of it, and it will be a useful part of the ecosystem more generally.</p>
<h2 class="anchor anchorTargetStickyNavbar_oJ_Z" id="how-complete-should-it-aim-to-be">How complete should it aim to be?<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/initial_design_notes#how-complete-should-it-aim-to-be" class="hash-link" aria-label="Direct link to How complete should it aim to be?" title="Direct link to How complete should it aim to be?" translate="no">​</a></h2>
<p>Hopefully, it will not require a huge amount of effort to be able to get at least a useful subset of the core data-loading functionality working well.</p>
<p>Some functionality that will be a lower priority are things like utilities for converting between raster <code>labels</code> and vector <code>shapes</code>. As of this writing, I don't have comprehensive knowledge of the original spec; writing this is a helpful exercise in better understanding it, but it could be that there are aspects of it I haven't</p>
<p>The very first version will likely not include any methods for altering the data - and it may require some careful consideration of how persistence should end up working, particularly from a frontend perspective. This is a somewhat high priority: from an MDV perspective, we likely want to use zarr stores rather than HDF5 for project data in the near future.</p>
<h2 class="anchor anchorTargetStickyNavbar_oJ_Z" id="what-should-the-api-look-like">What should the API look like?<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/initial_design_notes#what-should-the-api-look-like" class="hash-link" aria-label="Direct link to What should the API look like?" title="Direct link to What should the API look like?" translate="no">​</a></h2>
<p>The guiding principle is to make it such that Python code would translate in a direct way to JS/TS - so where in Python you have something like this:</p>
<div class="language-python codeBlockContainer_ghgD theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_gZt6"><pre tabindex="0" class="prism-code language-python codeBlock_fGlX thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_P0KV"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> spatialdata </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> sd</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">sdata </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> sd</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">read_zarr</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"path/to/zarr"</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>You would write something like this:</p>
<div class="language-ts codeBlockContainer_ghgD theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_gZt6"><pre tabindex="0" class="prism-code language-ts codeBlock_fGlX thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_P0KV"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> sd </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'spatialdata'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> sdata </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> sd</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">readZarr</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"path/to/zarr"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p><code>sdata</code> should be an object with a similar interface to the Python version (i.e. <code>class SpatialData</code> in both cases).</p>
<p>In the context of JS accessing remote data, this inevitably means a lot of <code>async</code> operations, and potentially complex data structures, that should use JavaScript equivalents of the packages used by <code>spatialdata</code> in Python.</p>
<p>I'm not so sure whether we want to mirror the ability to do things like</p>
<div class="language-python codeBlockContainer_ghgD theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_gZt6"><pre tabindex="0" class="prism-code language-python codeBlock_fGlX thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_P0KV"><div class="token-line" style="color:#393A34"><span class="token plain">sdata</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"some_arbitrary_name"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> sdata</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"table"</span><span class="token punctuation" style="color:#393A34">]</span><br></div></code></pre></div></div>
<p>I suppose it would be possible to use a <code>Proxy</code> for this, and it may not be a terrible idea... but at least in a first-pass, the data will be read-only, and access will likely be via somewhat more explicit/verbose interfaces. Certainly it would be a mistake to try to introduce too much clever meta-programming before at least having a working MVP.</p>
<p>Looking at the Python <code>repr</code> returned by a <code>SpatialData</code> object (names changed to protect the innocent):</p>
<div class="language-text codeBlockContainer_ghgD theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_gZt6"><pre tabindex="0" class="prism-code language-text codeBlock_fGlX thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_P0KV"><div class="token-line" style="color:#393A34"><span class="token plain">SpatialData object, with associated Zarr store: /path/to/spatialdata.zarr</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── Images</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│     └── 'Run3-14-7-23_Output_region_1_z3': DataTree[cyx] (5, 53066, 55984), (5, 26533, 27992), (5, 13266, 13996), (5, 6633, 6998), (5, 3316, 3499)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── Points</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│     └── 'Run3-14-7-23_Output_region_1_transcripts': DataFrame with shape: (&lt;Delayed&gt;, 9) (2D points)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── Shapes</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│     └── 'Run3-14-7-23_Output_region_1_polygons': GeoDataFrame shape: (23961, 9) (2D shapes)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">└── Tables</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      └── 'table': AnnData (23961, 466)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">with coordinate systems:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ▸ 'global', with elements:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Run3-14-7-23_Output_region_1_z3 (Images), Run3-14-7-23_Output_region_1_transcripts (Points), Run3-14-7-23_Output_region_1_polygons (Shapes)</span><br></div></code></pre></div></div>
<p>There are elements represented by <code>DataTree</code>, <code>dask.DataFrame</code>, <code>GeoDataFrame</code>, and <code>AnnData</code>... this is not an exhaustive list.</p>
<p>In most cases, a combination of <code>zarrita</code>, <code>AnnData.js</code>, and some of the methods implemented in <code>vitessce</code> should be able to represent these various models.</p>
<h2 class="anchor anchorTargetStickyNavbar_oJ_Z" id="validation-and-exception-handling">Validation and exception handling<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/initial_design_notes#validation-and-exception-handling" class="hash-link" aria-label="Direct link to Validation and exception handling" title="Direct link to Validation and exception handling" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_oJ_Z" id="images-and-labels---ome-ngff-schema">Images and Labels - OME-NGFF Schema<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/initial_design_notes#images-and-labels---ome-ngff-schema" class="hash-link" aria-label="Direct link to Images and Labels - OME-NGFF Schema" title="Direct link to Images and Labels - OME-NGFF Schema" translate="no">​</a></h3>
<p>The <a href="https://github.com/ome/ngff" target="_blank" rel="noopener noreferrer" class="">OME-NGFF specification</a> should be able to drive validation of these, perhaps via something like <a href="https://www.npmjs.com/package/zod-from-json-schema" target="_blank" rel="noopener noreferrer" class=""><code>zod-from-json-schema</code></a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_oJ_Z" id="visualization-and-experimental-features">Visualization and experimental features<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/initial_design_notes#visualization-and-experimental-features" class="hash-link" aria-label="Direct link to Visualization and experimental features" title="Direct link to Visualization and experimental features" translate="no">​</a></h2>
<p>The core module should avoid any dependencies on the <code>vis.gl</code> ecosystem that both MDV and vitessce/viv use.</p>
<p>Re-usable visual elements are out of the scope of what we've discussed for immediate plans. It may make sense to have some <code>@deck.gl/community-layers</code> type package that could have some common utilities for rendering, annotating etc...</p>
<p>I believe it will be particularly useful to have at least some sample visualizations that can be used for testing and demonstration purposes within this documentation. That means that while we are editing the code, we can have interactively updated feedback on the work as it progresses.</p>
<p>Perhaps rather than letting the <code>/docs</code> package in the monorepo get bloated, it'd be worth having some <code>packages/layers</code>, <code>packages/hooks</code> sooner rather than later...</p>
<p>Part of the shared interests we have as collaborators are around potential different ways of representing points in the SpatialData spec itself, and it may be that we have a package relating to experimental prototypes around such features.</p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[sketch]]></title>
        <id>https://taylor-ccb-group.github.io/SpatialData.js/blog/sketch</id>
        <link href="https://taylor-ccb-group.github.io/SpatialData.js/blog/sketch"/>
        <updated>2026-08-24T16:08:00.000Z</updated>
        <summary type="html"><![CDATA[Using MDX format to render a react component that will respond to HMR as we edit the code to start doing something useful.]]></summary>
    </entry>
    <entry>
        <title type="html"><![CDATA[Transformations, attrs, metadata versions, testing oh my!]]></title>
        <id>https://taylor-ccb-group.github.io/SpatialData.js/blog/transformations_attrs</id>
        <link href="https://taylor-ccb-group.github.io/SpatialData.js/blog/transformations_attrs"/>
        <updated>2026-08-24T16:08:00.000Z</updated>
        <summary type="html"><![CDATA[Should consolidated metadata be considered the source of truth?]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_oJ_Z" id="should-consolidated-metadata-be-considered-the-source-of-truth">Should consolidated metadata be considered the source of truth?<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/transformations_attrs#should-consolidated-metadata-be-considered-the-source-of-truth" class="hash-link" aria-label="Direct link to Should consolidated metadata be considered the source of truth?" title="Direct link to Should consolidated metadata be considered the source of truth?" translate="no">​</a></h2>
<p>Short answer to the above question is probably "no" in the long term, and "I don't see why not, as long as we're clear that we expect stores to be treated as immutable for now". I'd welcome any feedback on my stance there.</p>
<p>In the meanwhile, some thoughts on breaking out of my current procrastination loop.</p>
<!-- -->
<p>Development has felt somewhat stalled as I've been in a protracted procrastination loop about how to process and represent metadata, which is something of a pre-requisite to parsing transformations, which in turn is a pretty essential aspect of getting the library to actually be capable of doing anything useful or interesting.</p>
<p>Perfectionism and other distractions with MDV demos etc have somewhat disrupted my focus on this. At the same time, I've been doing a bit more work on <code>avivatorish</code> state in the demo <code>ImageView</code> component and I'm not really convinced that the way I'm modelling state there is right - and also haven't thought very much about how this'll be exposed as a public API. That's not what I want to address here, but I suppose it has been another detriment to focus.</p>
<p>I wasn't quite sure why <code>zarrita</code> had chosen to make the raw consolidated metadata so private... I've been allowing this to block me more than I should. Somehow, despite me having made a stated decision weeks ago to separately parse <code>zmetadata</code> and get on with life, it still hasn't quite been sitting right that it wasn't exposed so I <a href="https://github.com/manzt/zarrita.js/issues/322" target="_blank" rel="noopener noreferrer" class="">raised an issue</a>. I think my brain has been somewhat more focused on the question of "we need a coherent representation of the hierarchy and associated metadata" than "can we display an image with cell segmentation shapes overlaid, even if it does involve a few more <code>decode(await store.get(...))</code> than I'd like". I am very wary of releasing a version of this library that bakes in technical debt in the form of unergomic patterns for users.</p>
<p>My default stance is that I still have a relatively limited understanding of <code>zarr</code> and that others like Trevor Manz probably know better. There clearly is a rationale for the design of <code>zarrita</code>, and hopefully it will evolve to more comprehensively and ergonomically expose relevant things. That said, I find myself wanting to expand some of the things in <code>zarrUtils.ts</code> into a more generally re-usable <code>"zarrextra"</code> package built on top of it.</p>
<p>It should be stated that as of this writing, none of the data I have been using has been generated with the latest version of <code>spatialdata</code> (0.6.x) and corresponding <code>zarr v3</code> (with the associated changes to consolidated metadata, which in <code>v3</code> are still not entirely stable as far as I understand). So the requirements of supporting each of those has been somewhat on my mind, and hopefully will not be too difficult, but for the sake of breaking procrastination cycles it should be clearly stated that the initial implementation will work against the older specification. On the MDV side, this difference first came to my attention when a collaborator tried to use the <code>mdvtools.spatial.conversion</code> script with outputs from 0.6.0, and they failed to open with 0.5.0 that is currently used there.</p>
<p>We should aim to support both versions soon, and related to that, establish a set of test fixtures associated with them. The <code>defaultUrl = 'https://storage.googleapis.com/vitessce-demo-data/spatialdata-august-2025/visium_hd_3.0.0.spatialdata.zarr'</code> used by the demo app is actually not able to be opened with the version of <code>spatialdata</code> we have in the MDV environment currently.</p>
<div class="language-text codeBlockContainer_ghgD theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_gZt6"><pre tabindex="0" class="prism-code language-text codeBlock_fGlX thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_P0KV"><div class="token-line" style="color:#393A34"><span class="token plain">&gt;&gt;&gt; import spatialdata as sd</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">&gt;&gt;&gt; sdata = sd.read_zarr('https://storage.googleapis.com/vitessce-demo-data/spatialdata-august-2025/visium_hd_3.0.0.spatialdata.zarr')</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">...</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pyarrow.lib.ArrowInvalid: Unrecognized filesystem type in URI: https:/storage.googleapis.com/vitessce-demo-data/spatialdata-august-2025/visium_hd_3.0.0.spatialdata.zarr/shapes/Visium_HD_Mouse_Small_Intestine_square_002um/shapes.parquet</span><br></div></code></pre></div></div>
<p>Given that this is my go-to default datasource when working on this, that's not really a very reassuring thing to have lingering in the back of my mind.</p>
<p>Also as of this writing, there is no testing in place here to speak of, and limited coverage in MDV. While I don't necessarily want to go full TDD, the intention is definitely to have good coverage - and for that to stand as a useful reference as to the implementation status and use of various features. We might use Python in the <code>spatialdata.js</code> repo for the purposes of using <code>spatialdata</code> mock-data features for generating test fixtures. Given the known vagueries of output from different versions, there may even be a case to be made for swallowing the added test-environment-complexity of having tests based around different versions.</p>
<p>I do intend to update the version used in MDV at some point soon - particularly as this will clear up some issues we currently have with older python dependencies being brought in from there. It will make sense from my point of view to align <code>spatialdata.js</code> with <code>MDV</code> - and this is quite likely to mean that an initial <code>0.0.1</code> release of this will still be tied to older outputs, followed shortly after by an update aimed at supporting both. Alternatively, it may be that we prioritise support for the newer version to allow us to update the MDV dependency sooner rather than later.</p>
<h2 class="anchor anchorTargetStickyNavbar_oJ_Z" id="immediate-plans">Immediate plans<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/transformations_attrs#immediate-plans" class="hash-link" aria-label="Direct link to Immediate plans" title="Direct link to Immediate plans" translate="no">​</a></h2>
<p>Wrap up how we parse consolidated metadata in <code>zarrUtils.ts</code> and try to follow Mark's recommendations:</p>
<blockquote>
<p>Mark Keller: We should be able to use <a href="https://github.com/hms-dbmi/zod-ome-ngff" target="_blank" rel="noopener noreferrer" class="">https://github.com/hms-dbmi/zod-ome-ngff</a>, either directly, or by exporting sub-schemas that can be reused via composition of zod schemas <a href="https://github.com/hms-dbmi/zod-ome-ngff/issues/23" target="_blank" rel="noopener noreferrer" class="">https://github.com/hms-dbmi/zod-ome-ngff/issues/23</a>
Mark Keller: I recently updated the schemas there to support OME-NGFF v0.5
Mark Keller: A long time ago I started to implement typescript types for the transforms <a href="https://github.com/vitessce/vitessce/blob/a1e4ffddb5b75fb44d5402cf7d27374c127f6f28/packages/types/src/ngff-types.ts#L35" target="_blank" rel="noopener noreferrer" class="">here</a>. They are probably out of date now that the transformations proposals have evolved but maybe worth using as a starting point.</p>
</blockquote>
<p>I had a few sketchy things in my working copy that are probably mostly redundant WRT that but may be worth stashing somewhere... the <code>zod-ome-ngff</code> should be a good approach on the face of it.</p>
<h2 class="anchor anchorTargetStickyNavbar_oJ_Z" id="further-future-considerations-for-mutable-stores">Further future considerations for mutable stores.<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/transformations_attrs#further-future-considerations-for-mutable-stores" class="hash-link" aria-label="Direct link to Further future considerations for mutable stores." title="Direct link to Further future considerations for mutable stores." translate="no">​</a></h2>
<p>The initial version of this library and its use in MDV will be explicitly limited to stores that are considered effectively immutable - but this is actually not something that is likely to align with our goals for MDV in the mid-term. From my current understanding, consolidated metadata should support this use-case well.</p>
<p>Mutable stores of course open a whole new set of rabbit-holes... on the face of it, I think we'll need to seriously investigate <a href="https://icechunk.io/" target="_blank" rel="noopener noreferrer" class="">icechunk</a> if and when the time comes for this. Ideally, we'd be able to support workflows where a user makes a new project (with an associated empty <code>spatialdata</code> store), adds some image data, invokes a cell-segmentation job which after some time leads to more elements in that coordinate-system, annotates some of the data thus produced, etc etc. This is of course not to be taken at all lightly when it may involve multiple simultaneous users working with the same underlying store.</p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Notes on ported Vitessce code, TypeScript etc.]]></title>
        <id>https://taylor-ccb-group.github.io/SpatialData.js/blog/vitessce_porting_ts</id>
        <link href="https://taylor-ccb-group.github.io/SpatialData.js/blog/vitessce_porting_ts"/>
        <updated>2026-08-24T16:08:00.000Z</updated>
        <summary type="html"><![CDATA[A lot of the Vitessce code is written in .js files with // @ts-check and quite extensive type-annotations in jsdoc form.]]></summary>
        <content type="html"><![CDATA[<p>A lot of the Vitessce code is written in <code>.js</code> files with <code>// @ts-check</code> and quite extensive type-annotations in <code>jsdoc</code> form.</p>
<p>While moving the code across, I've been been changing this so that it is more regular TypeScript - which has mostly been a fairly straightforward process, and I think the result is somewhat cleaner... but some of these changes are also intermingled with what should be very minor changes to functionality...</p>
<!-- -->
<ul>
<li class="">the change of a <code>return null</code> to just <code>return</code> where another function was assinging the returned value to something annotated as 'optional' for example. I also noticed the mechanism for <code>getParquetModule</code> was being used in a way that would cause it to be re-fetched for instantiation of <code>SpatialDataTableSource</code> - I think the pattern used may have been following the way I'd implemented <a href="https://github.com/hms-dbmi/viv/pull/903" target="_blank" rel="noopener noreferrer" class="">importing openjpeg-wasm in this draft viv PR</a>, which I now notice I haven't updated with the equivalent of <a href="https://github.com/Taylor-CCB-Group/MDV/commit/4caeb4a8c435c64de3ab929284cd75fa1e7eff68" target="_blank" rel="noopener noreferrer" class="">how I changed this in MDV</a>.</li>
</ul>
<p>I don't <em>think</em> I've done anything that should intefere with functionality - but I've been through this process before adopting any actual tests or uses of the underlying code in any active code-path. I've circled the sun enough times to be very wary of assuming that everything will be fine without proper verification... and whether the changes are improvements or not, the fact that they exist is worth flagging.</p>
<p>It means that there is now the potential for the existence of two divergent implementations to exist - I believe the intention is that this library should be able to essentially stand-in for the existing implementations of <code>SpatialData</code> in Vitessce - but for that to work from their perspective would probably mean reviewing the extent to which code is ported, how it should be structured etc... The way I have so far structured things here is somewhat loose in certain ways, and I haven't (so far) comprehensively included everything that will ultimately be necessary.</p>
<h2 class="anchor anchorTargetStickyNavbar_oJ_Z" id="i-prefer-ts-expect-error-to-ts-ignore">I prefer <code>//@ts-expect-error</code> to <code>//@ts-ignore</code>.<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/vitessce_porting_ts#i-prefer-ts-expect-error-to-ts-ignore" class="hash-link" aria-label="Direct link to i-prefer-ts-expect-error-to-ts-ignore" title="Direct link to i-prefer-ts-expect-error-to-ts-ignore" translate="no">​</a></h2>
<p>There are a few places in the code where I've left <code>//@ts-expect-error</code> annotations, with comments. I prefer this to <code>ts-ignore</code> as it means that in such cases where later changes to other parts of the code make them redundant, they then appear as errors, showing that the annotation can be removed. It's less easy to know whether a <code>ts-ignore</code> is still relevant. There is only one <code>ts-ignore</code> in Vitessce so in a sense a bit of a moot point there - as of this writing there are a few here, and I would like to aim to eradicate them (there are quite a few in MDV sadly, and I don't know when I'll manage to get around to those).</p>
<h2 class="anchor anchorTargetStickyNavbar_oJ_Z" id="hopefully-we-can-make-any-history-at-some-point">Hopefully we can make <code>any</code> history at some point.<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/vitessce_porting_ts#hopefully-we-can-make-any-history-at-some-point" class="hash-link" aria-label="Direct link to hopefully-we-can-make-any-history-at-some-point" title="Direct link to hopefully-we-can-make-any-history-at-some-point" translate="no">​</a></h2>
<p>I would definitely prefer that we can type things well enough to avoid this.</p>
<p>There are a few places where better use of generics on things like <code>Chunk&lt;DataType&gt;</code> etc would help... here is a concrete example using Zarrita's <code>is</code> to type-guard in a <code>loadNumeric</code> method:</p>
<div class="language-ts codeBlockContainer_ghgD theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_gZt6"><pre tabindex="0" class="prism-code language-ts codeBlock_fGlX thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_P0KV"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">loadNumeric</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> storeRoot </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> arr </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">zarrOpen</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">storeRoot</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">resolve</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> kind</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'array'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">arr</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">is</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"number"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string string" style="color:#e3116c">Expected a numeric array at </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">path</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string string" style="color:#e3116c">, but got </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">arr</span><span class="token template-string interpolation punctuation" style="color:#393A34">.</span><span class="token template-string interpolation">dtype</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// now we have a type-guarded array, the return type will be correctly inferred</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">zarrGet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">arr</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// return zarrOpen(storeRoot.resolve(path), { kind: 'array' })</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">//   .then(arr =&gt; zarrGet(arr));</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>This will change runtime behaviour in cases where the <code>arr.is("number")</code> check doesn't pass. It seems like the occassions on that would be different should only be when the underlying assumptions in the code are false, and that it will result in better error-handling, but it is also possible that there is something wrong in my understanding here.</p>
<p>This type design in Zarrita seems like a really good thing, encouraging the use of types in a way that properly ensures actual runtime validation is reflected in what the LSP is able to understand about the working of the code (even if the above code was written in JS, a modern editor would likely have enough information to accurately reflect the types, aside from the trivial <code>path: string</code>).</p>
<p>If we do end up extensively using Vitessce code in SpatialData.js, hopefully it is useful to have another pair of eyes on it - and better levereging this feature is definitely something that I advocate.</p>
<h2 class="anchor anchorTargetStickyNavbar_oJ_Z" id="inheritence-hierarchy---is-this-the-right-abstraction">Inheritence hierarchy - is this the right abstraction?<a href="https://taylor-ccb-group.github.io/SpatialData.js/blog/vitessce_porting_ts#inheritence-hierarchy---is-this-the-right-abstraction" class="hash-link" aria-label="Direct link to Inheritence hierarchy - is this the right abstraction?" title="Direct link to Inheritence hierarchy - is this the right abstraction?" translate="no">​</a></h2>
<p><code>class SpatialDataShapesSource extends SpatialDataTableSource</code></p>
<div class="language-ts codeBlockContainer_ghgD theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_gZt6"><pre tabindex="0" class="prism-code language-ts codeBlock_fGlX thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_P0KV"><div class="token-line" style="color:#393A34"><span class="token doc-comment comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token doc-comment comment" style="color:#999988;font-style:italic"> * This class is a parent class for tables, shapes, and points.</span><br></div><div class="token-line" style="color:#393A34"><span class="token doc-comment comment" style="color:#999988;font-style:italic"> * This is because these share functionality, for example:</span><br></div><div class="token-line" style="color:#393A34"><span class="token doc-comment comment" style="color:#999988;font-style:italic"> * - both shapes (the latest version) and points use parquet-based formats.</span><br></div><div class="token-line" style="color:#393A34"><span class="token doc-comment comment" style="color:#999988;font-style:italic"> * - both shapes (a previous version) and tables use zarr-based formats.</span><br></div><div class="token-line" style="color:#393A34"><span class="token doc-comment comment" style="color:#999988;font-style:italic"> * - logic for manipulating spatialdata element paths is shared across all elements.</span><br></div><div class="token-line" style="color:#393A34"><span class="token doc-comment comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SpatialDataTableSource</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AnnDataSource</span><br></div></code></pre></div></div>
<p>This means that the interface for <code>Shapes</code> inherits everything from <code>AnnData</code>, which is not an accurate way of modelling the actual spec - there are a lot of things about <code>AnnData</code> that are not inherent to <code>GeoDataFrame</code>, which in python is what is used for <code>class Shapes(Elements[GeoDataFrame])</code>.</p>
<p>I find this distracting as my habbit when learning and reasoning about code tends to rely heavily on exploring what the editor thinks it 'knows' about what interface a given symbol...</p>
<p>I posit that the sharing of functionality between tables/points/shapes mentioned here could probably be accomplished through composition than inheritence; I haven't formulated a precise design for this just yet.</p>
<p>So... as I write this, on top of my local changes to rev <code>8ff418e</code> in this repository, I am investigating how the code looks if we start trying to use this <code>SpatialDataShapesSource</code> for <code>Elements&lt;'shapes'&gt;</code></p>
<div class="language-ts codeBlockContainer_ghgD theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_gZt6"><pre tabindex="0" class="prism-code language-ts codeBlock_fGlX thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_P0KV"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">Elements</span><span class="token class-name operator" style="color:#393A34">&lt;</span><span class="token class-name constant" style="color:#36acaa">T</span><span class="token class-name"> </span><span class="token class-name keyword" style="color:#00009f">extends</span><span class="token class-name"> ElementName</span><span class="token class-name operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> Record</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">Promise</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token constant" style="color:#36acaa">T</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'tables'</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> Table</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">T</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'shapes'</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> SpatialDataShapesSource </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> SpatialElement</span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SpatialData</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token operator" style="color:#393A34">...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">shapes</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// we already have a store in scope at this point and want to open a path within it, but I'm not sure we're allowed?</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> store </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tryConsolidated</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">zarr</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">FetchStore</span><span class="token punctuation" style="color:#393A34">(</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation keyword" style="color:#00009f">this</span><span class="token template-string interpolation punctuation" style="color:#393A34">.</span><span class="token template-string interpolation">url</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string string" style="color:#e3116c">/shapes/</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">key</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">SpatialDataShapesSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> store</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> fileType</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'.zarr'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// side-note, would rather these not be immediately-invoked</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>When I start trying to write some hooks that access <code>SpatialData.shapes</code>, while there are undoubtedly ways of using it to get the actual data we're interested in, it is somewhat obscured by other inherited things. In order to use the <code>loadPolygonShapes()</code> method I need to know a <code>path</code> to it...</p>
<p>So, working through my thought process... perhaps I should indeed be using the root <code>store</code> from the outer scope, and providing a more focused API for interfacing with the actual internal parquet data, with any relevant <code>path</code> captured within an appropriate scope - but as of this writing I seem to have a broken build, HMR not working as expected, and I think I need to get some fresh air/excercise/rest before a bit of other refactoring.</p>]]></content>
    </entry>
</feed>