-
Notifications
You must be signed in to change notification settings - Fork 2
/
+page.svelte
219 lines (193 loc) · 7.58 KB
/
+page.svelte
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
<script lang="ts">
// Svelte and UI Imports
import '../app.postcss';
import {
AppShell,
Drawer,
Modal,
ProgressBar,
storePopup,
initializeStores,
getModalStore,
type ModalSettings
} from '@skeletonlabs/skeleton';
import { computePosition, autoUpdate, flip, shift, offset, arrow } from '@floating-ui/dom';
import { onMount } from 'svelte';
// Svelte Component Imports
import AdvancedOptions from './AdvancedOptions.svelte';
import Footer from './Footer.svelte';
import Header from './Header.svelte';
import LinksAndDownloads from './LinksAndDownloads.svelte';
import MassLibraryUploader from './MassLibraryUploader.svelte';
import MsDataUploader from './MsDataUploader.svelte';
import FragmentsDataUploader from './FragmentsDataUploader.svelte';
import MuropeptidesDataUploader from './MuropeptidesDataUploader.svelte';
// PGFinder and JS Imports
import PGFinder from '$lib/pgfinder.ts?worker';
import { defaultPyio } from '$lib/constants';
// Import vite-plugin-wasm and Smithereens components
// 2024-05-03 - Throws an error
// TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".wasm" for
// /home/neil/work/git/hub/Mesnage-Org/pgfinder/web/node_modules/smithereens/smithereens_bg.wasm
import init, { Peptidoglycan, pg_to_fragments } from 'smithereens';
onMount(() => {
init().then(() => {
console.log("smithereens wasm loaded!");
})
})
// init().then((instance) => {
// instance.exports.
// })
import fileDownload from 'js-file-download';
import ErrorModal from './ErrorModal.svelte';
// Initialize Stores for Drawers and Modals
initializeStores();
// Get the Error Modal Store
const modalStore = getModalStore();
// Floating UI for Popups
storePopup.set({ computePosition, autoUpdate, flip, shift, offset, arrow });
// Pre-Declare Variables
let pyio: Pyio = { ...defaultPyio };
let loading = true;
let processingPGFinder = false;
let processingSmithereens = false;
let ready = false;
let advancedMode = false;
let pgfinderVersion: string;
let allowedModifications: Array<string>;
let massLibraries: MassLibraryIndex;
let fragmentsLibraries: FragmentsLibraryIndex;
let muropeptidesLibraries: MuropeptidesLibraryIndex;
// Start PGFinder
let pgfinder: Worker | undefined;
onMount(() => {
pgfinder = new PGFinder();
pgfinder.onmessage = ({ data: { type, content } }) => {
if (type === 'Ready') {
pgfinderVersion = content.pgfinderVersion;
allowedModifications = content.allowedModifications;
massLibraries = content.massLibraries;
fragmentsLibraries = content.fragmentsLibraries;
muropeptidesLibraries = content.muropeptidesLibraries;
loading = false;
} else if (type === 'Result') {
fileDownload(content.blob, content.filename);
processingPGFinder = false;
} else if (type === 'Error') {
const modal: ModalSettings = {
type: 'component',
component: {
ref: ErrorModal,
props: {
message: content.message
}
}
};
modalStore.trigger(modal);
processingPGFinder = false;
}
};
});
// Start Smithereens
let smithereens: Worker | undefined;
onMount(() => {
// Get a new PGFinder instance
init().then(() => {
console.log("smithereens wasm loaded!");
})
// 2024-05-01 - How to run the loadlibraries function defined in pgfinder.ts which calls the
// shim.load_libraries() Python function so we load the masses and muropeptides?
// pgfinder.loadlibraries = ({ data: { type, content } }) => {
// }
onMount(() => {
init().then(() =>{
console.log("smithereens wasm loaded!")
})
})
processingSmithereens = false;
})
// Reactively compute if Smithereens is ready
$: SmithereensReady = !loading && !processingSmithereens && pyio.fragmentsLibrary !== undefined && pyio.muropeptidesLibrary !== undefined;
$: console.log(`SmithereensReady : ${SmithereensReady}`);
$: console.log(`pyio.fragmentsLibrary : ${pyio.fragmentsLibrary}`);
$: console.log(`pyio.muropeptidesLibrary : ${pyio.muropeptidesLibrary}`);
$: console.log(`pyio.massLibrary : ${pyio.massLibrary}`);
// Send data to Smithereens for processing
function runSmithereensAnalysis() {
// TODO - Switch this to run smithereens WA using pyio.fragmentsLibrary and pyio.muropeptidesLibrary
console.log("We have made it into runSmithereensAnalysis!")
// SOMETHING GOES HERE TO PASS THE pyio.fragmentsLibrary and pyio.muropeptidesLibrary to Smithereens
// Use pgfinder to load the libraries, need to split functionality so this works without mass library
// pgfinder?.postMessage(pyio)
// 2024-05-01 - Because I can't import "$lib/smithereens" the following won't work
let pg = new Peptidoglycan("gm-AEJA")
console.log(`Monoisotopic Mass : ${pg.monoisotopic_mass()}`);
console.log(`Fragments :\n ${pg_to_fragments(pg)}`);
processingSmithereens = true;
}
// Reactively compute if PGFinder is ready
$: PGFinderReady = !loading && !processingPGFinder && pyio.msData !== undefined && pyio.massLibrary !== undefined;
// Send data to PGFinder for processing
function runPGFinderAnalysis() {
pgfinder?.postMessage(pyio);
processingPGFinder = true;
}
// Reactively adapt the UI when entering advanced mode
let uiWidth: string;
$: uiWidth = advancedMode ? 'md:w-[40rem]' : '';
// It's nice to animate the width when opening and closing advanced mode, but
// it seems like animating the opening leads to some jittery animations, so
// this is just enables the animation on close. If browsers ever put
// transitions in their own threads, then maybe this will look nice...
$: animateWidth = !advancedMode ? 'transition-all' : '';
</script>
<Modal regionBackdrop="bg-surface-backdrop-token overflow-y-hidden" />
<Drawer>
<LinksAndDownloads />
</Drawer>
<AppShell>
<svelte:fragment slot="header">
<Header {pgfinderVersion} />
</svelte:fragment>
<div class="h-full flex flex-cols-2 justify-center items-center">
<!-- Smithereens -->
<div class="card m-2 w-[20rem] {uiWidth} max-w-[90%] {animateWidth}">
<section class="flex flex-col space-y-4 justify-center p-4">
<FragmentsDataUploader bind:value={pyio.fragmentsLibrary} {fragmentsLibraries} />
</section>
<section class="flex flex-col space-y-4 justify-center p-4">
<MuropeptidesDataUploader bind:value={pyio.muropeptidesLibrary} {muropeptidesLibraries} />
<button type="button" class="btn variant-filled" on:click={runSmithereensAnalysis} disabled={!SmithereensReady}>
Build database
</button>
{#if processingSmithereens}
<ProgressBar />
{/if}
</section>
</div>
<!-- PGFinder -->
<div class="card m-2 w-[20rem] {uiWidth} max-w-[90%] {animateWidth}">
<section class="flex flex-col space-y-4 justify-center p-4">
<MsDataUploader bind:value={pyio.msData} />
<MassLibraryUploader bind:value={pyio.massLibrary} {massLibraries} />
<AdvancedOptions
bind:enabledModifications={pyio.enabledModifications}
bind:ppmTolerance={pyio.ppmTolerance}
bind:cleanupWindow={pyio.cleanupWindow}
bind:consolidationPpm={pyio.consolidationPpm}
bind:advancedMode
{allowedModifications}
/>
<button type="button" class="btn variant-filled" on:click={runPGFinderAnalysis} disabled={!PGFinderReady}>
Run Analysis
</button>
{#if processingPGFinder}
<ProgressBar />
{/if}
</section>
</div>
</div>
<svelte:fragment slot="footer">
<Footer />
</svelte:fragment>
</AppShell>