@zakodium/nmrium-core 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -538,9 +538,42 @@ export declare interface NMRiumPanelPreferences {
538
538
  }
539
539
 
540
540
  export declare interface NMRiumPlugin {
541
+ /**
542
+ * Unique identifier for the plugin across the plugins registered in the core.
543
+ *
544
+ * This should be a string in the format `<PackageName>#<PluginSymbol>`.
545
+ * The `<PackageName>` should be the name of the package that defines the plugin.
546
+ * The `<PluginSymbol>` could be a unique symbol that identifies the plugin and exported by the package.
547
+ * Or could be the name of the plugin, unrelated to any usable symbol.
548
+ */
541
549
  id: string;
550
+ /**
551
+ * Version of the plugin.
552
+ * Plugins must follow incremental versioning, like NMRium state versioning.
553
+ * The version should be incremented when a migration is needed.
554
+ */
542
555
  version: number;
556
+ /**
557
+ * Migrations are applied in ascending order
558
+ * and follow the `minCore` and `maxCore` conditions.
559
+ *
560
+ * Your migrations must be declared in ascending order.
561
+ * Your migrations must update the plugin version in the state.
562
+ * Your last migration must update the plugin version in the state to the current plugin version.
563
+ *
564
+ * For more information about how to write migrations
565
+ * @see `NMRiumPluginMigration.up`
566
+ */
543
567
  migrations: NMRiumPluginMigration[];
568
+ /**
569
+ * A configuration option to control if the plugin definition should be serialized into the state.
570
+ * Consider setting this option to true if the plugin is able to read or manipulate the state.
571
+ * If your plugin is `ui` only, you can set this false to avoid unnecessary serialization.
572
+ */
573
+ shouldSerialize: boolean;
574
+ /**
575
+ * Read hooks
576
+ */
544
577
  onReadProcess?: NMRiumPluginOnReadProcess;
545
578
  /**
546
579
  * UI components to render in nmrium components
@@ -588,8 +621,66 @@ export declare interface NMRiumPlugin {
588
621
  }
589
622
 
590
623
  export declare interface NMRiumPluginMigration {
624
+ /**
625
+ * Migration function.
626
+ *
627
+ * It is called during `core.migrate(state)` (used by some core read methods)
628
+ *
629
+ * You could mutate the state to apply the migration, but you must return it.
630
+ * If your migration returns nothing, the state will be lost, and it will break the core migration process.
631
+ * The process ensures to call the migration once (if needed).
632
+ * But you must update the plugin version in the state.
633
+ * /!\ the plugin may not exist yet in the state on firsts' migration.
634
+ *
635
+ * @param state - the nmrium state to migrate to the next version
636
+ * @returns the migrated nmrium state
637
+ *
638
+ * @example
639
+ *
640
+ * Your plugin was in version 1, and you have to update states to be compatible with version 2 of your plugin:
641
+ *
642
+ * ```ts
643
+ * const id = 'my-package#MyProcessingPlugin';
644
+ * defineNMRiumPlugin({
645
+ * id,
646
+ * version: 2,
647
+ * shouldSerialize: true,
648
+ * migrations: [
649
+ * {
650
+ * coreMin: 9,
651
+ * up(state: any): any {
652
+ * state.plugins[id] ??= { version: 1, id };
653
+ * state.plugins[id].version = 2;
654
+ *
655
+ * // mutate anything else in the state about your migration
656
+ *
657
+ * return state;
658
+ * },
659
+ * }
660
+ * ],
661
+ * onReadProcess: {
662
+ * onProcessing: (state, options) => {
663
+ * // process the state here
664
+ * },
665
+ * },
666
+ * });
667
+ * ```
668
+ */
591
669
  up(state: any): any;
670
+ /**
671
+ * Minimum core version supported to apply the migration.
672
+ * The lower nmrium core version supporting plugins is 9
673
+ * In doubt, put the current core version.
674
+ *
675
+ * @see CURRENT_EXPORT_VERSION
676
+ * @see NMRiumState.version
677
+ */
592
678
  minCore: number;
679
+ /**
680
+ * Maximum core version supported to apply the migration.
681
+ *
682
+ * @see NMRiumState.version
683
+ */
593
684
  maxCore?: number;
594
685
  }
595
686
 
@@ -638,10 +729,10 @@ export declare interface NmriumState {
638
729
  *
639
730
  * @example Minimal plugin declaration
640
731
  * ```ts
641
- * import type { NmriumStatePlugins, NmriumStateBasePlugin } from 'nmrium-core';
642
- *
643
- * export interface NmriumStatePlugins {
644
- * '@zakodium/nmrium-core-plugins#BrukerLoaderPlugin': NmriumStateBasePlugin;
732
+ * declare module '@zakodium/nmrium-core' {
733
+ * export interface NmriumStatePlugins {
734
+ * ['my-package#MyPlugin']?: NmriumStateBasePlugin & { config: object };
735
+ * }
645
736
  * }
646
737
  * ```
647
738
  */
@@ -1,4 +1,4 @@
1
- var ue={NORMAL:"NORMAL",FORMULA:"FORMULA"};var me={RELATIVE:"relative",ABSOLUTE:"absolute",MIN:"min",MAX:"max"};var fe=[{name:"pixels",unit:"px"},{name:"inches",unit:"in"},{name:"feet",unit:"ft"},{name:"yards",unit:"yd"},{name:"centimeters",unit:"cm"},{name:"millimeters",unit:"mm"},{name:"meters",unit:"m"},{name:"points",unit:"pt"},{name:"picas",unit:"pc"}];var P=9;var ge=[{key:"CT",description:"CT from NMR Solutions"}];import{isAnyArray as Se}from"is-any-array";import{xMultiply as j}from"ml-spectra-processing";var de=crypto.randomUUID.bind(crypto),b=de;function N(e){let{id:t=b(),meta:o,peaks:r={},filters:n=[],info:i={},ranges:p={},integrals:s={},selector:a,dependentVariables:l=[],...u}=e,c={id:t,meta:o,filters:n},{data:d=ye(l[0].components)}=e;if(Array.isArray(i.nucleus)&&(i.nucleus=i.nucleus[0]),c.data={x:[],re:[],im:[],...d},"scaleFactor"in i){let{scaleFactor:m}=i,{re:g,im:S}=c.data;j(g,m,{output:g}),S&&j(S,m,{output:S})}a&&(c.selector=a);let f=Se(d.im);if(c.info={phc0:0,phc1:0,nucleus:"1H",isFid:!1,isComplex:f,dimension:1,name:i?.name||t,...i},i.isFid&&i.reverse&&f){let{im:m}=c.data;j(m,-1,{output:m}),c.info.reverse=!1}return c.display={isVisible:!0,isPeaksMarkersVisible:!0,isRealSpectrumVisible:!0,isVisibleInDomain:!0,...e.display},c.peaks={values:[],options:{},...r},c.ranges={values:[],options:{sum:null,isSumConstant:!0,sumAuto:!0},...p},c.integrals={values:[],options:{},...s},{...u,...c}}function ye(e){let t=e[0]?.data?.x||[],o=e[0]?.data?.re||e[0]?.data?.y||[],r=e[0]?.data?.im||e[1]?.data?.y||null;return t.length>0&&t[0]>t[1]&&(t.reverse(),o.reverse(),r&&r.reverse()),{x:t,re:o,im:r}}import{matrixToArray as Pe,xMinMaxValues as xe,xNoiseSanPlot as be}from"ml-spectra-processing";var L={z:[[]],minX:0,minY:0,maxX:0,maxY:0},Ne={re:L,im:L},he={rr:L};function O(e){let{id:t=b(),meta:o={},dependentVariables:r=[],info:n={},filters:i=[],zones:p=[],...s}=e,a={id:t,meta:o,filters:i};a.info={nucleus:["1H","1H"],isFid:!1,isComplex:!1,name:n?.name||b(),...n},a.originalInfo=structuredClone(a.info),a.display={isPositiveVisible:!0,isNegativeVisible:!0,isVisible:!0,dimension:2,...e.display,...e.display};let{data:l=r[0].components}=e;if(a.data={...a.info.isFid?Ne:he,...l},a.originalData=structuredClone(a.data),!("spectrumSize"in n)){let u=n.isFid?"re":"rr",c=a.data[u].z.length,d=c>0?a.data[u].z[0].length:0;a.info.spectrumSize=[d,c]}if(!n.isFid){let u=a.data.rr,c=Pe(u.z),{positive:d,negative:f}=be(c),{min:m,max:g}=xe(c);a.data.rr={...u,minZ:m,maxZ:g},a.info.noise={positive:d,negative:f}}return a.zones={values:[],options:{},...p},{...s,...a}}import{xSequentialFillFromTo as Oe}from"ml-spectra-processing";import{isAnyArray as De}from"is-any-array";function U(e,t=0){if(De(e)){let o=e.at(t);if(o!==void 0)return o;throw new RangeError("An array with a index out of boundaries")}return e}var Re=new Set(["t1ir","T1"]);function J(e){let t=[];for(let o of e){let{info:{pulseSequence:r,isFid:n}}=o,{data:i,info:p,meta:{vdlistValues:s=[]}}=o;if(!(r&&Re.has(r))||s.length===0){t.push(o);continue}let l=n?"re":"rr",u={};for(let y in p)u[y]=U(p[y]);let{z:c,maxX:d,minX:f}=i[l],m=Oe({from:f,to:d,size:c[0].length}),[g,S]=Ie(o);for(let y=0;y<s.length;y++){let h={re:m,x:m};for(let D in i)h[Ce(D)]=i[D].z.at(g*(y+S));t.push(N({data:h,info:{...u,name:`${u.name}_${s[y]}`,dimension:1,vd:s[y]}}))}}return t}function Ce(e){return["rr","re"].includes(e)?"re":["im","ri","ir","ii"].includes(e)?"im":"x"}function Ie(e){let{meta:{PAGE:t}}=e,o=!0;if(t){let r=n=>Number.parseFloat(n.replace(/[F|T]1=/,""));o=r(t[0])>r(t[2])}return o?[-1,1]:[1,0]}var ve=2,Ae=1;function Te(e){let{spectra:t=[],molecules:o}=e,r=[];for(let n of t){let{info:i}=n;switch(i.dimension){case Ae:r.push(N(n));break;case ve:r.push(O(n));break;default:throw new Error("dimension does not supported")}}return{molecules:o,spectra:J(r)}}function we(e){return e}function R(e,t){e.plugins||(e.plugins={});let o=e.plugins;for(let r of t.values())o[r.id]||(o[r.id]={id:r.id,version:r.version}),o[r.id].id=r.id,o[r.id].version=r.version}function x(e,t){return JSON.parse(JSON.stringify(e),function(r,n){if(r in t){this[t[r]]=n;return}return n})}function V(e){if(e?.version===1)return e;let t={...e,version:1},o={j:"js",signal:"signals",integral:"integration",peak:"peaks",diaID:"diaIDs"};for(let r of t.spectra){if(r.ranges){let n=x(r.ranges,o);r.ranges=Array.isArray(n)?{values:n}:n}else if(r.zones){let n=x(r.zones,o);r.zones=Array.isArray(n)?{values:n}:n}r.peaks&&(r.peaks=Array.isArray(r.peaks)?{values:r.peaks}:r.peaks),r.integrals&&(r.integrals=Array.isArray(r.integrals)?{values:r.integrals}:r.integrals)}return t}function _(e){if(e?.version===2)return e;let t={...e,version:2},o={peaks:{delta:"x",originDelta:"originalX",intensity:"y"},ranges:{atomIDs:"atoms",intensity:"y"}};for(let r of t.spectra)r.peaks?r.peaks=x(r.peaks,o.peaks):r.ranges?r.ranges=x(r.ranges,o.ranges):r.zones&&(r.zones.values=Ee(r.zones.values));return t}function Ee(e){return e.map(t=>(t.signals&&(t.signals=t.signals.map(o=>{if(o.x&&o.y){let{x:{fromTo:r,...n},y:{fromTo:i,...p}}=o;o={...o,x:{...n,...r},y:{...p,...i}}}else{let{fromTo:r,deltaX:n,resolutionX:i,nucleusX:p,deltaY:s,resolutionY:a,nucleusY:l,shiftX:u,shiftY:c,...d}=o;o={...d,x:{from:r[0].from,to:r[0].to,delta:n,resolution:i,nucleus:p},y:{from:r[1].from,to:r[1].to,delta:s,resolution:a,nucleus:l}}}return o},[])),t),[])}var Me={name:"apodization",label:"Apodization",value:{lineBroadening:1,gaussBroadening:0,lineBroadeningCenter:0}};function z(e){if(e?.version===3)return e;let t={...e,version:3};for(let o of t.spectra)if(Array.isArray(o?.filters)&&o?.filters.length>0){let r=o.filters.findIndex(n=>n.name==="lineBroadening");if(r!==-1){let n={...o.filters[r],...Me};o.filters[r]=o.filters[r-1],o.filters[r-1]=n}}return t}function B(e){if(e?.version===4)return e;let{version:t,...o}=e,r=[],n={};for(let{source:s,...a}of o.spectra){let l={},{info:u={},display:c={}}=a;if(u?.dimension===2&&!s?.jcampURL)if(u.isFt)l.data={rr:a.data};else continue;if(s?.jcampURL){let{jcampURL:m,jcampSpectrumIndex:g}=s,S=m.match(/(?<baseURL>^\w+:\/{2}\w+\/)(?<relativePath>.*)/);n[m]||(n[m]={baseURL:S?.groups.baseURL||"",relativePath:S?.groups.relativePath||m.replace(/^\.\//,"")}),l.sourceSelector={files:[n[m].relativePath]},g!==void 0&&(l.sourceSelector.jcamp={index:g})}l.filters=Fe(a.filters);let{name:d,...f}=c;d&&(l.info={...u,name:d}),l.display=f,r.push({...a,...l})}let i={data:{...o,spectra:r},version:4},p={entries:Object.values(n)};return p.entries.length>0&&(i.data.source=p),i}function Fe(e=[]){let t=[];for(let o of e){let{name:r,value:n}=o;switch(r){case"zeroFilling":t.push({...o,value:{nbPoints:n}});break;case"shiftX":case"shift2DX":case"shift2DY":t.push({...o,value:{shift:n}});break;default:t.push({...o})}}return t}function K(e){if(e?.version===5)return e;let t={...e,version:5},o={originFrom:"originalFrom",originTo:"originalTo",originDelta:"originalDelta",originX:"originalX",originY:"originalY",originZ:"originalZ"};for(let r of t?.data?.spectra||[])for(let n of["peaks","ranges","zones"])r?.[n]&&(r[n]=x(r[n],o));return t}function X(e){if(e?.version===6)return e;let t={...e,version:6};for(let o of t?.data?.spectra||[]){let{digitalFilter:r,fft:n,phaseCorrection:i}=ke(o);n?.flag&&r?.flag&&i&&Math.floor(r.value.digitalFilterValue)%2>0&&(i.value.ph0-=180)}return t}function ke(e,t=["phaseCorrection","fft","digitalFilter"]){let{filters:o=[]}=e,r={};for(let n of t)r[n]=o.find(i=>i.name===n);return r}function C(e,t="localStorage"){if(e?.version===7)return e;if(t==="nmrium")return H(e);let o={...e,version:7};for(let r in e.workspaces)o.workspaces[r]=H(o.workspaces[r]);return o}function H(e){let{formatting:{nuclei:t,panels:o}={nuclei:null,panels:null},version:r,...n}=e,i={...n};return t&&(i.nuclei=je(t)),o&&(i.panels=o),i}function je(e){let t=[],o={name:"nucleus",ppm:"ppmFormat",hz:"hzFormat"};for(let r in e)t.push(x(e[r],o));return t}function Y(e){if(e?.version===7)return e;let t={...e,version:7};return t?.settings&&(t.settings=C(t.settings,"nmrium")),t}function I(e,t="localStorage"){if(e?.version===8)return e;if(t==="nmrium")return Q(e);let o={...e,version:8};for(let r in e.workspaces)o.workspaces[r]=Q(o.workspaces[r]);return o}function Q(e){let{version:t,...o}=e,r={...o};return r.display.panels=Le(e),r}function Le(e){let t={},o=e.display.panels;for(let r of Object.keys(o)){let{display:n,open:i}=o[r];t[r]={display:n,visible:n,open:i}}return t}function W(e){if(e?.version===8)return e;let t={...e,version:8};t?.settings&&(t.settings=I(t.settings,"nmrium"));for(let o of t?.data?.spectra||[]){let{filters:r=[]}=o;for(let s=0;s<r.length;s++){let{flag:a,isDeleteAllow:l,label:u,...c}=r[s];r[s]={...c,enabled:a}}let n=r.findIndex(s=>s.name==="apodization");if(n!==-1){let s=r[n],{lineBroadening:a,gaussBroadening:l,lineBroadeningCenter:u}=s.value;s.value={exponential:{apply:!0,options:{lineBroadening:l>0?-a:a}}},l>0&&(s.value.gaussian={apply:!0,options:{lineBroadening:.6*l,lineBroadeningCenter:u}}),r[n]=s}let i=r.findIndex(s=>s.name==="apodizationDimension1"),p=r.findIndex(s=>s.name==="apodizationDimension2");if(i!==-1){let s=r[i],{shapes:a}=s.value.compose;s.value=ee(a)}if(p!==-1){let s=r[p],{shapes:a}=s.value.compose;s.value=ee(a)}}return t}function ee(e){let t={};for(let{shape:o}of e){let{kind:r,options:n}=o;if(r==="sineBell"){let{exponent:i,offset:p}=n,s=i===2?"sineSquare":"sineBell";t[s]={apply:!0,options:{offset:p}}}}return t}function $(e){let{version:t,plugins:o,...r}=e;return t===9?e:{version:9,plugins:{},...r}}var Ue=[V,_,z,B,K,X,Y,W,$];function te(e,t,o){let r=structuredClone(e),n=Object.entries(e?.plugins??{});for(let[s,{version:a}]of n){let l=o.get(s);if(!(l&&l.version>=a)){if(l){console.warn(`Plugin "${l.id}" is loaded with a version older (${l.version}) than the one used to save the state (${a}).
1
+ var ue={NORMAL:"NORMAL",FORMULA:"FORMULA"};var me={RELATIVE:"relative",ABSOLUTE:"absolute",MIN:"min",MAX:"max"};var fe=[{name:"pixels",unit:"px"},{name:"inches",unit:"in"},{name:"feet",unit:"ft"},{name:"yards",unit:"yd"},{name:"centimeters",unit:"cm"},{name:"millimeters",unit:"mm"},{name:"meters",unit:"m"},{name:"points",unit:"pt"},{name:"picas",unit:"pc"}];var P=9;var ge=[{key:"CT",description:"CT from NMR Solutions"}];import{isAnyArray as Se}from"is-any-array";import{xMultiply as j}from"ml-spectra-processing";var de=crypto.randomUUID.bind(crypto),b=de;function N(e){let{id:t=b(),meta:o,peaks:r={},filters:n=[],info:i={},ranges:p={},integrals:s={},selector:a,dependentVariables:l=[],...u}=e,c={id:t,meta:o,filters:n},{data:d=ye(l[0].components)}=e;if(Array.isArray(i.nucleus)&&(i.nucleus=i.nucleus[0]),c.data={x:[],re:[],im:[],...d},"scaleFactor"in i){let{scaleFactor:m}=i,{re:g,im:S}=c.data;j(g,m,{output:g}),S&&j(S,m,{output:S})}a&&(c.selector=a);let f=Se(d.im);if(c.info={phc0:0,phc1:0,nucleus:"1H",isFid:!1,isComplex:f,dimension:1,name:i?.name||t,...i},i.isFid&&i.reverse&&f){let{im:m}=c.data;j(m,-1,{output:m}),c.info.reverse=!1}return c.display={isVisible:!0,isPeaksMarkersVisible:!0,isRealSpectrumVisible:!0,isVisibleInDomain:!0,...e.display},c.peaks={values:[],options:{},...r},c.ranges={values:[],options:{sum:null,isSumConstant:!0,sumAuto:!0},...p},c.integrals={values:[],options:{},...s},{...u,...c}}function ye(e){let t=e[0]?.data?.x||[],o=e[0]?.data?.re||e[0]?.data?.y||[],r=e[0]?.data?.im||e[1]?.data?.y||null;return t.length>0&&t[0]>t[1]&&(t.reverse(),o.reverse(),r&&r.reverse()),{x:t,re:o,im:r}}import{matrixToArray as Pe,xMinMaxValues as xe,xNoiseSanPlot as be}from"ml-spectra-processing";var L={z:[[]],minX:0,minY:0,maxX:0,maxY:0},Ne={re:L,im:L},he={rr:L};function O(e){let{id:t=b(),meta:o={},dependentVariables:r=[],info:n={},filters:i=[],zones:p=[],...s}=e,a={id:t,meta:o,filters:i};a.info={nucleus:["1H","1H"],isFid:!1,isComplex:!1,name:n?.name||b(),...n},a.originalInfo=structuredClone(a.info),a.display={isPositiveVisible:!0,isNegativeVisible:!0,isVisible:!0,dimension:2,...e.display,...e.display};let{data:l=r[0].components}=e;if(a.data={...a.info.isFid?Ne:he,...l},a.originalData=structuredClone(a.data),!("spectrumSize"in n)){let u=n.isFid?"re":"rr",c=a.data[u].z.length,d=c>0?a.data[u].z[0].length:0;a.info.spectrumSize=[d,c]}if(!n.isFid){let u=a.data.rr,c=Pe(u.z),{positive:d,negative:f}=be(c),{min:m,max:g}=xe(c);a.data.rr={...u,minZ:m,maxZ:g},a.info.noise={positive:d,negative:f}}return a.zones={values:[],options:{},...p},{...s,...a}}import{xSequentialFillFromTo as Oe}from"ml-spectra-processing";import{isAnyArray as De}from"is-any-array";function U(e,t=0){if(De(e)){let o=e.at(t);if(o!==void 0)return o;throw new RangeError("An array with a index out of boundaries")}return e}var Re=new Set(["t1ir","T1"]);function J(e){let t=[];for(let o of e){let{info:{pulseSequence:r,isFid:n}}=o,{data:i,info:p,meta:{vdlistValues:s=[]}}=o;if(!(r&&Re.has(r))||s.length===0){t.push(o);continue}let l=n?"re":"rr",u={};for(let y in p)u[y]=U(p[y]);let{z:c,maxX:d,minX:f}=i[l],m=Oe({from:f,to:d,size:c[0].length}),[g,S]=Ie(o);for(let y=0;y<s.length;y++){let h={re:m,x:m};for(let D in i)h[Ce(D)]=i[D].z.at(g*(y+S));t.push(N({data:h,info:{...u,name:`${u.name}_${s[y]}`,dimension:1,vd:s[y]}}))}}return t}function Ce(e){return["rr","re"].includes(e)?"re":["im","ri","ir","ii"].includes(e)?"im":"x"}function Ie(e){let{meta:{PAGE:t}}=e,o=!0;if(t){let r=n=>Number.parseFloat(n.replace(/[F|T]1=/,""));o=r(t[0])>r(t[2])}return o?[-1,1]:[1,0]}var ve=2,Ae=1;function Te(e){let{spectra:t=[],molecules:o}=e,r=[];for(let n of t){let{info:i}=n;switch(i.dimension){case Ae:r.push(N(n));break;case ve:r.push(O(n));break;default:throw new Error("dimension does not supported")}}return{molecules:o,spectra:J(r)}}function we(e){return e}function R(e,t){e.plugins||(e.plugins={});let o=e.plugins;for(let r of t.values()){if(!r.shouldSerialize){delete o[r.id];continue}o[r.id]||(o[r.id]={id:r.id,version:r.version}),o[r.id].id=r.id,o[r.id].version=r.version}}function x(e,t){return JSON.parse(JSON.stringify(e),function(r,n){if(r in t){this[t[r]]=n;return}return n})}function V(e){if(e?.version===1)return e;let t={...e,version:1},o={j:"js",signal:"signals",integral:"integration",peak:"peaks",diaID:"diaIDs"};for(let r of t.spectra){if(r.ranges){let n=x(r.ranges,o);r.ranges=Array.isArray(n)?{values:n}:n}else if(r.zones){let n=x(r.zones,o);r.zones=Array.isArray(n)?{values:n}:n}r.peaks&&(r.peaks=Array.isArray(r.peaks)?{values:r.peaks}:r.peaks),r.integrals&&(r.integrals=Array.isArray(r.integrals)?{values:r.integrals}:r.integrals)}return t}function _(e){if(e?.version===2)return e;let t={...e,version:2},o={peaks:{delta:"x",originDelta:"originalX",intensity:"y"},ranges:{atomIDs:"atoms",intensity:"y"}};for(let r of t.spectra)r.peaks?r.peaks=x(r.peaks,o.peaks):r.ranges?r.ranges=x(r.ranges,o.ranges):r.zones&&(r.zones.values=Ee(r.zones.values));return t}function Ee(e){return e.map(t=>(t.signals&&(t.signals=t.signals.map(o=>{if(o.x&&o.y){let{x:{fromTo:r,...n},y:{fromTo:i,...p}}=o;o={...o,x:{...n,...r},y:{...p,...i}}}else{let{fromTo:r,deltaX:n,resolutionX:i,nucleusX:p,deltaY:s,resolutionY:a,nucleusY:l,shiftX:u,shiftY:c,...d}=o;o={...d,x:{from:r[0].from,to:r[0].to,delta:n,resolution:i,nucleus:p},y:{from:r[1].from,to:r[1].to,delta:s,resolution:a,nucleus:l}}}return o},[])),t),[])}var Me={name:"apodization",label:"Apodization",value:{lineBroadening:1,gaussBroadening:0,lineBroadeningCenter:0}};function z(e){if(e?.version===3)return e;let t={...e,version:3};for(let o of t.spectra)if(Array.isArray(o?.filters)&&o?.filters.length>0){let r=o.filters.findIndex(n=>n.name==="lineBroadening");if(r!==-1){let n={...o.filters[r],...Me};o.filters[r]=o.filters[r-1],o.filters[r-1]=n}}return t}function B(e){if(e?.version===4)return e;let{version:t,...o}=e,r=[],n={};for(let{source:s,...a}of o.spectra){let l={},{info:u={},display:c={}}=a;if(u?.dimension===2&&!s?.jcampURL)if(u.isFt)l.data={rr:a.data};else continue;if(s?.jcampURL){let{jcampURL:m,jcampSpectrumIndex:g}=s,S=m.match(/(?<baseURL>^\w+:\/{2}\w+\/)(?<relativePath>.*)/);n[m]||(n[m]={baseURL:S?.groups.baseURL||"",relativePath:S?.groups.relativePath||m.replace(/^\.\//,"")}),l.sourceSelector={files:[n[m].relativePath]},g!==void 0&&(l.sourceSelector.jcamp={index:g})}l.filters=Fe(a.filters);let{name:d,...f}=c;d&&(l.info={...u,name:d}),l.display=f,r.push({...a,...l})}let i={data:{...o,spectra:r},version:4},p={entries:Object.values(n)};return p.entries.length>0&&(i.data.source=p),i}function Fe(e=[]){let t=[];for(let o of e){let{name:r,value:n}=o;switch(r){case"zeroFilling":t.push({...o,value:{nbPoints:n}});break;case"shiftX":case"shift2DX":case"shift2DY":t.push({...o,value:{shift:n}});break;default:t.push({...o})}}return t}function K(e){if(e?.version===5)return e;let t={...e,version:5},o={originFrom:"originalFrom",originTo:"originalTo",originDelta:"originalDelta",originX:"originalX",originY:"originalY",originZ:"originalZ"};for(let r of t?.data?.spectra||[])for(let n of["peaks","ranges","zones"])r?.[n]&&(r[n]=x(r[n],o));return t}function X(e){if(e?.version===6)return e;let t={...e,version:6};for(let o of t?.data?.spectra||[]){let{digitalFilter:r,fft:n,phaseCorrection:i}=ke(o);n?.flag&&r?.flag&&i&&Math.floor(r.value.digitalFilterValue)%2>0&&(i.value.ph0-=180)}return t}function ke(e,t=["phaseCorrection","fft","digitalFilter"]){let{filters:o=[]}=e,r={};for(let n of t)r[n]=o.find(i=>i.name===n);return r}function C(e,t="localStorage"){if(e?.version===7)return e;if(t==="nmrium")return H(e);let o={...e,version:7};for(let r in e.workspaces)o.workspaces[r]=H(o.workspaces[r]);return o}function H(e){let{formatting:{nuclei:t,panels:o}={nuclei:null,panels:null},version:r,...n}=e,i={...n};return t&&(i.nuclei=je(t)),o&&(i.panels=o),i}function je(e){let t=[],o={name:"nucleus",ppm:"ppmFormat",hz:"hzFormat"};for(let r in e)t.push(x(e[r],o));return t}function Y(e){if(e?.version===7)return e;let t={...e,version:7};return t?.settings&&(t.settings=C(t.settings,"nmrium")),t}function I(e,t="localStorage"){if(e?.version===8)return e;if(t==="nmrium")return Q(e);let o={...e,version:8};for(let r in e.workspaces)o.workspaces[r]=Q(o.workspaces[r]);return o}function Q(e){let{version:t,...o}=e,r={...o};return r.display.panels=Le(e),r}function Le(e){let t={},o=e.display.panels;for(let r of Object.keys(o)){let{display:n,open:i}=o[r];t[r]={display:n,visible:n,open:i}}return t}function W(e){if(e?.version===8)return e;let t={...e,version:8};t?.settings&&(t.settings=I(t.settings,"nmrium"));for(let o of t?.data?.spectra||[]){let{filters:r=[]}=o;for(let s=0;s<r.length;s++){let{flag:a,isDeleteAllow:l,label:u,...c}=r[s];r[s]={...c,enabled:a}}let n=r.findIndex(s=>s.name==="apodization");if(n!==-1){let s=r[n],{lineBroadening:a,gaussBroadening:l,lineBroadeningCenter:u}=s.value;s.value={exponential:{apply:!0,options:{lineBroadening:l>0?-a:a}}},l>0&&(s.value.gaussian={apply:!0,options:{lineBroadening:.6*l,lineBroadeningCenter:u}}),r[n]=s}let i=r.findIndex(s=>s.name==="apodizationDimension1"),p=r.findIndex(s=>s.name==="apodizationDimension2");if(i!==-1){let s=r[i],{shapes:a}=s.value.compose;s.value=ee(a)}if(p!==-1){let s=r[p],{shapes:a}=s.value.compose;s.value=ee(a)}}return t}function ee(e){let t={};for(let{shape:o}of e){let{kind:r,options:n}=o;if(r==="sineBell"){let{exponent:i,offset:p}=n,s=i===2?"sineSquare":"sineBell";t[s]={apply:!0,options:{offset:p}}}}return t}function $(e){let{version:t,plugins:o,...r}=e;return t===9?e:{version:9,plugins:{},...r}}var Ue=[V,_,z,B,K,X,Y,W,$];function te(e,t,o){let r=structuredClone(e),n=Object.entries(e?.plugins??{});for(let[s,{version:a}]of n){let l=o.get(s);if(!(l&&l.version>=a)){if(l){console.warn(`Plugin "${l.id}" is loaded with a version older (${l.version}) than the one used to save the state (${a}).
2
2
  NMRium may fail to load the state.
3
3
  Please update the plugin to the latest version.`);continue}console.warn(`Plugin "${s}@${a}" is not registered. NMRium may fail to load the state.
4
4
  Please consider open this file with the plugin installed.`)}}let i=new Set,p=()=>{let s=r.version;for(let a of o.values())for(let l of a.migrations){if(i.has(l)||s<l.minCore||l.maxCore&&s>l.maxCore)continue;if((r.plugins?.[a.id]?.version||0)===a.version)break;r=l.up(r),i.add(l)}};for(let s=e?.version||0;s<t;s++){let a=Ue[s];r=a(r),p()}return p(),R(r,o),r}import{FileCollection as $e}from"file-collection";var re={SDF:"sdf",MOL:"mol",NMRIUM:"nmrium",JSON:"json",JCAMP:"jcamp",DX:"dx",JDX:"jdx",JDF:"jdf",NMREDATA:"nmredata",SMILES:"smiles",SMI:"smi"};function v(e){return e.includes(".")?e.replace(/^.*\./,"").toLowerCase():""}function T(e,t={},o){let{data:r,...n}=e;if(!r)return e;let{spectra:i=[]}=r,{keep1D:p=!0,keep2D:s=!0,onlyReal:a}=t,l=a?"ft":t.dataSelection||"both",u=[];for(let c of i){if(!c.info){u.push(c);continue}let{isFid:d,dimension:f,name:m}=c.info;if(!A(f===1&&!p,m,o)&&!A(f===2&&!s,m,o)&&!A(d&&l==="ft",m,o)&&!A(!d&&l==="fid",m,o))if(a&&!d)if(c.info.isComplex=!1,Ve(c)){let{rr:g}=c.data;u.push({...c,data:{rr:g}})}else{let{re:g,x:S}=c.data;u.push({...c,data:{re:g,x:S}})}else u.push(c)}return{data:{...r,spectra:u},...n}}function A(e,t,o){return e?(o?.warn(`Skipping ${t} because it didn't match the import filters.`),!0):!1}function Ve(e){let{info:t}=e;return t?.dimension===2}function w(e){let{nmriumState:t,plugins:o,options:r}=e;for(let n of o.values()){let i=n.onReadProcess?.onProcessing;i&&i(t,r)}}async function E(e,t,o={}){let{sourceSelector:r,converter:n,keepSource:i,logger:p}=o,s=[],a=[];for(let f of t.values()){let{onReadProcess:m}=f;m&&(m?.onFiles&&s.push(f),m?.supportedExtensions?.length&&m?.onFile&&a.push(f))}let l=await Promise.allSettled(s.map(f=>f.onReadProcess.onFiles(e,o))),u=[],c=await Promise.allSettled(e.files.flatMap(f=>{let m=v(f.name).toLowerCase();return a.flatMap(g=>{let{supportedExtensions:S,onFile:y}=g.onReadProcess;return S.includes(m)?(u.push({file:f,plugin:g}),y(f,{logger:p,sourceSelector:r,converter:n,keepSource:i})):[]})})),d={spectra:[],molecules:[]};for(let f=0;f<l.length;f++){let m=l[f];switch(m.status){case"fulfilled":{let{spectra:g=[],molecules:S=[]}=m.value||{};d.spectra.push(...g),d.molecules.push(...S);break}case"rejected":{let g=m.reason,S=s[f];o.logger?.error(`Load file collection with plugin ${S.id}@${S.version} fails with: ${g}`);break}}}for(let f=0;f<c.length;f++){let m=c[f];switch(m.status){case"fulfilled":{let{spectra:g=[],molecules:S=[]}=m.value||{};d.spectra.push(...g),d.molecules.push(...S);break}case"rejected":{let g=m.reason,{file:S,plugin:y}=u[f];o.logger?.error(`Load file ${S.relativePath} with plugin ${y.id}@${y.version} fails with: ${g}`);break}}}return d}import{FileCollection as Xe}from"file-collection";import{FileCollection as _e}from"file-collection";import oe from"lodash.merge";import{xIsEquallySpaced as ze}from"ml-spectra-processing";async function M(e){let{nmriumObjectInput:t,options:o={},migrator:r,plugins:n}=e,i=r(t),{data:p,...s}=i;if(!p)return{...s};let a={data:{...p,spectra:[]},...s},l=a.data,{source:u,spectra:c,molecules:d}=l,f;u&&(f=await _e.fromSource(u,{unzip:{zipExtensions:["zip","nmredata"]}}));let m=[];for(let g of p.spectra)if(f){let{sourceSelector:S}=g,y=F({input:f,migrator:r,plugins:n,options:{...o,sourceSelector:S}}).then(h=>{let{nmriumState:{data:D}}=h,{spectra:pe=[],molecules:q=[]}=D||{};q.length>0&&d.length===0&&d.push(...q);for(let ce of pe)c.push(Be(g,Ke(ce)))});m.push(y)}else{let{dimension:S}=g.info;if(S===1){if(!ze(g.data)){o.logger?.error('The ".nmrium" file is corrupted; the X-axis values are not equally distant.');continue}c.push(N(g))}else S===2&&c.push(O(g))}return await Promise.allSettled(m),a}function Be(e,t){let{data:o,...r}=e;if("ranges"in t){let{data:n,...i}=t;return{...oe(i,r),data:n}}else if("zones"in t){let{data:n,...i}=t;return{...oe(i,r),data:n}}else return t}function Ke(e){return{...e,id:b()}}async function ne(e){let{file:t,options:o={},migrator:r,plugins:n}=e,i=await t.arrayBuffer(),p=await(We(i)?Ye(i):t.text());return M({nmriumObjectInput:JSON.parse(p),plugins:n,migrator:r,options:o})}async function Ye(e){let t=await Xe.fromZip(e);if(t.files.length===0)throw new Error("compressed nmrium file is corrupted");return t.files[0].text()}function We(e){if(e.byteLength<4)return!1;let t=new Uint8Array(e);return t[0]===80&&t[1]===75&&(t[2]===3||t[2]===5||t[2]===7)&&(t[3]===4||t[3]===6||t[3]===8)}async function F(e){let{options:t={},input:o,migrator:r,plugins:n}=e,i=qe(await Ge(o),t.sourceSelector?.files),p=Je(i);if(p)return{nmriumState:await ne({file:p,migrator:r,plugins:n,options:t}),containsNmrium:!0};let s=await E(i,n,t),a=T({version:9,data:s},t?.sourceSelector?.general,t.logger),{onLoadProcessing:l,experimentalFeatures:u}=t,c={...l,autoProcessing:l?.autoProcessing??!1,experimentalFeatures:u};return w({nmriumState:a,plugins:n,options:c}),{nmriumState:a,containsNmrium:!1}}function Ge(e){return Array.isArray(e)?Promise.reject(new Error("For a set of fileCollectionItems pass a FileCollection instance")):Ze(e)?Promise.resolve(e):new $e().appendExtendedSource({...e,uuid:crypto.randomUUID()})}function Ze(e){return typeof e=="object"&&"files"in e}function qe(e,t){if(!t)return e;let o=new Set(t);return e.filter(r=>o.has(r.relativePath))}function Je(e){return e.files.find(t=>v(t.name).toLowerCase()===re.NMRIUM)}function k(e,t){let o={};for(let r in e)t.includes(r)||(o[r]=e[r]);return o}var He=["data","originalData","info","originalInfo","meta","customInfo"],Qe=["sourceSelector","originalData","originalInfo"];function ie(e,t,o={}){let{version:r,data:n}=e;if(n.actionType)return e;let i={version:r,plugins:e.plugins},{includeData:p}=o;p!=="noData"&&(i.data=et({...n},p));let{includeSettings:s,includeView:a}=o;return s&&(i.settings=e.settings),a&&(i.view=e.view),R(i,t),i}function et(e,t="rawData"){let{spectra:o}=e;switch(t){case"dataSource":return tt(e);case"rawData":return{...k(e,["source"]),spectra:o.map(ot)};default:return e}}function tt(e){let{spectra:t}=e;if(!e.source)throw new Error("source property should exists for dataSource serialization");return{...e,spectra:t.map(rt)}}function rt(e){return k(e,He)}function ot(e){let{data:t,info:o,originalData:r,originalInfo:n}=e,i=k(e,Qe);return i.data=r||t,i.info=n||o,i}var nt=["topbar.right","topbar.about_us.modal"],it=[],qr=[...nt,...it],st={},G={};{let e=st,t=G;for(let[o,r]of Object.entries(e))t[r]||(t[r]=[]),t[r]?.push(o)}function*se(e){let{slot:t,plugins:o,supportedToDeprecatedSlots:r=G}=e,n=r[t];for(let[i,p]of o.entries()){let s=p.ui;if(!s)continue;let a=s[t];if(a){yield[i,a];continue}if(n)for(let l of n){let u=p.ui?.[l];if(u){yield[i,u],console.warn(`Plugin ${p.id} used deprecated slot "${l}". Please update this plugin to use "${t}" instead.`);break}}}}import{FileCollection as at}from"file-collection";async function ae(e){let{source:t,plugins:o,options:r={}}=e,{keepSource:n=!0,converter:i,...p}=r,s={source:t,spectra:[],molecules:[]},a=await at.fromSource(t,{unzip:{zipExtensions:["zip","nmredata"]}}),{spectra:l=[],molecules:u=[]}=await E(a,o,{keepSource:n,converter:{...i,bruker:{keepFiles:!0,...Reflect.get(i??{},"bruker")}},...p});s.spectra.push(...l),s.molecules.push(...u);let c=T({version:9,data:s},r?.sourceSelector?.general),{onLoadProcessing:d}=p,f={filters:d?.filters,autoProcessing:d?.autoProcessing??!1,experimentalFeatures:r.experimentalFeatures};return w({nmriumState:c,plugins:o,options:f}),c}var Z=class{version=9;#e=new Map;registerPlugin(t){if(this.#e.has(t.id)){console.warn(`Plugin ${t.id} is already registered. skip.`),console.debug("Plugin already registered:",this.#e.get(t.id)),console.debug("Plugin to register:",t);return}this.#e.set(t.id,t)}registerPlugins(t){for(let o of t)this.registerPlugin(o)}migrate(t){return te(t,this.version,this.#e)}read(t,o={}){return F({input:t,migrator:this.migrate.bind(this),plugins:this.#e,options:o})}readNMRiumObject(t,o){return M({nmriumObjectInput:t,options:o,plugins:this.#e,migrator:this.migrate.bind(this)})}readFromWebSource(t,o){return ae({source:t,options:o,plugins:this.#e})}serializeNmriumState(t,o){return ie(t,this.#e,o)}slot(t){return se({slot:t,plugins:this.#e})}};function lt(e,t){if(t>9)return 0;let o=-1;for(let r=0;r<e.length;r++)if(e[r].version>t){o=r;break}return o}var le=[{version:6,fun:C},{version:7,fun:I}];function pt(e){let{version:t}=e||{},o=lt(le,t);if(o===-1)return{...e,version:9};let r=le.slice(o);for(let n of r)e=n.fun(e);return e}export{ue as ANALYSIS_COLUMN_TYPES,me as ANALYSIS_COLUMN_VALUES_KEYS,P as CURRENT_EXPORT_VERSION,ge as EXTERNAL_API_KEYS,Z as NMRiumCore,we as defineNMRiumPlugin,Te as formatSpectra,b as generateID,U as getOneIfArray,pt as migrateSettings,fe as units};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zakodium/nmrium-core",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "The core of NMRium: types, state, state migration and plugin system.",
5
5
  "author": "Zakodium Sàrl",
6
6
  "license": "CC-BY-NC-SA-4.0",
@@ -24,12 +24,13 @@
24
24
  },
25
25
  "devDependencies": {
26
26
  "@types/lodash.merge": "^4.6.9",
27
- "@types/node": "^24.5.2",
27
+ "@types/node": "^24.7.2",
28
28
  "@types/react": "^18.3.13",
29
- "@zakodium/nmr-types": "^0.2.0",
29
+ "@zakodium/nmr-types": "^0.2.1",
30
30
  "esbuild": "^0.25.10",
31
31
  "jest-matcher-deep-close-to": "^3.0.2",
32
32
  "rimraf": "^6.0.1",
33
+ "typescript": "~5.9.3",
33
34
  "vitest": "^3.2.4"
34
35
  },
35
36
  "dependencies": {
@@ -44,5 +45,5 @@
44
45
  "volta": {
45
46
  "extends": "../../../package.json"
46
47
  },
47
- "gitHead": "3ae265679edc9e722d29dc66f3338d9fb8ab2062"
48
+ "gitHead": "590a8e4b1d464902733151fcefa7c9a739fddccf"
48
49
  }