5f2d2b3mri-scanner: in-browser Bloch simulation of pulseq sequencesJeremy Magland 1// Web Worker that runs the Bloch simulation off the main thread. It parses the
2// .seq text, runs simulate(), streams throttled progress messages, and posts
3// the raw signal back. Cancellation is handled by the main thread terminating
4// the worker (no in-loop cancel needed).
5import { parseSeq } from '../seq/parseSeq.ts'
6import { simulate } from './simulate.ts'
7import type { SimProgress } from './simulate.ts'
8import type { Phantom } from '../phantom/phantomTypes.ts'
10export interface RunMessage {
11 type: 'run'
12 seqText: string
13 phantom: Phantom
14}
16export type WorkerOut =
17 | { type: 'progress'; progress: SimProgress; elapsedMs: number }
18 | {
19 type: 'done'
20 re: Float64Array
21 im: Float64Array
22 numReadouts: number
23 samplesPerReadout: Int32Array
24 offsets: Int32Array
25 maxSamplesPerReadout: number
26 elapsedMs: number
27 }
28 | { type: 'error'; message: string }
30const ctx = self as unknown as Worker
32ctx.onmessage = (ev: MessageEvent<RunMessage>) => {
33 const msg = ev.data
34 if (msg.type !== 'run') return
35 const started = Date.now()
36 try {
37 const seq = parseSeq(msg.seqText)
38 let lastPost = 0
39 const result = simulate(seq, msg.phantom, {
40 progressEvery: 128,
41 onProgress: (progress) => {
42 const now = Date.now()
43 if (now - lastPost >= 100 || progress.fraction >= 1) {
44 lastPost = now
45 const out: WorkerOut = { type: 'progress', progress, elapsedMs: now - started }
46 ctx.postMessage(out)
47 }
48 },
49 })
50 const out: WorkerOut = {
51 type: 'done',
52 re: result.re,
53 im: result.im,
54 numReadouts: result.numReadouts,
55 samplesPerReadout: result.samplesPerReadout,
56 offsets: result.offsets,
57 maxSamplesPerReadout: result.maxSamplesPerReadout,
58 elapsedMs: Date.now() - started,
59 }
60 ctx.postMessage(out, [result.re.buffer, result.im.buffer])
61 } catch (err) {
62 const out: WorkerOut = { type: 'error', message: err instanceof Error ? err.message : String(err) }
63 ctx.postMessage(out)
64 }
65}