diff --git a/package-lock.json b/package-lock.json
index df9a88a1..6a7685ce 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,7 +12,9 @@
"@babel/eslint-parser": "^7.22.7",
"@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-brands-svg-icons": "^6.4.0",
+ "@fortawesome/free-solid-svg-icons": "^7.2.0",
"@fortawesome/pro-regular-svg-icons": "^6.4.0",
+ "@fortawesome/pro-solid-svg-icons": "^6.7.1",
"@fortawesome/react-fontawesome": "^0.2.0",
"@testing-library/cypress": "^10.0.1",
"@testing-library/jest-dom": "^5.16.5",
@@ -8757,6 +8759,27 @@
"node": ">=6"
}
},
+ "node_modules/@fortawesome/free-solid-svg-icons": {
+ "version": "7.2.0",
+ "resolved": "https://npm.fontawesome.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-7.2.0.tgz",
+ "integrity": "sha512-YTVITFGN0/24PxzXrwqCgnyd7njDuzp5ZvaCx5nq/jg55kUYd94Nj8UTchBdBofi/L0nwRfjGOg0E41d2u9T1w==",
+ "license": "(CC-BY-4.0 AND MIT)",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "7.2.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/free-solid-svg-icons/node_modules/@fortawesome/fontawesome-common-types": {
+ "version": "7.2.0",
+ "resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-7.2.0.tgz",
+ "integrity": "sha512-IpR0bER9FY25p+e7BmFH25MZKEwFHTfRAfhOyJubgiDnoJNsSvJ7nigLraHtp4VOG/cy8D7uiV0dLkHOne5Fhw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@fortawesome/pro-regular-svg-icons": {
"version": "6.4.0",
"resolved": "https://npm.fontawesome.com/@fortawesome/pro-regular-svg-icons/-/6.4.0/pro-regular-svg-icons-6.4.0.tgz",
@@ -8768,6 +8791,25 @@
"node": ">=6"
}
},
+ "node_modules/@fortawesome/pro-solid-svg-icons": {
+ "version": "6.7.1",
+ "resolved": "https://npm.fontawesome.com/@fortawesome/pro-solid-svg-icons/-/6.7.1/pro-solid-svg-icons-6.7.1.tgz",
+ "integrity": "sha512-YMehuODXC+puZRJigjfB+hwCeiUsfEfiDXJV0W1iSbrqX9xBbDl0Ovbnai3EUlwIVWpgfoWew6Cx207wwVAEnA==",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.7.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/pro-solid-svg-icons/node_modules/@fortawesome/fontawesome-common-types": {
+ "version": "6.7.1",
+ "resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-common-types/-/6.7.1/fontawesome-common-types-6.7.1.tgz",
+ "integrity": "sha512-gbDz3TwRrIPT3i0cDfujhshnXO9z03IT1UKRIVi/VEjpNHtSBIP2o5XSm+e816FzzCFEzAxPw09Z13n20PaQJQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@fortawesome/react-fontawesome": {
"version": "0.2.0",
"resolved": "https://npm.fontawesome.com/@fortawesome/react-fontawesome/-/0.2.0/react-fontawesome-0.2.0.tgz",
diff --git a/package.json b/package.json
index b830ec3e..75f9243f 100644
--- a/package.json
+++ b/package.json
@@ -1,13 +1,15 @@
{
"name": "neuronbridge",
- "version": "3.4.0",
+ "version": "3.5.0",
"private": true,
"dependencies": {
"@ant-design/icons": "^5.1.4",
"@babel/eslint-parser": "^7.22.7",
"@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-brands-svg-icons": "^6.4.0",
+ "@fortawesome/free-solid-svg-icons": "^7.2.0",
"@fortawesome/pro-regular-svg-icons": "^6.4.0",
+ "@fortawesome/pro-solid-svg-icons": "^6.7.1",
"@fortawesome/react-fontawesome": "^0.2.0",
"@testing-library/cypress": "^10.0.1",
"@testing-library/jest-dom": "^5.16.5",
diff --git a/public/RELEASENOTES.md b/public/RELEASENOTES.md
index 6909f125..32f84f8e 100644
--- a/public/RELEASENOTES.md
+++ b/public/RELEASENOTES.md
@@ -1,3 +1,44 @@
+## VERSION 3.5.0 - 2026-04-17
+
+### Major Features
+
+ - **Curated Matches of Split-GAL4 Lines to Cell Types**: Search results now include a curated matches section that displays expert-annotated associations between Split-GAL4 lines and cell types
+ - Results are shown in a collapsible, paginated table with confidence level (Confident/Candidate), anatomical region, and source columns
+ - Curated matches appear above computed matches with a bookmark indicator when results are available
+ - See the [Curated Results section of the help page](/help#curated_results) for details on confidence levels and data sources.
+
+ - **Line Name Links**: Line names in search result metadata are now clickable links that navigate to a new search for that line
+
+### UI/UX Improvements
+
+ - **Updated Search Examples**: The example search terms have been refreshed to showcase curated matches functionality
+ - **Help Documentation**: Added a new help section explaining the curated matches feature
+
+---
+
+## VERSION 3.4.0 - 2026-04-17
+
+### Major Features
+
+ - **Aligned Volume Download for Custom Searches**: Custom search results now include a download link for the aligned volume, making it easier to retrieve aligned data for further analysis
+ - The "View in 3D" button is now available for custom uploads when an aligned volume exists
+
+ - **Searched Libraries Display**: The Color Depth Search step now shows which libraries were searched along with result counts, providing better visibility into search coverage
+
+### UI/UX Improvements
+
+ - **External Links Open in New Tabs**: All links to external sources now open in a new tab, preventing users from losing their place on the site
+
+### Bug Fixes & Improvements
+
+ - **Search & Navigation**:
+ - Improved search result filtering and duplicate removal logic
+ - Fixed external EM links to use id instead of library
+ - Fixed the "View" button to be clickable anywhere on the button area
+ - Updated search examples for accuracy
+
+---
+
## VERSION 3.3.1 - 2024-09-22
### Major Features
diff --git a/src/App.css b/src/App.css
index 90b7a7a7..70bb13e3 100644
--- a/src/App.css
+++ b/src/App.css
@@ -74,3 +74,11 @@ body {
list-style: none;
padding: 0;
}
+
+/* hides the anchor offset on any page that needs it */
+.anchorOffset {
+ display: block;
+ position: relative;
+ top: -80px;
+ visibility: hidden;
+}
diff --git a/src/components/CuratedResults.jsx b/src/components/CuratedResults.jsx
new file mode 100644
index 00000000..52cf43e9
--- /dev/null
+++ b/src/components/CuratedResults.jsx
@@ -0,0 +1,83 @@
+import PropTypes from "prop-types";
+import { Table, Typography } from "antd";
+import { Link } from "react-router-dom";
+
+const { Paragraph } = Typography;
+
+const columns = [
+ {
+ title: "Line Name",
+ dataIndex: "name",
+ key: "name",
+ render: (name) => {name},
+ },
+ {
+ title: "Confidence",
+ dataIndex: "confidence",
+ key: "confidence",
+ },
+ {
+ title: "Anatomical Region",
+ dataIndex: "anatomicalRegion",
+ key: "anatomicalRegion",
+ },
+ {
+ title: "Source",
+ dataIndex: "source",
+ key: "source",
+ },
+ {
+ title: "Cell Type / Neuron ID",
+ dataIndex: "matched",
+ key: "matched",
+ // if the match is a cell type, then we add a wildcard to the search
+ // to get all the sub cell types.
+ render: (matched, row) => {matched},
+ },
+];
+
+export default function CuratedResults({ results, loadError }) {
+ // if we didn't find anything, then don't display anything.
+ if (results.length === 0) {
+ return null;
+ }
+
+ let pagination = {
+ position: ["bottomLeft"],
+ pageSizeOptions: ["2", "5", "10", "15", "20"],
+ defaultPageSize: 2,
+ showSizeChanger: true,
+ showQuickJumper: true
+ };
+
+ if (results.length < 3) {
+ pagination = false;
+ }
+
+ if (loadError) {
+ return (
+ <>
+
+ There was a problem retrieving the curated matches.
+
+ Reloading the page may resolve the issue.
+
+ If this problem persists, please contact us at{" "}
+
+ neuronbridge@janelia.hhmi.org
+
+ . Please provide the search term used and any other relevant details.
+
+ >
+ );
+ }
+
+ return (
+
+ );
+}
+
+CuratedResults.propTypes = {
+ results: PropTypes.arrayOf(PropTypes.object).isRequired,
+ loadError: PropTypes.bool.isRequired,
+};
diff --git a/src/components/Help/HelpButton.jsx b/src/components/Help/HelpButton.jsx
index ea748feb..fe87296d 100644
--- a/src/components/Help/HelpButton.jsx
+++ b/src/components/Help/HelpButton.jsx
@@ -6,10 +6,17 @@ import { AppContext } from "../../containers/AppContext";
export default function HelpButton({target, text, onClick}) {
const { appState, setAppState } = useContext(AppContext);
- const handleHelp = () => {
+ const handleHelp = (event) => {
+ // call the onClick callback if it is provided
if (onClick) {
- onClick();
+ onClick(event);
}
+ // Toggle help if the button is clicked again
+ if (appState.helpTarget === target) {
+ setAppState({ ...appState, showHelp: !appState.showHelp });
+ return;
+ }
+ // Show help for the target
setAppState({ ...appState, showHelp: true, helpTarget: target });
}
diff --git a/src/components/Help/HelpContents.jsx b/src/components/Help/HelpContents.jsx
index 8ec9ce4d..8a009b60 100644
--- a/src/components/Help/HelpContents.jsx
+++ b/src/components/Help/HelpContents.jsx
@@ -34,29 +34,24 @@ export default function HelpContents({ scroll }) {
SearchInput: useRef(),
UploadAlignment: useRef(),
UploadSearch: useRef(),
+ CuratedResults: useRef(),
};
// use Effect to scroll to target set in the appState?
useEffect(() => {
if (scroll) {
- if (refLookup[appState.helpTarget]) {
- if (refLookup[appState.helpTarget].current) {
- helpContentRef.current.parentElement.scrollTop =
- refLookup[appState.helpTarget].current.offsetTop - 60;
- refLookup[appState.helpTarget].current.classList.add("highlighted");
- window.setTimeout(() => {
- if (
- refLookup[appState.helpTarget] &&
- refLookup[appState.helpTarget].current
- ) {
- refLookup[appState.helpTarget].current.classList.remove(
- "highlighted"
- );
- }
- }, 3000);
+ const observer = new IntersectionObserver(([entry]) => {
+ if (entry.isIntersecting) {
+ refLookup[appState.helpTarget].current.scrollIntoView({ behavior: "instant" });
+ observer.disconnect();
}
+ });
+ observer.observe(helpContentRef.current);
+ return () => {
+ observer.disconnect();
}
}
+ return () => {};
}, [appState.helpTarget, refLookup, scroll]);
const handleResultsPerLine = (count) => {
@@ -325,6 +320,33 @@ export default function HelpContents({ scroll }) {
+
+ #curated_results
+
+ Curated Results
+
+ Curated results are based on human evaluations of EM cell types labeled in LM images of split-GAL4 lines. In general they should be more accurate than the average NeuronBridge image search hit. The name of the primary person evaluating the cell type is listed.
+
+
+ Curated results come from two sources:
+
+
Annotations generated as part of split-GAL4 publications, and included with releases posted to https://splitgal4.janelia.org.
+
Scoring of PatchPerPixMatch EM search results for a subset of the cell type lines published in Meissner et al., 2025. These scores and additional details may be published in a forthcoming standalone paper or addendum to the above paper.
+
+
+ Results have one of three confidence levels:
+
+
Confident: >95% confidence, based on detailed examination of all potential associations, similar to criteria for publication.
+
Probable: 70-95% confidence, an association that seems correct but has not been as fully validated.
+
Candidate: 30-70% confidence, where more work is needed for validation and there are often multiple candidates.