From 256822ddd7aae013866bcd8c54c7140ca711477b Mon Sep 17 00:00:00 2001 From: Heberto Mayorquin Date: Thu, 25 Apr 2024 16:11:26 -0600 Subject: [PATCH 1/2] install zarrita --- package-lock.json | 93 +++++++++++++++++++++++++++++++++++++++++++---- package.json | 3 +- 2 files changed, 88 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 02f3924..1e80cd2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "template_library", + "name": "hybrid_template_library", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "template_library", + "name": "hybrid_template_library", "version": "1.0.0", "dependencies": { "@testing-library/jest-dom": "^5.17.0", @@ -17,7 +17,8 @@ "react-scripts": "^5.0.1", "react-syntax-highlighter": "^15.5.0", "web-vitals": "^2.1.4", - "zarr": "^0.6.3" + "zarr": "^0.6.3", + "zarrita": "^0.4.0-next.10" }, "devDependencies": { "eslint": "^8.57.0", @@ -4805,6 +4806,48 @@ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, + "node_modules/@zarrita/core": { + "version": "0.1.0-next.8", + "resolved": "https://registry.npmjs.org/@zarrita/core/-/core-0.1.0-next.8.tgz", + "integrity": "sha512-WdpTxX4JLVfpP1LAt4aAoQsC/dkgpZzhFTHKykPOGSQ7tkLRfn3ON4T7dxYVcD9uQkRE+ZTTBjhkAFnVQkNasQ==", + "dependencies": { + "@zarrita/storage": "^0.1.0-next.4", + "@zarrita/typedarray": "^0.1.0-next.2", + "numcodecs": "^0.3.1" + } + }, + "node_modules/@zarrita/core/node_modules/numcodecs": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/numcodecs/-/numcodecs-0.3.1.tgz", + "integrity": "sha512-ywIyGpJ+c6Ojktq9a8jsWSy12ZSUcW/W+I3jlH0q0zv9aR/ZiMsN7IrWaNq9YV2FRdLu6r/M6lp35jMA6fug/A==", + "dependencies": { + "fflate": "^0.8.0" + } + }, + "node_modules/@zarrita/indexing": { + "version": "0.1.0-next.10", + "resolved": "https://registry.npmjs.org/@zarrita/indexing/-/indexing-0.1.0-next.10.tgz", + "integrity": "sha512-WOquXdNUNBf22Kl3qkdJmWnzMDLKxpyrgdC87HNR8Y8imQMTdRjejFiI7FvOrY/7HqViDgrckYsyxRrkbLUHjg==", + "dependencies": { + "@zarrita/core": "^0.1.0-next.8", + "@zarrita/storage": "^0.1.0-next.4", + "@zarrita/typedarray": "^0.1.0-next.2" + } + }, + "node_modules/@zarrita/storage": { + "version": "0.1.0-next.4", + "resolved": "https://registry.npmjs.org/@zarrita/storage/-/storage-0.1.0-next.4.tgz", + "integrity": "sha512-+Gqaw/dA3VD53gLdXfQs3UKZmchE5CL0N35A1mXrT/QS9dxGQrcp9q7Tcdx9VlqU1eirh8cPVM0z+xPFLiYYyw==", + "dependencies": { + "reference-spec-reader": "^0.2.0", + "unzipit": "^1.4.3" + } + }, + "node_modules/@zarrita/typedarray": { + "version": "0.1.0-next.2", + "resolved": "https://registry.npmjs.org/@zarrita/typedarray/-/typedarray-0.1.0-next.2.tgz", + "integrity": "sha512-utFKMocqLk5j4GXCKkuZQr3mAakskjq77GoUV5B55HJh0leXH9idDIelzpUszEsLpSIkFwO2Id/NHuClhCuzSw==" + }, "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -8293,6 +8336,11 @@ "bser": "2.1.1" } }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==" + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -15357,6 +15405,11 @@ "node": ">=8" } }, + "node_modules/reference-spec-reader": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/reference-spec-reader/-/reference-spec-reader-0.2.0.tgz", + "integrity": "sha512-q0mfCi5yZSSHXpCyxjgQeaORq3tvDsxDyzaadA/5+AbAUwRyRuuTh0aRQuE/vAOt/qzzxidJ5iDeu1cLHaNBlQ==" + }, "node_modules/reflect.getprototypeof": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", @@ -17423,16 +17476,16 @@ } }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=14.17" + "node": ">=4.2.0" } }, "node_modules/unbox-primitive": { @@ -17527,6 +17580,17 @@ "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==" }, + "node_modules/unzipit": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unzipit/-/unzipit-1.4.3.tgz", + "integrity": "sha512-gsq2PdJIWWGhx5kcdWStvNWit9FVdTewm4SEG7gFskWs+XCVaULt9+BwuoBtJiRE8eo3L1IPAOrbByNLtLtIlg==", + "dependencies": { + "uzip-module": "^1.0.2" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/upath": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", @@ -17622,6 +17686,11 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/uzip-module": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/uzip-module/-/uzip-module-1.0.3.tgz", + "integrity": "sha512-AMqwWZaknLM77G+VPYNZLEruMGWGzyigPK3/Whg99B3S6vGHuqsyl5ZrOv1UUF3paGK1U6PM0cnayioaryg/fA==" + }, "node_modules/v8-to-istanbul": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", @@ -18627,6 +18696,16 @@ "engines": { "node": ">=12" } + }, + "node_modules/zarrita": { + "version": "0.4.0-next.10", + "resolved": "https://registry.npmjs.org/zarrita/-/zarrita-0.4.0-next.10.tgz", + "integrity": "sha512-S9SODuy40xuv4jSYP0AtfdItWOetKTyEGGRCO0uv7NQ+JY66Q/k4kvGxuM040sxVIIboKkjuA7V+pT3uyPtgLA==", + "dependencies": { + "@zarrita/core": "^0.1.0-next.8", + "@zarrita/indexing": "^0.1.0-next.10", + "@zarrita/storage": "^0.1.0-next.4" + } } } } diff --git a/package.json b/package.json index 484f5cd..c2ed839 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,8 @@ "react-scripts": "^5.0.1", "react-syntax-highlighter": "^15.5.0", "web-vitals": "^2.1.4", - "zarr": "^0.6.3" + "zarr": "^0.6.3", + "zarrita": "^0.4.0-next.10" }, "eslintConfig": { "extends": [ From bb986c4d41b919559a0d961de20593a35b3cc46c Mon Sep 17 00:00:00 2001 From: Heberto Mayorquin Date: Fri, 26 Apr 2024 10:29:32 -0600 Subject: [PATCH 2/2] add extra table information --- src/components/App.js | 61 ++++++++++++++++++++++++++---- src/components/RowPlotContainer.js | 38 ++++++++++++------- 2 files changed, 79 insertions(+), 20 deletions(-) diff --git a/src/components/App.js b/src/components/App.js index 7363226..e1ef1e4 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,20 +1,25 @@ import React, { useState, useEffect} from "react"; import { HTTPStore } from "zarr"; +import { FetchStore, open, get} from "zarrita"; import CodeSnippet from "./CodeSnippet"; import RowPlotContainer from "./RowPlotContainer"; import "../styles/App.css"; +//const url = "http://localhost:8000/zarr_store.zarr"; +const url = "https://spikeinterface-template-database.s3.us-east-2.amazonaws.com/test_templates"; + + function App() { - const url = "https://spikeinterface-template-database.s3.us-east-2.amazonaws.com/test_templates"; - //const url = "http://localhost:8000/zarr_store.zarr"; const storeRef = new HTTPStore(url); + const [selectedTemplates, setSelectedTemplates] = useState(new Set()); // Updated to useState const [templateIndices, setTemplateIndices] = useState([]); const [hasMore, setHasMore] = useState(true); - const batchSize = 15; + const batchSize = 10; + const [dataDictionary, setDataDictionary] = useState({}); - const loadTemplates = () => { + const loadTempalteIndices = () => { const nextIndex = templateIndices.length === 0 ? 0 : Math.max(...templateIndices) + 1; const newIndices = Array.from({ length: batchSize }, (_, i) => i + nextIndex); @@ -24,6 +29,47 @@ function App() { } }; + + async function loadSessionData() { + + const store = new FetchStore(url); + const root = await open(store, { kind: "group" }); + + const brainAreaZarrArray = await open(root.resolve("brain_area"), { kind: "array" }); + const brainAreaArrayData = await get(brainAreaZarrArray, null); + const brainAreaArrayJS = Array.from(brainAreaArrayData.data); + + const unitIdsZarrArray = await open(root.resolve("unit_ids"), { kind: "array" }); + const unitIdsArrayData = await get(unitIdsZarrArray, null); + const unitIdsArrayJS = Array.from(unitIdsArrayData.data); + const unitIDsArrayJSString = unitIdsArrayJS.map(String) + + + const ChannelIDsZarrArray = await open(root.resolve("channel_ids"), { kind: "array" }); + const ChannelIDsArrayData = await get(ChannelIDsZarrArray, null); + const ChannelIDsArrayJS = Array.from(ChannelIDsArrayData.data); + const ChannelIDsArrayJSString = ChannelIDsArrayJS.map(String) + + const SpikesPerUnitZarrArray = await open(root.resolve("spikes_per_unit"), { kind: "array" }); + const SpikesPerUnitArrayData = await get(SpikesPerUnitZarrArray, null); + const SpikesPerUnitArrayJS = Array.from(SpikesPerUnitArrayData.data); + + + const BestChannelsZarrArray = await open(root.resolve("channel_ids"), { kind: "array" }); + const BestChannelsArrayData = await get(BestChannelsZarrArray, null); + const BestChannelsArrayJS = Array.from(BestChannelsArrayData.data); + + let dataDictionary_ = {}; + dataDictionary_["brain_area"] = brainAreaArrayJS; + dataDictionary_["unit_ids"] = unitIDsArrayJSString; + dataDictionary_["spikes_per_unit"] = SpikesPerUnitArrayJS + dataDictionary_["channel_ids"] = ChannelIDsArrayJSString + dataDictionary_["best_channels"] = BestChannelsArrayJS + + + setDataDictionary(dataDictionary_); + } + const toggleTemplateSelection = (templateIndex) => { const newSet = new Set(selectedTemplates); if (newSet.has(templateIndex)) { @@ -32,11 +78,11 @@ function App() { newSet.add(templateIndex); } setSelectedTemplates(newSet); // Trigger re-render - console.log("Selected Templates: ", Array.from(newSet)); }; useEffect(() => { - loadTemplates(); + loadTempalteIndices(); + loadSessionData(); }, []); return ( @@ -49,6 +95,7 @@ function App() { toggleTemplateSelection(templateIndex)} @@ -56,7 +103,7 @@ function App() { ))} {hasMore && ( - )} diff --git a/src/components/RowPlotContainer.js b/src/components/RowPlotContainer.js index 6d5b85e..3065858 100644 --- a/src/components/RowPlotContainer.js +++ b/src/components/RowPlotContainer.js @@ -9,7 +9,7 @@ import calculatePeakToPeakValues from "../utils/CalculationUtils"; import { percentageToFilterChannels } from "../styles/StyleConstants"; -const RowPlotContainer = ({ templateIndex, storeRef, isSelected, toggleSelection }) => { +const RowPlotContainer = ({ templateIndex, storeRef, dataDictionary, isSelected, toggleSelection }) => { const [isLoading, setIsLoading] = useState(true); const [probeXCoordinates, setProbeXCoordinates] = useState([]); const [probeYCoordinates, setProbeYCoordinates] = useState([]); @@ -22,6 +22,7 @@ const RowPlotContainer = ({ templateIndex, storeRef, isSelected, toggleSelection useEffect(() => { const loadData = async () => { try { + const zarrGroup = await openGroup(storeRef); const probeGroup = await openGroup(storeRef, "probe", "r"); @@ -39,6 +40,7 @@ const RowPlotContainer = ({ templateIndex, storeRef, isSelected, toggleSelection const templateArray = await zarrGroup.getItem("templates_array"); setTemplateArray(templateArray); const singleTemplate = await templateArray.get([templateIndex, null, null]); + const peakToPeakValues = calculatePeakToPeakValues(singleTemplate); const bestChannel = peakToPeakValues.indexOf(Math.max(...peakToPeakValues)); @@ -48,23 +50,33 @@ const RowPlotContainer = ({ templateIndex, storeRef, isSelected, toggleSelection .filter((index) => index !== null); setActiveIndices(_activeIndices); - // Set table data (mockup or real) - const data = [ - { attribute: "Number of Samples", value: "855" }, - { attribute: "Dataset", value: "IBL" }, - { attribute: "Brain Location", value: "Hippocampus" }, - { attribute: "Channel with max amplitude", value: bestChannel }, - { attribute: "Amplitude", value: peakToPeakValues[bestChannel] }, - { attribute: "Sampling Frequency", value: samplingFrequency }, - { attribute: "Location", value: location }, - ]; - setTableData(data); - // Set location based on best channel const locationX = xCoords.data[bestChannel]; const locationY = yCoords.data[bestChannel]; setLocation([locationX, locationY]); + // Set table data (mockup or real) + const brainArea = dataDictionary["brain_area"][templateIndex]; + const NumberOfSpikes = dataDictionary["spikes_per_unit"][templateIndex] + const bestChannelID = dataDictionary["channel_ids"][bestChannel] + const UnitID = dataDictionary["unit_ids"][templateIndex] + + const peakToPeakBestChannel = peakToPeakValues[bestChannel] + const peakToPeakBestChannelDecimalsRounded = peakToPeakBestChannel.toFixed(2) + + const data = [ + // { attribute: "Template Index", value: templateIndex}, + // { attribute: "Channel with max amplitude", value: bestChannel }, + { attribute: "UnitID", value: UnitID }, + { attribute: "Number of Spikes", value: NumberOfSpikes }, + { attribute: "Best ChannelID", value: bestChannelID}, + { attribute: "Brain Location", value: brainArea}, + { attribute: "Peak To Peak (mV)", value: peakToPeakBestChannelDecimalsRounded}, + { attribute: "Depth (um)", value: location[1]}, + + ]; + setTableData(data); + setIsLoading(false); } catch (error) { console.error("Error loading data for template index " + templateIndex + ":", error);