Compare commits
7 Commits
05f2d2d7ca
...
cd853679a0
| Author | SHA1 | Date |
|---|---|---|
|
|
cd853679a0 | |
|
|
0c40c5de62 | |
|
|
b861ff3441 | |
|
|
eecfbcdf8a | |
|
|
87bc2fe505 | |
|
|
fdac4bfcda | |
|
|
43f853d61a |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
|||
:root{--bg-0: #07090d;--bg-1: #0d1117;--bg-2: #131a23;--bg-3: #1a232f;--line: #1f2a38;--line-2: #2a3848;--ink: #e6edf3;--ink-2: #b8c2cc;--ink-3: #7c8694;--ink-4: #4a5462;--accent: oklch(.78 .14 70);--accent-2: oklch(.78 .12 195);--accent-3: oklch(.72 .18 330);--accent-4: oklch(.78 .14 145);--warn: oklch(.7 .18 35);--ok: oklch(.78 .14 145);--bad: oklch(.65 .22 25);--grid: rgba(255, 255, 255, .04);--shadow: 0 20px 60px -20px rgba(0, 0, 0, .6), 0 4px 12px -4px rgba(0, 0, 0, .4);--radius: 12px;--radius-sm: 8px;--mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;--sans: "Inter", system-ui, -apple-system, sans-serif}[data-theme=light]{--bg-0: #f4f5f7;--bg-1: #fbfbfc;--bg-2: #ffffff;--bg-3: #f0f2f5;--line: #e3e7ec;--line-2: #d1d7de;--ink: #11161d;--ink-2: #38424f;--ink-3: #6b7684;--ink-4: #9ba4b0;--grid: rgba(0, 0, 0, .05);--shadow: 0 12px 40px -16px rgba(15, 30, 55, .18), 0 2px 8px -2px rgba(15, 30, 55, .08)}*{box-sizing:border-box}html,body{margin:0;padding:0}body{font-family:var(--sans);background:var(--bg-0);color:var(--ink);font-size:14px;line-height:1.45;overflow:hidden;height:100vh;-webkit-font-smoothing:antialiased;letter-spacing:-.005em}button{font-family:inherit;color:inherit;cursor:pointer}input,select{font-family:inherit;color:inherit}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:4px}::-webkit-scrollbar-thumb:hover{background:var(--ink-4)}@keyframes pulse{50%{opacity:.5}}@keyframes dash{to{stroke-dashoffset:-200}}@keyframes float-up{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes diamond-spin{0%{transform:rotateY(0) rotateX(8deg)}to{transform:rotateY(360deg) rotateX(8deg)}}@keyframes spin{to{transform:rotate(360deg)}}body.reduce-motion *,body.reduce-motion *:before,body.reduce-motion *:after{animation:none!important;transition:none!important}body.density-comfy{font-size:15px}body.density-default{font-size:14px}body.density-compact{font-size:13px}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,2 @@
|
|||
var U=Symbol.for("preact-signals");function l(){if(e>1)e--;else{var t,i=!1;for(function(){var s=a;for(a=void 0;s!==void 0;)s.S.v===s.v&&(s.S.i=s.i),s=s.o}();u!==void 0;){var o=u;for(u=void 0,d++;o!==void 0;){var n=o.u;if(o.u=void 0,o.f&=-3,!(8&o.f)&&x(o))try{o.c()}catch(s){i||(t=s,i=!0)}o=n}}if(d=0,e--,i)throw t}}var r=void 0;function S(t){var i=r;r=void 0;try{return t()}finally{r=i}}var u=void 0,e=0,d=0,y=0,a=void 0,c=0;function w(t){if(r!==void 0){var i=t.n;if(i===void 0||i.t!==r)return i={i:0,S:t,p:r.s,n:void 0,t:r,e:void 0,x:void 0,r:i},r.s!==void 0&&(r.s.n=i),r.s=i,t.n=i,32&r.f&&t.S(i),i;if(i.i===-1)return i.i=0,i.n!==void 0&&(i.n.p=i.p,i.p!==void 0&&(i.p.n=i.n),i.p=r.s,i.n=void 0,r.s.n=i,r.s=i),i}}function f(t,i){this.v=t,this.i=0,this.n=void 0,this.t=void 0,this.l=0,this.W=i?.watched,this.Z=i?.unwatched,this.name=i?.name}f.prototype.brand=U;f.prototype.h=function(){return!0};f.prototype.S=function(t){var i=this,o=this.t;o!==t&&t.e===void 0&&(t.x=o,this.t=t,o!==void 0?o.e=t:S(function(){var n;(n=i.W)==null||n.call(i)}))};f.prototype.U=function(t){var i=this;if(this.t!==void 0){var o=t.e,n=t.x;o!==void 0&&(o.x=n,t.e=void 0),n!==void 0&&(n.e=o,t.x=void 0),t===this.t&&(this.t=n,n===void 0&&S(function(){var s;(s=i.Z)==null||s.call(i)}))}};f.prototype.subscribe=function(t){var i=this;return N(function(){var o=i.value,n=r;r=void 0;try{t(o)}finally{r=n}},{name:"sub"})};f.prototype.valueOf=function(){return this.value};f.prototype.toString=function(){return this.value+""};f.prototype.toJSON=function(){return this.value};f.prototype.peek=function(){var t=r;r=void 0;try{return this.value}finally{r=t}};Object.defineProperty(f.prototype,"value",{get:function(){var t=w(this);return t!==void 0&&(t.i=this.i),this.v},set:function(t){if(t!==this.v){if(d>100)throw new Error("Cycle detected");(function(o){e!==0&&d===0&&o.l!==y&&(o.l=y,a={S:o,v:o.v,i:o.i,o:a})})(this),this.v=t,this.i++,c++,e++;try{for(var i=this.t;i!==void 0;i=i.x)i.t.N()}finally{l()}}}});function O(t,i){return new f(t,i)}function x(t){for(var i=t.s;i!==void 0;i=i.n)if(i.S.i!==i.i||!i.S.h()||i.S.i!==i.i)return!0;return!1}function m(t){for(var i=t.s;i!==void 0;i=i.n){var o=i.S.n;if(o!==void 0&&(i.r=o),i.S.n=i,i.i=-1,i.n===void 0){t.s=i;break}}}function b(t){for(var i=t.s,o=void 0;i!==void 0;){var n=i.p;i.i===-1?(i.S.U(i),n!==void 0&&(n.n=i.n),i.n!==void 0&&(i.n.p=n)):o=i,i.S.n=i.r,i.r!==void 0&&(i.r=void 0),i=n}t.s=o}function h(t,i){f.call(this,void 0),this.x=t,this.s=void 0,this.g=c-1,this.f=4,this.W=i?.watched,this.Z=i?.unwatched,this.name=i?.name}h.prototype=new f;h.prototype.h=function(){if(this.f&=-3,1&this.f)return!1;if((36&this.f)==32||(this.f&=-5,this.g===c))return!0;if(this.g=c,this.f|=1,this.i>0&&!x(this))return this.f&=-2,!0;var t=r;try{m(this),r=this;var i=this.x();(16&this.f||this.v!==i||this.i===0)&&(this.v=i,this.f&=-17,this.i++)}catch(o){this.v=o,this.f|=16,this.i++}return r=t,b(this),this.f&=-2,!0};h.prototype.S=function(t){if(this.t===void 0){this.f|=36;for(var i=this.s;i!==void 0;i=i.n)i.S.S(i)}f.prototype.S.call(this,t)};h.prototype.U=function(t){if(this.t!==void 0&&(f.prototype.U.call(this,t),this.t===void 0)){this.f&=-33;for(var i=this.s;i!==void 0;i=i.n)i.S.U(i)}};h.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var t=this.t;t!==void 0;t=t.x)t.t.N()}};Object.defineProperty(h.prototype,"value",{get:function(){if(1&this.f)throw new Error("Cycle detected");var t=w(this);if(this.h(),t!==void 0&&(t.i=this.i),16&this.f)throw this.v;return this.v}});function j(t,i){return new h(t,i)}function g(t){var i=t.m;if(t.m=void 0,typeof i=="function"){e++;var o=r;r=void 0;try{i()}catch(n){throw t.f&=-2,t.f|=8,p(t),n}finally{r=o,l()}}}function p(t){for(var i=t.s;i!==void 0;i=i.n)i.S.U(i);t.x=void 0,t.s=void 0,g(t)}function E(t){if(r!==this)throw new Error("Out-of-order effect");b(this),r=t,this.f&=-2,8&this.f&&p(this),l()}function v(t,i){this.x=t,this.m=void 0,this.s=void 0,this.u=void 0,this.f=32,this.name=i?.name}v.prototype.c=function(){var t=this.S();try{if(8&this.f||this.x===void 0)return;var i=this.x();typeof i=="function"&&(this.m=i)}finally{t()}};v.prototype.S=function(){if(1&this.f)throw new Error("Cycle detected");this.f|=1,this.f&=-9,g(this),m(this),e++;var t=r;return r=this,E.bind(this,t)};v.prototype.N=function(){2&this.f||(this.f|=2,this.u=u,u=this)};v.prototype.d=function(){this.f|=8,1&this.f||p(this)};v.prototype.dispose=function(){this.d()};function N(t,i){var o=new v(t,i);try{o.c()}catch(s){throw o.d(),s}var n=o.d.bind(o);return n[Symbol.dispose]=n,n}export{j as g,N as j,O as y};
|
||||
//# sourceMappingURL=signals-SG45zFCj.js.map
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,2 @@
|
|||
const d=self;let o,_,x,g,W;async function B(r){const e=new URL(r,d.location.origin).href,s=await import(new URL("nvsim-pkg/nvsim.js",e).href);await s.default(),o=s.WasmPipeline,_=s.referenceSceneJson,x=s.expectedReferenceWitnessHex,g=s.hexWitness,W=s.referenceWitness}let a=null,p="",b="",F=BigInt(3405691582),m=!1,l=null,i=0,w=0;function f(){b||(b=_()),p||(p=JSON.stringify({digitiser:{f_s_hz:1e4,f_mod_hz:1e3},sensor:{gamma_fwhm_hz:1e6,t1_s:.005,t2_s:1e-6,t2_star_s:2e-7,contrast:.03,n_spins:1e12,shot_noise_disabled:!1},dt_s:null})),a?.free?.(),a=new o(b,p,Number(F&0xFFFFFFFFn))}function t(r,e=[]){d.postMessage(r,e)}function S(){if(l!==null)return;w=performance.now(),i=0;const r=()=>{if(!m||!a)return;const e=32,n=a.run(e);i+=e;const s=(performance.now()-w)/1e3,c=s>0?i/s:0;t({type:"frames",batch:n.buffer,count:e,fps:c,framesEmitted:i},[n.buffer]),l=d.setTimeout(r,16)};l=d.setTimeout(r,0)}function h(){l!==null&&(d.clearTimeout(l),l=null)}d.addEventListener("message",async r=>{const e=r.data;try{switch(e.type){case"boot":{const n=e.base??"/";await B(n),f(),t({type:"booted",id:e.id,buildVersion:o.buildVersion(),frameMagic:o.frameMagic(),frameBytes:o.frameBytes(),expectedWitnessHex:x()});break}case"setScene":{b=e.json,f(),t({type:"ack",id:e.id});break}case"setConfig":{p=e.json,f(),t({type:"ack",id:e.id});break}case"setSeed":{F=BigInt(e.seed),f(),t({type:"ack",id:e.id});break}case"reset":{h(),m=!1,f(),i=0,t({type:"ack",id:e.id}),t({type:"state",running:!1,framesEmitted:i});break}case"run":{a||f(),m=!0,S(),t({type:"ack",id:e.id}),t({type:"state",running:!0,framesEmitted:i});break}case"pause":{m=!1,h(),t({type:"ack",id:e.id}),t({type:"state",running:!1,framesEmitted:i});break}case"step":{a||f();const n=a.run(1);i+=1,t({type:"frames",batch:n.buffer,count:1,fps:0,framesEmitted:i},[n.buffer]),t({type:"ack",id:e.id});break}case"witnessGenerate":{a||f();const n=e.samples??256,s=a.runWithWitness(n),c=g(s.witness);t({type:"witness",id:e.id,witness:s.witness.buffer,hex:c,frameCount:s.frameCount},[s.witness.buffer]);break}case"witnessVerify":{const n=e.expected,s=new Uint8Array(n),c=W();let y=c.length===s.length;if(y){for(let u=0;u<s.length;u++)if(c[u]!==s[u]){y=!1;break}}const k=c.slice().buffer;t({type:"verify",id:e.id,ok:y,actual:k,actualHex:g(c)},[k]);break}case"buildId":{t({type:"buildId",id:e.id,buildId:`nvsim@${o.buildVersion()}`});break}default:t({type:"err",id:e.id,msg:`unknown op ${e.type}`})}}catch(n){t({type:"err",id:e.id,msg:n.message??String(n)})}});t({type:"ready"});
|
||||
//# sourceMappingURL=worker-BW0kLvYS.js.map
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,2 @@
|
|||
const u=self;let l,x,_,k,F,T;async function S(o){const e=new URL(o,u.location.origin).href,t=await import(new URL("nvsim-pkg/nvsim.js",e).href);await t.default(),l=t.WasmPipeline,x=t.referenceSceneJson,_=t.expectedReferenceWitnessHex,k=t.hexWitness,F=t.referenceWitness,T=t.runTransient}let c=null,b="",y="",W=BigInt(3405691582),g=!1,d=null,a=0,w=0;function f(){y||(y=x()),b||(b=JSON.stringify({digitiser:{f_s_hz:1e4,f_mod_hz:1e3},sensor:{gamma_fwhm_hz:1e6,t1_s:.005,t2_s:1e-6,t2_star_s:2e-7,contrast:.03,n_spins:1e12,shot_noise_disabled:!1},dt_s:null})),c?.free?.(),c=new l(y,b,Number(W&0xFFFFFFFFn))}function s(o,e=[]){u.postMessage(o,e)}function H(){if(d!==null)return;w=performance.now(),a=0;const o=()=>{if(!g||!c)return;const e=32,n=c.run(e);a+=e;const t=(performance.now()-w)/1e3,i=t>0?a/t:0;s({type:"frames",batch:n.buffer,count:e,fps:i,framesEmitted:a},[n.buffer]),d=u.setTimeout(o,16)};d=u.setTimeout(o,0)}function h(){d!==null&&(u.clearTimeout(d),d=null)}u.addEventListener("message",async o=>{const e=o.data;try{switch(e.type){case"boot":{const n=e.base??"/";await S(n),f(),s({type:"booted",id:e.id,buildVersion:l.buildVersion(),frameMagic:l.frameMagic(),frameBytes:l.frameBytes(),expectedWitnessHex:_()});break}case"setScene":{y=e.json,f(),s({type:"ack",id:e.id});break}case"setConfig":{b=e.json,f(),s({type:"ack",id:e.id});break}case"setSeed":{W=BigInt(e.seed),f(),s({type:"ack",id:e.id});break}case"reset":{h(),g=!1,f(),a=0,s({type:"ack",id:e.id}),s({type:"state",running:!1,framesEmitted:a});break}case"run":{c||f(),g=!0,H(),s({type:"ack",id:e.id}),s({type:"state",running:!0,framesEmitted:a});break}case"pause":{g=!1,h(),s({type:"ack",id:e.id}),s({type:"state",running:!1,framesEmitted:a});break}case"step":{c||f();const n=c.run(1);a+=1,s({type:"frames",batch:n.buffer,count:1,fps:0,framesEmitted:a},[n.buffer]),s({type:"ack",id:e.id});break}case"witnessGenerate":{c||f();const n=e.samples??256,t=c.runWithWitness(n),i=k(t.witness);s({type:"witness",id:e.id,witness:t.witness.buffer,hex:i,frameCount:t.frameCount},[t.witness.buffer]);break}case"witnessVerify":{const n=e.expected,t=new Uint8Array(n),i=F();let p=i.length===t.length;if(p){for(let m=0;m<t.length;m++)if(i[m]!==t[m]){p=!1;break}}const r=i.slice().buffer;s({type:"verify",id:e.id,ok:p,actual:r,actualHex:k(i)},[r]);break}case"runTransient":{const n=e.scene,t=e.config,i=e.seed??0,p=e.samples??64,r=T(n,t,i,p);s({type:"transient",id:e.id,bRecoveredT:Array.from(r.bRecoveredT),bMagT:r.bMagT,noiseFloorPtSqrtHz:r.noiseFloorPtSqrtHz,sigmaPt:Array.from(r.sigmaPt),nFrames:r.nFrames,witnessHex:r.witnessHex});break}case"buildId":{s({type:"buildId",id:e.id,buildId:`nvsim@${l.buildVersion()}`});break}default:s({type:"err",id:e.id,msg:`unknown op ${e.type}`})}}catch(n){s({type:"err",id:e.id,msg:n.message??String(n)})}});s({type:"ready"});
|
||||
//# sourceMappingURL=worker-C19MRcXs.js.map
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,2 @@
|
|||
const d=self;let o,_,x,g,W;async function S(){const r=`${d.location.origin}/`,t=await import(new URL("nvsim-pkg/nvsim.js",r).href);await t.default(),o=t.WasmPipeline,_=t.referenceSceneJson,x=t.expectedReferenceWitnessHex,g=t.hexWitness,W=t.referenceWitness}let a=null,p="",m="",F=BigInt(3405691582),b=!1,l=null,i=0,w=0;function f(){m||(m=_()),p||(p=JSON.stringify({digitiser:{f_s_hz:1e4,f_mod_hz:1e3},sensor:{gamma_fwhm_hz:1e6,t1_s:.005,t2_s:1e-6,t2_star_s:2e-7,contrast:.03,n_spins:1e12,shot_noise_disabled:!1},dt_s:null})),a?.free?.(),a=new o(m,p,Number(F&0xFFFFFFFFn))}function s(r,e=[]){d.postMessage(r,e)}function B(){if(l!==null)return;w=performance.now(),i=0;const r=()=>{if(!b||!a)return;const e=32,t=a.run(e);i+=e;const n=(performance.now()-w)/1e3,c=n>0?i/n:0;s({type:"frames",batch:t.buffer,count:e,fps:c,framesEmitted:i},[t.buffer]),l=d.setTimeout(r,16)};l=d.setTimeout(r,0)}function h(){l!==null&&(d.clearTimeout(l),l=null)}d.addEventListener("message",async r=>{const e=r.data;try{switch(e.type){case"boot":{await S(),f(),s({type:"booted",id:e.id,buildVersion:o.buildVersion(),frameMagic:o.frameMagic(),frameBytes:o.frameBytes(),expectedWitnessHex:x()});break}case"setScene":{m=e.json,f(),s({type:"ack",id:e.id});break}case"setConfig":{p=e.json,f(),s({type:"ack",id:e.id});break}case"setSeed":{F=BigInt(e.seed),f(),s({type:"ack",id:e.id});break}case"reset":{h(),b=!1,f(),i=0,s({type:"ack",id:e.id}),s({type:"state",running:!1,framesEmitted:i});break}case"run":{a||f(),b=!0,B(),s({type:"ack",id:e.id}),s({type:"state",running:!0,framesEmitted:i});break}case"pause":{b=!1,h(),s({type:"ack",id:e.id}),s({type:"state",running:!1,framesEmitted:i});break}case"step":{a||f();const t=a.run(1);i+=1,s({type:"frames",batch:t.buffer,count:1,fps:0,framesEmitted:i},[t.buffer]),s({type:"ack",id:e.id});break}case"witnessGenerate":{a||f();const t=e.samples??256,n=a.runWithWitness(t),c=g(n.witness);s({type:"witness",id:e.id,witness:n.witness.buffer,hex:c,frameCount:n.frameCount},[n.witness.buffer]);break}case"witnessVerify":{const t=e.expected,n=new Uint8Array(t),c=W();let y=c.length===n.length;if(y){for(let u=0;u<n.length;u++)if(c[u]!==n[u]){y=!1;break}}const k=c.slice().buffer;s({type:"verify",id:e.id,ok:y,actual:k,actualHex:g(c)},[k]);break}case"buildId":{s({type:"buildId",id:e.id,buildId:`nvsim@${o.buildVersion()}`});break}default:s({type:"err",id:e.id,msg:`unknown op ${e.type}`})}}catch(t){s({type:"err",id:e.id,msg:t.message??String(t)})}});s({type:"ready"});
|
||||
//# sourceMappingURL=worker-DBavH9su.js.map
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 192" width="192" height="192">
|
||||
<rect width="192" height="192" rx="36" fill="#e6a86b"/>
|
||||
<text x="96" y="124" text-anchor="middle" font-family="ui-monospace,SFMono-Regular,Menlo,monospace" font-weight="700" font-size="80" fill="#1a0f00">NV</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 313 B |
|
|
@ -0,0 +1,10 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" x2="1" y1="0" y2="1">
|
||||
<stop offset="0" stop-color="#e6a86b"/>
|
||||
<stop offset="1" stop-color="#a4633a"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="512" height="512" rx="96" fill="url(#g)"/>
|
||||
<text x="256" y="332" text-anchor="middle" font-family="ui-monospace,SFMono-Regular,Menlo,monospace" font-weight="700" font-size="220" fill="#1a0f00">NV</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 504 B |
|
|
@ -0,0 +1,21 @@
|
|||
<!doctype html>
|
||||
<html lang="en" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||||
<title>RuView · nvsim — NV-Diamond Magnetometer Simulator</title>
|
||||
<meta name="description" content="Deterministic forward simulator for NV-diamond magnetometry. WASM-backed CW-ODMR pipeline with witness-grade SHA-256 proofs." />
|
||||
<meta name="theme-color" content="#0d1117" />
|
||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><rect width='32' height='32' rx='6' fill='%23e6a86b'/><text x='16' y='22' text-anchor='middle' font-family='monospace' font-weight='700' font-size='14' fill='%231a0f00'>NV</text></svg>" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
||||
<script type="module" crossorigin src="/RuView/nvsim/assets/index-CjC_xGBQ.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/RuView/nvsim/assets/lit-BS7WqYd5.js">
|
||||
<link rel="modulepreload" crossorigin href="/RuView/nvsim/assets/signals-SG45zFCj.js">
|
||||
<link rel="stylesheet" crossorigin href="/RuView/nvsim/assets/index-CyUCBwRA.css">
|
||||
<link rel="manifest" href="/RuView/nvsim/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/RuView/nvsim/registerSW.js"></script></head>
|
||||
<body>
|
||||
<nv-app></nv-app>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"name":"nvsim — NV-Diamond Magnetometer Simulator","short_name":"nvsim","description":"Deterministic forward simulator for NV-diamond magnetometry. WASM-backed CW-ODMR pipeline with witness-grade SHA-256 proofs.","start_url":"/RuView/nvsim/","display":"standalone","background_color":"#0d1117","theme_color":"#0d1117","lang":"en","scope":"/RuView/nvsim/","icons":[{"src":"icon-192.svg","sizes":"192x192","type":"image/svg+xml","purpose":"any maskable"},{"src":"icon-512.svg","sizes":"512x512","type":"image/svg+xml","purpose":"any maskable"}]}
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
# nvsim
|
||||
|
||||
**Deterministic Rust simulator for NV-diamond ensemble magnetometers.**
|
||||
Synthesise the magnetic-field trace a real sensor *would have produced* —
|
||||
without the hardware, the lab, or the $8 K vendor receipt.
|
||||
|
||||
---
|
||||
|
||||
## What this is, in one paragraph
|
||||
|
||||
NV-diamond magnetometers are exotic but real: they detect magnetic fields by
|
||||
shining green laser at a diamond and watching how its red fluorescence shifts
|
||||
under microwave excitation. They are sensitive enough to feel a person's
|
||||
heartbeat from across a room — when they work. The catch: a working ensemble
|
||||
sensor costs ~$8 K and lives in a lab. **`nvsim` runs the same forward
|
||||
pipeline in software**, end-to-end, deterministically, so you can ask "what
|
||||
would my magnetometer have seen if a steel rebar walked past it" without
|
||||
wiring up any of it.
|
||||
|
||||
It is **not** a hardware-control stack, microscope simulator, full
|
||||
Hamiltonian solver, or claim of fT-level sensitivity. This crate does not
|
||||
control lasers, microwave sources, ADC hardware, or real NV sensors. It is
|
||||
a deterministic Rust simulator with **explicit physics approximations and
|
||||
no hidden mocks** — every formula is cited; every conjectural default is
|
||||
flagged in code; every random number comes from a seeded ChaCha20 PRNG.
|
||||
|
||||
## Why you might use it
|
||||
|
||||
| If you are a… | …`nvsim` lets you… |
|
||||
|---|---|
|
||||
| **Sensor researcher** evaluating a new pipeline | Replay a synthetic trace through your own DSP and check it against a published-physics ground truth before buying hardware |
|
||||
| **DSP / ML engineer** building anomaly detectors | Generate magnetic-anomaly traces with a known answer key — useful for regression replay, deterministic CI, and "did my detector regress?" gates |
|
||||
| **Educator** teaching magnetometry / NV physics | Run real Biot-Savart, Lorentzian ODMR, and 4-axis projection in Rust without standing up a Python+QuTiP environment |
|
||||
| **RuView pipeline contributor** | Get a binary `MagFrame` shape (`0xC51A_6E70`) you can plumb into existing observability, with optional ruvector trace compression behind a feature flag |
|
||||
| **Auditor / compliance reviewer** | Re-run the included determinism check (`same scene + seed → byte-identical proof bundle`) and verify the simulator's output across machines without re-running the whole pipeline |
|
||||
|
||||
## Capabilities (what's shipping today)
|
||||
|
||||
| Capability | What's in the crate |
|
||||
|---|---|
|
||||
| **Scene primitives** | `DipoleSource`, `CurrentLoop`, `FerrousObject`, `EddyCurrent`, `Scene` aggregate. JSON round-trip safe. |
|
||||
| **Magnetic-field synthesis** | Closed-form analytic dipole, numerical Biot-Savart over 64-segment current loops, linearly-induced ferrous-object moment, multi-source aggregation. **All in `f64`** for near-field stability; clamped at 1 mm with a saturation flag. |
|
||||
| **Per-material attenuation** | Air / drywall / brick / dry concrete / reinforced concrete / sheet steel — with a `HEAVY_ATTENUATION` flag for the materials whose loss values are admittedly conjectural. **NaN-safe** on adversarial input (negative or non-finite path lengths). |
|
||||
| **NV-ensemble physics** | ODMR Lorentzian (FWHM ≈ 1 MHz), shot-noise floor `δB ∝ 1/(γ_e·C·√(N·t·T₂*))`, T₂ decay envelope, 4-axis 〈111〉 crystallographic projection with closed-form LSQ inversion. Defaults match Barry et al. *Rev. Mod. Phys.* 92 (2020) Table III for COTS bulk diamond. |
|
||||
| **Determinism** | Same `(B_in, dt, seed)` → byte-identical `NvReading`. ChaCha20-seeded shot noise; no global state, no time-of-day field, no allocator randomness. |
|
||||
| **Binary frame format** | `MagFrame` — 60-byte fixed-layout record, magic `0xC51A_6E70` (distinct from ADR-018 CSI `0xC51F...` and ADR-084 sketch `0xC511_0084`). Round-trips byte-exact, deserialiser rejects bad magic / bad version / wrong length without panicking. |
|
||||
|
||||
### Not yet shipped (next two passes)
|
||||
|
||||
- `digitiser.rs` — ADC quantization + 4ᵗʰ-order Butterworth anti-alias + lockin demodulation
|
||||
- `pipeline.rs` — wires every stage end-to-end and emits a `MagFrame` stream
|
||||
- `proof.rs` + criterion bench — deterministic SHA-256 witness bundle + ≥ 1 kHz wall-clock throughput target
|
||||
|
||||
These complete the six-pass plan in
|
||||
`docs/research/quantum-sensing/15-nvsim-implementation-plan.md`.
|
||||
|
||||
## How it compares
|
||||
|
||||
The closest existing tools each cover one slice of what `nvsim` covers
|
||||
end-to-end. Nothing in the open-source ecosystem (as of early 2026) covers
|
||||
the whole forward pipeline at once — see
|
||||
`docs/research/quantum-sensing/14-nv-diamond-sensor-simulator.md` §2.2.
|
||||
|
||||
| Tool | Source synthesis | Material attenuation | NV ensemble physics | Digitiser + lockin | Witness bundle | Language |
|
||||
|---|---|---|---|---|---|---|
|
||||
| [Magpylib](https://magpylib.readthedocs.io/) | ✅ analytic dipole + Biot-Savart | ❌ | ❌ | ❌ | ❌ | Python |
|
||||
| [QuTiP](https://qutip.org/) NV scripts | ❌ | ❌ | ✅ full Hamiltonian + Lindblad | ❌ | ❌ | Python |
|
||||
| Vendor sims (Element Six, etc.) | partial | partial | ✅ proprietary | partial | ❌ | closed |
|
||||
| **`nvsim`** | ✅ analytic + Biot-Savart | ✅ 6 materials, NaN-safe | ✅ leading-order ensemble proxy | 🚧 Pass 5 | 🚧 Pass 6 | Rust, deterministic |
|
||||
|
||||
`nvsim` deliberately **does not** try to compete with QuTiP on Hamiltonian
|
||||
fidelity (full Lindblad solver is plan §6 out-of-scope). It picks the
|
||||
linear-readout proxy that Barry 2020 §III.A validates as adequate for
|
||||
ensemble magnetometers in the linear regime, and ships that path
|
||||
end-to-end with witness-anchored reproducibility.
|
||||
|
||||
## Value proposition
|
||||
|
||||
You get **three things at once** that no other open simulator combines:
|
||||
|
||||
1. **Forward end-to-end pipeline.** Scene → source → propagation → NV → digitiser → frame → witness, in one crate, in one language. No Python ↔ Rust marshalling, no manual gluing of three half-tools.
|
||||
2. **Strong determinism.** Same inputs and seed → byte-identical output across machines, runs, and time. CI pipelines treat the simulator's output as a content-addressable artifact: a SHA-256 over the frame stream is the build's "did the physics drift?" canary.
|
||||
3. **Honest physics.** Every formula is cited. Every conjectural default is flagged in code, not buried in a footnote. The acceptance suite includes a Wolf 2015 sanity-floor test that fires if anyone silently changes the ensemble constants — i.e. the simulator can tell you when its own model breaks.
|
||||
|
||||
The cost: `nvsim` is a *forward simulator only*. It does not do inverse
|
||||
problems (estimating field sources from sensor readings), full Hamiltonian
|
||||
dynamics, or hardware control. If you need those, you escalate to QuTiP,
|
||||
COMSOL, or a real lab respectively.
|
||||
|
||||
## Usage guide
|
||||
|
||||
### Install
|
||||
|
||||
```bash
|
||||
# Inside the workspace:
|
||||
cargo build -p nvsim --no-default-features
|
||||
cargo test -p nvsim --no-default-features # currently 34 passing
|
||||
```
|
||||
|
||||
`nvsim` is a standalone leaf crate. It depends only on `serde`, `thiserror`,
|
||||
`tracing`, `rand`, and `rand_chacha`. RuView ecosystem integrations
|
||||
(`wifi-densepose-core` frame alignment, `ruvector-core` trace compression)
|
||||
land behind feature flags after the core simulator is shipping. None are
|
||||
required to use this crate.
|
||||
|
||||
### Synthesize a scene's magnetic field at a sensor
|
||||
|
||||
```rust
|
||||
use nvsim::{Scene, DipoleSource, scene_field_at};
|
||||
|
||||
let mut scene = Scene::new();
|
||||
// 1 mA·m² dipole at (0,0,0.5 m) pointing along +ẑ
|
||||
scene.add_dipole(DipoleSource::new([0.0, 0.0, 0.5], [0.0, 0.0, 1.0e-3]));
|
||||
|
||||
// Field at the origin
|
||||
let (b_tesla, near_field_flag) = scene_field_at(&scene, [0.0, 0.0, 0.0]);
|
||||
println!("B = {:?} T (near-field saturated: {})", b_tesla, near_field_flag);
|
||||
```
|
||||
|
||||
### Run the full sensor model
|
||||
|
||||
```rust
|
||||
use nvsim::{NvSensor, NvSensorConfig};
|
||||
|
||||
let sensor = NvSensor::cots_defaults();
|
||||
let b_in = [1.0e-9, 0.0, 0.0]; // 1 nT along +x̂
|
||||
let dt = 1.0e-3; // 1 ms integration
|
||||
let seed = 0xCAFE_BABE;
|
||||
|
||||
let reading = sensor.sample(b_in, dt, seed);
|
||||
println!("recovered B = {:?}", reading.b_recovered);
|
||||
println!("σ per axis = {:?} T", reading.sigma_per_axis);
|
||||
println!("δB floor = {:e} T/√Hz", reading.noise_floor_t_sqrt_hz);
|
||||
```
|
||||
|
||||
### Apply per-material attenuation
|
||||
|
||||
```rust
|
||||
use nvsim::{attenuate, LosSegment, Material};
|
||||
|
||||
let b_in = [1.0e-9, 0.0, 0.0];
|
||||
let segments = [
|
||||
LosSegment { material: Material::Air, path_m: 1.0 },
|
||||
LosSegment { material: Material::Drywall, path_m: 0.1 },
|
||||
LosSegment { material: Material::ReinforcedConcrete, path_m: 0.2 }, // raises HEAVY flag
|
||||
];
|
||||
let (b_attenuated, heavy) = attenuate(b_in, &segments);
|
||||
```
|
||||
|
||||
### Serialise a binary frame
|
||||
|
||||
```rust
|
||||
use nvsim::{MagFrame, MAG_FRAME_MAGIC};
|
||||
use nvsim::frame::flag;
|
||||
|
||||
let mut f = MagFrame::empty(7); // sensor_id 7
|
||||
f.b_pt = [1500.0, -250.0, 800.0]; // pT
|
||||
f.set_flag(flag::ADC_SATURATED);
|
||||
|
||||
let bytes = f.to_bytes(); // 60 bytes, deterministic
|
||||
let parsed = MagFrame::from_bytes(&bytes)
|
||||
.expect("round-trip must succeed");
|
||||
assert_eq!(parsed, f);
|
||||
```
|
||||
|
||||
## Acceptance commitments (per implementation plan §5)
|
||||
|
||||
These are the four numbers `nvsim` commits to as a finished simulator:
|
||||
|
||||
- **Pipeline throughput**: ≥ 1 kHz simulated samples per second of wall-clock on a Cortex-A53-class CPU.
|
||||
- **Determinism**: same `(scene, seed)` produces byte-identical proof-bundle output across runs and machines.
|
||||
- **Noise-floor reproduction**: simulator with shot noise OFF reproduces the analytical Biot-Savart result to ≤ 0.1% RMS.
|
||||
- **Lockin SNR floor**: 1 nT @ 1 kHz vs 100 pT/√Hz floor → SNR ≥ 10 in 1 s.
|
||||
|
||||
The first and last numbers come online with Pass 5/6. The middle two are
|
||||
already enforced in the test suite.
|
||||
|
||||
## Physics primary sources
|
||||
|
||||
- Jackson, *Classical Electrodynamics* 3e (1999), §5.4–5.8 — Biot–Savart, dipole field.
|
||||
- Doherty et al., *Phys. Rep.* 528, 1 (2013) — NV ground-state Hamiltonian, ODMR transition.
|
||||
- Barry et al., *Rev. Mod. Phys.* 92, 015004 (2020) — NV-ensemble sensitivity, Lorentzian lineshape, T₁/T₂/T₂*, contrast and spin-count defaults.
|
||||
- Wolf et al., *Phys. Rev. X* 5, 041001 (2015) — bulk-diamond pT/√Hz reference floor used as the sanity-floor test boundary.
|
||||
- Cullity & Graham, *Introduction to Magnetic Materials* 2e (2009), Ch. 2 — χ_steel for ferrous-object linear-induced moment.
|
||||
- Ortner & Bandeira, *SoftwareX* 11, 100466 (2020) — Magpylib reference implementation for analytic dipole / current-loop fields.
|
||||
|
||||
For the full SOTA survey and the build/skip verdict, see
|
||||
`docs/research/quantum-sensing/14-nv-diamond-sensor-simulator.md`. For the
|
||||
six-pass implementation plan that drives the build, see
|
||||
`docs/research/quantum-sensing/15-nvsim-implementation-plan.md`.
|
||||
|
||||
## Limitations and out-of-scope
|
||||
|
||||
Per `15-nvsim-implementation-plan.md` §6:
|
||||
|
||||
- Single-NV imaging / ODMR scanning microscopy — `nvsim` is room-scale, not nm.
|
||||
- Full Lindblad solver, NV-NV entanglement, photonic-crystal cavities — escalate to QuTiP if needed.
|
||||
- Diamond growth / NV creation chemistry — vendor (Element Six, Adamas) handles.
|
||||
- Cryogenic operation — RuView ships room-temperature; `nvsim` follows.
|
||||
- Real hardware control (laser drivers, microwave sources, AOM) — `nvsim` is forward-only.
|
||||
- Pulsed dynamical-decoupling sequences — defer to dedicated tooling.
|
||||
- fT-floor sensitivity claims — out of COTS reach in 2026; `nvsim` commits to a pT-floor honestly.
|
||||
- Inverse problems — given sensor readings, the simulator does not estimate scene parameters back.
|
||||
|
||||
If your use case needs any of the above, `nvsim` is the wrong starting
|
||||
point. If your use case is *forward simulation of a deterministic NV
|
||||
magnetometer pipeline you can run in CI*, it is the right one.
|
||||
|
||||
## WebAssembly
|
||||
|
||||
`nvsim` is **WASM-ready by construction**. Zero `std::time` / `std::fs` /
|
||||
`std::env` / `std::process` / `std::thread` / `Mutex` / `RwLock` calls in
|
||||
the crate's source — every dependency in the tree (`serde`, `thiserror`,
|
||||
`tracing`, `rand`, `rand_chacha`, `sha2`, `ndarray`) compiles cleanly to
|
||||
`wasm32-unknown-unknown`. The shot-noise PRNG is seeded from a
|
||||
caller-supplied `u64` so no OS-entropy bridge is needed.
|
||||
|
||||
```bash
|
||||
rustup target add wasm32-unknown-unknown # one-time, on the dev machine
|
||||
cargo build -p nvsim --target wasm32-unknown-unknown --no-default-features
|
||||
```
|
||||
|
||||
Why it matters: cluster-Pi inference, browser-side sensor demos, and
|
||||
Cloudflare-Worker / Deno-deploy edge workloads can all run the
|
||||
deterministic pipeline. A 28-byte `MagFrame` shape and a 32-byte SHA-256
|
||||
witness make it straightforward to ship simulator output across any
|
||||
HTTP / WebSocket / IPC channel.
|
||||
|
||||
## License
|
||||
|
||||
MIT OR Apache-2.0 (matches workspace default).
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
* In-browser pipeline. Wraps [`Pipeline`] with JS-friendly construction
|
||||
* (JSON for `Scene` and `PipelineConfig`) and `Vec<u8>` outputs (raw
|
||||
* concatenated [`MagFrame`] bytes — 60 bytes/frame, magic `0xC51A_6E70`).
|
||||
*/
|
||||
export class WasmPipeline {
|
||||
free(): void;
|
||||
[Symbol.dispose](): void;
|
||||
/**
|
||||
* nvsim build version (semver from Cargo.toml).
|
||||
*/
|
||||
static buildVersion(): string;
|
||||
/**
|
||||
* Bytes-per-frame for v1 — `60` today; surfaced so the dashboard
|
||||
* can advance its parse cursor without re-deriving the layout.
|
||||
*/
|
||||
static frameBytes(): number;
|
||||
/**
|
||||
* Magic constant for the `MagFrame` v1 binary record. The dashboard's
|
||||
* hex-dump panel highlights these four bytes (`0xC51A_6E70` → `701A6EC5`
|
||||
* little-endian) as a sanity check.
|
||||
*/
|
||||
static frameMagic(): number;
|
||||
/**
|
||||
* Construct from JSON strings + a `seed` (BigInt-friendly; passed in
|
||||
* as `f64` since wasm-bindgen does not yet ergonomically pass `u64`,
|
||||
* then bit-cast through `as u64`). The dashboard sends seeds as
|
||||
* `Number(seed_hex)` from a 32-bit value to fit cleanly.
|
||||
*/
|
||||
constructor(scene_json: string, config_json: string, seed: number);
|
||||
/**
|
||||
* Run `n_samples` of the pipeline and return the concatenated raw
|
||||
* `MagFrame` bytes (`n_samples * sensors * 60` bytes). The dashboard
|
||||
* parses this into typed records on the main thread.
|
||||
*/
|
||||
run(n_samples: number): Uint8Array;
|
||||
/**
|
||||
* Run + SHA-256 witness in one call. Returns a JS object
|
||||
* `{ frames: Uint8Array, witness: Uint8Array }`. Same
|
||||
* `(scene, config, seed)` produces byte-identical `witness` across
|
||||
* runs, machines, and transports — the regression dashboard pins.
|
||||
*/
|
||||
runWithWitness(n_samples: number): any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected reference witness for `Proof::REFERENCE_SCENE_JSON @ seed=42,
|
||||
* N=256` — the bytes the dashboard's Verify panel compares against.
|
||||
*/
|
||||
export function expectedReferenceWitnessHex(): string;
|
||||
|
||||
/**
|
||||
* Hex-encode a 32-byte witness for display.
|
||||
*/
|
||||
export function hexWitness(witness: Uint8Array): string;
|
||||
|
||||
/**
|
||||
* Convenience: parse the bundled reference scene to JSON. Lets the
|
||||
* dashboard's "load reference scene" flow round-trip through the Rust
|
||||
* type system instead of duplicating the JSON literal in the JS code.
|
||||
*/
|
||||
export function referenceSceneJson(): string;
|
||||
|
||||
/**
|
||||
* Run the canonical reference pipeline (`Proof::generate`) end-to-end and
|
||||
* return the SHA-256 witness as a 32-byte `Uint8Array`. This is the
|
||||
* dashboard's source of truth for the Verify-witness panel.
|
||||
*/
|
||||
export function referenceWitness(): Uint8Array;
|
||||
|
||||
/**
|
||||
* One-shot pipeline run that doesn't disturb the dashboard's main
|
||||
* pipeline. Used by the Ghost Murmur interactive demo (and any other
|
||||
* "run-against-this-scene-please" flow) to ask: given a scene + config,
|
||||
* what does the NV sensor recover at the origin?
|
||||
*
|
||||
* Returns a JS object:
|
||||
* ```js
|
||||
* {
|
||||
* bRecoveredT: [number, number, number], // recovered B (Tesla)
|
||||
* bMagT: number, // |B| (Tesla)
|
||||
* noiseFloorPtSqrtHz: number, // δB pT/√Hz from this config
|
||||
* sigmaPt: [number, number, number], // per-axis 1σ noise estimate (pT)
|
||||
* nFrames: number, // samples actually run
|
||||
* witnessHex: string // SHA-256 witness for this run
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export function runTransient(scene_json: string, config_json: string, seed: number, n_samples: number): any;
|
||||
|
||||
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||
|
||||
export interface InitOutput {
|
||||
readonly memory: WebAssembly.Memory;
|
||||
readonly __wbg_wasmpipeline_free: (a: number, b: number) => void;
|
||||
readonly expectedReferenceWitnessHex: (a: number) => void;
|
||||
readonly hexWitness: (a: number, b: number, c: number) => void;
|
||||
readonly referenceSceneJson: (a: number) => void;
|
||||
readonly referenceWitness: (a: number) => void;
|
||||
readonly runTransient: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
||||
readonly wasmpipeline_buildVersion: (a: number) => void;
|
||||
readonly wasmpipeline_frameBytes: () => number;
|
||||
readonly wasmpipeline_frameMagic: () => number;
|
||||
readonly wasmpipeline_new: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||
readonly wasmpipeline_run: (a: number, b: number, c: number) => void;
|
||||
readonly wasmpipeline_runWithWitness: (a: number, b: number, c: number) => void;
|
||||
readonly __wbindgen_export: (a: number) => void;
|
||||
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
||||
readonly __wbindgen_export2: (a: number, b: number, c: number) => void;
|
||||
readonly __wbindgen_export3: (a: number, b: number) => number;
|
||||
readonly __wbindgen_export4: (a: number, b: number, c: number, d: number) => number;
|
||||
}
|
||||
|
||||
export type SyncInitInput = BufferSource | WebAssembly.Module;
|
||||
|
||||
/**
|
||||
* Instantiates the given `module`, which can either be bytes or
|
||||
* a precompiled `WebAssembly.Module`.
|
||||
*
|
||||
* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
|
||||
*
|
||||
* @returns {InitOutput}
|
||||
*/
|
||||
export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
|
||||
|
||||
/**
|
||||
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
||||
* for everything else, calls `WebAssembly.instantiate` directly.
|
||||
*
|
||||
* @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
|
||||
*
|
||||
* @returns {Promise<InitOutput>}
|
||||
*/
|
||||
export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
|
||||
|
|
@ -0,0 +1,575 @@
|
|||
/* @ts-self-types="./nvsim.d.ts" */
|
||||
|
||||
/**
|
||||
* In-browser pipeline. Wraps [`Pipeline`] with JS-friendly construction
|
||||
* (JSON for `Scene` and `PipelineConfig`) and `Vec<u8>` outputs (raw
|
||||
* concatenated [`MagFrame`] bytes — 60 bytes/frame, magic `0xC51A_6E70`).
|
||||
*/
|
||||
export class WasmPipeline {
|
||||
__destroy_into_raw() {
|
||||
const ptr = this.__wbg_ptr;
|
||||
this.__wbg_ptr = 0;
|
||||
WasmPipelineFinalization.unregister(this);
|
||||
return ptr;
|
||||
}
|
||||
free() {
|
||||
const ptr = this.__destroy_into_raw();
|
||||
wasm.__wbg_wasmpipeline_free(ptr, 0);
|
||||
}
|
||||
/**
|
||||
* nvsim build version (semver from Cargo.toml).
|
||||
* @returns {string}
|
||||
*/
|
||||
static buildVersion() {
|
||||
let deferred1_0;
|
||||
let deferred1_1;
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
wasm.wasmpipeline_buildVersion(retptr);
|
||||
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||
deferred1_0 = r0;
|
||||
deferred1_1 = r1;
|
||||
return getStringFromWasm0(r0, r1);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
wasm.__wbindgen_export2(deferred1_0, deferred1_1, 1);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Bytes-per-frame for v1 — `60` today; surfaced so the dashboard
|
||||
* can advance its parse cursor without re-deriving the layout.
|
||||
* @returns {number}
|
||||
*/
|
||||
static frameBytes() {
|
||||
const ret = wasm.wasmpipeline_frameBytes();
|
||||
return ret >>> 0;
|
||||
}
|
||||
/**
|
||||
* Magic constant for the `MagFrame` v1 binary record. The dashboard's
|
||||
* hex-dump panel highlights these four bytes (`0xC51A_6E70` → `701A6EC5`
|
||||
* little-endian) as a sanity check.
|
||||
* @returns {number}
|
||||
*/
|
||||
static frameMagic() {
|
||||
const ret = wasm.wasmpipeline_frameMagic();
|
||||
return ret >>> 0;
|
||||
}
|
||||
/**
|
||||
* Construct from JSON strings + a `seed` (BigInt-friendly; passed in
|
||||
* as `f64` since wasm-bindgen does not yet ergonomically pass `u64`,
|
||||
* then bit-cast through `as u64`). The dashboard sends seeds as
|
||||
* `Number(seed_hex)` from a 32-bit value to fit cleanly.
|
||||
* @param {string} scene_json
|
||||
* @param {string} config_json
|
||||
* @param {number} seed
|
||||
*/
|
||||
constructor(scene_json, config_json, seed) {
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
const ptr0 = passStringToWasm0(scene_json, wasm.__wbindgen_export3, wasm.__wbindgen_export4);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(config_json, wasm.__wbindgen_export3, wasm.__wbindgen_export4);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
wasm.wasmpipeline_new(retptr, ptr0, len0, ptr1, len1, seed);
|
||||
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
||||
if (r2) {
|
||||
throw takeObject(r1);
|
||||
}
|
||||
this.__wbg_ptr = r0 >>> 0;
|
||||
WasmPipelineFinalization.register(this, this.__wbg_ptr, this);
|
||||
return this;
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Run `n_samples` of the pipeline and return the concatenated raw
|
||||
* `MagFrame` bytes (`n_samples * sensors * 60` bytes). The dashboard
|
||||
* parses this into typed records on the main thread.
|
||||
* @param {number} n_samples
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
run(n_samples) {
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
wasm.wasmpipeline_run(retptr, this.__wbg_ptr, n_samples);
|
||||
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||
var v1 = getArrayU8FromWasm0(r0, r1).slice();
|
||||
wasm.__wbindgen_export2(r0, r1 * 1, 1);
|
||||
return v1;
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Run + SHA-256 witness in one call. Returns a JS object
|
||||
* `{ frames: Uint8Array, witness: Uint8Array }`. Same
|
||||
* `(scene, config, seed)` produces byte-identical `witness` across
|
||||
* runs, machines, and transports — the regression dashboard pins.
|
||||
* @param {number} n_samples
|
||||
* @returns {any}
|
||||
*/
|
||||
runWithWitness(n_samples) {
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
wasm.wasmpipeline_runWithWitness(retptr, this.__wbg_ptr, n_samples);
|
||||
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
||||
if (r2) {
|
||||
throw takeObject(r1);
|
||||
}
|
||||
return takeObject(r0);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Symbol.dispose) WasmPipeline.prototype[Symbol.dispose] = WasmPipeline.prototype.free;
|
||||
|
||||
/**
|
||||
* Expected reference witness for `Proof::REFERENCE_SCENE_JSON @ seed=42,
|
||||
* N=256` — the bytes the dashboard's Verify panel compares against.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function expectedReferenceWitnessHex() {
|
||||
let deferred1_0;
|
||||
let deferred1_1;
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
wasm.expectedReferenceWitnessHex(retptr);
|
||||
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||
deferred1_0 = r0;
|
||||
deferred1_1 = r1;
|
||||
return getStringFromWasm0(r0, r1);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
wasm.__wbindgen_export2(deferred1_0, deferred1_1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hex-encode a 32-byte witness for display.
|
||||
* @param {Uint8Array} witness
|
||||
* @returns {string}
|
||||
*/
|
||||
export function hexWitness(witness) {
|
||||
let deferred3_0;
|
||||
let deferred3_1;
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
const ptr0 = passArray8ToWasm0(witness, wasm.__wbindgen_export3);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.hexWitness(retptr, ptr0, len0);
|
||||
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
||||
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
||||
var ptr2 = r0;
|
||||
var len2 = r1;
|
||||
if (r3) {
|
||||
ptr2 = 0; len2 = 0;
|
||||
throw takeObject(r2);
|
||||
}
|
||||
deferred3_0 = ptr2;
|
||||
deferred3_1 = len2;
|
||||
return getStringFromWasm0(ptr2, len2);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
wasm.__wbindgen_export2(deferred3_0, deferred3_1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience: parse the bundled reference scene to JSON. Lets the
|
||||
* dashboard's "load reference scene" flow round-trip through the Rust
|
||||
* type system instead of duplicating the JSON literal in the JS code.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function referenceSceneJson() {
|
||||
let deferred1_0;
|
||||
let deferred1_1;
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
wasm.referenceSceneJson(retptr);
|
||||
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||
deferred1_0 = r0;
|
||||
deferred1_1 = r1;
|
||||
return getStringFromWasm0(r0, r1);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
wasm.__wbindgen_export2(deferred1_0, deferred1_1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the canonical reference pipeline (`Proof::generate`) end-to-end and
|
||||
* return the SHA-256 witness as a 32-byte `Uint8Array`. This is the
|
||||
* dashboard's source of truth for the Verify-witness panel.
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
export function referenceWitness() {
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
wasm.referenceWitness(retptr);
|
||||
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
||||
if (r2) {
|
||||
throw takeObject(r1);
|
||||
}
|
||||
return takeObject(r0);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* One-shot pipeline run that doesn't disturb the dashboard's main
|
||||
* pipeline. Used by the Ghost Murmur interactive demo (and any other
|
||||
* "run-against-this-scene-please" flow) to ask: given a scene + config,
|
||||
* what does the NV sensor recover at the origin?
|
||||
*
|
||||
* Returns a JS object:
|
||||
* ```js
|
||||
* {
|
||||
* bRecoveredT: [number, number, number], // recovered B (Tesla)
|
||||
* bMagT: number, // |B| (Tesla)
|
||||
* noiseFloorPtSqrtHz: number, // δB pT/√Hz from this config
|
||||
* sigmaPt: [number, number, number], // per-axis 1σ noise estimate (pT)
|
||||
* nFrames: number, // samples actually run
|
||||
* witnessHex: string // SHA-256 witness for this run
|
||||
* }
|
||||
* ```
|
||||
* @param {string} scene_json
|
||||
* @param {string} config_json
|
||||
* @param {number} seed
|
||||
* @param {number} n_samples
|
||||
* @returns {any}
|
||||
*/
|
||||
export function runTransient(scene_json, config_json, seed, n_samples) {
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
const ptr0 = passStringToWasm0(scene_json, wasm.__wbindgen_export3, wasm.__wbindgen_export4);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(config_json, wasm.__wbindgen_export3, wasm.__wbindgen_export4);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
wasm.runTransient(retptr, ptr0, len0, ptr1, len1, seed, n_samples);
|
||||
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
||||
if (r2) {
|
||||
throw takeObject(r1);
|
||||
}
|
||||
return takeObject(r0);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
}
|
||||
}
|
||||
|
||||
function __wbg_get_imports() {
|
||||
const import0 = {
|
||||
__proto__: null,
|
||||
__wbg___wbindgen_throw_6ddd609b62940d55: function(arg0, arg1) {
|
||||
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||
},
|
||||
__wbg_length_550d8a396009cd38: function(arg0) {
|
||||
const ret = getObject(arg0).length;
|
||||
return ret;
|
||||
},
|
||||
__wbg_length_ea16607d7b61445b: function(arg0) {
|
||||
const ret = getObject(arg0).length;
|
||||
return ret;
|
||||
},
|
||||
__wbg_new_ab79df5bd7c26067: function() {
|
||||
const ret = new Object();
|
||||
return addHeapObject(ret);
|
||||
},
|
||||
__wbg_new_with_length_825018a1616e9e55: function(arg0) {
|
||||
const ret = new Uint8Array(arg0 >>> 0);
|
||||
return addHeapObject(ret);
|
||||
},
|
||||
__wbg_new_with_length_eae667475c36c4e4: function(arg0) {
|
||||
const ret = new Float64Array(arg0 >>> 0);
|
||||
return addHeapObject(ret);
|
||||
},
|
||||
__wbg_set_636d1e3e4286e068: function(arg0, arg1, arg2) {
|
||||
getObject(arg0).set(getArrayF64FromWasm0(arg1, arg2));
|
||||
},
|
||||
__wbg_set_7eaa4f96924fd6b3: function() { return handleError(function (arg0, arg1, arg2) {
|
||||
const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2));
|
||||
return ret;
|
||||
}, arguments); },
|
||||
__wbg_set_8c0b3ffcf05d61c2: function(arg0, arg1, arg2) {
|
||||
getObject(arg0).set(getArrayU8FromWasm0(arg1, arg2));
|
||||
},
|
||||
__wbindgen_cast_0000000000000001: function(arg0) {
|
||||
// Cast intrinsic for `F64 -> Externref`.
|
||||
const ret = arg0;
|
||||
return addHeapObject(ret);
|
||||
},
|
||||
__wbindgen_cast_0000000000000002: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Ref(String) -> Externref`.
|
||||
const ret = getStringFromWasm0(arg0, arg1);
|
||||
return addHeapObject(ret);
|
||||
},
|
||||
__wbindgen_object_drop_ref: function(arg0) {
|
||||
takeObject(arg0);
|
||||
},
|
||||
};
|
||||
return {
|
||||
__proto__: null,
|
||||
"./nvsim_bg.js": import0,
|
||||
};
|
||||
}
|
||||
|
||||
const WasmPipelineFinalization = (typeof FinalizationRegistry === 'undefined')
|
||||
? { register: () => {}, unregister: () => {} }
|
||||
: new FinalizationRegistry(ptr => wasm.__wbg_wasmpipeline_free(ptr >>> 0, 1));
|
||||
|
||||
function addHeapObject(obj) {
|
||||
if (heap_next === heap.length) heap.push(heap.length + 1);
|
||||
const idx = heap_next;
|
||||
heap_next = heap[idx];
|
||||
|
||||
heap[idx] = obj;
|
||||
return idx;
|
||||
}
|
||||
|
||||
function dropObject(idx) {
|
||||
if (idx < 1028) return;
|
||||
heap[idx] = heap_next;
|
||||
heap_next = idx;
|
||||
}
|
||||
|
||||
function getArrayF64FromWasm0(ptr, len) {
|
||||
ptr = ptr >>> 0;
|
||||
return getFloat64ArrayMemory0().subarray(ptr / 8, ptr / 8 + len);
|
||||
}
|
||||
|
||||
function getArrayU8FromWasm0(ptr, len) {
|
||||
ptr = ptr >>> 0;
|
||||
return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
|
||||
}
|
||||
|
||||
let cachedDataViewMemory0 = null;
|
||||
function getDataViewMemory0() {
|
||||
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
|
||||
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
|
||||
}
|
||||
return cachedDataViewMemory0;
|
||||
}
|
||||
|
||||
let cachedFloat64ArrayMemory0 = null;
|
||||
function getFloat64ArrayMemory0() {
|
||||
if (cachedFloat64ArrayMemory0 === null || cachedFloat64ArrayMemory0.byteLength === 0) {
|
||||
cachedFloat64ArrayMemory0 = new Float64Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachedFloat64ArrayMemory0;
|
||||
}
|
||||
|
||||
function getStringFromWasm0(ptr, len) {
|
||||
ptr = ptr >>> 0;
|
||||
return decodeText(ptr, len);
|
||||
}
|
||||
|
||||
let cachedUint8ArrayMemory0 = null;
|
||||
function getUint8ArrayMemory0() {
|
||||
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
||||
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachedUint8ArrayMemory0;
|
||||
}
|
||||
|
||||
function getObject(idx) { return heap[idx]; }
|
||||
|
||||
function handleError(f, args) {
|
||||
try {
|
||||
return f.apply(this, args);
|
||||
} catch (e) {
|
||||
wasm.__wbindgen_export(addHeapObject(e));
|
||||
}
|
||||
}
|
||||
|
||||
let heap = new Array(1024).fill(undefined);
|
||||
heap.push(undefined, null, true, false);
|
||||
|
||||
let heap_next = heap.length;
|
||||
|
||||
function passArray8ToWasm0(arg, malloc) {
|
||||
const ptr = malloc(arg.length * 1, 1) >>> 0;
|
||||
getUint8ArrayMemory0().set(arg, ptr / 1);
|
||||
WASM_VECTOR_LEN = arg.length;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
function passStringToWasm0(arg, malloc, realloc) {
|
||||
if (realloc === undefined) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
const ptr = malloc(buf.length, 1) >>> 0;
|
||||
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
||||
WASM_VECTOR_LEN = buf.length;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
let len = arg.length;
|
||||
let ptr = malloc(len, 1) >>> 0;
|
||||
|
||||
const mem = getUint8ArrayMemory0();
|
||||
|
||||
let offset = 0;
|
||||
|
||||
for (; offset < len; offset++) {
|
||||
const code = arg.charCodeAt(offset);
|
||||
if (code > 0x7F) break;
|
||||
mem[ptr + offset] = code;
|
||||
}
|
||||
if (offset !== len) {
|
||||
if (offset !== 0) {
|
||||
arg = arg.slice(offset);
|
||||
}
|
||||
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
||||
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
||||
const ret = cachedTextEncoder.encodeInto(arg, view);
|
||||
|
||||
offset += ret.written;
|
||||
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
||||
}
|
||||
|
||||
WASM_VECTOR_LEN = offset;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
function takeObject(idx) {
|
||||
const ret = getObject(idx);
|
||||
dropObject(idx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
||||
cachedTextDecoder.decode();
|
||||
const MAX_SAFARI_DECODE_BYTES = 2146435072;
|
||||
let numBytesDecoded = 0;
|
||||
function decodeText(ptr, len) {
|
||||
numBytesDecoded += len;
|
||||
if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
|
||||
cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
||||
cachedTextDecoder.decode();
|
||||
numBytesDecoded = len;
|
||||
}
|
||||
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
||||
}
|
||||
|
||||
const cachedTextEncoder = new TextEncoder();
|
||||
|
||||
if (!('encodeInto' in cachedTextEncoder)) {
|
||||
cachedTextEncoder.encodeInto = function (arg, view) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
view.set(buf);
|
||||
return {
|
||||
read: arg.length,
|
||||
written: buf.length
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
let WASM_VECTOR_LEN = 0;
|
||||
|
||||
let wasmModule, wasm;
|
||||
function __wbg_finalize_init(instance, module) {
|
||||
wasm = instance.exports;
|
||||
wasmModule = module;
|
||||
cachedDataViewMemory0 = null;
|
||||
cachedFloat64ArrayMemory0 = null;
|
||||
cachedUint8ArrayMemory0 = null;
|
||||
return wasm;
|
||||
}
|
||||
|
||||
async function __wbg_load(module, imports) {
|
||||
if (typeof Response === 'function' && module instanceof Response) {
|
||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||
try {
|
||||
return await WebAssembly.instantiateStreaming(module, imports);
|
||||
} catch (e) {
|
||||
const validResponse = module.ok && expectedResponseType(module.type);
|
||||
|
||||
if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
|
||||
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||
|
||||
} else { throw e; }
|
||||
}
|
||||
}
|
||||
|
||||
const bytes = await module.arrayBuffer();
|
||||
return await WebAssembly.instantiate(bytes, imports);
|
||||
} else {
|
||||
const instance = await WebAssembly.instantiate(module, imports);
|
||||
|
||||
if (instance instanceof WebAssembly.Instance) {
|
||||
return { instance, module };
|
||||
} else {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
function expectedResponseType(type) {
|
||||
switch (type) {
|
||||
case 'basic': case 'cors': case 'default': return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function initSync(module) {
|
||||
if (wasm !== undefined) return wasm;
|
||||
|
||||
|
||||
if (module !== undefined) {
|
||||
if (Object.getPrototypeOf(module) === Object.prototype) {
|
||||
({module} = module)
|
||||
} else {
|
||||
console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
|
||||
}
|
||||
}
|
||||
|
||||
const imports = __wbg_get_imports();
|
||||
if (!(module instanceof WebAssembly.Module)) {
|
||||
module = new WebAssembly.Module(module);
|
||||
}
|
||||
const instance = new WebAssembly.Instance(module, imports);
|
||||
return __wbg_finalize_init(instance, module);
|
||||
}
|
||||
|
||||
async function __wbg_init(module_or_path) {
|
||||
if (wasm !== undefined) return wasm;
|
||||
|
||||
|
||||
if (module_or_path !== undefined) {
|
||||
if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
|
||||
({module_or_path} = module_or_path)
|
||||
} else {
|
||||
console.warn('using deprecated parameters for the initialization function; pass a single object instead')
|
||||
}
|
||||
}
|
||||
|
||||
if (module_or_path === undefined) {
|
||||
module_or_path = new URL('nvsim_bg.wasm', import.meta.url);
|
||||
}
|
||||
const imports = __wbg_get_imports();
|
||||
|
||||
if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
|
||||
module_or_path = fetch(module_or_path);
|
||||
}
|
||||
|
||||
const { instance, module } = await __wbg_load(await module_or_path, imports);
|
||||
|
||||
return __wbg_finalize_init(instance, module);
|
||||
}
|
||||
|
||||
export { initSync, __wbg_init as default };
|
||||
Binary file not shown.
|
|
@ -0,0 +1,20 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export const memory: WebAssembly.Memory;
|
||||
export const __wbg_wasmpipeline_free: (a: number, b: number) => void;
|
||||
export const expectedReferenceWitnessHex: (a: number) => void;
|
||||
export const hexWitness: (a: number, b: number, c: number) => void;
|
||||
export const referenceSceneJson: (a: number) => void;
|
||||
export const referenceWitness: (a: number) => void;
|
||||
export const runTransient: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
||||
export const wasmpipeline_buildVersion: (a: number) => void;
|
||||
export const wasmpipeline_frameBytes: () => number;
|
||||
export const wasmpipeline_frameMagic: () => number;
|
||||
export const wasmpipeline_new: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||
export const wasmpipeline_run: (a: number, b: number, c: number) => void;
|
||||
export const wasmpipeline_runWithWitness: (a: number, b: number, c: number) => void;
|
||||
export const __wbindgen_export: (a: number) => void;
|
||||
export const __wbindgen_add_to_stack_pointer: (a: number) => number;
|
||||
export const __wbindgen_export2: (a: number, b: number, c: number) => void;
|
||||
export const __wbindgen_export3: (a: number, b: number) => number;
|
||||
export const __wbindgen_export4: (a: number, b: number, c: number, d: number) => number;
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"name": "nvsim",
|
||||
"type": "module",
|
||||
"collaborators": [
|
||||
"rUv <ruv@ruv.net>",
|
||||
"WiFi-DensePose Contributors"
|
||||
],
|
||||
"description": "Deterministic NV-diamond magnetometer pipeline simulator (source -> propagation -> NV ensemble -> ADC + lockin demod)",
|
||||
"version": "0.3.0",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ruvnet/wifi-densepose"
|
||||
},
|
||||
"files": [
|
||||
"nvsim_bg.wasm",
|
||||
"nvsim.js",
|
||||
"nvsim.d.ts"
|
||||
],
|
||||
"main": "nvsim.js",
|
||||
"types": "nvsim.d.ts",
|
||||
"sideEffects": [
|
||||
"./snippets/*"
|
||||
],
|
||||
"keywords": [
|
||||
"nv-diamond",
|
||||
"magnetometer",
|
||||
"simulator",
|
||||
"physics",
|
||||
"biot-savart"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
if('serviceWorker' in navigator) {window.addEventListener('load', () => {navigator.serviceWorker.register('/RuView/nvsim/sw.js', { scope: '/RuView/nvsim/' })})}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,r)=>{const c=e||("document"in self?document.currentScript.src:"")||location.href;if(s[c])return;let o={};const l=e=>i(e,c),d={module:{uri:c},exports:o,require:l};s[c]=Promise.all(n.map(e=>d[e]||l(e))).then(e=>(r(...e),o))}}define(["./workbox-8c29f6e4"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"registerSW.js",revision:"4bcaa063d693b37532f242f566232490"},{url:"index.html",revision:"a81e9aaaffb4924e759f42842815b902"},{url:"icon-512.svg",revision:"98fc1c8102c279bf1c0dd52559821ddc"},{url:"icon-192.svg",revision:"e73b6aa9016dca426a59e0f8ff4f1b04"},{url:"nvsim-pkg/nvsim_bg.wasm",revision:"a617e7e24b2d5e976ce7e8d4f473104d"},{url:"nvsim-pkg/nvsim.js",revision:"ff4ecdcc8ace84fd24c4ad396809bd88"},{url:"assets/worker-C19MRcXs.js",revision:null},{url:"assets/signals-SG45zFCj.js",revision:null},{url:"assets/lit-BS7WqYd5.js",revision:null},{url:"assets/index-CyUCBwRA.css",revision:null},{url:"assets/index-CjC_xGBQ.js",revision:null},{url:"icon-192.svg",revision:"e73b6aa9016dca426a59e0f8ff4f1b04"},{url:"icon-512.svg",revision:"98fc1c8102c279bf1c0dd52559821ddc"},{url:"nvsim-pkg/nvsim.js",revision:"ff4ecdcc8ace84fd24c4ad396809bd88"},{url:"nvsim-pkg/nvsim_bg.wasm",revision:"a617e7e24b2d5e976ce7e8d4f473104d"},{url:"manifest.webmanifest",revision:"e8c97968cae19a0ed3b64c1303a27a90"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html")))});
|
||||
//# sourceMappingURL=sw.js.map
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"sw.js","sources":["../../../AppData/Local/Temp/969fa6b57e97cb6342d7d6f135306c48/sw.js"],"sourcesContent":["import {clientsClaim as workbox_core_clientsClaim} from 'C:/Users/ruv/Projects/wifi-densepose/dashboard/node_modules/workbox-core/clientsClaim.mjs';\nimport {precacheAndRoute as workbox_precaching_precacheAndRoute} from 'C:/Users/ruv/Projects/wifi-densepose/dashboard/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {cleanupOutdatedCaches as workbox_precaching_cleanupOutdatedCaches} from 'C:/Users/ruv/Projects/wifi-densepose/dashboard/node_modules/workbox-precaching/cleanupOutdatedCaches.mjs';\nimport {registerRoute as workbox_routing_registerRoute} from 'C:/Users/ruv/Projects/wifi-densepose/dashboard/node_modules/workbox-routing/registerRoute.mjs';\nimport {NavigationRoute as workbox_routing_NavigationRoute} from 'C:/Users/ruv/Projects/wifi-densepose/dashboard/node_modules/workbox-routing/NavigationRoute.mjs';\nimport {createHandlerBoundToURL as workbox_precaching_createHandlerBoundToURL} from 'C:/Users/ruv/Projects/wifi-densepose/dashboard/node_modules/workbox-precaching/createHandlerBoundToURL.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\n\n\n\n\nself.skipWaiting();\n\nworkbox_core_clientsClaim();\n\n\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"registerSW.js\",\n \"revision\": \"4bcaa063d693b37532f242f566232490\"\n },\n {\n \"url\": \"index.html\",\n \"revision\": \"a81e9aaaffb4924e759f42842815b902\"\n },\n {\n \"url\": \"icon-512.svg\",\n \"revision\": \"98fc1c8102c279bf1c0dd52559821ddc\"\n },\n {\n \"url\": \"icon-192.svg\",\n \"revision\": \"e73b6aa9016dca426a59e0f8ff4f1b04\"\n },\n {\n \"url\": \"nvsim-pkg/nvsim_bg.wasm\",\n \"revision\": \"a617e7e24b2d5e976ce7e8d4f473104d\"\n },\n {\n \"url\": \"nvsim-pkg/nvsim.js\",\n \"revision\": \"ff4ecdcc8ace84fd24c4ad396809bd88\"\n },\n {\n \"url\": \"assets/worker-C19MRcXs.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/signals-SG45zFCj.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/lit-BS7WqYd5.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-CyUCBwRA.css\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-CjC_xGBQ.js\",\n \"revision\": null\n },\n {\n \"url\": \"icon-192.svg\",\n \"revision\": \"e73b6aa9016dca426a59e0f8ff4f1b04\"\n },\n {\n \"url\": \"icon-512.svg\",\n \"revision\": \"98fc1c8102c279bf1c0dd52559821ddc\"\n },\n {\n \"url\": \"nvsim-pkg/nvsim.js\",\n \"revision\": \"ff4ecdcc8ace84fd24c4ad396809bd88\"\n },\n {\n \"url\": \"nvsim-pkg/nvsim_bg.wasm\",\n \"revision\": \"a617e7e24b2d5e976ce7e8d4f473104d\"\n },\n {\n \"url\": \"manifest.webmanifest\",\n \"revision\": \"e8c97968cae19a0ed3b64c1303a27a90\"\n }\n], {});\nworkbox_precaching_cleanupOutdatedCaches();\nworkbox_routing_registerRoute(new workbox_routing_NavigationRoute(workbox_precaching_createHandlerBoundToURL(\"index.html\")));\n\n\n\n\n\n\n"],"names":["self","skipWaiting","workbox_core_clientsClaim","workbox_precaching_precacheAndRoute","url","revision","workbox_precaching_cleanupOutdatedCaches","workbox","registerRoute","workbox_routing_NavigationRoute","NavigationRoute","workbox_precaching_createHandlerBoundToURL"],"mappings":"inBAwBAA,KAAKC,cAELC,EAAAA,eAQAC,EAAAA,iBAAoC,CAClC,CACEC,IAAO,gBACPC,SAAY,oCAEd,CACED,IAAO,aACPC,SAAY,oCAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,MAEd,CACED,IAAO,6BACPC,SAAY,MAEd,CACED,IAAO,yBACPC,SAAY,MAEd,CACED,IAAO,4BACPC,SAAY,MAEd,CACED,IAAO,2BACPC,SAAY,MAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,0BACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,qCAEb,CAAE,GACLC,EAAAA,wBAC6BC,EAAAC,cAAC,IAAIC,EAA+BC,gBAACC,0BAA2C"}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue