Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ input UpdateSearchInput {
anatomicalRegion: String
cdsFinished: AWSDateTime
cdsStarted: AWSDateTime
channel: Int
completedBatches: Int
computedMIPs: [String]
dataThreshold: Int
Expand Down
25 changes: 22 additions & 3 deletions src/components/CustomSearch/ColorDepthSearchStep.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import React from "react";
import React, { useContext } from "react";
import PropTypes from "prop-types";
import { formatRelative, formatDistanceStrict } from "date-fns";
import StepTitle from "./StepTitle";
import LibraryFormatter from "../LibraryFormatter";
import { AppContext } from "../../containers/AppContext";

export default function ColorDepthSearchStep({ started, finished, state }) {
export default function ColorDepthSearchStep({ started, finished, state, librariesCountsMap }) {
const { appState } = useContext(AppContext);
let searchEnd = "";
let duration = "";

Expand All @@ -14,11 +17,25 @@ export default function ColorDepthSearchStep({ started, finished, state }) {
}
}

const hasLibraries = librariesCountsMap && Object.keys(librariesCountsMap).length > 0;

return (
<>
<StepTitle state={state} step={4} text="Color Depth Search" />
<p style={{ marginTop: "1em" }}>{searchEnd}</p>
<p style={{ marginTop: "1em" }}>{duration}</p>
{hasLibraries ? (
<>
<p style={{ marginTop: "1em" }}>Libraries searched:</p>
{Object.entries(librariesCountsMap).map(([library, count]) => (
<p key={library} style={{ marginTop: "0.5em", marginLeft: "1em" }}>
<LibraryFormatter type={library} /> ({count})
</p>
))}
</>
) : appState.debug ? (
<p style={{ marginTop: "1em", fontStyle: "italic", color: "#999" }}>Libraries data not available for this search</p>
) : null}
</>
);
}
Expand All @@ -27,9 +44,11 @@ ColorDepthSearchStep.propTypes = {
state: PropTypes.string.isRequired,
finished: PropTypes.string,
started: PropTypes.string,
librariesCountsMap: PropTypes.object,
};

ColorDepthSearchStep.defaultProps = {
finished: null,
started: null
started: null,
librariesCountsMap: null,
};
23 changes: 23 additions & 0 deletions src/components/CustomSearch/ImageAlignmentStep.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ import HelpButton from "../Help/HelpButton";
export default function ImageAlignmentStep({ state, search }) {
const [thumbnailUrl, setThumbnailUrl] = useState(null);
const [movieUrl, setMovieUrl] = useState(null);
const [alignedVolume, setAlignmentFile] = useState(null);


useEffect(() =>{
if (search.alignedVolume) {
const alignedVolumeUrl = `${search.searchDir}/${search.alignedVolume}`;
signedLink(alignedVolumeUrl).then((result) => {
setAlignmentFile(result);
});
} else {
setAlignmentFile(null);
}
}, [search.searchDir, search.alignedVolume]);

useEffect(() => {
if (search.alignmentMovie) {
Expand Down Expand Up @@ -80,6 +93,16 @@ export default function ImageAlignmentStep({ state, search }) {
) : (
""
)}

{alignedVolume ? (
<div>
<a href={alignedVolume} download>
Download Alignment File
</a>
</div>
) : (
""
)}
</>
);
} else if (search.alignmentErrorMessage || search.errorMessage) {
Expand Down
10 changes: 10 additions & 0 deletions src/components/CustomSearch/SearchSteps.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ export default function SearchSteps({ search }) {
currentStep = 5;
}

let librariesCountsMap = null;
if (search.librariesCountsMap) {
try {
librariesCountsMap = JSON.parse(search.librariesCountsMap);
} catch (error) {
console.error("Failed to parse librariesCountsMap:", error);
}
}

return (
<div className="searchSteps">
<Row>
Expand Down Expand Up @@ -67,6 +76,7 @@ export default function SearchSteps({ search }) {
started={search.cdsStarted}
finished={search.cdsFinished}
state={stepState(3, currentStep, errorMessage)}
librariesCountsMap={librariesCountsMap}
/>
</Col>
<Col xs={4}>
Expand Down
4 changes: 2 additions & 2 deletions src/components/MaskSelection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export default function MaskSelection({ match }) {
});
}

const maskDetails = { searchMask: maskName, id: searchMeta.id };
const maskDetails = { searchMask: maskName, channel, id: searchMeta.id };
const searchParams = { ...searchFormData, ...maskDetails };
API.graphql(
graphqlOperation(mutations.updateSearch, { input: searchParams }),
Expand Down Expand Up @@ -216,7 +216,7 @@ export default function MaskSelection({ match }) {
wrapperCol={{ span: 16 }}
name="basic"
initialValues={{
selectedLibraries: searchMeta.searchType || getDefaultLibrary(appState?.dataConfig?.stores, searchMeta.anatomicalRegion) || undefined,
selectedLibraries: [searchMeta.searchType || getDefaultLibrary(appState?.dataConfig?.stores, searchMeta.anatomicalRegion)].filter(Boolean),
dataThreshold: searchMeta.dataThreshold || 100,
maskThreshold: searchMeta.maskThreshold || 100,
xyShift: searchMeta.xyShift || 0,
Expand Down
36 changes: 29 additions & 7 deletions src/components/MatchModal/Download3D.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useState, useEffect } from "react";
import PropTypes from "prop-types";
import { useParams } from "react-router-dom";
import { Row, Col, Typography } from "antd";
Expand All @@ -7,6 +7,7 @@ import FileExclamationOutlined from "@ant-design/icons/FileExclamationOutlined";
import { faExternalLink } from "@fortawesome/pro-regular-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import ViewIn3DButton from "./ViewIn3DButton";
import { signedLink } from "../../libs/awsLib";

const { Title, Text, Paragraph } = Typography;

Expand Down Expand Up @@ -39,6 +40,18 @@ function getH5JLink(construct) {
export default function Download3D(props) {
const { selectedMatch, mask, isLM } = props;
const { algorithm } = useParams();
const [alignedVolumeUrl, setAlignedVolumeUrl] = useState(null);

useEffect(() => {
if (mask.alignedVolume && mask.searchDir) {
const volumePath = `${mask.searchDir}/${mask.alignedVolume}`;
signedLink(volumePath).then((result) => {
setAlignedVolumeUrl(result);
});
} else {
setAlignedVolumeUrl(null);
}
}, [mask.searchDir, mask.alignedVolume]);

// If the match has either an AlignedBodySWC or a VisuallyLosslessStack
// file, then we need to make it available for download, the same needs
Expand All @@ -53,11 +66,20 @@ export default function Download3D(props) {
const downloadLinks = (
<>
{!mask.precomputed ? (
<Text type="danger">
<FileExclamationOutlined style={fileIconStyles} /> We don&apos;t have
a 3D representation of your uploaded file. You will need to generate
one from your original imagery.
</Text>
alignedVolumeUrl ? (
<Paragraph>
<FileImageOutlined style={fileIconStyles} />{" "}
<a href={alignedVolumeUrl} download>
Download Aligned Volume (H5J)
</a>
</Paragraph>
) : (
<Text type="danger">
<FileExclamationOutlined style={fileIconStyles} /> We don&apos;t have
a 3D representation of your uploaded file. You will need to generate
one from your original imagery.
</Text>
)
) : (
""
)}
Expand All @@ -75,7 +97,7 @@ export default function Download3D(props) {

return (
<>
{algorithm !== "pppm" && !mask.identityId ? (
{algorithm !== "pppm" && (!mask.identityId || mask.alignedVolume) ? (
<p>
<ViewIn3DButton isLM={isLM} mask={mask} match={selectedMatch} /> -
View the match in our online volume viewer{" "}
Expand Down
2 changes: 1 addition & 1 deletion src/components/MatchModal/Summary.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export default function Summary(props) {
>
{appState.compactMeta ? "Show" : "Hide"} Match Info
</Button>
{algorithm !== "pppm" && !mask.identityId ? (
{algorithm !== "pppm" && (!mask.identityId || mask.alignedVolume) ? (
<ViewIn3DButton
style={{ float: "right", marginRight: "0.5em" }}
isLM={isLM}
Expand Down
45 changes: 33 additions & 12 deletions src/components/MatchModal/ViewIn3DButton.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Button } from "antd";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCube } from "@fortawesome/pro-regular-svg-icons";
import config from "../../config";
import { signedPublicLink } from "../../libs/awsLib";
import { signedPublicLink, signedLink } from "../../libs/awsLib";

function getH5JLink(construct) {
const imageStack = construct?.files?.VisuallyLosslessStack;
Expand All @@ -18,30 +18,51 @@ function getSWCLink(construct) {

export default function ViewIn3DButton({ isLM, match, mask, style }) {
const [signedSwc, setSignedSwc] = React.useState(undefined);
const [signedH5j, setSignedH5j] = React.useState(undefined);
const [isDisabled, setDisabled] = React.useState(true);
const ref = window.location;
const h5j = isLM ? getH5JLink(match.image) : getH5JLink(mask);
const channel = isLM
? parseInt(match.image.channel, 10)
: parseInt(mask.channel, 10);
const isCustomUpload = Boolean(mask.identityId && mask.alignedVolume);
const h5j = isCustomUpload
? null
: isLM ? getH5JLink(match.image) : getH5JLink(mask);
const channel = isCustomUpload
? parseInt(mask.channel, 10) || 0
: isLM
? parseInt(match.image.channel, 10)
: parseInt(mask.channel, 10);
const { mirrored } = match;

React.useEffect(() => {
const swc = isLM ? getSWCLink(mask) : getSWCLink(match.image);
signedPublicLink(swc).then((signed) => {
setSignedSwc(signed);
});
const swc = isCustomUpload
? getSWCLink(match.image)
: isLM ? getSWCLink(mask) : getSWCLink(match.image);

if (swc && h5j) {
if (swc) {
signedPublicLink(swc).then((signed) => {
setSignedSwc(signed);
});
}

if (isCustomUpload) {
const volumePath = `${mask.searchDir}/${mask.alignedVolume}`;
signedLink(volumePath).then((signed) => {
setSignedH5j(signed);
if (swc) {
setDisabled(false);
}
});
} else if (swc && h5j) {
setDisabled(false);
}
}, [isLM, mask, match, h5j]);
}, [isLM, isCustomUpload, mask, match, h5j]);

const h5jUrl = isCustomUpload ? signedH5j : h5j;

// must encode the signedSWC, so that it makes it to the volume viewer in the
// correct state for loading the swc
const volViewerLink = `${config.volumeViewer}?ref=${encodeURIComponent(
ref
)}&h5j=${encodeURIComponent(h5j)}&swc=${encodeURIComponent(
)}&h5j=${encodeURIComponent(h5jUrl)}&swc=${encodeURIComponent(
signedSwc
)}&ch=${channel}&mx=${mirrored}`;

Expand Down
2 changes: 1 addition & 1 deletion src/components/Results.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export default function Results({ match }) {
fr.readAsText(results.Body);
})
.catch(error => {
if (error.response.status === 404) {
if (error.response && error.response.status === 404) {
setSearchResults({ results: [] });
} else {
message.error({
Expand Down
1 change: 1 addition & 0 deletions src/graphql/mutations.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const updateSearch = /* GraphQL */ `
identityId
owner
step
channel
upload
uploadThumbnail
searchDir
Expand Down
12 changes: 10 additions & 2 deletions src/graphql/queries.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const getSearch = /* GraphQL */ `
alignmentErrorMessage
alignmentScore
alignmentMovie
alignedVolume
step
anatomicalRegion
algorithm
Expand All @@ -27,6 +28,7 @@ export const getSearch = /* GraphQL */ `
voxelX
voxelY
voxelZ
channel
referenceChannel
alignStarted
alignFinished
Expand Down Expand Up @@ -56,7 +58,9 @@ export const listSearches = /* GraphQL */ `
alignmentErrorMessage
alignmentScore
alignmentMovie
anatomicalRegion
alignedVolume
anatomicalRegion
channel
cdsStarted
cdsFinished
step
Expand All @@ -70,6 +74,7 @@ export const listSearches = /* GraphQL */ `
alignFinished
alignStarted
anatomicalRegion
librariesCountsMap
}
nextToken
}
Expand All @@ -95,7 +100,9 @@ export const listItemsByOwner = `
alignmentErrorMessage
alignmentScore
alignmentMovie
anatomicalRegion
alignedVolume
anatomicalRegion
channel
cdsStarted
cdsFinished
step
Expand All @@ -109,6 +116,7 @@ export const listItemsByOwner = `
alignFinished
alignStarted
anatomicalRegion
librariesCountsMap

}
nextToken
Expand Down
4 changes: 4 additions & 0 deletions src/graphql/subscriptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ export const onCreateSearch = /* GraphQL */ `
anatomicalRegion
alignmentScore
alignmentMovie
alignedVolume
alignStarted
alignFinished
librariesCountsMap
}
}
`;
Expand Down Expand Up @@ -60,8 +62,10 @@ export const onUpdateSearch = /* GraphQL */ `
anatomicalRegion
alignmentScore
alignmentMovie
alignedVolume
alignFinished
alignStarted
librariesCountsMap
}
}
`;
Expand Down
Loading