From ad12f84f9d8d96e82d8d8d12e0c183b7c1782df6 Mon Sep 17 00:00:00 2001 From: Lane Sawyer Date: Tue, 28 Apr 2026 16:22:15 -0700 Subject: [PATCH 1/3] chore: Migrate to oxfmt --- .github/ISSUE_TEMPLATE/bug_report.md | 14 +- .github/PULL_REQUEST_TEMPLATE.md | 36 +-- .oxfmtrc.json | 11 + CODE_OF_CONDUCT.md | 30 +-- CONTRIBUTING.md | 86 +++---- README.md | 8 +- biome.json | 10 +- cliff.toml | 36 +-- package.json | 11 +- packages/core/README.md | 2 +- packages/core/src/abstract/async-frame.ts | 6 +- packages/core/src/abstract/render-server.ts | 4 +- packages/core/src/abstract/types.ts | 4 +- packages/core/src/dataset-cache.ts | 14 +- packages/core/src/index.ts | 13 +- packages/core/src/layers/layer-2D.ts | 4 +- packages/core/src/layers/types.ts | 2 +- packages/core/src/render-queue.ts | 4 +- .../priority-cache.test.ts | 98 ++++---- .../shared-priority-cache/priority-cache.ts | 2 +- .../src/shared-priority-cache/shared-cache.ts | 8 +- .../core/src/shared-priority-cache/utils.ts | 4 +- packages/core/src/test/render-cache.test.ts | 4 +- packages/core/src/test/render-queue.test.ts | 8 +- packages/core/src/test/test-utils.ts | 2 +- packages/core/src/workers/worker-pool.ts | 2 +- packages/dzi/changelog.md | 2 +- packages/dzi/src/index.ts | 6 +- packages/dzi/src/renderer.ts | 2 +- packages/geometry/changelog.md | 6 +- packages/geometry/src/axisAngle.ts | 4 +- packages/geometry/src/index.ts | 17 +- packages/geometry/src/spatialIndexing/tree.ts | 4 +- .../geometry/src/tests/Rectangle2D.test.ts | 2 +- packages/geometry/src/tests/box2D.test.ts | 2 +- packages/geometry/src/tests/box3D.test.ts | 4 +- packages/omezarr/changelog.md | 8 +- packages/omezarr/src/index.ts | 6 +- packages/omezarr/src/sliceview/loader.test.ts | 2 +- packages/omezarr/src/sliceview/loader.ts | 6 +- .../omezarr/src/sliceview/slice-renderer.ts | 6 +- packages/omezarr/src/zarr/cache-lower.ts | 4 +- .../fetch-data.worker-loader.ts | 6 +- .../zarr/cached-loading/fetch-slice.worker.ts | 4 +- .../src/zarr/cached-loading/store.test.ts | 4 +- .../omezarr/src/zarr/cached-loading/store.ts | 10 +- packages/omezarr/src/zarr/loading.ts | 18 +- packages/omezarr/src/zarr/types.ts | 2 +- packages/scatterbrain/readme.md | 5 +- packages/scatterbrain/src/dataset.ts | 12 +- packages/scatterbrain/src/renderer.ts | 18 +- packages/scatterbrain/src/shader.ts | 14 +- pnpm-lock.yaml | 217 ++++++++++++++++++ site/changelog.md | 2 +- .../content/docs/developers/dependencies.md | 2 + .../content/docs/developers/development.md | 13 ++ .../src/content/docs/developers/publishing.md | 2 +- site/src/content/docs/examples/dzi.mdx | 45 ++-- site/src/content/docs/examples/layers.mdx | 14 +- site/src/content/docs/examples/overview.mdx | 2 +- .../content/docs/getting-started/packages.md | 1 + site/src/content/docs/index.mdx | 54 +++-- site/src/content/docs/packages/core.mdx | 4 +- site/src/content/docs/packages/dzi.mdx | 5 +- site/src/content/docs/packages/geometry.mdx | 4 +- site/src/content/docs/packages/ome-zarr.mdx | 5 +- .../content/docs/packages/scatterbrain.mdx | 5 +- site/src/examples/common/camera.ts | 2 +- .../common/loaders/scatterplot/data.ts | 6 +- .../scatterplot/scatterbrain-loader.ts | 12 +- .../data-renderers/annotation-renderer.ts | 8 +- .../dynamicGridSlideRenderer.ts | 12 +- .../examples/data-renderers/lineRenderer.ts | 2 +- .../examples/data-renderers/scatterplot.ts | 2 +- .../simpleAnnotationRenderer.ts | 4 +- .../examples/data-renderers/versa-renderer.ts | 4 +- .../data-renderers/volumeSliceRenderer.ts | 12 +- .../annotation/annotation-to-mesh.ts | 19 +- site/src/examples/dzi/dzi-demo.tsx | 5 +- site/src/examples/dzi/dzi-viewer.tsx | 2 +- site/src/examples/layers.ts | 34 +-- .../multithreading/multithreading-demo.tsx | 10 +- .../omezarr/gallery-demo/omezarr-gallery.tsx | 30 ++- .../omezarr/minimal-example/sliceview.tsx | 6 +- .../priority-cache-demo/omezarr-client.tsx | 12 +- .../omezarr-via-priority-cache.tsx | 5 +- .../priority-cache-demo/render-utils.ts | 10 +- .../selectable-image-demo/omezarr-demo.tsx | 38 ++- .../selectable-image-demo/omezarr-viewer.tsx | 6 +- site/src/examples/scatterbrain/demo.tsx | 10 +- site/src/examples/ui/contact-sheet.tsx | 18 +- site/src/examples/ui/slice-ui.tsx | 18 +- 92 files changed, 793 insertions(+), 466 deletions(-) create mode 100644 .oxfmtrc.json diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index f44de2f5..b5c68e55 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -25,16 +25,16 @@ If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** -- OS: [e.g. iOS] -- Browser [e.g. chrome, safari] -- Version [e.g. 22] +- OS: [e.g. iOS] +- Browser [e.g. chrome, safari] +- Version [e.g. 22] **Smartphone (please complete the following information):** -- Device: [e.g. iPhone6] -- OS: [e.g. iOS8.1] -- Browser [e.g. stock browser, safari] -- Version [e.g. 22] +- Device: [e.g. iPhone6] +- OS: [e.g. iOS8.1] +- Browser [e.g. stock browser, safari] +- Version [e.g. 22] **Additional context** Add any other context about the problem here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 971bd0b6..7ad14632 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,10 +2,10 @@ _This section is optional if the PR is fully ready for review_ -- Create the PR as a "draft" PR -- Add [WIP] to the title -- Use the template below to ask for specific feedback -- [ ] @name: Could you look at \_\_\_? I'm trying to do... (etc.) +- Create the PR as a "draft" PR +- Add [WIP] to the title +- Use the template below to ask for specific feedback +- [ ] @name: Could you look at \_\_\_? I'm trying to do... (etc.) # What @@ -19,20 +19,20 @@ Replace this txt describing what kind of technical overlaying code changes were _This section is optional if there are no visible changes_ -- If possible add screenshots of the visible additions in the UI. -- If there are changes in the UI, add **Before** and **After** Screenshots for quick overview. -- If there was a Figma design, add a link to that here as well. -- Hint : Drag and Drop any images you want to add to the PR. Also you can create a gif of an interactive version and add that! +- If possible add screenshots of the visible additions in the UI. +- If there are changes in the UI, add **Before** and **After** Screenshots for quick overview. +- If there was a Figma design, add a link to that here as well. +- Hint : Drag and Drop any images you want to add to the PR. Also you can create a gif of an interactive version and add that! # PR Checklist -- [ ] Is your PR title following our conventional commit naming recommendations? -- [ ] Have you filled in the PR Description Template? -- [ ] Is your branch up to date with the latest in `main`? -- [ ] Do the CI checks pass successfully? -- [ ] Have you smoke tested the example applications? -- [ ] Did you check that the changes meet accessibility standards? -- [ ] Have you tested the application on these browsers? - - [ ] Chrome (Fully supported) - - [ ] Firefox (Major bug fixes supported) - - [ ] Safari (Major bug fixes supported) +- [ ] Is your PR title following our conventional commit naming recommendations? +- [ ] Have you filled in the PR Description Template? +- [ ] Is your branch up to date with the latest in `main`? +- [ ] Do the CI checks pass successfully? +- [ ] Have you smoke tested the example applications? +- [ ] Did you check that the changes meet accessibility standards? +- [ ] Have you tested the application on these browsers? + - [ ] Chrome (Fully supported) + - [ ] Firefox (Major bug fixes supported) + - [ ] Safari (Major bug fixes supported) diff --git a/.oxfmtrc.json b/.oxfmtrc.json new file mode 100644 index 00000000..1da6bbd5 --- /dev/null +++ b/.oxfmtrc.json @@ -0,0 +1,11 @@ +{ + "$schema": "./node_modules/oxfmt/configuration_schema.json", + "printWidth": 120, + "trailingComma": "es5", + "tabWidth": 4, + "singleQuote": true, + "semi": true, + "singleAttributePerLine": true, + "sortPackageJson": false, + "ignorePatterns": ["dist", "pnpm-lock.yaml"] +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 75278a1a..2f8bf968 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -14,24 +14,24 @@ appearance, race, religion, or sexual identity and orientation. Examples of behavior that contributes to a positive environment for our community include: -- Demonstrating empathy and kindness toward other people -- Being respectful of differing opinions, viewpoints, and experiences -- Giving and gracefully accepting constructive feedback -- Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -- Focusing on what is best not just for us as individuals, but for the - overall community +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +- Focusing on what is best not just for us as individuals, but for the + overall community Examples of unacceptable behavior include: -- The use of sexualized language or imagery, and sexual attention or - advances -- Trolling, insulting or derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or email - address, without their explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting +- The use of sexualized language or imagery, and sexual attention or + advances +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email + address, without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting ## Our Responsibilities diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7396d8e0..bdcd0304 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,25 +8,25 @@ All types of contributions are encouraged and valued. See the [Table of Contents > And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about: > -> - Star the project -> - Tweet about it -> - Refer this project in your project's readme -> - Mention the project at local meetups and tell your friends/colleagues +> - Star the project +> - Tweet about it +> - Refer this project in your project's readme +> - Mention the project at local meetups and tell your friends/colleagues ## Table of Contents -- [Code of Conduct](#code-of-conduct) -- [I Have a Question](#i-have-a-question) -- [I Want To Contribute](#i-want-to-contribute) - - [Reporting Bugs](#reporting-bugs) - - [Suggesting Enhancements](#suggesting-enhancements) - - [Your First Code Contribution](#your-first-code-contribution) - - [Improving The Documentation](#improving-the-documentation) -- [Styleguides](#styleguides) - - [Commit Messages](#commit-messages) -- [Join The Project Team](#join-the-project-team) +- [Code of Conduct](#code-of-conduct) +- [I Have a Question](#i-have-a-question) +- [I Want To Contribute](#i-want-to-contribute) + - [Reporting Bugs](#reporting-bugs) + - [Suggesting Enhancements](#suggesting-enhancements) + - [Your First Code Contribution](#your-first-code-contribution) + - [Improving The Documentation](#improving-the-documentation) +- [Styleguides](#styleguides) + - [Commit Messages](#commit-messages) +- [Join The Project Team](#join-the-project-team) ## Code of Conduct @@ -43,9 +43,9 @@ Before you ask a question, it is best to search for existing [Issues](https://gi If you then still feel the need to ask a question and need clarification, we recommend the following: -- Open an [Issue](https://github.com/AllenInstitute/vis/issues/new). -- Provide as much context as you can about what you're running into. -- Provide project and platform versions (nodejs, npm, etc), depending on what seems relevant. +- Open an [Issue](https://github.com/AllenInstitute/vis/issues/new). +- Provide as much context as you can about what you're running into. +- Provide project and platform versions (nodejs, npm, etc), depending on what seems relevant. We will then take care of the issue as soon as possible. @@ -63,16 +63,16 @@ We will then take care of the issue as soon as possible. A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible. -- Make sure that you are using the latest version. -- Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](https://github.com/AllenInstitute/vis/tree/main/docs). If you are looking for support, you might want to check [this section](#i-have-a-question)). -- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/AllenInstitute/visissues?q=label%3Abug). -- Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue. -- Collect information about the bug: - - Stack trace (Traceback) - - OS, Platform and Version (Windows, Linux, macOS, x86, ARM) - - Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant. - - Possibly your input and the output - - Can you reliably reproduce the issue? And can you also reproduce it with older versions? +- Make sure that you are using the latest version. +- Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](https://github.com/AllenInstitute/vis/tree/main/docs). If you are looking for support, you might want to check [this section](#i-have-a-question)). +- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/AllenInstitute/visissues?q=label%3Abug). +- Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue. +- Collect information about the bug: + - Stack trace (Traceback) + - OS, Platform and Version (Windows, Linux, macOS, x86, ARM) + - Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant. + - Possibly your input and the output + - Can you reliably reproduce the issue? And can you also reproduce it with older versions? @@ -82,16 +82,16 @@ A good bug report shouldn't leave others needing to chase you up for more inform We use GitHub issues to track bugs and errors. If you run into an issue with the project: -- Open an [Issue](https://github.com/AllenInstitute/vis/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.) -- Explain the behavior you would expect and the actual behavior. -- Please provide as much context as possible and describe the _reproduction steps_ that someone else can follow to recreate the issue on their own. This usually includes your code. For good issue reports you should isolate the problem and create a reduced test case. -- Provide the information you collected in the previous section. +- Open an [Issue](https://github.com/AllenInstitute/vis/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.) +- Explain the behavior you would expect and the actual behavior. +- Please provide as much context as possible and describe the _reproduction steps_ that someone else can follow to recreate the issue on their own. This usually includes your code. For good issue reports you should isolate the problem and create a reduced test case. +- Provide the information you collected in the previous section. Once it's filed: -- The project team will label the issue accordingly. -- A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps and mark the issue as `needs-repro`. Issues with the `needs-repro` tag will not be addressed until they are reproduced. -- If the team is able to reproduce the issue, it will be marked `needs-fix`, as well as possibly other tags (such as `critical`), and the issue will be left to be [implemented by someone](#your-first-code-contribution). +- The project team will label the issue accordingly. +- A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps and mark the issue as `needs-repro`. Issues with the `needs-repro` tag will not be addressed until they are reproduced. +- If the team is able to reproduce the issue, it will be marked `needs-fix`, as well as possibly other tags (such as `critical`), and the issue will be left to be [implemented by someone](#your-first-code-contribution). ### Suggesting Enhancements @@ -101,10 +101,10 @@ This section guides you through submitting an enhancement suggestion for Visuali #### Before Submitting an Enhancement -- Make sure that you are using the latest version. -- Read the [documentation](https://github.com/AllenInstitute/vis/tree/main/docs) carefully and find out if the functionality is already covered, maybe by an individual configuration. -- Perform a [search](https://github.com/AllenInstitute/vis/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. -- Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library. +- Make sure that you are using the latest version. +- Read the [documentation](https://github.com/AllenInstitute/vis/tree/main/docs) carefully and find out if the functionality is already covered, maybe by an individual configuration. +- Perform a [search](https://github.com/AllenInstitute/vis/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. +- Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library. @@ -112,11 +112,11 @@ This section guides you through submitting an enhancement suggestion for Visuali Enhancement suggestions are tracked as [GitHub issues](https://github.com/AllenInstitute/vis/issues). -- Use a **clear and descriptive title** for the issue to identify the suggestion. -- Provide a **step-by-step description of the suggested enhancement** in as many details as possible. -- **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you. -- You may want to **include screenshots and animated GIFs** which help you demonstrate the steps or point out the part which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux. -- **Explain why this enhancement would be useful** to most Visualization Toolkit users. You may also want to point out the other projects that solved it better and which could serve as inspiration. +- Use a **clear and descriptive title** for the issue to identify the suggestion. +- Provide a **step-by-step description of the suggested enhancement** in as many details as possible. +- **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you. +- You may want to **include screenshots and animated GIFs** which help you demonstrate the steps or point out the part which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux. +- **Explain why this enhancement would be useful** to most Visualization Toolkit users. You may also want to point out the other projects that solved it better and which could serve as inspiration. ### Your First Code Contribution diff --git a/README.md b/README.md index 0dabf019..8f300ac8 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,10 @@ This repository contains a collection of TypeScript libraries to help software e The following is the list of packages and their descriptions: -- `vis-dzi`: A renderer for [Deep Zoom Images](https://en.wikipedia.org/wiki/Deep_Zoom) -- `vis-geometry`: A collection of vector functions for 2D and 3D geometry -- `vis-omezarr`: A renderer for [OME-Zarr](https://ngff.openmicroscopy.org/latest/) datasets -- `vis-core`: A collection of useful utilities used to build our big-data, scalable, data visualization tools, including the DZI viewer, OME-Zarr viewer, and our scatterplot tool "Scatterbrain" for the [ABC Atlas](https://knowledge.brain-map.org/abcatlas) in the Brain Knowledge Platform web application +- `vis-dzi`: A renderer for [Deep Zoom Images](https://en.wikipedia.org/wiki/Deep_Zoom) +- `vis-geometry`: A collection of vector functions for 2D and 3D geometry +- `vis-omezarr`: A renderer for [OME-Zarr](https://ngff.openmicroscopy.org/latest/) datasets +- `vis-core`: A collection of useful utilities used to build our big-data, scalable, data visualization tools, including the DZI viewer, OME-Zarr viewer, and our scatterplot tool "Scatterbrain" for the [ABC Atlas](https://knowledge.brain-map.org/abcatlas) in the Brain Knowledge Platform web application We use [Semantic Versioning](https://semver.org/) for our packages. As of November 2024, all of them are in the `0.0.x` range, indicating that they are in early development. diff --git a/biome.json b/biome.json index c7796cb7..2154894a 100644 --- a/biome.json +++ b/biome.json @@ -10,10 +10,7 @@ "includes": ["**", "!**/dist/**/*", "!**/coverage/**/*", "!**/.astro/**/*", "!**/*.astro"] }, "formatter": { - "enabled": true, - "indentStyle": "space", - "indentWidth": 4, - "lineWidth": 120 + "enabled": false }, "assist": { "actions": { @@ -46,10 +43,5 @@ "noUselessElse": "error" } } - }, - "javascript": { - "formatter": { - "quoteStyle": "single" - } } } diff --git a/cliff.toml b/cliff.toml index 4c5c77d2..902318f1 100644 --- a/cliff.toml +++ b/cliff.toml @@ -36,8 +36,8 @@ footer = """ trim = true # postprocessors postprocessors = [ - # GitHub PR link, appears as (#1234) - { pattern = "#(\\d+)", replace = "[#$1](https://github.com/AllenInstitute/vis/pull/$1)"}, + # GitHub PR link, appears as (#1234) + { pattern = "#(\\d+)", replace = "[#$1](https://github.com/AllenInstitute/vis/pull/$1)" }, ] # render body even when there are no releases to process # render_always = true @@ -53,25 +53,25 @@ filter_unconventional = true split_commits = false # regex for preprocessing the commit messages commit_preprocessors = [ - # Replace issue numbers - #{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))"}, - # Check spelling of the commit with https://github.com/crate-ci/typos - # If the spelling is incorrect, it will be automatically fixed. - #{ pattern = '.*', replace_command = 'typos --write-changes -' }, + # Replace issue numbers + #{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))"}, + # Check spelling of the commit with https://github.com/crate-ci/typos + # If the spelling is incorrect, it will be automatically fixed. + #{ pattern = '.*', replace_command = 'typos --write-changes -' }, ] # regex for parsing and grouping commits commit_parsers = [ - { message = "^feat", group = "๐Ÿš€ Features" }, - { message = "^fix", group = "๐Ÿ› Bug Fixes" }, - { message = "^doc", group = "๐Ÿ“š Documentation" }, - { message = "^perf", group = "โšก Performance" }, - { message = "^refactor", group = "๐Ÿšœ Refactor" }, - { message = "^style", group = "๐ŸŽจ Styling" }, - { message = "^test", group = "๐Ÿงช Testing" }, - { message = "^chore|^ci", group = "โš™๏ธ Miscellaneous Tasks" }, - { body = ".*security", group = "๐Ÿ›ก๏ธ Security" }, - { message = "^revert", group = "โ—€๏ธ Revert" }, - { message = ".*", group = "๐Ÿ’ผ Other" }, + { message = "^feat", group = "๐Ÿš€ Features" }, + { message = "^fix", group = "๐Ÿ› Bug Fixes" }, + { message = "^doc", group = "๐Ÿ“š Documentation" }, + { message = "^perf", group = "โšก Performance" }, + { message = "^refactor", group = "๐Ÿšœ Refactor" }, + { message = "^style", group = "๐ŸŽจ Styling" }, + { message = "^test", group = "๐Ÿงช Testing" }, + { message = "^chore|^ci", group = "โš™๏ธ Miscellaneous Tasks" }, + { body = ".*security", group = "๐Ÿ›ก๏ธ Security" }, + { message = "^revert", group = "โ—€๏ธ Revert" }, + { message = ".*", group = "๐Ÿ’ผ Other" }, ] # filter out the commits that are not matched by commit parsers filter_commits = false diff --git a/package.json b/package.json index cf4ca967..84af0547 100644 --- a/package.json +++ b/package.json @@ -7,16 +7,17 @@ "test": "pnpm -r run --no-bail test:ci", "coverage": "pnpm -r run coverage", "typecheck": "pnpm -r --no-bail run typecheck", - "check": "biome check .", - "check:fix": "biome check . --write", - "fmt": "biome format . --write", - "fmt:check": "biome format .", + "fmt": "oxfmt", + "fmt:check": "oxfmt --check", "lint": "biome lint . --write", "lint:check": "biome lint .", + "check": "oxfmt --check && biome lint .", + "check:fix": "oxfmt && biome lint . --write", "changelog": "pnpm -r run changelog" }, "devDependencies": { "@biomejs/biome": "2.4.9", + "oxfmt": "0.46.0", "@parcel/packager-ts": "2.16.4", "@parcel/transformer-typescript-types": "2.16.4", "@vitest/coverage-istanbul": "4.1.1", @@ -28,7 +29,7 @@ "vitest": "4.1.1" }, "volta": { - "node": "22.11.0", + "node": "24.15.0", "pnpm": "10.33.0" }, "packageManager": "pnpm@10.33.0" diff --git a/packages/core/README.md b/packages/core/README.md index 9bed4d1e..40089263 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -1,4 +1,4 @@ -# Core +# Core This README is under construction! diff --git a/packages/core/src/abstract/async-frame.ts b/packages/core/src/abstract/async-frame.ts index d0eb3390..5b951550 100644 --- a/packages/core/src/abstract/async-frame.ts +++ b/packages/core/src/abstract/async-frame.ts @@ -56,7 +56,7 @@ export type RenderFrameConfig< item: Item, dataset: Dataset, settings: Settings, - signal?: AbortSignal, + signal?: AbortSignal ) => Record Promise>; lifecycleCallback: RenderCallback; cacheKeyForRequest: (item: Item, requestKey: RqKey, dataset: Dataset, settings: Settings) => CacheKey; @@ -140,7 +140,7 @@ export function beginFrame< requestsForItem(itemToRender, dataset, settings, abort.signal), partial(renderItemWrapper, itemToRender), toCacheKey, - () => reportStatus({ status: 'progress', dataset, renderedItems: [itemToRender] }, synchronous), + () => reportStatus({ status: 'progress', dataset, renderedItems: [itemToRender] }, synchronous) ); if (result !== undefined) { // put this cancel callback in a list where we can invoke if something goes wrong @@ -207,7 +207,7 @@ export function buildAsyncRenderer< settings: Settings, callback: RenderCallback, target: REGL.Framebuffer2D | null, - cache: AsyncDataCache, + cache: AsyncDataCache ) => { const { renderItem, isPrepared, cacheKey, fetchItemContent, getVisibleItems } = renderer; const config: RenderFrameConfig = { diff --git a/packages/core/src/abstract/render-server.ts b/packages/core/src/abstract/render-server.ts index 302220a7..29fb0b55 100644 --- a/packages/core/src/abstract/render-server.ts +++ b/packages/core/src/abstract/render-server.ts @@ -41,7 +41,7 @@ type ServerCallback = (event: RenderEvent) => void; type RenderFrameFn = ( target: REGL.Framebuffer2D | null, cache: AsyncDataCache, - callback: RenderCallback, + callback: RenderCallback ) => FrameLifecycle | null; type Client = HTMLCanvasElement; @@ -101,7 +101,7 @@ export class RenderServer { updateRequested(ctx, img); } catch { logger.error( - 'error - we tried to copy to a client buffer, but maybe it got unmounted? that can happen, its ok', + 'error - we tried to copy to a client buffer, but maybe it got unmounted? that can happen, its ok' ); } } diff --git a/packages/core/src/abstract/types.ts b/packages/core/src/abstract/types.ts index f1008a97..32bcf199 100644 --- a/packages/core/src/abstract/types.ts +++ b/packages/core/src/abstract/types.ts @@ -34,7 +34,7 @@ export type Renderer Record Promise>; /** * @@ -56,7 +56,7 @@ export type Renderer void; /** * compute a unique (but please not random!) string that the cache system can use to identify the content diff --git a/packages/core/src/dataset-cache.ts b/packages/core/src/dataset-cache.ts index e227bc9c..252c2e0a 100644 --- a/packages/core/src/dataset-cache.ts +++ b/packages/core/src/dataset-cache.ts @@ -6,7 +6,7 @@ export interface AsyncCache Promise>, use: (items: Record) => void, - cacheKey: (semantic: SemanticKey) => CacheKey, + cacheKey: (semantic: SemanticKey) => CacheKey ): cancelFn | undefined; } @@ -24,7 +24,7 @@ function updatePendingRequest, key: SemanticKey, cacheKey: CacheKey, - item: D, + item: D ): boolean { if (req.awaiting.has(cacheKey)) { const remaningAwaited = req.awaiting.get(cacheKey); @@ -57,9 +57,11 @@ type MutableCacheEntry = { * } */ -export class AsyncDataCache - implements AsyncCache -{ +export class AsyncDataCache implements AsyncCache< + SemanticKey, + CacheKey, + D +> { private limit: number; private size: (d: D) => number; private destroyer: (d: D) => void; @@ -243,7 +245,7 @@ export class AsyncDataCache) => void, toCacheKey: (semanticKey: SemanticKey) => CacheKey, // TODO: consider removing taskFinished - it would be more simple to let the caller handle this in their use() function - taskFinished?: () => void, + taskFinished?: () => void ): cancelFn | undefined { const keys: SemanticKey[] = Object.keys(workingSet) as SemanticKey[]; const req: MutablePendingRequest = { diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 995da9b4..45f8e8e7 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -6,17 +6,8 @@ export * from './resources'; export * from './errors'; export * from './colors'; -export { - beginFrame, - buildAsyncRenderer, - type RenderFrameConfig, -} from './abstract/async-frame'; -export type { - CachedTexture, - CachedVertexBuffer, - ReglCacheEntry, - Renderer, -} from './abstract/types'; +export { beginFrame, buildAsyncRenderer, type RenderFrameConfig } from './abstract/async-frame'; +export type { CachedTexture, CachedVertexBuffer, ReglCacheEntry, Renderer } from './abstract/types'; export { RenderServer } from './abstract/render-server'; export { Logger, logger } from './logger'; diff --git a/packages/core/src/layers/layer-2D.ts b/packages/core/src/layers/layer-2D.ts index bad6ef36..893141e8 100644 --- a/packages/core/src/layers/layer-2D.ts +++ b/packages/core/src/layers/layer-2D.ts @@ -18,7 +18,7 @@ export class ReglLayer2D { regl: REGL.Regl, imgRenderer: ImageRenderer, renderFn: RenderFn, - resolution: vec2, + resolution: vec2 ) { this.buffers = { readFrom: { @@ -54,7 +54,7 @@ export class ReglLayer2D { readonly data: Readonly; readonly settings: Readonly; }, - cancel = true, + cancel = true ) { if (cancel && this.runningFrame) { this.runningFrame.cancelFrame(); diff --git a/packages/core/src/layers/types.ts b/packages/core/src/layers/types.ts index 749d4bf9..623ab83f 100644 --- a/packages/core/src/layers/types.ts +++ b/packages/core/src/layers/types.ts @@ -5,7 +5,7 @@ import type { FrameLifecycle } from '../render-queue'; export type RenderFn = ( target: REGL.Framebuffer2D | null, thing: Readonly, - settings: Readonly, + settings: Readonly ) => FrameLifecycle; export type Image = { diff --git a/packages/core/src/render-queue.ts b/packages/core/src/render-queue.ts index 8d6d7c92..851b3fe5 100644 --- a/packages/core/src/render-queue.ts +++ b/packages/core/src/render-queue.ts @@ -61,7 +61,7 @@ export function beginLongRunningFrame( render: (item: Item, settings: Settings, columns: Record) => void, lifecycleCallback: RenderCallback, cacheKeyForRequest: (requestKey: string, item: Item, settings: Settings) => string = (key) => key, - queueTimeBudgetMS: number = queueProcessingIntervalMS / 3, + queueTimeBudgetMS: number = queueProcessingIntervalMS / 3 ): FrameLifecycle { const abort = new AbortController(); const queue: Item[] = []; @@ -159,7 +159,7 @@ export function beginLongRunningFrame( requestsForItem(itemToRender, settings, abort.signal), partial(render, itemToRender, settings), toCacheKey, - () => reportNormalStatus('progress'), + () => reportNormalStatus('progress') ); if (result !== undefined) { // put this cancel callback in a list where we can invoke if something goes wrong diff --git a/packages/core/src/shared-priority-cache/priority-cache.test.ts b/packages/core/src/shared-priority-cache/priority-cache.test.ts index 64863d51..9c5fe3fc 100644 --- a/packages/core/src/shared-priority-cache/priority-cache.test.ts +++ b/packages/core/src/shared-priority-cache/priority-cache.test.ts @@ -92,7 +92,7 @@ describe.skip('throughput', () => { return priorities[item] ?? 0; }, 1000, - 20, + 20 ); const newItem = (ID: string): Cacheable => { priorities[ID] = Math.random() * 100; @@ -119,56 +119,60 @@ describe.skip('throughput', () => { // a photon travels about 1000 feet in that time expect(numEvicted).toBe(999000); }); - test('performs well under non-stop puts with random prioritization values, and intermittant re-prioritizations', { - timeout: 10000, - }, () => { - // because puts get called as the result of a promise resolution, its hard to isolate the cost - // using a "realistic" example - lets just call put in a loop? - const fakeStore: FakeStore = new FakeStore(); - const priorities: Record = {}; - let numEvicted = 0; - const score = (k: string) => priorities[k] ?? 0; - const cache: AsyncPriorityCache = new AsyncPriorityCache(fakeStore, score, 1000, 20); - const newItem = (ID: string): Cacheable => { - priorities[ID] = Math.random() * 100; - return { - sizeInBytes: () => 1, - destroy: () => { - delete priorities[ID]; - numEvicted += 1; - }, + test( + 'performs well under non-stop puts with random prioritization values, and intermittant re-prioritizations', + { + timeout: 10000, + }, + () => { + // because puts get called as the result of a promise resolution, its hard to isolate the cost + // using a "realistic" example - lets just call put in a loop? + const fakeStore: FakeStore = new FakeStore(); + const priorities: Record = {}; + let numEvicted = 0; + const score = (k: string) => priorities[k] ?? 0; + const cache: AsyncPriorityCache = new AsyncPriorityCache(fakeStore, score, 1000, 20); + const newItem = (ID: string): Cacheable => { + priorities[ID] = Math.random() * 100; + return { + sizeInBytes: () => 1, + destroy: () => { + delete priorities[ID]; + numEvicted += 1; + }, + }; }; - }; - let putOverheadMS = 0; - let rePrioritizeOverheadMS = 0; - let rePrioritizeEvents = 0; - const onemil = 1_000_000; - for (let i = 0; i < onemil; i++) { - const ID = `item_${i}`; - const item = newItem(ID); - const begin = performance.now(); - cache.put(ID, item); - putOverheadMS += performance.now() - begin; - if (i % 100 === 0) { - // this is the same score function, but we changed all the numbers... that is exactly what we want - for (const k in priorities) { - priorities[k] = Math.random() * 100; - } - rePrioritizeEvents += 1; + let putOverheadMS = 0; + let rePrioritizeOverheadMS = 0; + let rePrioritizeEvents = 0; + const onemil = 1_000_000; + for (let i = 0; i < onemil; i++) { + const ID = `item_${i}`; + const item = newItem(ID); const begin = performance.now(); - cache.reprioritize(score); - rePrioritizeOverheadMS += performance.now() - begin; + cache.put(ID, item); + putOverheadMS += performance.now() - begin; + if (i % 100 === 0) { + // this is the same score function, but we changed all the numbers... that is exactly what we want + for (const k in priorities) { + priorities[k] = Math.random() * 100; + } + rePrioritizeEvents += 1; + const begin = performance.now(); + cache.reprioritize(score); + rePrioritizeOverheadMS += performance.now() - begin; + } } + console.log('1 million puts,', numEvicted, 'evictions,', putOverheadMS, 'ms total'); + console.log('each put (avg ms): ', putOverheadMS / onemil); + console.log('avg ms to reprioritize 1000 items: ', rePrioritizeOverheadMS / rePrioritizeEvents); + expect(putOverheadMS / onemil).toBeLessThan(0.01); // yup, we are expecting this call to take less than 10 microseconds on average. + // a photon travels about 10,000 feet in that time + expect(numEvicted).toBe(999000); + expect(rePrioritizeEvents).toBe(onemil / 100); + expect(rePrioritizeOverheadMS / rePrioritizeEvents).toBeLessThan(0.1); } - console.log('1 million puts,', numEvicted, 'evictions,', putOverheadMS, 'ms total'); - console.log('each put (avg ms): ', putOverheadMS / onemil); - console.log('avg ms to reprioritize 1000 items: ', rePrioritizeOverheadMS / rePrioritizeEvents); - expect(putOverheadMS / onemil).toBeLessThan(0.01); // yup, we are expecting this call to take less than 10 microseconds on average. - // a photon travels about 10,000 feet in that time - expect(numEvicted).toBe(999000); - expect(rePrioritizeEvents).toBe(onemil / 100); - expect(rePrioritizeOverheadMS / rePrioritizeEvents).toBeLessThan(0.1); - }); + ); test('enqueue with instant fetching - overall speed', { timeout: 10000 }, async () => { const promises = new PromiseFarm(); const fakeStore: FakeStore = new FakeStore(); diff --git a/packages/core/src/shared-priority-cache/priority-cache.ts b/packages/core/src/shared-priority-cache/priority-cache.ts index c46a1c1a..aca2ff02 100644 --- a/packages/core/src/shared-priority-cache/priority-cache.ts +++ b/packages/core/src/shared-priority-cache/priority-cache.ts @@ -131,7 +131,7 @@ export class AsyncPriorityCache extends PriorityCache { score: (k: CacheKey) => number, limitInBytes: number, maxFetches: number, - onDataArrived?: (key: CacheKey, result: FetchResult) => void, + onDataArrived?: (key: CacheKey, result: FetchResult) => void ) { super(store, score, limitInBytes); diff --git a/packages/core/src/shared-priority-cache/shared-cache.ts b/packages/core/src/shared-priority-cache/shared-cache.ts index 0df0f32f..5bf163bc 100644 --- a/packages/core/src/shared-priority-cache/shared-cache.ts +++ b/packages/core/src/shared-priority-cache/shared-cache.ts @@ -32,14 +32,14 @@ function entries>(t: T): ReadonlyArray> } function mapFields, Result>( r: R, - fn: (v: R[keyof R]) => Result, + fn: (v: R[keyof R]) => Result ): { [k in keyof R]: Result } { return entries(r).reduce( (acc, [k, v]) => { acc[k] = fn(v); return acc; }, - {} as { [k in keyof R]: Result }, + {} as { [k in keyof R]: Result } ); } @@ -61,11 +61,11 @@ export class SharedPriorityCache { (ck) => this.importance[ck] ?? 0, limitInBytes, max_concurrent_fetches, - (ck, result) => this.onCacheEntryArrived(ck, result), + (ck, result) => this.onCacheEntryArrived(ck, result) ); } registerClient>( - spec: ClientSpec, + spec: ClientSpec ): CacheInterface { const id = uniqueId('client'); this.clients[id] = { priorities: {}, notify: spec.onDataArrived }; diff --git a/packages/core/src/shared-priority-cache/utils.ts b/packages/core/src/shared-priority-cache/utils.ts index 1ef2775a..ee8df1c6 100644 --- a/packages/core/src/shared-priority-cache/utils.ts +++ b/packages/core/src/shared-priority-cache/utils.ts @@ -6,7 +6,7 @@ import type { ClientSpec } from './shared-cache'; export function prioritizeCacheKeys>( spec: ClientSpec, items: Iterable, - priority: 1 | 2, + priority: 1 | 2 ) { const pri: Record = {}; for (const item of items) { @@ -32,7 +32,7 @@ export function mergeAndAdd(A: Record, B: Record export function priorityDelta( old: Record, current: Record, - update: (key: string, value: number) => void, + update: (key: string, value: number) => void ) { for (const o in old) { const curPri = current[o] ?? 0; diff --git a/packages/core/src/test/render-cache.test.ts b/packages/core/src/test/render-cache.test.ts index 4e09fe38..521b5f31 100644 --- a/packages/core/src/test/render-cache.test.ts +++ b/packages/core/src/test/render-cache.test.ts @@ -102,7 +102,7 @@ describe('async cache', () => { let cache = new AsyncDataCache( (_item: Data) => {}, () => 1, - 10, + 10 ); let disposed: Data[] = []; let rendered: SpyOnRenderer[] = []; // these are just for spying @@ -115,7 +115,7 @@ describe('async cache', () => { disposed.push(item); }, () => 1, - 10, + 10 ); disposed = []; rendered = []; diff --git a/packages/core/src/test/render-queue.test.ts b/packages/core/src/test/render-queue.test.ts index d7786053..eb19c9a6 100644 --- a/packages/core/src/test/render-queue.test.ts +++ b/packages/core/src/test/render-queue.test.ts @@ -16,7 +16,7 @@ describe('beginLongRunningFrame', () => { let cache: AsyncDataCache = new AsyncDataCache( () => {}, () => 1, - 9999, + 9999 ); let renderSequence: FakeTask[] = []; function renderPretender(item: FakeItem, settings: FakeSettings, tasks: Record) { @@ -39,7 +39,7 @@ describe('beginLongRunningFrame', () => { // a less wordy fake frame: const fakeFrame = ( items: number, - eventHandler: (event: { status: NormalStatus } | { status: 'error'; error: unknown }) => void, + eventHandler: (event: { status: NormalStatus } | { status: 'error'; error: unknown }) => void ) => beginLongRunningFrame( 5, @@ -51,13 +51,13 @@ describe('beginLongRunningFrame', () => { renderPretender, eventHandler, (_rq: string, item: FakeItem, settings: FakeSettings) => cacheKey(item, settings), - 9999, + 9999 ); beforeEach(() => { cache = new AsyncDataCache( () => {}, () => 1, - 9999, + 9999 ); renderSequence = []; }); diff --git a/packages/core/src/test/test-utils.ts b/packages/core/src/test/test-utils.ts index 0c4dbedd..0aa777d4 100644 --- a/packages/core/src/test/test-utils.ts +++ b/packages/core/src/test/test-utils.ts @@ -10,6 +10,6 @@ export const fakeFetch = (data: FakeTask, signal?: AbortSignal): Promi resolve(data); } }, - 100 * Math.random() + 50, + 100 * Math.random() + 50 ); }); diff --git a/packages/core/src/workers/worker-pool.ts b/packages/core/src/workers/worker-pool.ts index 47690484..57d5dc6b 100644 --- a/packages/core/src/workers/worker-pool.ts +++ b/packages/core/src/workers/worker-pool.ts @@ -97,7 +97,7 @@ export class WorkerPool { message: WorkerMessage, responseValidator: MessageValidator, transfers: Transferable[], - signal?: AbortSignal | undefined, + signal?: AbortSignal | undefined ): Promise { if (this.#workers.length < 1) { return Promise.reject('this woorker pool has been disposed'); diff --git a/packages/dzi/changelog.md b/packages/dzi/changelog.md index 98c055cf..b2dd4361 100644 --- a/packages/dzi/changelog.md +++ b/packages/dzi/changelog.md @@ -34,6 +34,6 @@ All notable changes to this project will be documented in this file. - Rename vis-scatterbrain package to vis-core ([#118](https://github.com/AllenInstitute/vis/pull/118)) - Add helpful linting rules ([#127](https://github.com/AllenInstitute/vis/pull/127)) - Dev command, reorganized docs, added stubs ([#163](https://github.com/AllenInstitute/vis/pull/163)) -- *(deps)* Bump @biomejs/biome from 1.9.4 to 2.0.6 ([#174](https://github.com/AllenInstitute/vis/pull/174)) +- _(deps)_ Bump @biomejs/biome from 1.9.4 to 2.0.6 ([#174](https://github.com/AllenInstitute/vis/pull/174)) diff --git a/packages/dzi/src/index.ts b/packages/dzi/src/index.ts index 7e50ac66..915a09cc 100644 --- a/packages/dzi/src/index.ts +++ b/packages/dzi/src/index.ts @@ -1,6 +1,2 @@ export { fetchDziMetadata, getVisibleTiles, type DziImage, type DziTile } from './loader'; -export { - buildDziRenderer, - buildAsyncDziRenderer, - type RenderSettings as DziRenderSettings, -} from './renderer'; +export { buildDziRenderer, buildAsyncDziRenderer, type RenderSettings as DziRenderSettings } from './renderer'; diff --git a/packages/dzi/src/renderer.ts b/packages/dzi/src/renderer.ts index 02014789..0d9585e7 100644 --- a/packages/dzi/src/renderer.ts +++ b/packages/dzi/src/renderer.ts @@ -32,7 +32,7 @@ export function buildDziRenderer(regl: REGL.Regl): Renderer Promise> => { return { pixels: () => { diff --git a/packages/geometry/changelog.md b/packages/geometry/changelog.md index 01d653db..a62cb995 100644 --- a/packages/geometry/changelog.md +++ b/packages/geometry/changelog.md @@ -7,12 +7,12 @@ All notable changes to this project will be documented in this file. ### ๐Ÿš€ Features - Publishing documentation and config changes ([#3](https://github.com/AllenInstitute/vis/pull/3)) -- *(geometry)* LineSegmentsIntersect and det ([#21](https://github.com/AllenInstitute/vis/pull/21)) +- _(geometry)_ LineSegmentsIntersect and det ([#21](https://github.com/AllenInstitute/vis/pull/21)) - Support for arbitrary color channels in OME-Zarr images [DC-530] ([#123](https://github.com/AllenInstitute/vis/pull/123)) ### ๐Ÿ› Bug Fixes -- *(vis-geometry)* Adds missing functionality from `bkp-client` ([#10](https://github.com/AllenInstitute/vis/pull/10)) +- _(vis-geometry)_ Adds missing functionality from `bkp-client` ([#10](https://github.com/AllenInstitute/vis/pull/10)) - Expose Rectangle2D functions, remove glob export from Interval ([#13](https://github.com/AllenInstitute/vis/pull/13)) - CI tests weren't running [DT-7060] ([#87](https://github.com/AllenInstitute/vis/pull/87)) - Remove non-null assertions ([#101](https://github.com/AllenInstitute/vis/pull/101)) @@ -38,6 +38,6 @@ All notable changes to this project will be documented in this file. - Updates to package versions for Core, Geometry, OmeZarr + examples [DC-530] ([#124](https://github.com/AllenInstitute/vis/pull/124)) - Add helpful linting rules ([#127](https://github.com/AllenInstitute/vis/pull/127)) - Dev command, reorganized docs, added stubs ([#163](https://github.com/AllenInstitute/vis/pull/163)) -- *(deps)* Bump @biomejs/biome from 1.9.4 to 2.0.6 ([#174](https://github.com/AllenInstitute/vis/pull/174)) +- _(deps)_ Bump @biomejs/biome from 1.9.4 to 2.0.6 ([#174](https://github.com/AllenInstitute/vis/pull/174)) diff --git a/packages/geometry/src/axisAngle.ts b/packages/geometry/src/axisAngle.ts index b1be3a35..7e91290c 100644 --- a/packages/geometry/src/axisAngle.ts +++ b/packages/geometry/src/axisAngle.ts @@ -30,7 +30,7 @@ export function composeRotation(b: AxisAngle, a: AxisAngle): AxisAngle { const D = Vec3.add( Vec3.add(Vec3.scale(B, sinB * cosA), Vec3.scale(A, sinA * cosB)), - Vec3.scale(Vec3.cross(B, A), sinB * sinA), + Vec3.scale(Vec3.cross(B, A), sinB * sinA) ); const dir = Vec3.normalize(D); @@ -55,6 +55,6 @@ export function rotateVector(rotation: AxisAngle, v: vec3): vec3 { return Vec3.add( Vec3.add(Vec3.scale(v, c), Vec3.scale(Vec3.cross(k, v), s)), - Vec3.scale(k, Vec3.dot(k, v) * (1 - c)), + Vec3.scale(k, Vec3.dot(k, v) * (1 - c)) ); } diff --git a/packages/geometry/src/index.ts b/packages/geometry/src/index.ts index 7d7c54fd..7470ba83 100644 --- a/packages/geometry/src/index.ts +++ b/packages/geometry/src/index.ts @@ -10,22 +10,9 @@ export { Box2D } from './box2D'; export type { box2D } from './box2D'; export { Box3D } from './box3D'; export type { box3D } from './box3D'; -export { - size, - within, - isFiniteInterval, - isValid, - fixOrder, - intersection, - limit, - intervalToVec2, -} from './interval'; +export { size, within, isFiniteInterval, isValid, fixOrder, intersection, limit, intervalToVec2 } from './interval'; export type { box } from './BoundingBox'; -export { - getMinimumBoundingBox, - scaleFromPoint, - interpolateRectangles, -} from './Rectangle2D'; +export { getMinimumBoundingBox, scaleFromPoint, interpolateRectangles } from './Rectangle2D'; export { type CartesianAxis, type OrthogonalCartesianAxes, diff --git a/packages/geometry/src/spatialIndexing/tree.ts b/packages/geometry/src/spatialIndexing/tree.ts index 1a2edac8..3c1cbe25 100644 --- a/packages/geometry/src/spatialIndexing/tree.ts +++ b/packages/geometry/src/spatialIndexing/tree.ts @@ -10,7 +10,7 @@ export function visitBFS( tree: Tree, children: (t: Tree) => ReadonlyArray, visitor: (tree: Tree) => void, - traversalPredicate?: (t: Tree) => boolean, + traversalPredicate?: (t: Tree) => boolean ): void { const frontier: Tree[] = [tree]; while (frontier.length > 0) { @@ -28,7 +28,7 @@ export function visitBFS( export function visitBFSMaybe( tree: Tree, children: (t: Tree) => ReadonlyArray, - visitor: (tree: Tree) => boolean, + visitor: (tree: Tree) => boolean ): void { const frontier: Tree[] = [tree]; while (frontier.length > 0) { diff --git a/packages/geometry/src/tests/Rectangle2D.test.ts b/packages/geometry/src/tests/Rectangle2D.test.ts index eebcfd1b..678594b5 100644 --- a/packages/geometry/src/tests/Rectangle2D.test.ts +++ b/packages/geometry/src/tests/Rectangle2D.test.ts @@ -17,7 +17,7 @@ describe('scaleFromPoint', () => { size: [1, 1], }, 100, - [5, 5], + [5, 5] ); expect(scaled.center).toEqual([5, 5]); expect(scaled.size).toEqual([100, 100]); diff --git a/packages/geometry/src/tests/box2D.test.ts b/packages/geometry/src/tests/box2D.test.ts index 6dd5c795..c17d1c93 100644 --- a/packages/geometry/src/tests/box2D.test.ts +++ b/packages/geometry/src/tests/box2D.test.ts @@ -25,7 +25,7 @@ describe('box2D', () => { }); test('map', () => { expect(Box2D.map(Box2D.create([0, 0], [1, 1]), (v) => Vec2.scale(v, 200))).toStrictEqual( - Box2D.create([0, 0], [200, 200]), + Box2D.create([0, 0], [200, 200]) ); }); test('isValid', () => { diff --git a/packages/geometry/src/tests/box3D.test.ts b/packages/geometry/src/tests/box3D.test.ts index 006eb3d4..457fa1e9 100644 --- a/packages/geometry/src/tests/box3D.test.ts +++ b/packages/geometry/src/tests/box3D.test.ts @@ -33,7 +33,7 @@ describe('Box3D', () => { }); test('map', () => { expect(Box3D.map(Box3D.create([0, 0, 0], [1, 1, 1]), (v) => Vec3.scale(v, 300))).toStrictEqual( - Box3D.create([0, 0, 0], [300, 300, 300]), + Box3D.create([0, 0, 0], [300, 300, 300]) ); }); test('isValid', () => { @@ -44,7 +44,7 @@ describe('Box3D', () => { expect(nanBox).toBeFalsy(); const infinityBox = Box3D.isValid( - Box3D.create([Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY], [1, 1, 1]), + Box3D.create([Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY], [1, 1, 1]) ); expect(infinityBox).toBeFalsy(); diff --git a/packages/omezarr/changelog.md b/packages/omezarr/changelog.md index 4b6d94c3..f43e5498 100644 --- a/packages/omezarr/changelog.md +++ b/packages/omezarr/changelog.md @@ -36,10 +36,10 @@ All notable changes to this project will be documented in this file. - Rename vis-scatterbrain package to vis-core ([#118](https://github.com/AllenInstitute/vis/pull/118)) - Updates to package versions for Core, Geometry, OmeZarr + examples [DC-530] ([#124](https://github.com/AllenInstitute/vis/pull/124)) - Add helpful linting rules ([#127](https://github.com/AllenInstitute/vis/pull/127)) -- *(deps)* Bump zod from 3.24.2 to 3.24.3 ([#154](https://github.com/AllenInstitute/vis/pull/154)) +- _(deps)_ Bump zod from 3.24.2 to 3.24.3 ([#154](https://github.com/AllenInstitute/vis/pull/154)) - Dev command, reorganized docs, added stubs ([#163](https://github.com/AllenInstitute/vis/pull/163)) -- *(deps)* Bump zod from 3.24.3 to 3.25.46 ([#165](https://github.com/AllenInstitute/vis/pull/165)) -- *(deps)* Bump @biomejs/biome from 1.9.4 to 2.0.6 ([#174](https://github.com/AllenInstitute/vis/pull/174)) -- *(deps)* Bump zarrita from 0.5.1 to 0.5.2 ([#175](https://github.com/AllenInstitute/vis/pull/175)) +- _(deps)_ Bump zod from 3.24.3 to 3.25.46 ([#165](https://github.com/AllenInstitute/vis/pull/165)) +- _(deps)_ Bump @biomejs/biome from 1.9.4 to 2.0.6 ([#174](https://github.com/AllenInstitute/vis/pull/174)) +- _(deps)_ Bump zarrita from 0.5.1 to 0.5.2 ([#175](https://github.com/AllenInstitute/vis/pull/175)) diff --git a/packages/omezarr/src/index.ts b/packages/omezarr/src/index.ts index e6d5535e..a61653e6 100644 --- a/packages/omezarr/src/index.ts +++ b/packages/omezarr/src/index.ts @@ -7,11 +7,7 @@ export { type RenderSettingsChannels, } from './sliceview/slice-renderer'; export { VisZarrError, VisZarrDataError, VisZarrIndexError } from './errors'; -export { - type VoxelTile, - defaultDecoder, - getVisibleTiles, -} from './sliceview/loader'; +export { type VoxelTile, defaultDecoder, getVisibleTiles } from './sliceview/loader'; export { buildTileRenderCommand, buildRGBTileRenderCommand } from './sliceview/tile-renderer'; export { type ZarrDimension, diff --git a/packages/omezarr/src/sliceview/loader.test.ts b/packages/omezarr/src/sliceview/loader.test.ts index 8c712b40..855000f1 100644 --- a/packages/omezarr/src/sliceview/loader.test.ts +++ b/packages/omezarr/src/sliceview/loader.test.ts @@ -212,7 +212,7 @@ const exampleOmeZarr: OmeZarrMetadata = new OmeZarrMetadata( shape: [3, 142, 58, 78], }, ], - 2, + 2 ); describe('omezarr basic tiled loading', () => { diff --git a/packages/omezarr/src/sliceview/loader.ts b/packages/omezarr/src/sliceview/loader.ts index 30f40179..53c1fc73 100644 --- a/packages/omezarr/src/sliceview/loader.ts +++ b/packages/omezarr/src/sliceview/loader.ts @@ -53,7 +53,7 @@ function getVisibleTilesInLayer( orthoVal: number, dataset: OmeZarrMetadata, tileSize: number, - level: OmeZarrShapedDataset, + level: OmeZarrShapedDataset ) { const size = planeSizeInVoxels(plane, dataset.attrs.multiscales[0].axes, level); const realSize = sizeInUnits(plane, dataset.attrs.multiscales[0].axes, level); @@ -96,7 +96,7 @@ export function getVisibleTiles( plane: CartesianPlane, planeLocation: number, metadata: OmeZarrMetadata, - tileSize: number, + tileSize: number ): VoxelTile[] { // TODO (someday) open the array, look at its chunks, use that size for the size of the tiles I request! @@ -120,7 +120,7 @@ export const defaultDecoder = ( metadata: OmeZarrMetadata, r: ZarrRequest, level: OmeZarrShapedDataset, - signal?: AbortSignal, + signal?: AbortSignal ): Promise => { return loadSlice(metadata, r, level, signal).then((result: { shape: number[]; buffer: Chunk<'float32'> }) => { const { shape, buffer } = result; diff --git a/packages/omezarr/src/sliceview/slice-renderer.ts b/packages/omezarr/src/sliceview/slice-renderer.ts index c6846ac3..d80b1f83 100644 --- a/packages/omezarr/src/sliceview/slice-renderer.ts +++ b/packages/omezarr/src/sliceview/slice-renderer.ts @@ -101,7 +101,7 @@ type Decoder = ( dataset: OmeZarrMetadata, req: ZarrRequest, level: OmeZarrShapedDataset, - signal?: AbortSignal, + signal?: AbortSignal ) => Promise; export type OmeZarrSliceRendererOptions = { @@ -114,7 +114,7 @@ const DEFAULT_NUM_CHANNELS = 3; export function buildOmeZarrSliceRenderer( regl: REGL.Regl, decoder: Decoder, - options?: OmeZarrSliceRendererOptions | undefined, + options?: OmeZarrSliceRendererOptions | undefined ): Renderer { const numChannels = options?.numChannels ?? DEFAULT_NUM_CHANNELS; function sliceAsTexture(slice: VoxelTileImage): CachedTexture { @@ -151,7 +151,7 @@ export function buildOmeZarrSliceRenderer( for (const key in settings.channels) { contents[key] = (signal) => decoder(dataset, toZarrRequest(item, settings.channels[key].index), item.level, signal).then( - sliceAsTexture, + sliceAsTexture ); } return contents; diff --git a/packages/omezarr/src/zarr/cache-lower.ts b/packages/omezarr/src/zarr/cache-lower.ts index 431b59a3..0a29fff8 100644 --- a/packages/omezarr/src/zarr/cache-lower.ts +++ b/packages/omezarr/src/zarr/cache-lower.ts @@ -11,11 +11,11 @@ export function decoderFactory(url: string, workerModule: WorkerInit, options?: metadata: OmeZarrMetadata, req: ZarrRequest, level: OmeZarrShapedDataset, - signal?: AbortSignal, + signal?: AbortSignal ) => { if (metadata.url !== url) { throw new Error( - 'trying to use a decoder from a different store - we cant do that yet, although we could build a map of url->stores here if we wanted later - TODO', + 'trying to use a decoder from a different store - we cant do that yet, although we could build a map of url->stores here if we wanted later - TODO' ); } const scene = metadata.attrs.multiscales[0]; diff --git a/packages/omezarr/src/zarr/cached-loading/fetch-data.worker-loader.ts b/packages/omezarr/src/zarr/cached-loading/fetch-data.worker-loader.ts index 9eed2388..4fee705e 100644 --- a/packages/omezarr/src/zarr/cached-loading/fetch-data.worker-loader.ts +++ b/packages/omezarr/src/zarr/cached-loading/fetch-data.worker-loader.ts @@ -17,7 +17,7 @@ const fetchFile = async ( rootUrl: string, path: AbsolutePath, options?: TransferrableRequestInit | undefined, - abortController?: AbortController | undefined, + abortController?: AbortController | undefined ): Promise => { const store = new FetchStore(rootUrl); return store.get(path, { ...(options || {}), signal: abortController?.signal ?? null }); @@ -28,7 +28,7 @@ const fetchSlice = async ( path: AbsolutePath, range: RangeQuery, options?: TransferrableRequestInit | undefined, - abortController?: AbortController | undefined, + abortController?: AbortController | undefined ): Promise => { const store = new FetchStore(rootUrl); const wait = async (ms: number) => @@ -78,7 +78,7 @@ const handleFetch = (message: FetchMessage, abortControllers: Record { diff --git a/packages/omezarr/src/zarr/cached-loading/fetch-slice.worker.ts b/packages/omezarr/src/zarr/cached-loading/fetch-slice.worker.ts index bd845a25..2af1154a 100644 --- a/packages/omezarr/src/zarr/cached-loading/fetch-slice.worker.ts +++ b/packages/omezarr/src/zarr/cached-loading/fetch-slice.worker.ts @@ -10,7 +10,7 @@ async function fetchSlice( path: AbsolutePath, range: RangeQuery, options?: TransferrableRequestInit | undefined, - abortController?: AbortController | undefined, + abortController?: AbortController | undefined ): Promise { const store = new FetchStore(rootUrl); return store.getRange(path, range, { ...(options || {}), signal: abortController?.signal }); @@ -40,7 +40,7 @@ const handleFetchSlice = (message: FetchSliceMessage) => { id, payload: result?.buffer, }, - { ...options }, + { ...options } ); }) .catch((e) => { diff --git a/packages/omezarr/src/zarr/cached-loading/store.test.ts b/packages/omezarr/src/zarr/cached-loading/store.test.ts index 3b2f4936..47aed9f8 100644 --- a/packages/omezarr/src/zarr/cached-loading/store.test.ts +++ b/packages/omezarr/src/zarr/cached-loading/store.test.ts @@ -21,7 +21,7 @@ class Whatever implements RequestHandler { message: FetchMessage, _responseValidator: (obj: unknown) => obj is FetchResponseMessage, _transfers: Transferable[], - signal?: AbortSignal | undefined, + signal?: AbortSignal | undefined ): Promise { // so the generic parameters here cant work - the compile-time types of the interface to the worker are determined at construction time, not request time. // you can make the types work out here, but its a foot-gun. if you pass a responseValidator that the worker cant handle, the types will work out, but none of your promises will ever @@ -127,7 +127,7 @@ describe('basics', () => { a.then( // biome-ignore lint/suspicious/noConsole: Provides test outcome context (x) => console.log('a should be cancelled, but instead its', x), - () => {}, + () => {} ); expect(B instanceof Uint8Array).toBeTruthy(); expect(pool.log).toHaveLength(1); diff --git a/packages/omezarr/src/zarr/cached-loading/store.ts b/packages/omezarr/src/zarr/cached-loading/store.ts index d5642114..589e198c 100644 --- a/packages/omezarr/src/zarr/cached-loading/store.ts +++ b/packages/omezarr/src/zarr/cached-loading/store.ts @@ -100,7 +100,7 @@ export interface RequestHandler { message: RequestType, responseValidator: Guard, transfers: Transferable[], - signal?: AbortSignal | undefined, + signal?: AbortSignal | undefined ): Promise; destroy: () => void; } @@ -157,7 +157,7 @@ export class CachingMultithreadedFetchStore extends zarr.FetchStore { this.#dataCache = new PriorityCache( new Map(), this.#scoreFn, - options?.maxBytes ?? getDataCacheSizeLimit(), + options?.maxBytes ?? getDataCacheSizeLimit() ); this.#priorityByTimestamp = new Map(); this.#workerPool = handler; @@ -216,7 +216,7 @@ export class CachingMultithreadedFetchStore extends zarr.FetchStore { key: zarr.AbsolutePath, range: zarr.RangeQuery | undefined, options: TransferableRequestInit, - abort: AbortSignal | undefined, + abort: AbortSignal | undefined ): Promise { const cacheKey = asCacheKey(key, range); @@ -257,7 +257,7 @@ export class CachingMultithreadedFetchStore extends zarr.FetchStore { }, isFetchResponseMessage, [], - chain.signal, + chain.signal ); request @@ -297,7 +297,7 @@ export class CachingMultithreadedFetchStore extends zarr.FetchStore { async getRange( key: zarr.AbsolutePath, range: zarr.RangeQuery, - options?: RequestInit, + options?: RequestInit ): Promise { const cacheKey = asCacheKey(key, range); const cached = this.#fromCache(cacheKey); diff --git a/packages/omezarr/src/zarr/loading.ts b/packages/omezarr/src/zarr/loading.ts index c5f7f04a..e20f535e 100644 --- a/packages/omezarr/src/zarr/loading.ts +++ b/packages/omezarr/src/zarr/loading.ts @@ -54,7 +54,7 @@ export async function loadZarrArrayFile( res: WebResource, path: string, version = 2, - loadV2Attrs = true, + loadV2Attrs = true ): Promise { const url = getResourceUrl(res); const store = new zarr.FetchStore(url); @@ -66,7 +66,7 @@ export async function loadZarrArrayFileFromStore( store: zarr.FetchStore, path: string, version = 2, - loadV2Attrs = true, + loadV2Attrs = true ): Promise { const root = zarr.root(store); let array: zarr.Array; @@ -114,7 +114,7 @@ export async function loadMetadata(res: WebResource, loadV2ArrayAttrs = true): P ); }) .reduce((prev, curr) => prev.concat(curr)) - .filter((v) => v !== undefined), + .filter((v) => v !== undefined) ); return new OmeZarrMetadata(url, attrs, arrays, version); } @@ -137,7 +137,7 @@ export function pickBestScale( zarr: OmeZarrMetadata, plane: CartesianPlane, relativeView: box2D, // a box in data-unit-space - displayResolution: vec2, // in the plane given above + displayResolution: vec2 // in the plane given above ): OmeZarrShapedDataset { const datasets = zarr.getAllShapedDatasets(0); const axes = zarr.attrs.multiscales[0].axes; @@ -195,7 +195,7 @@ export function indexOfRelativeSlice( layer: OmeZarrShapedDataset, axes: readonly OmeZarrAxis[], parameter: number, - dim: ZarrDimension, + dim: ZarrDimension ): number { const dimIndex = indexFor(dim, axes); return Math.floor(layer.shape[dimIndex] * Math.max(0, Math.min(1, parameter))); @@ -211,7 +211,7 @@ export function nextSliceStep( zarr: OmeZarrMetadata, plane: CartesianPlane, relativeView: box2D, // a box in data-unit-space - displayResolution: vec2, // in the plane given above + displayResolution: vec2 // in the plane given above ) { // figure out what layer we'd be viewing const layer = pickBestScale(zarr, plane, relativeView, displayResolution); @@ -235,7 +235,7 @@ export function nextSliceStep( export function sizeInUnits( plane: CartesianPlane, axes: readonly OmeZarrAxis[], - dataset: OmeZarrShapedDataset, + dataset: OmeZarrShapedDataset ): vec2 | undefined { const vxls = planeSizeInVoxels(plane, axes, dataset); @@ -281,7 +281,7 @@ export function sizeInVoxels(dim: ZarrDimension, axes: readonly OmeZarrAxis[], d export function planeSizeInVoxels( plane: CartesianPlane, axes: readonly OmeZarrAxis[], - dataset: OmeZarrShapedDataset, + dataset: OmeZarrShapedDataset ): vec2 | undefined { // first - u&v must not refer to the same dimension, // and both should exist in the axes... @@ -335,7 +335,7 @@ export async function loadSlice( metadata: OmeZarrMetadata, r: ZarrRequest, level: OmeZarrShapedDataset, - signal?: AbortSignal, + signal?: AbortSignal ) { // put the request in native order const store = new zarr.FetchStore(metadata.url); diff --git a/packages/omezarr/src/zarr/types.ts b/packages/omezarr/src/zarr/types.ts index 9fe58875..0f0ccf76 100644 --- a/packages/omezarr/src/zarr/types.ts +++ b/packages/omezarr/src/zarr/types.ts @@ -371,7 +371,7 @@ export class OmeZarrMetadata { */ #getShapeElementMax( getShapeElement: (a: OmeZarrArrayMetadata, multiscaleIndex: number) => number, - multiscale?: number | string, + multiscale?: number | string ): number { const multiscaleIndex = this.#getValidMultiscaleIndex(multiscale); return this.#attrs.multiscales[multiscaleIndex].datasets diff --git a/packages/scatterbrain/readme.md b/packages/scatterbrain/readme.md index 7d033ea6..cdc74bda 100644 --- a/packages/scatterbrain/readme.md +++ b/packages/scatterbrain/readme.md @@ -1,15 +1,14 @@ - # Scatterbrain rendering utilities to render scatter plots, with specific support for 'scatterbrain' style (quad-tree spatial indexed) data sources as used for years now in ABC-atlas -## Why? ## +## Why? We wrote the ABC-atlas version of Scatterbrain rendering in a hot hot hurry a few years ago. At the time, we were preparing for a lot of variation along certain paths of development, and as is often the case, those guesses were a bit off the mark. As a result, the flexibility points we built into that version are not helping us much. For example, we take great pains to generate shaders with readable "column names" as users select different filter settings. However, for reasons, the names are just referenceIds from the backend, and we really never bother to debug the shaders in that way - they either fail up-front, or work fine, or are broken in more subtle ways that tend to have nothing to do with the names of the data. -## What is the goal here? ## +## What is the goal here? The goal is to modernize and simplify the WebGL powered features of ABC-atlas. We'd like to be able to understand the management of rendering resources, have more comprehensible interop with the rest of the React UI system, and in general reduce the confusingly generic (and needlessly generic) nature of various parts, as well as having less verbose and weird areas around diff --git a/packages/scatterbrain/src/dataset.ts b/packages/scatterbrain/src/dataset.ts index 98d00044..4ec5f05b 100644 --- a/packages/scatterbrain/src/dataset.ts +++ b/packages/scatterbrain/src/dataset.ts @@ -60,13 +60,13 @@ function dropZ(box: box3D) { function getVisibleItemsInTree( dataset: { root: TreeNode; boundingBox: volumeBound }, camera: { view: box2D; screenResolution: vec2 }, - limit: number, + limit: number ) { const { root, boundingBox } = dataset; const hits: { node: TreeNode; bounds: box2D }[] = []; const rootBounds = Box3D.create( [boundingBox.lx, boundingBox.ly, boundingBox.lz], - [boundingBox.ux, boundingBox.uy, boundingBox.uz], + [boundingBox.ux, boundingBox.uy, boundingBox.uz] ); visitBFSMaybe(root, children, (t) => { const B = dropZ(bounds(rootBounds, sanitizeName(t.file))); @@ -83,7 +83,7 @@ function getVisibleItemsInTree( export function getVisibleItems( dataset: Dataset, camera: { view: box2D; screenResolution: vec2; layout?: Record }, - visibilitySizeThreshold: number, + visibilitySizeThreshold: number ) { // determine if (dataset.type === 'normal') { @@ -110,8 +110,8 @@ export function getVisibleItems( ...getVisibleItemsInTree( slide.tree, { ...camera, view: Box2D.translate(camera.view, offset) }, - visibilitySizeThreshold, - ), + visibilitySizeThreshold + ) ); } return hits; @@ -141,7 +141,7 @@ const commonMetadataSchema = z.object({ return reduce>( attrs, (acc, attr) => ({ ...acc, [attr.name]: attr }), - {}, + {} ); }), }); diff --git a/packages/scatterbrain/src/renderer.ts b/packages/scatterbrain/src/renderer.ts index 10a9e983..758a486e 100644 --- a/packages/scatterbrain/src/renderer.ts +++ b/packages/scatterbrain/src/renderer.ts @@ -19,7 +19,7 @@ export function buildScatterbrainCacheClient( allNeededColumns: readonly string[], regl: REGL.Regl, cache: SharedPriorityCache, - onDataArrived: () => void, + onDataArrived: () => void ) { const client = cache.registerClient({ cacheKeys: (item) => { @@ -30,7 +30,7 @@ export function buildScatterbrainCacheClient( ...acc, [key]: `${dataset.metadata.metadataFileEndpoint}/${node.file}/${col.name}`, }), - {}, + {} ); }, fetch: (item) => { @@ -60,11 +60,11 @@ export function buildScatterbrainCacheClient( bytes: buff.byteLength, type: 'buffer', }); - }), + }) ), }; }, - {}, + {} ); return proms; }, @@ -84,13 +84,13 @@ export function buildScatterbrainCacheClient( function columnsForItem( config: Config, col2shader: Record, - dataset: ScatterbrainDataset | SlideviewScatterbrainDataset, + dataset: ScatterbrainDataset | SlideviewScatterbrainDataset ) { const columns: Record = {}; const s2c = reduce( keys(col2shader), (acc, col) => ({ ...acc, [col2shader[col]]: col }), - {} as Record, + {} as Record ); for (const c of config.categoricalColumns) { @@ -116,7 +116,7 @@ function columnsForItem( */ export function setCategoricalLookupTableValues( categories: Record>, - texture: REGL.Texture2D, + texture: REGL.Texture2D ) { const categoryKeys = keys(categories).toSorted(); const columns = categoryKeys.length; @@ -154,14 +154,14 @@ export function setCategoricalLookupTableValues( export function updateCategoricalValue( categories: readonly string[], update: { category: string; row: number; color: vec4; filteredIn: boolean }, - texture: REGL.Texture2D, + texture: REGL.Texture2D ) { const { category, row, color, filteredIn } = update; const col = categories.toSorted().indexOf(category); if (texture.width <= col || texture.height <= row || row < 0 || col < 0) { // todo - it might be better to let regl throw the same error... think about it throw new Error( - `attempted to update metadata lookup table with invalid coordinates: row=${row},col=${col} is not within ${texture.width}, ${texture.height}`, + `attempted to update metadata lookup table with invalid coordinates: row=${row},col=${col} is not within ${texture.width}, ${texture.height}` ); } const data = new Uint8Array(4); diff --git a/packages/scatterbrain/src/shader.ts b/packages/scatterbrain/src/shader.ts index f27a2482..bb314a5a 100644 --- a/packages/scatterbrain/src/shader.ts +++ b/packages/scatterbrain/src/shader.ts @@ -140,7 +140,7 @@ export function buildScatterbrainRenderCommand(config: Config, regl: REGL.Regl) const ranges = reduce( quantitativeColumns, (unis, col) => ({ ...unis, [rangeFor(col)]: prop(rangeFor(col)) }), - {} as Record>, + {} as Record> ); const { vs, fs } = buildShaders(config); const uniforms = { @@ -159,7 +159,7 @@ export function buildScatterbrainRenderCommand(config: Config, regl: REGL.Regl) frag: fs, attributes: [positionColumn, ...categoricalColumns, ...quantitativeColumns].reduce( (attribs, col) => ({ ...attribs, [col]: regl.prop(col) }), - {}, + {} ), uniforms, blend: { @@ -186,7 +186,7 @@ export function buildScatterbrainRenderCommand(config: Config, regl: REGL.Regl) const filterRanges = reduce( keys(quantitativeRangeFilters), (acc, cur) => ({ ...acc, [rangeFor(cur)]: quantitativeRangeFilters[cur] }), - {}, + {} ); const { view, screenResolution } = camera; const { count, columnData } = item; @@ -217,7 +217,7 @@ function categoricalFilterExpression(categoricalColumns: readonly string[], tabl return categoricalColumns .map( (attrib, i) => - /*glsl*/ `step(0.01,texture2D(${tableName},vec2(${i.toFixed(0)}.5,${attrib}+0.5)/vec2(${w.toFixed(1)},${h.toFixed(1)})).a)`, + /*glsl*/ `step(0.01,texture2D(${tableName},vec2(${i.toFixed(0)}.5,${attrib}+0.5)/vec2(${w.toFixed(1)},${h.toFixed(1)})).a)` ) .join(' * '); } @@ -351,7 +351,7 @@ export function configureShader(settings: ShaderSettings): { const longestCategory = reduce( keys(categoricalFilters), (highest, cur) => Math.max(highest, categoricalFilters[cur]), - 0, + 0 ); // the goal here is to associate column names with shader-safe names @@ -363,13 +363,13 @@ export function configureShader(settings: ShaderSettings): { const qAttrs = reduce( quantitativeFilters.toSorted(), (quantAttrs, quantFilter, i) => ({ ...quantAttrs, [quantFilter]: `MEASURE_${i.toFixed(0)}` }), - initialQuantitativeAttrs, + initialQuantitativeAttrs ); // we map each categorical filter's name to the shader-safe attribute name: CATEGORY_{i} const cAttrs = reduce( categories, (catAttrs, categoricalFilter, i) => ({ ...catAttrs, [categoricalFilter]: `CATEGORY_${i.toFixed(0)}` }), - initialCategoricalAttrs, + initialCategoricalAttrs ); const colToAttribute = { ...qAttrs, ...cAttrs, [dataset.metadata.spatialColumn]: 'position' }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ad508093..2f9a8210 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ importers: git-cliff: specifier: 2.12.0 version: 2.12.0 + oxfmt: + specifier: 0.46.0 + version: 0.46.0 parcel: specifier: 2.16.4 version: 2.16.4(@swc/helpers@0.5.17) @@ -1008,6 +1011,128 @@ packages: '@oslojs/encoding@1.1.0': resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + '@oxfmt/binding-android-arm-eabi@0.46.0': + resolution: {integrity: sha512-b1doV4WRcJU+BESSlCvCjV+5CEr/T6h0frArAdV26Nir+gGNFNaylvDiiMPfF1pxeV0txZEs38ojzJaxBYg+ng==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxfmt/binding-android-arm64@0.46.0': + resolution: {integrity: sha512-v6+HhjsoV3GO0u2u9jLSAZrvWfTraDxKofUIQ7/ktS7tzS+epVsxdHmeM+XxuNcAY/nWxxU1Sg4JcGTNRXraBA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxfmt/binding-darwin-arm64@0.46.0': + resolution: {integrity: sha512-3eeooJGrqGIlI5MyryDZsAcKXSmKIgAD4yYtfRrRJzXZ0UTFZtiSveIur56YPrGMYZwT4XyVhHsMqrNwr1XeFA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxfmt/binding-darwin-x64@0.46.0': + resolution: {integrity: sha512-QG8BDM0CXWbu84k2SKmCqfEddPQPFiBicwtYnLqHRWZZl57HbtOLRMac/KTq2NO4AEc4ICCBpFxJIV9zcqYfkQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxfmt/binding-freebsd-x64@0.46.0': + resolution: {integrity: sha512-9DdCqS/n2ncu/Chazvt3cpgAjAmIGQDz7hFKSrNItMApyV/Ja9mz3hD4JakIE3nS8PW9smEbPWnb389QLBY4nw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxfmt/binding-linux-arm-gnueabihf@0.46.0': + resolution: {integrity: sha512-Dgs7VeE2jT0LHMhw6tPEt0xQYe54kBqHEovmWsv4FVQlegCOvlIJNx0S8n4vj8WUtpT+Z6BD2HhKJPLglLxvZg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxfmt/binding-linux-arm-musleabihf@0.46.0': + resolution: {integrity: sha512-Zxn3adhTH13JKnU4xXJj8FeEfF680XjXh3gSShKl57HCMBRde2tUJTgogV/1MSHA80PJEVrDa7r66TLVq3Ia7Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxfmt/binding-linux-arm64-gnu@0.46.0': + resolution: {integrity: sha512-+TWipjrgVM8D7aIdDD0tlr3teLTTvQTn7QTE5BpT10H1Fj82gfdn9X6nn2sDgx/MepuSCfSnzFNJq2paLL0OiA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-arm64-musl@0.46.0': + resolution: {integrity: sha512-aAUPBWJ1lGwwnxZUEDLJ94+Iy6MuwJwPxUgO4sCA5mEEyDk7b+cDQ+JpX1VR150Zoyd+D49gsrUzpUK5h587Eg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxfmt/binding-linux-ppc64-gnu@0.46.0': + resolution: {integrity: sha512-ufBCJukyFX/UDrokP/r6BGDoTInnsDs7bxyzKAgMiZlt2Qu8GPJSJ6Zm6whIiJzKk0naxA8ilwmbO1LMw6Htxw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-riscv64-gnu@0.46.0': + resolution: {integrity: sha512-eqtlC2YmPqjun76R1gVfGLuKWx7NuEnLEAudZ7n6ipSKbCZTqIKSs1b5Y8K/JHZsRpLkeSmAAjig5HOIg8fQzQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-riscv64-musl@0.46.0': + resolution: {integrity: sha512-yccVOO2nMXkQLGgy0He3EQEwKD7NF0zEk+/OWmroznkqXyJdN6bfK0LtNnr6/14Bh3FjpYq7bP33l/VloCnxpA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxfmt/binding-linux-s390x-gnu@0.46.0': + resolution: {integrity: sha512-aAf7fG23OQCey6VRPj9IeCraoYtpgtx0ZyJ1CXkPyT1wjzBE7c3xtuxHe/AdHaJfVVb/SXpSk8Gl1LzyQupSqw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-x64-gnu@0.46.0': + resolution: {integrity: sha512-q0JPsTMyJNjYrBvYFDz4WbVsafNZaPCZv4RnFypRotLqpKROtBZcEaXQW4eb9YmvLU3NckVemLJnzkSZSdmOxw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-x64-musl@0.46.0': + resolution: {integrity: sha512-7LsLY9Cw57GPkhSR+duI3mt9baRczK/DtHYSldQ4BEU92da9igBQNl4z7Vq5U9NNPsh1FmpKvv1q9WDtiUQR1A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxfmt/binding-openharmony-arm64@0.46.0': + resolution: {integrity: sha512-lHiBOz8Duaku7JtRNLlps3j++eOaICPZSd8FCVmTDM4DFOPT71Bjn7g6iar1z7StXlKRweUKxWUs4sA+zWGDXg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxfmt/binding-win32-arm64-msvc@0.46.0': + resolution: {integrity: sha512-/5ktYUliP89RhgC37DBH1x20U5zPSZMy3cMEcO0j3793rbHP9MWsknBwQB6eozRzWmYrh0IFM/p20EbPvDlYlg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxfmt/binding-win32-ia32-msvc@0.46.0': + resolution: {integrity: sha512-3WTnoiuIr8XvV0DIY7SN+1uJSwKf4sPpcbHfobcRT9JutGcLaef/miyBB87jxd3aqH+mS0+G5lsgHuXLUwjjpQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxfmt/binding-win32-x64-msvc@0.46.0': + resolution: {integrity: sha512-IXxiQpkYnOwNfP23vzwSfhdpxJzyiPTY7eTn6dn3DsriKddESzM8i6kfq9R7CD/PUJwCvQT22NgtygBeug3KoA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@pagefind/darwin-arm64@1.4.0': resolution: {integrity: sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==} cpu: [arm64] @@ -3109,6 +3234,11 @@ packages: ordered-binary@1.6.0: resolution: {integrity: sha512-IQh2aMfMIDbPjI/8a3Edr+PiOpcsB7yo8NdW7aHWVaoR/pcDldunMvnnwbk/auPGqmKeAdxtZl7MHX/QmPwhvQ==} + oxfmt@0.46.0: + resolution: {integrity: sha512-CopwJOwPAjZ9p76fCvz+mSOJTw9/NY3cSksZK3VO/bUQ8UoEcketNgUuYS0UB3p+R9XnXe7wGGXUmyFxc7QxJA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + p-limit@6.2.0: resolution: {integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==} engines: {node: '>=18'} @@ -3506,6 +3636,10 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} + tinypool@2.1.0: + resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==} + engines: {node: ^20.0.0 || >=22.0.0} + tinyrainbow@3.1.0: resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} engines: {node: '>=14.0.0'} @@ -4760,6 +4894,63 @@ snapshots: '@oslojs/encoding@1.1.0': {} + '@oxfmt/binding-android-arm-eabi@0.46.0': + optional: true + + '@oxfmt/binding-android-arm64@0.46.0': + optional: true + + '@oxfmt/binding-darwin-arm64@0.46.0': + optional: true + + '@oxfmt/binding-darwin-x64@0.46.0': + optional: true + + '@oxfmt/binding-freebsd-x64@0.46.0': + optional: true + + '@oxfmt/binding-linux-arm-gnueabihf@0.46.0': + optional: true + + '@oxfmt/binding-linux-arm-musleabihf@0.46.0': + optional: true + + '@oxfmt/binding-linux-arm64-gnu@0.46.0': + optional: true + + '@oxfmt/binding-linux-arm64-musl@0.46.0': + optional: true + + '@oxfmt/binding-linux-ppc64-gnu@0.46.0': + optional: true + + '@oxfmt/binding-linux-riscv64-gnu@0.46.0': + optional: true + + '@oxfmt/binding-linux-riscv64-musl@0.46.0': + optional: true + + '@oxfmt/binding-linux-s390x-gnu@0.46.0': + optional: true + + '@oxfmt/binding-linux-x64-gnu@0.46.0': + optional: true + + '@oxfmt/binding-linux-x64-musl@0.46.0': + optional: true + + '@oxfmt/binding-openharmony-arm64@0.46.0': + optional: true + + '@oxfmt/binding-win32-arm64-msvc@0.46.0': + optional: true + + '@oxfmt/binding-win32-ia32-msvc@0.46.0': + optional: true + + '@oxfmt/binding-win32-x64-msvc@0.46.0': + optional: true + '@pagefind/darwin-arm64@1.4.0': optional: true @@ -7494,6 +7685,30 @@ snapshots: ordered-binary@1.6.0: {} + oxfmt@0.46.0: + dependencies: + tinypool: 2.1.0 + optionalDependencies: + '@oxfmt/binding-android-arm-eabi': 0.46.0 + '@oxfmt/binding-android-arm64': 0.46.0 + '@oxfmt/binding-darwin-arm64': 0.46.0 + '@oxfmt/binding-darwin-x64': 0.46.0 + '@oxfmt/binding-freebsd-x64': 0.46.0 + '@oxfmt/binding-linux-arm-gnueabihf': 0.46.0 + '@oxfmt/binding-linux-arm-musleabihf': 0.46.0 + '@oxfmt/binding-linux-arm64-gnu': 0.46.0 + '@oxfmt/binding-linux-arm64-musl': 0.46.0 + '@oxfmt/binding-linux-ppc64-gnu': 0.46.0 + '@oxfmt/binding-linux-riscv64-gnu': 0.46.0 + '@oxfmt/binding-linux-riscv64-musl': 0.46.0 + '@oxfmt/binding-linux-s390x-gnu': 0.46.0 + '@oxfmt/binding-linux-x64-gnu': 0.46.0 + '@oxfmt/binding-linux-x64-musl': 0.46.0 + '@oxfmt/binding-openharmony-arm64': 0.46.0 + '@oxfmt/binding-win32-arm64-msvc': 0.46.0 + '@oxfmt/binding-win32-ia32-msvc': 0.46.0 + '@oxfmt/binding-win32-x64-msvc': 0.46.0 + p-limit@6.2.0: dependencies: yocto-queue: 1.2.1 @@ -8032,6 +8247,8 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 + tinypool@2.1.0: {} + tinyrainbow@3.1.0: {} to-regex-range@5.0.1: diff --git a/site/changelog.md b/site/changelog.md index 377749a9..20798f64 100644 --- a/site/changelog.md +++ b/site/changelog.md @@ -12,6 +12,6 @@ All notable changes to this project will be documented in this file. - Upgrade Astro ([#161](https://github.com/AllenInstitute/vis/pull/161)) - Dev command, reorganized docs, added stubs ([#163](https://github.com/AllenInstitute/vis/pull/163)) -- *(deps)* Bump @biomejs/biome from 1.9.4 to 2.0.6 ([#174](https://github.com/AllenInstitute/vis/pull/174)) +- _(deps)_ Bump @biomejs/biome from 1.9.4 to 2.0.6 ([#174](https://github.com/AllenInstitute/vis/pull/174)) diff --git a/site/src/content/docs/developers/dependencies.md b/site/src/content/docs/developers/dependencies.md index 97e03505..e7b13387 100644 --- a/site/src/content/docs/developers/dependencies.md +++ b/site/src/content/docs/developers/dependencies.md @@ -4,11 +4,13 @@ description: A reference page describing how dependencies are managed in the vis --- ## Locked Dependencies + All dependencies in this project are locked to specific versions using the `.npmrc` file at the root of the project. This is to ensure that the project is built and tested with the same versions of dependencies across different environments, and reduces the threat of security vulnerabilities from a more permissive versioning strategy. ## Dependabot + We run a monthly Dependabot to automatically open PRs to update our dependencies. These are controlled in the `.github/dependabot.yml` file. Because we have multiple packages within this monorepo, that file is somewhat verbose. When adding a new package or example app, be sure to add a new section to `dependabot.yml`. diff --git a/site/src/content/docs/developers/development.md b/site/src/content/docs/developers/development.md index c07afd93..77b13852 100644 --- a/site/src/content/docs/developers/development.md +++ b/site/src/content/docs/developers/development.md @@ -8,6 +8,7 @@ sidebar: This document covers the tools, processes, and standards that we follow went developing within the `vis` repository. ## Development Servers + To get started developing in the `vis` repsitory, you can use the following command to watch for changes in all packages and the documentation site: ```sh @@ -23,6 +24,7 @@ If you'd rather run individual commands in multiple terminals, you can always us These tools will mostly be found in the `packages` directory. Each `example` will have its own needs and may not necessarily use all of these tools. ### Bundling + We use [Parcel](https://parceljs.org/) to bundle our libraries. You can produce a builds of all our packages suitable for upload to a JavaScript package repository by running the following command from the root directory or inside each `packages` folder: ```sh @@ -30,40 +32,49 @@ pnpm run build ``` ### Linter/Formatting + We use [Biome](https://biomejs.dev) for linting and formatting. To run the linter, use the following command: + ```sh pnpm run lint ``` To run the formatter, use the following command: + ```sh pnpm run fmt ``` You can also run the linter and formatter at the same time to see if there are issues (without fixing them): + ```sh pnpm run checks ``` And you can auto-apply simple fixes to both lints and formatting with the following: + ```sh pnpm run checks:fix ``` ### Testing + We use [Vitest](https://vitest.dev/) for testing. To run the tests, use the following command: + ```sh pnpm run test ``` #### Test Coverage + We use [Istanbul](https://istanbul.js.org/) for test coverage. To check coverage, use the following command: + ```sh pnpm run coverage ``` @@ -71,9 +82,11 @@ pnpm run coverage This will output coverage information to the CLI and also generate an HTML report in the `coverage` directory. ### Documentation and Example Site + We use [Starlight](https://starlight.astro.build/) for documentation and example site generation. To run the documentation site, use the following command from the `site` directory: + ```sh pnpm run dev ``` diff --git a/site/src/content/docs/developers/publishing.md b/site/src/content/docs/developers/publishing.md index f6cf2e26..68919082 100644 --- a/site/src/content/docs/developers/publishing.md +++ b/site/src/content/docs/developers/publishing.md @@ -1,6 +1,6 @@ --- title: Publishing Packages -description: A page describing how to publish packages in the vis project. +description: A page describing how to publish packages in the vis project. --- The `vis` project contains multiple packages, each of which is published to the Allen Institute NPM organization package registry. diff --git a/site/src/content/docs/examples/dzi.mdx b/site/src/content/docs/examples/dzi.mdx index 43862c2e..5ae72427 100644 --- a/site/src/content/docs/examples/dzi.mdx +++ b/site/src/content/docs/examples/dzi.mdx @@ -8,7 +8,7 @@ import { DziDemo } from '../../../examples/dzi/dzi-demo.tsx'; import dziViewerCode from '../../../examples/dzi/dzi-viewer.tsx?raw'; import dziDemoCode from '../../../examples/dzi/dzi-demo.tsx?raw'; -[Deep Zoom Image (DZI)](https://learn.microsoft.com/en-us/previous-versions/windows/silverlight/dotnet-windows-silverlight/cc645077(v=vs.95)) +[Deep Zoom Image (DZI)]() is a tile-based image pyramid format originally created for Microsoft Silverlight. It is well-suited for displaying very large images (gigapixels or larger) in a web browser because only the tiles visible at the current zoom level and viewport need to be fetched at any one time. @@ -43,11 +43,11 @@ import type { DziImage } from '@alleninstitute/vis-dzi'; const image: DziImage = { // URL of the *_files/ directory that holds the layer subfolders imagesUrl: 'https://example.com/my-image_files/', - format: 'jpeg', // 'jpeg' | 'png' | 'jpg' | 'JPG' | 'PNG' - overlap: 1, // pixels of overlap added on each side of a tile - tileSize: 512, // nominal tile edge length in pixels (power of 2) + format: 'jpeg', // 'jpeg' | 'png' | 'jpg' | 'JPG' | 'PNG' + overlap: 1, // pixels of overlap added on each side of a tile + tileSize: 512, // nominal tile edge length in pixels (power of 2) size: { - width: 15936, // full-resolution image width in pixels + width: 15936, // full-resolution image width in pixels height: 11526, }, }; @@ -112,7 +112,8 @@ export function RenderServerProvider({ children }: PropsWithChildren) { ``` ### Building the renderer and starting a frame @@ -121,16 +122,23 @@ Create the `RenderServer` inside a `useState` initializer so it is only instanti ```tsx import { useContext, useEffect, useRef } from 'react'; -import { buildAsyncDziRenderer, type DziImage, type DziRenderSettings, type DziTile, type GpuProps as CachedPixels } from '@alleninstitute/vis-dzi'; +import { + buildAsyncDziRenderer, + type DziImage, + type DziRenderSettings, + type DziTile, + type GpuProps as CachedPixels, +} from '@alleninstitute/vis-dzi'; import type { buildAsyncRenderer, RenderFrameFn } from '@alleninstitute/vis-core'; // Inside your component: const server = useContext(renderServerContext); const canvas = useRef(null); -const renderer = useRef< - ReturnType> ->(undefined); +const renderer = + useRef>>( + undefined + ); // Create the renderer once when the server is available useEffect(() => { @@ -169,7 +177,7 @@ useEffect(() => { }); } }, - canvas.current, + canvas.current ); }, [server, dzi, camera]); ``` @@ -209,10 +217,7 @@ import { Box2D, Vec2, type box2D, type vec2 } from '@alleninstitute/vis-geometry /** Zoom toward/away from a mouse position (in screen pixels). */ function zoom(view: box2D, screenSize: vec2, scale: number, mousePos: vec2): box2D { const zoomPoint = Vec2.add(view.minCorner, Vec2.mul(Vec2.div(mousePos, screenSize), Box2D.size(view))); - return Box2D.translate( - Box2D.scale(Box2D.translate(view, Vec2.scale(zoomPoint, -1)), [scale, scale]), - zoomPoint, - ); + return Box2D.translate(Box2D.scale(Box2D.translate(view, Vec2.scale(zoomPoint, -1)), [scale, scale]), zoomPoint); } /** Pan by a pixel delta. */ @@ -226,10 +231,16 @@ function pan(view: box2D, screenSize: vec2, delta: vec2): box2D {
dzi-demo.tsx โ€” the demo wrapper with shared camera and SVG overlay - +
dzi-viewer.tsx โ€” the reusable viewer component - +
diff --git a/site/src/content/docs/examples/layers.mdx b/site/src/content/docs/examples/layers.mdx index 9f774dfd..0703f013 100644 --- a/site/src/content/docs/examples/layers.mdx +++ b/site/src/content/docs/examples/layers.mdx @@ -8,10 +8,16 @@ import { ClientLayersScript } from '../../../examples/layers/layers-loader.tsx'; See instructions below the demo app UI for how to run this example.
-
- - -
+
+ + +
diff --git a/site/src/content/docs/examples/overview.mdx b/site/src/content/docs/examples/overview.mdx index 7b8452e8..722578b6 100644 --- a/site/src/content/docs/examples/overview.mdx +++ b/site/src/content/docs/examples/overview.mdx @@ -1,5 +1,5 @@ --- -title: Overview +title: Overview description: A page pointing to the examples in the `vis` project. sidebar: order: 0 diff --git a/site/src/content/docs/getting-started/packages.md b/site/src/content/docs/getting-started/packages.md index 887b615d..5f705bc3 100644 --- a/site/src/content/docs/getting-started/packages.md +++ b/site/src/content/docs/getting-started/packages.md @@ -20,6 +20,7 @@ To install and use these packages, see the instructions on [using packages](../u The following is a list of packages that we would like to create in the future. If you are interested in contributing to the development of any of these packages, please reach out on GitHub to get started! + - `vis-components` - A collection of web components for displaying visualizations built with our `vis` packages - `vis-react` - React component implementations of each of the visualization packages - `vis-[your favorite framework]` - Any other framework-specific implementations of our visualization packages, as driven by community needs diff --git a/site/src/content/docs/index.mdx b/site/src/content/docs/index.mdx index 32ca36d3..3ce1ea2f 100644 --- a/site/src/content/docs/index.mdx +++ b/site/src/content/docs/index.mdx @@ -3,33 +3,43 @@ title: Vis description: Homepage for the Vis open-source project template: splash hero: - tagline: Typescript packages for building big-data visualization tools & components, with examples for a variety of common data types & formats. Built by the Allen Institute for Brain Science. - image: - file: ../../assets/umap.png - actions: - - text: Get Started - link: /vis/getting-started/packages - variant: primary - - text: Examples - link: /vis/examples/omezarr1 - variant: secondary + tagline: Typescript packages for building big-data visualization tools & components, with examples for a variety of common data types & formats. Built by the Allen Institute for Brain Science. + image: + file: ../../assets/umap.png + actions: + - text: Get Started + link: /vis/getting-started/packages + variant: primary + - text: Examples + link: /vis/examples/omezarr1 + variant: secondary --- import { Card, CardGrid } from '@astrojs/starlight/components'; -## Powered by Vis +## Powered by Vis - - The [Allen Brain Cell Atlas (ABC Atlas)](https://knowledge.brain-map.org/abcatlas) - uses `@alleninstitute/vis-core` to visualize millions of points of data in the browser. - - - The [Genetic Tools Atlas (GTA)](https://knowledge.brain-map.org/data/7CVKSF7QGAKIQ8LM5LC/specimens/HTS03VQD4BBB67I3BAP) - uses `@alleninstitute/vis-omezarr` to display OME-Zarr previews. - - - The [SEA-AD project](https://knowledge.brain-map.org/data/JGN327NUXRZSHEV88TN/specimens/JGCXWER774NLNWX2NNR) + + The [Allen Brain Cell Atlas (ABC Atlas)](https://knowledge.brain-map.org/abcatlas) uses + `@alleninstitute/vis-core` to visualize millions of points of data in the browser. + + + The [Genetic Tools Atlas + (GTA)](https://knowledge.brain-map.org/data/7CVKSF7QGAKIQ8LM5LC/specimens/HTS03VQD4BBB67I3BAP) uses + `@alleninstitute/vis-omezarr` to display OME-Zarr previews. + + + The [SEA-AD project](https://knowledge.brain-map.org/data/JGN327NUXRZSHEV88TN/specimens/JGCXWER774NLNWX2NNR) uses `@alleninstitute/vis-dzi` to display Deep Zoom Image (DZI) views. - + diff --git a/site/src/content/docs/packages/core.mdx b/site/src/content/docs/packages/core.mdx index be39f0a2..a3ada49d 100644 --- a/site/src/content/docs/packages/core.mdx +++ b/site/src/content/docs/packages/core.mdx @@ -7,10 +7,10 @@ import PackageManagerTabs from '../../../components/PackageManagerTabs.astro'; ## Installation -To install the `@alleninstitute/vis-core` package, make sure you've followed the instructions for [authenticating +To install the `@alleninstitute/vis-core` package, make sure you've followed the instructions for [authenticating with the Allen Institute's npm registry on GitHub](../../getting-started/using-packages), then run the following command in your terminal: - { hits.push(tree); }, - (tree) => isVisible(view, sizeLimit, tree), + (tree) => isVisible(view, sizeLimit, tree) ); return hits; } @@ -54,7 +54,7 @@ export function getVisibleItemsInSlide(dataset: SlideViewDataset, slide: string, (tree) => { hits.push(tree); }, - (tree) => isVisible(view, sizeLimit, tree), + (tree) => isVisible(view, sizeLimit, tree) ); return hits; } @@ -68,7 +68,7 @@ function fetchAndUpload( settings: { dataset: Dataset; regl: REGL.Regl }, node: ColumnarNode, req: ColumnRequest, - signal?: AbortSignal | undefined, + signal?: AbortSignal | undefined ) { const { dataset, regl } = settings; return fetchColumn(node, dataset, req, signal).then((cd) => toReglBuffer(cd, regl)); diff --git a/site/src/examples/common/loaders/scatterplot/scatterbrain-loader.ts b/site/src/examples/common/loaders/scatterplot/scatterbrain-loader.ts index 62e054cc..f1c7ab47 100644 --- a/site/src/examples/common/loaders/scatterplot/scatterbrain-loader.ts +++ b/site/src/examples/common/loaders/scatterplot/scatterbrain-loader.ts @@ -120,7 +120,7 @@ function convertTree2D( bounds: box3D, depth: number, metadataPath: string, - genePath: string, + genePath: string ): ColumnarTree { const safeName = sanitizeName(n.file); return { @@ -140,8 +140,8 @@ function convertTree2D( getChildBoundsUsingPotreeIndexing(bounds, getRelativeIndex(safeName, sanitizeName(c.file))), depth + 1, metadataPath, - genePath, - ), + genePath + ) ) : [], }; @@ -178,7 +178,7 @@ function loadSlideViewDataset(metadata: SlideColumnarMetadata, _datasetUrl: stri } as const, }); }, - {} as Record, + {} as Record ); const slideTrees: SlideTree[] = slides.map((slide) => { @@ -217,7 +217,7 @@ export function loadDataset(metadata: ColumnarMetadata, datasetUrl: string) { } as const, }); }, - {} as Record, + {} as Record ); return { dimensions: 2, @@ -256,7 +256,7 @@ export async function fetchColumn( node: ColumnarNode>, dataset: ReturnType, column: ColumnRequest, - signal?: AbortSignal, + signal?: AbortSignal ): Promise { const referenceIdForEmbedding = dataset.visualizationReferenceId; const getColumnUrl = (columnName: string) => `${node.url}${columnName}/${referenceIdForEmbedding}/${node.name}.bin`; diff --git a/site/src/examples/data-renderers/annotation-renderer.ts b/site/src/examples/data-renderers/annotation-renderer.ts index 30c2e91d..540dac4e 100644 --- a/site/src/examples/data-renderers/annotation-renderer.ts +++ b/site/src/examples/data-renderers/annotation-renderer.ts @@ -47,7 +47,7 @@ function isMesh(obj: object | undefined): obj is CacheContentType { function fetchAnnotationsForSlide( item: SlideAnnotations, settings: Settings, - _abort: AbortSignal | undefined, + _abort: AbortSignal | undefined ): Record Promise> { const { regl } = settings; const toCacheEntry = (m: AnnotationMesh | undefined): CacheContentType | undefined => @@ -73,7 +73,7 @@ type RProps = Parameters>[0]; function renderSlideAnnotations( item: SlideAnnotations, settings: Settings, - columns: Record, + columns: Record ) { const { camera, viewport, target, regl, loopRenderer, meshRenderer, stencilMeshRenderer } = settings; // const { view } = camera.projection === 'webImage' ? flipY(camera) : camera @@ -150,7 +150,7 @@ export type RenderSettings = { export function renderAnnotationGrid( target: REGL.Framebuffer2D | null, grid: AnnotationGrid, - settings: RenderSettings, + settings: RenderSettings ): FrameLifecycle { const { dataset, annotationBaseUrl, levelFeature, stroke, fill } = grid; const { @@ -212,7 +212,7 @@ export function renderAnnotationGrid( renderSlideAnnotations, callback, (rq: string, item: SlideAnnotations, _settings: Settings) => `${rq}_${item.gridFeature}_${item.levelFeature}`, - cpuLimit, + cpuLimit ); return frame; } diff --git a/site/src/examples/data-renderers/dynamicGridSlideRenderer.ts b/site/src/examples/data-renderers/dynamicGridSlideRenderer.ts index eb3d44bd..738cc709 100644 --- a/site/src/examples/data-renderers/dynamicGridSlideRenderer.ts +++ b/site/src/examples/data-renderers/dynamicGridSlideRenderer.ts @@ -29,7 +29,7 @@ const cacheKey = (reqKey: string, item: ColumnarTree, settings: { colorBy: export function renderSlide( target: REGL.Framebuffer2D | null, slide: DynamicGridSlide, - settings: RenderSettings, + settings: RenderSettings ) { const { cache, @@ -64,14 +64,14 @@ export function renderSlide( renderer, callback, cacheKey, - cpuLimit, + cpuLimit ); } export function renderDynamicGrid( target: REGL.Framebuffer2D | null, grid: DynamicGrid, - settings: RenderSettings, + settings: RenderSettings ) { const { cache, @@ -102,8 +102,8 @@ export function renderDynamicGrid( if (Box2D.intersection(view, realBounds)) { items.push( ...getVisibleItemsInSlide(grid.dataset, slide.id, settings.camera.view, 10 * unitsPerPixel[0]).map( - (t) => ({ ...t, offset }), - ), + (t) => ({ ...t, offset }) + ) ); } }); @@ -119,6 +119,6 @@ export function renderDynamicGrid( renderer, callback, cacheKey, - cpuLimit, + cpuLimit ); } diff --git a/site/src/examples/data-renderers/lineRenderer.ts b/site/src/examples/data-renderers/lineRenderer.ts index c2a344ac..31d81adb 100644 --- a/site/src/examples/data-renderers/lineRenderer.ts +++ b/site/src/examples/data-renderers/lineRenderer.ts @@ -73,7 +73,7 @@ export function buildPathRenderer(regl: REGL.Regl) { return ( item: Path, settings: { view: box2D; target: REGL.Framebuffer2D | null }, - tasks: Record, + tasks: Record ) => { const pos = tasks.position; const { view, target } = settings; diff --git a/site/src/examples/data-renderers/scatterplot.ts b/site/src/examples/data-renderers/scatterplot.ts index 6b424137..a6d56c69 100644 --- a/site/src/examples/data-renderers/scatterplot.ts +++ b/site/src/examples/data-renderers/scatterplot.ts @@ -72,7 +72,7 @@ export function buildRenderer(regl: REGL.Regl) { const renderDots = ( item: ColumnarTree & { offset?: vec2 | undefined }, settings: RenderSettings, - columns: Record, + columns: Record ) => { const { color, position } = columns; const count = item.content.count; diff --git a/site/src/examples/data-renderers/simpleAnnotationRenderer.ts b/site/src/examples/data-renderers/simpleAnnotationRenderer.ts index 6cfa8f9e..24e28a43 100644 --- a/site/src/examples/data-renderers/simpleAnnotationRenderer.ts +++ b/site/src/examples/data-renderers/simpleAnnotationRenderer.ts @@ -39,7 +39,7 @@ function requestsForPath(p: Path) { export function renderAnnotationLayer( target: REGL.Framebuffer2D | null, layer: SimpleAnnotation & OptionalTransform, - settings: RenderSettings, + settings: RenderSettings ) { const { camera, cache, renderer, callback } = settings; const items = getVisibleStrokes(camera, layer); @@ -55,6 +55,6 @@ export function renderAnnotationLayer( requestsForPath, renderer, callback, - (rq: string, path: Path) => `${rq}_${path.id}_${path.points.length}`, + (rq: string, path: Path) => `${rq}_${path.id}_${path.points.length}` ); } diff --git a/site/src/examples/data-renderers/versa-renderer.ts b/site/src/examples/data-renderers/versa-renderer.ts index 79bec6ef..e3ead7da 100644 --- a/site/src/examples/data-renderers/versa-renderer.ts +++ b/site/src/examples/data-renderers/versa-renderer.ts @@ -134,7 +134,7 @@ export function buildVersaRenderer(regl: REGL.Regl) { return ( item: VoxelTile, settings: VoxelSliceRenderSettings, - channels: Record, + channels: Record ) => { const { view, gamut, target, rotation } = settings; const { realBounds } = item; @@ -272,7 +272,7 @@ export function getVisibleTiles( plane: CartesianPlane, planeIndex: number, metadata: OmeZarrMetadata, - offset?: vec2, + offset?: vec2 ): { layer: number; view: box2D; tiles: VoxelTile[] } { const layer = pickBestScale(metadata, plane, camera.view, camera.screen); // TODO: open the array, look at its chunks, use that size for the size of the tiles I request! diff --git a/site/src/examples/data-renderers/volumeSliceRenderer.ts b/site/src/examples/data-renderers/volumeSliceRenderer.ts index 7c1cd2aa..e9594944 100644 --- a/site/src/examples/data-renderers/volumeSliceRenderer.ts +++ b/site/src/examples/data-renderers/volumeSliceRenderer.ts @@ -40,7 +40,7 @@ function preferCachedEntries( location: { plane: CartesianPlane; orthoVal: number; - }, + } ) { const { plane, orthoVal } = location; const idealTiles = getVisibleTiles(camera, plane, orthoVal, grid.metadata, offset); @@ -60,7 +60,7 @@ function preferCachedEntries( plane, orthoVal, grid.metadata, - offset, + offset ); fakes.push(...lowerLOD.tiles); } @@ -74,7 +74,7 @@ function preferCachedEntries( export function renderGrid( target: REGL.Framebuffer2D | null, grid: AxisAlignedZarrSliceGrid, - settings: RenderSettings, + settings: RenderSettings ) { const { cache, renderer, callback, regl } = settings; let { camera, concurrentTasks, queueInterval, cpuLimit } = settings; @@ -150,7 +150,7 @@ export function renderGrid( renderer, callback, cacheKeyFactory, - cpuLimit, + cpuLimit ); return frame; } @@ -158,7 +158,7 @@ export function renderGrid( export function renderSlice( target: REGL.Framebuffer2D | null, slice: AxisAlignedZarrSlice, - settings: RenderSettings, + settings: RenderSettings ) { const { cache, renderer, callback, regl } = settings; let { camera, concurrentTasks, queueInterval, cpuLimit } = settings; @@ -201,7 +201,7 @@ export function renderSlice( renderer, callback, cacheKeyFactory, - cpuLimit, + cpuLimit ); return frame; } diff --git a/site/src/examples/data-sources/annotation/annotation-to-mesh.ts b/site/src/examples/data-sources/annotation/annotation-to-mesh.ts index 3081486e..892c05e3 100644 --- a/site/src/examples/data-sources/annotation/annotation-to-mesh.ts +++ b/site/src/examples/data-sources/annotation/annotation-to-mesh.ts @@ -26,7 +26,7 @@ function groupLoops(path: Path) { } return loops; }, - [[]] as PathCommand[][], + [[]] as PathCommand[][] ) ?? []; return closed.filter((loop) => loop.length > 0); } @@ -78,15 +78,12 @@ function closedPolygon(loop: PathCommand[]) { }, initialState); } function onlyDefined(collection: ReadonlyArray): ReadonlyArray { - return collection.reduce( - (defined, cur) => { - if (cur !== undefined) { - (defined as T[]).push(cur); - } - return defined; - }, - [] as ReadonlyArray, - ); + return collection.reduce((defined, cur) => { + if (cur !== undefined) { + (defined as T[]).push(cur); + } + return defined; + }, [] as ReadonlyArray); } // intersection stuff: @@ -201,7 +198,7 @@ export function MeshFromAnnotation(annotation: Annotation): AnnotationMesh | und // we have to pre-allocate a big pile of 32-bit floats, so we have to count all the lengths: const totalNumbers = groups.reduce( (sum, group) => sum + group.loops.reduce((total, loop) => total + (loop?.data.length ?? 0), 0), - 0, + 0 ); const points = new Float32Array(totalNumbers); diff --git a/site/src/examples/dzi/dzi-demo.tsx b/site/src/examples/dzi/dzi-demo.tsx index c960920e..0314a561 100644 --- a/site/src/examples/dzi/dzi-demo.tsx +++ b/site/src/examples/dzi/dzi-demo.tsx @@ -72,7 +72,10 @@ export function DziDemo() {
{images.map((v) => ( -
+
, - [w, h], + [w, h] ); this.layers.push({ type: 'scatterplotGrid', @@ -236,7 +236,7 @@ export class Demo { | ZarrSliceConfig | ZarrSliceGridConfig | ScatterPlotGridSlideConfig - | AnnotationGridConfig, + | AnnotationGridConfig ) { switch (config.type) { case 'AnnotationGridConfig': @@ -260,7 +260,7 @@ export class Demo { this.regl, this.imgRenderer, renderAnnotationLayer, - [w, h], + [w, h] ), }); this.uiChange(); @@ -276,7 +276,7 @@ export class Demo { this.regl, this.imgRenderer, renderAnnotationLayer, - [w, h], + [w, h] ), }); this.uiChange(); @@ -289,7 +289,7 @@ export class Demo { this.regl, this.imgRenderer, renderSlide, - [w, h], + [w, h] ); this.layers.push({ type: 'scatterplot', @@ -354,7 +354,7 @@ export class Demo { this.regl, this.imgRenderer, renderAnnotationGrid, - [w, h], + [w, h] ), }); // look at it! @@ -370,7 +370,7 @@ export class Demo { this.regl, this.imgRenderer, renderGrid, - [w, h], + [w, h] ); this.layers.push({ type: 'volumeGrid', @@ -395,7 +395,7 @@ export class Demo { screen: [w, h], projection: projection === 'webImage' ? 'cartesian' : 'webImage', }, - this.layers, + this.layers ); // create an offscreen canvas... const cnvs = new OffscreenCanvas(w, h); @@ -427,7 +427,7 @@ export class Demo { const layerPromises: Array<() => FrameLifecycle> = []; const nextLayerWhenFinished: RenderCallback = ( - e: { status: NormalStatus } | { status: 'error'; error: unknown }, + e: { status: NormalStatus } | { status: 'error'; error: unknown } ) => { const { status } = e; switch (status) { @@ -467,7 +467,7 @@ export class Demo { renderGrid(target, layer.data, { ...settings, renderer: renderers[layer.type], - }), + }) ); break; case 'annotationGrid': @@ -475,7 +475,7 @@ export class Demo { renderAnnotationGrid(target, layer.data, { ...settings, renderers: renderers[layer.type], - }), + }) ); break; case 'volumeSlice': @@ -483,7 +483,7 @@ export class Demo { renderSlice(target, layer.data, { ...settings, renderer: renderers[layer.type], - }), + }) ); break; case 'scatterplot': @@ -491,7 +491,7 @@ export class Demo { renderSlide(target, layer.data, { ...settings, renderer: renderers[layer.type], - }), + }) ); break; case 'annotationLayer': @@ -499,7 +499,7 @@ export class Demo { renderAnnotationLayer(target, layer.data, { ...settings, renderer: renderers[layer.type], - }), + }) ); break; case 'scatterplotGrid': @@ -507,7 +507,7 @@ export class Demo { renderDynamicGrid(target, layer.data, { ...settings, renderer: renderers[layer.type], - }), + }) ); break; } @@ -578,7 +578,7 @@ export class Demo { renderer: renderers[layer.type], }, }, - this.mode === 'pan', + this.mode === 'pan' ); // dont cancel while drawing } else if (layer.type === 'volumeGrid') { layer.render.onChange({ @@ -695,7 +695,7 @@ export class Demo { this.zoom(e.deltaY > 0 ? 1.1 : 0.9); e.preventDefault(); }, - { passive: false }, + { passive: false } ); window.onkeyup = (e: KeyboardEvent) => { diff --git a/site/src/examples/multithreading/multithreading-demo.tsx b/site/src/examples/multithreading/multithreading-demo.tsx index 218a2c79..ade45eba 100644 --- a/site/src/examples/multithreading/multithreading-demo.tsx +++ b/site/src/examples/multithreading/multithreading-demo.tsx @@ -52,14 +52,20 @@ export function MultithreadingDemo() { value={numWorkers} onChange={(e) => setNumWorkers(Number.parseInt(e.target.value, 10))} /> - ) : ( {numWorkers} - diff --git a/site/src/examples/omezarr/gallery-demo/omezarr-gallery.tsx b/site/src/examples/omezarr/gallery-demo/omezarr-gallery.tsx index 05f33549..8521d777 100644 --- a/site/src/examples/omezarr/gallery-demo/omezarr-gallery.tsx +++ b/site/src/examples/omezarr/gallery-demo/omezarr-gallery.tsx @@ -14,22 +14,40 @@ export function OmezarrGalleryDemo() {
- +
- +
- +
- +
- +
- +
diff --git a/site/src/examples/omezarr/minimal-example/sliceview.tsx b/site/src/examples/omezarr/minimal-example/sliceview.tsx index 364d9545..eaad514a 100644 --- a/site/src/examples/omezarr/minimal-example/sliceview.tsx +++ b/site/src/examples/omezarr/minimal-example/sliceview.tsx @@ -79,7 +79,7 @@ export function SliceView(props: Props) { { ...settings, camera: { ...settings.camera, view } }, callback, target, - cache, + cache ); } return null; @@ -105,7 +105,7 @@ export function SliceView(props: Props) { } } }, - cnvs.current, + cnvs.current ); } }, [server, omezarr, view]); @@ -118,7 +118,7 @@ export function SliceView(props: Props) { setView(v); } }, - [view], + [view] ); return ( { @@ -166,10 +166,16 @@ export function OmeZarrView(props: Props) { onMouseMove={handlePan} />
- -
diff --git a/site/src/examples/omezarr/priority-cache-demo/omezarr-via-priority-cache.tsx b/site/src/examples/omezarr/priority-cache-demo/omezarr-via-priority-cache.tsx index 22c5f29a..deda929a 100644 --- a/site/src/examples/omezarr/priority-cache-demo/omezarr-via-priority-cache.tsx +++ b/site/src/examples/omezarr/priority-cache-demo/omezarr-via-priority-cache.tsx @@ -8,7 +8,10 @@ const screenSize: vec2 = [800, 800]; export function OmezarrDemo() { return ( - + ); } diff --git a/site/src/examples/omezarr/priority-cache-demo/render-utils.ts b/site/src/examples/omezarr/priority-cache-demo/render-utils.ts index 6c2de288..44d7b1ac 100644 --- a/site/src/examples/omezarr/priority-cache-demo/render-utils.ts +++ b/site/src/examples/omezarr/priority-cache-demo/render-utils.ts @@ -34,7 +34,7 @@ function mapValues, V, R>(obj: T, fn: (v: V) => R): acc[k] = fn(obj[k]); return acc; }, - {} as { [k in keyof T]: R }, + {} as { [k in keyof T]: R } ); } @@ -43,7 +43,7 @@ export function buildConnectedRenderer( screenSize: vec2, cache: SharedPriorityCache, decoder: Decoder, - onData: () => void, + onData: () => void ) { const renderer = buildOmeZarrSliceRenderer(regl, decoder); const client = cache.registerClient>({ @@ -67,7 +67,7 @@ export function buildConnectedRenderer( }, isValue: (v): v is Record => renderer.isPrepared( - mapValues(v, (tx: Cacheable | undefined) => (tx && tx instanceof Tex ? tx.texture : undefined)), + mapValues(v, (tx: Cacheable | undefined) => (tx && tx instanceof Tex ? tx.texture : undefined)) ), onDataArrived: onData, }); @@ -99,7 +99,7 @@ export function buildConnectedRenderer( }); client.setPriorities( new Set(items.map((tile) => ({ tile, dataset, settings }))), - new Set(baselayer.map((tile) => ({ tile, dataset, settings }))), + new Set(baselayer.map((tile) => ({ tile, dataset, settings }))) ); regl.clear({ framebuffer: target, color: [0, 0, 0, 1], depth: 1 }); @@ -113,7 +113,7 @@ export function buildConnectedRenderer( dataset, settings, // { ...settings, camera: { ...settings.camera, view: upsideDown } }, - mapValues(drawme, (d: Tex) => d.texture), + mapValues(drawme, (d: Tex) => d.texture) ); } } diff --git a/site/src/examples/omezarr/selectable-image-demo/omezarr-demo.tsx b/site/src/examples/omezarr/selectable-image-demo/omezarr-demo.tsx index 3d33485e..193e840a 100644 --- a/site/src/examples/omezarr/selectable-image-demo/omezarr-demo.tsx +++ b/site/src/examples/omezarr/selectable-image-demo/omezarr-demo.tsx @@ -53,7 +53,7 @@ export function OmezarrDemo() { const settings: RenderSettings | undefined = useMemo( () => (omezarr ? makeZarrSettings(screenSize, view, planeIndex, omezarr) : undefined), - [omezarr, view, planeIndex], + [omezarr, view, planeIndex] ); const load = (res: WebResource) => { @@ -133,16 +133,29 @@ export function OmezarrDemo() {
- + {OMEZARR_DEMO_FILESETS.map((opt) => ( - ))} - @@ -154,7 +167,10 @@ export function OmezarrDemo() { onChange={(e) => setCustomUrl(e.target.value)} style={{ flexGrow: 1 }} /> -
@@ -208,10 +224,16 @@ export function OmezarrDemo() { )) || No image loaded}
- -
diff --git a/site/src/examples/omezarr/selectable-image-demo/omezarr-viewer.tsx b/site/src/examples/omezarr/selectable-image-demo/omezarr-viewer.tsx index 513cbf32..2185a6a2 100644 --- a/site/src/examples/omezarr/selectable-image-demo/omezarr-viewer.tsx +++ b/site/src/examples/omezarr/selectable-image-demo/omezarr-viewer.tsx @@ -145,7 +145,7 @@ export function OmezarrViewer({ { ...settings, camera: { view: settings.camera.view, screenSize: [1, 1] } }, callback, target, - cache, + cache ); } return null; @@ -162,7 +162,7 @@ export function OmezarrViewer({ depth: 1, }); lowResPreview(e.target, server.cache, (_e) => {})?.cancelFrame( - 'lowres preview beneath actual frame', + 'lowres preview beneath actual frame' ); if (imgRenderer.current && stash.current) { imgRenderer.current({ @@ -197,7 +197,7 @@ export function OmezarrViewer({ } } }, - canvas.current, + canvas.current ); } }, [server, omezarr, settings]); diff --git a/site/src/examples/scatterbrain/demo.tsx b/site/src/examples/scatterbrain/demo.tsx index 26c11f3c..e88be784 100644 --- a/site/src/examples/scatterbrain/demo.tsx +++ b/site/src/examples/scatterbrain/demo.tsx @@ -79,7 +79,7 @@ function Demo(props: Props) { const { render, connectToCache } = buildScatterbrainRenderFn( // @ts-expect-error we'll deal with this later regl, - { ...settings, dataset }, + { ...settings, dataset } ); // this ts error is bogus, dont know why const renderOneFrame = () => { @@ -105,5 +105,11 @@ function Demo(props: Props) { renderOneFrame(); } }, [dataset, server, screenSize]); - return ; + return ( + + ); } diff --git a/site/src/examples/ui/contact-sheet.tsx b/site/src/examples/ui/contact-sheet.tsx index bce7d9cb..e0d18b3a 100644 --- a/site/src/examples/ui/contact-sheet.tsx +++ b/site/src/examples/ui/contact-sheet.tsx @@ -85,13 +85,25 @@ export function ContactSheetUI(props: { demo: Demo }) { />
- - -
diff --git a/site/src/examples/ui/slice-ui.tsx b/site/src/examples/ui/slice-ui.tsx index 75aceb0d..4ea65011 100644 --- a/site/src/examples/ui/slice-ui.tsx +++ b/site/src/examples/ui/slice-ui.tsx @@ -97,13 +97,25 @@ export function SliceViewLayer(props: { demo: Demo }) { demo.setSlice(Number(e.target.value)); }} /> - - -
From dc4fab7771c937ebbaa7706ad42679d1bad685d1 Mon Sep 17 00:00:00 2001 From: Lane Sawyer Date: Mon, 4 May 2026 14:18:08 -0700 Subject: [PATCH 2/3] Add prettier to fmt Astro files too --- package.json | 8 +-- pnpm-lock.yaml | 60 ++++++++++++++++---- site/.prettierrc | 10 ++++ site/package.json | 4 +- site/src/components/PackageManagerTabs.astro | 15 ++++- 5 files changed, 77 insertions(+), 20 deletions(-) create mode 100644 site/.prettierrc diff --git a/package.json b/package.json index cc9e6191..226b6a4c 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,12 @@ "test": "pnpm -r run --no-bail test:ci", "coverage": "pnpm -r run coverage", "typecheck": "pnpm -r --no-bail run typecheck", - "fmt": "oxfmt", - "fmt:check": "oxfmt --check", + "fmt": "oxfmt && cd site && prettier --write '**/*.astro'", + "fmt:check": "oxfmt --check && cd site && prettier --check '**/*.astro'", "lint": "biome lint . --write", "lint:check": "biome lint .", - "check": "oxfmt --check && biome lint .", - "check:fix": "oxfmt && biome lint . --write", + "check": "oxfmt --check && (cd site && prettier --check '**/*.astro') && biome lint .", + "check:fix": "oxfmt && (cd site && prettier --write '**/*.astro') && biome lint . --write", "changelog": "pnpm -r run changelog" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7b657e94..0f5c04a4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -137,7 +137,7 @@ importers: version: link:../packages/scatterbrain '@astrojs/check': specifier: 0.9.6 - version: 0.9.6(prettier@3.8.1)(typescript@5.9.3) + version: 0.9.6(prettier-plugin-astro@0.14.1)(prettier@3.5.3)(typescript@5.9.3) '@astrojs/mdx': specifier: 4.3.13 version: 4.3.13(astro@5.17.1(@types/node@22.1.0)(lightningcss@1.30.2)(rollup@4.60.2)(typescript@5.9.3)(yaml@2.8.1)) @@ -193,6 +193,12 @@ importers: '@types/node': specifier: 22.1.0 version: 22.1.0 + prettier: + specifier: 3.5.3 + version: 3.5.3 + prettier-plugin-astro: + specifier: 0.14.1 + version: 0.14.1 packages: @@ -3329,8 +3335,12 @@ packages: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} - prettier@3.8.1: - resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} + prettier-plugin-astro@0.14.1: + resolution: {integrity: sha512-RiBETaaP9veVstE4vUwSIcdATj6dKmXljouXc/DDNwBSPTp8FRkLGDSGFClKsAFeeg+13SB0Z1JZvbD76bigJw==} + engines: {node: ^14.15.0 || >=16.0.0} + + prettier@3.5.3: + resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} engines: {node: '>=14'} hasBin: true @@ -3498,9 +3508,15 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + s.color@0.0.15: + resolution: {integrity: sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + sass-formatter@0.7.9: + resolution: {integrity: sha512-CWZ8XiSim+fJVG0cFLStwDvft1VI7uvXdCNJYXhDvowiv+DsbD1nXLiQ4zrE5UBvj5DWZJ93cwN0NX5PMsr1Pw==} + sax@1.4.1: resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} @@ -3605,6 +3621,9 @@ packages: style-to-object@1.0.9: resolution: {integrity: sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==} + suf-log@2.5.3: + resolution: {integrity: sha512-KvC8OPjzdNOe+xQ4XWJV2whQA0aM1kGVczMQ8+dStAO6KfEB140JEVQ9dE76ONZ0/Ylf67ni4tILPJB41U0eow==} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -4165,9 +4184,9 @@ packages: snapshots: - '@astrojs/check@0.9.6(prettier@3.8.1)(typescript@5.9.3)': + '@astrojs/check@0.9.6(prettier-plugin-astro@0.14.1)(prettier@3.5.3)(typescript@5.9.3)': dependencies: - '@astrojs/language-server': 2.16.3(prettier@3.8.1)(typescript@5.9.3) + '@astrojs/language-server': 2.16.3(prettier-plugin-astro@0.14.1)(prettier@3.5.3)(typescript@5.9.3) chokidar: 4.0.3 kleur: 4.1.5 typescript: 5.9.3 @@ -4180,7 +4199,7 @@ snapshots: '@astrojs/internal-helpers@0.7.5': {} - '@astrojs/language-server@2.16.3(prettier@3.8.1)(typescript@5.9.3)': + '@astrojs/language-server@2.16.3(prettier-plugin-astro@0.14.1)(prettier@3.5.3)(typescript@5.9.3)': dependencies: '@astrojs/compiler': 2.13.0 '@astrojs/yaml2ts': 0.2.2 @@ -4194,14 +4213,15 @@ snapshots: volar-service-css: 0.0.68(@volar/language-service@2.4.28) volar-service-emmet: 0.0.68(@volar/language-service@2.4.28) volar-service-html: 0.0.68(@volar/language-service@2.4.28) - volar-service-prettier: 0.0.68(@volar/language-service@2.4.28)(prettier@3.8.1) + volar-service-prettier: 0.0.68(@volar/language-service@2.4.28)(prettier@3.5.3) volar-service-typescript: 0.0.68(@volar/language-service@2.4.28) volar-service-typescript-twoslash-queries: 0.0.68(@volar/language-service@2.4.28) volar-service-yaml: 0.0.68(@volar/language-service@2.4.28) vscode-html-languageservice: 5.6.1 vscode-uri: 3.1.0 optionalDependencies: - prettier: 3.8.1 + prettier: 3.5.3 + prettier-plugin-astro: 0.14.1 transitivePeerDependencies: - typescript @@ -7823,7 +7843,13 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - prettier@3.8.1: {} + prettier-plugin-astro@0.14.1: + dependencies: + '@astrojs/compiler': 2.13.0 + prettier: 3.5.3 + sass-formatter: 0.7.9 + + prettier@3.5.3: {} pretty-ms@9.3.0: dependencies: @@ -8100,8 +8126,14 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.60.2 fsevents: 2.3.3 + s.color@0.0.15: {} + safe-buffer@5.2.1: {} + sass-formatter@0.7.9: + dependencies: + suf-log: 2.5.3 + sax@1.4.1: {} scheduler@0.27.0: {} @@ -8222,6 +8254,10 @@ snapshots: dependencies: inline-style-parser: 0.2.4 + suf-log@2.5.3: + dependencies: + s.color: 0.0.15 + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -8492,12 +8528,12 @@ snapshots: optionalDependencies: '@volar/language-service': 2.4.28 - volar-service-prettier@0.0.68(@volar/language-service@2.4.28)(prettier@3.8.1): + volar-service-prettier@0.0.68(@volar/language-service@2.4.28)(prettier@3.5.3): dependencies: vscode-uri: 3.1.0 optionalDependencies: '@volar/language-service': 2.4.28 - prettier: 3.8.1 + prettier: 3.5.3 volar-service-typescript-twoslash-queries@0.0.68(@volar/language-service@2.4.28): dependencies: @@ -8607,7 +8643,7 @@ snapshots: ajv: 8.17.1 ajv-draft-04: 1.0.0(ajv@8.17.1) lodash: 4.17.21 - prettier: 3.8.1 + prettier: 3.5.3 request-light: 0.5.8 vscode-json-languageservice: 4.1.8 vscode-languageserver: 9.0.1 diff --git a/site/.prettierrc b/site/.prettierrc new file mode 100644 index 00000000..6b8ad282 --- /dev/null +++ b/site/.prettierrc @@ -0,0 +1,10 @@ +{ + "plugins": ["prettier-plugin-astro"], + "printWidth": 120, + "trailingComma": "es5", + "tabWidth": 4, + "singleQuote": true, + "semi": true, + "singleAttributePerLine": true, + "endOfLine": "auto" +} diff --git a/site/package.json b/site/package.json index 308577e8..c8597f00 100644 --- a/site/package.json +++ b/site/package.json @@ -42,7 +42,9 @@ "@types/file-saver": "2.0.7", "@types/node": "22.1.0", "@types/react": "18.3.0", - "@types/react-dom": "18.3.0" + "@types/react-dom": "18.3.0", + "prettier": "3.5.3", + "prettier-plugin-astro": "0.14.1" }, "dependencies": { "@alleninstitute/vis-core": "workspace:*", diff --git a/site/src/components/PackageManagerTabs.astro b/site/src/components/PackageManagerTabs.astro index d70400d1..c5a16ddb 100644 --- a/site/src/components/PackageManagerTabs.astro +++ b/site/src/components/PackageManagerTabs.astro @@ -12,12 +12,21 @@ const { npm, pnpm, yarn } = Astro.props; - + - + - + From f3a3ee75731e13f15617cfde7f77bcba2c17594b Mon Sep 17 00:00:00 2001 From: Lane Sawyer Date: Mon, 4 May 2026 14:22:59 -0700 Subject: [PATCH 3/3] fix CI --- package.json | 10 ++++++---- pnpm-lock.yaml | 12 ++++++------ site/package.json | 4 +--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 226b6a4c..2032f6f3 100644 --- a/package.json +++ b/package.json @@ -7,17 +7,19 @@ "test": "pnpm -r run --no-bail test:ci", "coverage": "pnpm -r run coverage", "typecheck": "pnpm -r --no-bail run typecheck", - "fmt": "oxfmt && cd site && prettier --write '**/*.astro'", - "fmt:check": "oxfmt --check && cd site && prettier --check '**/*.astro'", + "fmt": "oxfmt && prettier --write 'site/**/*.astro'", + "fmt:check": "oxfmt --check && prettier --check 'site/**/*.astro'", "lint": "biome lint . --write", "lint:check": "biome lint .", - "check": "oxfmt --check && (cd site && prettier --check '**/*.astro') && biome lint .", - "check:fix": "oxfmt && (cd site && prettier --write '**/*.astro') && biome lint . --write", + "check": "oxfmt --check && prettier --check 'site/**/*.astro' && biome lint .", + "check:fix": "oxfmt && prettier --write 'site/**/*.astro' && biome lint . --write", "changelog": "pnpm -r run changelog" }, "devDependencies": { "@biomejs/biome": "2.4.13", "oxfmt": "0.46.0", + "prettier": "3.5.3", + "prettier-plugin-astro": "0.14.1", "@parcel/packager-ts": "2.16.4", "@parcel/transformer-typescript-types": "2.16.4", "@vitest/coverage-istanbul": "4.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0f5c04a4..eacbe12d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,6 +32,12 @@ importers: parcel: specifier: 2.16.4 version: 2.16.4(@swc/helpers@0.5.17) + prettier: + specifier: 3.5.3 + version: 3.5.3 + prettier-plugin-astro: + specifier: 0.14.1 + version: 0.14.1 process: specifier: 0.11.10 version: 0.11.10 @@ -193,12 +199,6 @@ importers: '@types/node': specifier: 22.1.0 version: 22.1.0 - prettier: - specifier: 3.5.3 - version: 3.5.3 - prettier-plugin-astro: - specifier: 0.14.1 - version: 0.14.1 packages: diff --git a/site/package.json b/site/package.json index c8597f00..308577e8 100644 --- a/site/package.json +++ b/site/package.json @@ -42,9 +42,7 @@ "@types/file-saver": "2.0.7", "@types/node": "22.1.0", "@types/react": "18.3.0", - "@types/react-dom": "18.3.0", - "prettier": "3.5.3", - "prettier-plugin-astro": "0.14.1" + "@types/react-dom": "18.3.0" }, "dependencies": { "@alleninstitute/vis-core": "workspace:*",