Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

frontend: export chain csvs #68

Merged
merged 6 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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 gui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@monaco-editor/react": "^4.6.0",
"@mui/icons-material": "^5.15.17",
"@mui/material": "^5.15.17",
"jszip": "^3.10.1",
"monaco-editor": "^0.48.0",
"plotly.js": "^2.33.0",
"react": "^18.2.0",
Expand Down
54 changes: 49 additions & 5 deletions gui/src/app/SamplerOutputView/SamplerOutputView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import TabWidget from "../TabWidget/TabWidget"
import TracePlotsView from "./TracePlotsView"
import SummaryView from "./SummaryView"
import HistsView from "./HistsView"
import JSZip from 'jszip'

type SamplerOutputViewProps = {
width: number
Expand Down Expand Up @@ -142,13 +143,33 @@ const DrawsView: FunctionComponent<DrawsViewProps> = ({ width, height, draws, pa
const csvText = prepareCsvText(draws, paramNames, drawChainIds, drawNumbers);
downloadTextFile(csvText, 'draws.csv');
}, [draws, paramNames, drawChainIds, drawNumbers]);
const handleExportToMultipleCsvs = useCallback(async () => {
const uniqueChainIds = Array.from(new Set(drawChainIds));
const csvTexts = prepareMultipleCsvsText(draws, paramNames, drawChainIds, uniqueChainIds);
const blob = await createZipBlobForMultipleCsvs(csvTexts, uniqueChainIds);
const fileName = 'SP-draws.zip';
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = fileName;
a.click();
URL.revokeObjectURL(url);
}, [draws, paramNames, drawChainIds]);
return (
<div style={{position: 'absolute', width, height, overflow: 'auto'}}>
<SmallIconButton
icon={<Download />}
label="Export to .csv"
onClick={handleExportToCsv}
/>
<div>
<SmallIconButton
icon={<Download />}
label="Export to single .csv"
onClick={handleExportToCsv}
/>
&nbsp;
<SmallIconButton
icon={<Download />}
label="Export to multiple .csv"
onClick={handleExportToMultipleCsvs}
/>
</div>
<table className="draws-table">
<thead>
<tr>
Expand Down Expand Up @@ -197,6 +218,29 @@ const prepareCsvText = (draws: number[][], paramNames: string[], drawChainIds: n
return [['Chain', 'Draw', ...paramNames].join(','), ...lines].join('\n')
}

const prepareMultipleCsvsText = (draws: number[][], paramNames: string[], drawChainIds: number[], uniqueChainIds: number[]) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind adding some comments to this function? I’m having a hard time telling the difference between the drawChainIds and the unique ones (or even what size that they would be expected to be)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comments.

return uniqueChainIds.map(chainId => {
const drawIndicesForChain = drawChainIds.map((id, i) => id === chainId ? i : -1).filter(i => i >= 0);
const lines = drawIndicesForChain.map(i => {
return paramNames.map((_, j) => draws[j][i]).join(',')
})

return [paramNames.join(','), ...lines].join('\n')
})
}

const createZipBlobForMultipleCsvs = async (csvTexts: string[], uniqueChainIds: number[]) => {
const zip = new JSZip();
// put them all in a folder called 'draws'
const folder = zip.folder('draws');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really a separate feature request, but it would be nice if we included samplerOpts.json in this download as well, for reference. Not necessary in V1 on this, since I think that would make it depend on some other PRs

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

created new issue.

if (!folder) throw new Error('Failed to create folder');
csvTexts.forEach((text, i) => {
folder.file(`chain_${uniqueChainIds[i]}.csv`, text);
});
const blob = await zip.generateAsync({type: 'blob'});
return blob;
}

const downloadTextFile = (text: string, filename: string) => {
const blob = new Blob([text], {type: 'text/plain'});
const url = URL.createObjectURL(blob);
Expand Down
1 change: 1 addition & 0 deletions gui/src/app/SamplerOutputView/SummaryView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ const computeEss = (x: number[], chainIds: number[]) => {
draws[chainIndex].push(x[i]);
}
const ess = compute_effective_sample_size(draws);
// const ess = compute_split_effective_sample_size(draws);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is from a merge gone awry or something

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

return ess;
}

Expand Down
32 changes: 32 additions & 0 deletions gui/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3483,6 +3483,11 @@ ignore@^5.2.0, ignore@^5.2.4:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef"
integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==

immediate@~3.0.5:
version "3.0.6"
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==

import-fresh@^3.2.1:
version "3.3.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
Expand Down Expand Up @@ -3932,6 +3937,16 @@ json5@^2.2.3:
object.assign "^4.1.4"
object.values "^1.1.6"

jszip@^3.10.1:
version "3.10.1"
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2"
integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==
dependencies:
lie "~3.3.0"
pako "~1.0.2"
readable-stream "~2.3.6"
setimmediate "^1.0.5"

katex@^0.16.0:
version "0.16.10"
resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.10.tgz#6f81b71ac37ff4ec7556861160f53bc5f058b185"
Expand Down Expand Up @@ -3964,6 +3979,13 @@ levn@^0.4.1:
prelude-ls "^1.2.1"
type-check "~0.4.0"

lie@~3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==
dependencies:
immediate "~3.0.5"

lines-and-columns@^1.1.6:
version "1.2.4"
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
Expand Down Expand Up @@ -5054,6 +5076,11 @@ p-locate@^5.0.0:
dependencies:
p-limit "^3.0.2"

pako@~1.0.2:
version "1.0.11"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==

parent-module@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
Expand Down Expand Up @@ -5897,6 +5924,11 @@ set-function-name@^2.0.1, set-function-name@^2.0.2:
functions-have-names "^1.2.3"
has-property-descriptors "^1.0.2"

setimmediate@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==

[email protected]:
version "0.0.1"
resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170"
Expand Down