@zakodium/nmrium-core 0.1.3 → 0.1.5

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.
package/README.md CHANGED
@@ -31,14 +31,14 @@ It contains the following features:
31
31
  ## Usage
32
32
 
33
33
  ```js
34
- import { fileCollectionFromPath } from 'filelist-utils';
34
+ import { FileCollection } from 'file-collection';
35
35
  import { NMRiumCore } from '@zakodium/nmrium-core';
36
36
  import plugins from '@zakodium/nmrium-core-plugins';
37
37
 
38
38
  const core = new NMRiumCore();
39
39
  core.registerPlugins(plugins);
40
40
 
41
- const fileCollection = fileCollectionFromPath('path_to_data');
41
+ const fileCollection = FileCollection.fromPath('path_to_data');
42
42
  // we can read a zip, jdx, jdf, nmredata, json, nmrium file extensions
43
43
  const result = await core.read(fileCollection, options);
44
44
 
@@ -1,7 +1,7 @@
1
1
  import type { CorrelationData } from 'nmr-correlation';
2
2
  import type { FifoLoggerOptions } from 'fifo-logger';
3
- import { FileCollection } from 'filelist-utils';
4
- import type { FileCollectionItem } from 'filelist-utils';
3
+ import { FileCollection } from 'file-collection';
4
+ import type { FileItem } from 'file-collection';
5
5
  import type { Filter1DEntry } from '@zakodium/nmr-types';
6
6
  import type { Filter1DOptions } from '@zakodium/nmr-types';
7
7
  import type { Filter2DEntry } from '@zakodium/nmr-types';
@@ -15,8 +15,9 @@ import type { NmrData1D } from 'cheminfo-types';
15
15
  import type { NmrData2D } from 'cheminfo-types';
16
16
  import type { Peaks } from '@zakodium/nmr-types';
17
17
  import type { Ranges } from '@zakodium/nmr-types';
18
+ import type { ReactNode } from 'react';
18
19
  import { SerializedNmriumState } from './core_serialize.js';
19
- import type { WebSource } from 'filelist-utils';
20
+ import type { Source } from 'file-collection';
20
21
  import type { Zones } from '@zakodium/nmr-types';
21
22
 
22
23
  export declare interface ActiveSpectrum {
@@ -32,6 +33,13 @@ export declare interface AdvanceExportSettings extends BaseExportSettings {
32
33
  unit: Unit;
33
34
  }
34
35
 
36
+ /**
37
+ * Used by plugins to register UI slots.
38
+ */
39
+ export declare const ALLOWED_UI_SLOTS: readonly ["topbar.right"];
40
+
41
+ export declare type AllowedUISlot = (typeof ALLOWED_UI_SLOTS)[number];
42
+
35
43
  export declare const ANALYSIS_COLUMN_TYPES: {
36
44
  NORMAL: string;
37
45
  FORMULA: string;
@@ -199,6 +207,18 @@ export declare type DeepPartial<T> = {
199
207
  [P in keyof T]?: DeepPartial<T[P]>;
200
208
  };
201
209
 
210
+ /**
211
+ * Used by core to mark a slot as deprecated.
212
+ */
213
+ export declare const DEPRECATED_UI_SLOTS: readonly [];
214
+
215
+ /**
216
+ * Used by core to map deprecated UI slots to supported UI slots.
217
+ */
218
+ export declare const DEPRECATED_UI_TO_SUPPORTED_UI_SLOTS: Record<DeprecatedUISlot, SupportedUISlot>;
219
+
220
+ export declare type DeprecatedUISlot = (typeof DEPRECATED_UI_SLOTS)[number];
221
+
202
222
  declare interface Display {
203
223
  isVisible: boolean;
204
224
  }
@@ -420,20 +440,21 @@ export declare class NMRiumCore {
420
440
  registerPlugin(plugin: NMRiumPlugin): void;
421
441
  registerPlugins(plugins: NMRiumPlugin[]): void;
422
442
  private migrate;
423
- read(input: FileCollection | FileCollectionItem, options?: Partial<ParsingOptions>): ReturnType<typeof read>;
443
+ read(input: FileCollection | FileItem, options?: Partial<ParsingOptions>): ReturnType<typeof read>;
424
444
  readNMRiumObject(nmriumObjectInput: object, options?: ParsingOptions): Promise<Partial<NmriumState>>;
425
- readFromWebSource(source: WebSource, options?: ParsingOptions): Promise<Partial<NmriumState>>;
445
+ readFromWebSource(source: Source, options?: ParsingOptions): Promise<Partial<NmriumState>>;
426
446
  serializeNmriumState(nmriumState: NmriumState, options?: SerializeNmriumStateOptions): SerializedNmriumState;
447
+ slot(slot: SupportedUISlot): IteratorObject<[pluginId: string, Component: PluginUIComponent], void>;
427
448
  }
428
449
 
429
450
  export declare interface NmriumData extends BaseNmriumData {
430
451
  spectra: Spectrum[];
431
- source?: WebSource;
452
+ source?: Source;
432
453
  }
433
454
 
434
455
  export declare interface NmriumDataSource extends BaseNmriumData {
435
456
  spectra: SpectraSource[];
436
- source: WebSource;
457
+ source: Source;
437
458
  }
438
459
 
439
460
  export declare interface NMRiumGeneralPreferences {
@@ -470,6 +491,49 @@ export declare interface NMRiumPlugin {
470
491
  version: number;
471
492
  migrations: NMRiumPluginMigration[];
472
493
  onReadProcess?: NMRiumPluginOnReadProcess;
494
+ /**
495
+ * UI components to render in nmrium components
496
+ *
497
+ * @example
498
+ * ```tsx
499
+ * const MyPluginContext = createContext();
500
+ *
501
+ * function MyPluginProvider({children}) {
502
+ * const api = useMemo(() => ({ saveAction: () => console.log('save') }), []);
503
+ *
504
+ * return (
505
+ * <MyPluginContext.Provider value={api}>
506
+ * {children}
507
+ * </MyPluginContext.Provider>
508
+ * )
509
+ * }
510
+ *
511
+ * function MyPluginTopBar() {
512
+ * const ctx = useContext(MyPluginContext);
513
+ *
514
+ * return (
515
+ * <Button onClick={ctx.saveAction}>Save (My Plugin)</Button>
516
+ * )
517
+ * }
518
+ *
519
+ * const core = init();
520
+ * core.registerPlugin({
521
+ * id: 'my-plugin',
522
+ * version: 1,
523
+ * migrations: [],
524
+ * ui: {
525
+ * 'topbar.right': MyPluginTopBar,
526
+ * },
527
+ * });
528
+ *
529
+ * createRoot(document.getElementById('root')).render(
530
+ * <MyPluginProvider>
531
+ * <NMRium core={core} />
532
+ * </MyPluginProvider>
533
+ * );
534
+ * ```
535
+ * */
536
+ ui?: PluginUIComponentRegistry;
473
537
  }
474
538
 
475
539
  export declare interface NMRiumPluginMigration {
@@ -498,7 +562,7 @@ export declare interface NMRiumPluginOnReadProcess {
498
562
  * @param file
499
563
  * @param options
500
564
  */
501
- onFile?: (file: FileCollectionItem, options?: ParsingOptions) => Promise<NmriumData>;
565
+ onFile?: (file: FileItem, options?: ParsingOptions) => Promise<NmriumData>;
502
566
  /**
503
567
  * Hooks on processFileCollection, in last steps, after fully load data.
504
568
  * Filter data, apply processing, etc.
@@ -671,6 +735,18 @@ export declare interface PeaksViewState {
671
735
  displayingMode: 'spread' | 'single';
672
736
  }
673
737
 
738
+ export declare type PluginUIComponent = (props: PluginUIComponentProps) => ReactNode;
739
+
740
+ export declare type PluginUIComponentProps = PluginUIComponentTopBarRightProps;
741
+
742
+ export declare type PluginUIComponentRegistry = Partial<Record<AllowedUISlot, PluginUIComponent>>;
743
+
744
+ export declare interface PluginUIComponentSlotProps<Slot extends AllowedUISlot> {
745
+ slot: Slot;
746
+ }
747
+
748
+ export declare type PluginUIComponentTopBarRightProps = PluginUIComponentSlotProps<'topbar.right'>;
749
+
674
750
  declare type PosibleInput = string | number | boolean;
675
751
 
676
752
  declare type PredefinedLegend = 'intensity' | 'name';
@@ -806,7 +882,7 @@ export declare interface RangesViewState {
806
882
  declare function read(_options: ReadOptions): Promise<ReadReturn>;
807
883
 
808
884
  declare interface ReadOptions {
809
- input: FileCollection | FileCollectionItem;
885
+ input: FileCollection | FileItem;
810
886
  migrator: (state: object) => any;
811
887
  plugins: Map<string, NMRiumPlugin>;
812
888
  options?: ParsingOptions;
@@ -944,6 +1020,21 @@ export declare interface SumOptions {
944
1020
  moleculeId?: string;
945
1021
  }
946
1022
 
1023
+ /**
1024
+ * Used by nmrium components to render plugin ui components
1025
+ * Naming convention is `snake_case.scope.slot_name`.
1026
+ * Constraint to doesn't break camelCase when declaring slot in plugin ui props:
1027
+ * do not use single `top_level_scope` (no dot, no underscore).
1028
+ */
1029
+ export declare const SUPPORTED_UI_SLOTS: readonly ["topbar.right"];
1030
+
1031
+ /**
1032
+ * Cache inverted relationship between deprecated and supported.
1033
+ */
1034
+ export declare const SUPPORTED_UI_TO_DEPRECATED_UI_SLOTS: Partial<Record<SupportedUISlot, DeprecatedUISlot[]>>;
1035
+
1036
+ export declare type SupportedUISlot = (typeof SUPPORTED_UI_SLOTS)[number];
1037
+
947
1038
  export declare type Unit = UnitElement['unit'];
948
1039
 
949
1040
  declare type UnitElement = (typeof units)[number];
@@ -1,4 +1,4 @@
1
- var le={NORMAL:"NORMAL",FORMULA:"FORMULA"};var ce={RELATIVE:"relative",ABSOLUTE:"absolute",MIN:"min",MAX:"max"};var ue=[{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 pe=[{key:"CT",description:"CT from NMR Solutions"}];import{isAnyArray as fe}from"is-any-array";import{xMultiply as I}from"ml-spectra-processing";var me=crypto.randomUUID.bind(crypto),b=me;function N(e){let{id:t=b(),meta:n,peaks:r={},filters:o=[],info:s={},ranges:u={},integrals:i={},selector:a,dependentVariables:c=[],...f}=e,l={id:t,meta:n,filters:o},{data:d=ge(c[0].components)}=e;if(Array.isArray(s.nucleus)&&(s.nucleus=s.nucleus[0]),l.data={x:[],re:[],im:[],...d},"scaleFactor"in s){let{scaleFactor:p}=s,{re:g,im:y}=l.data;I(g,p,{output:g}),y&&I(y,p,{output:y})}a&&(l.selector=a);let m=fe(d.im);if(l.info={phc0:0,phc1:0,nucleus:"1H",isFid:!1,isComplex:m,dimension:1,name:s?.name||t,...s},s.isFid&&s.reverse&&m){let{im:p}=l.data;I(p,-1,{output:p}),l.info.reverse=!1}return l.display={isVisible:!0,isPeaksMarkersVisible:!0,isRealSpectrumVisible:!0,isVisibleInDomain:!0,...e.display},l.peaks={values:[],options:{},...r},l.ranges={values:[],options:{sum:null,isSumConstant:!0,sumAuto:!0},...u},l.integrals={values:[],options:{},...i},{...f,...l}}function ge(e){let t=e[0]?.data?.x||[],n=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(),n.reverse(),r&&r.reverse()),{x:t,re:n,im:r}}import{matrixToArray as de,xMinMaxValues as ye,xNoiseSanPlot as Se}from"ml-spectra-processing";var j={z:[[]],minX:0,minY:0,maxX:0,maxY:0},Pe={re:j,im:j},xe={rr:j};function O(e){let{id:t=b(),meta:n={},dependentVariables:r=[],info:o={},filters:s=[],zones:u=[],...i}=e,a={id:t,meta:n,filters:s};a.info={nucleus:["1H","1H"],isFid:!1,isComplex:!1,name:o?.name||b(),...o},a.originalInfo=structuredClone(a.info),a.display={isPositiveVisible:!0,isNegativeVisible:!0,isVisible:!0,dimension:2,...e.display,...e.display};let{data:c=r[0].components}=e;if(a.data={...a.info.isFid?Pe:xe,...c},a.originalData=structuredClone(a.data),!("spectrumSize"in o)){let f=o.isFid?"re":"rr",l=a.data[f].z.length,d=l>0?a.data[f].z[0].length:0;a.info.spectrumSize=[d,l]}if(!o.isFid){let f=a.data.rr,l=de(f.z),{positive:d,negative:m}=Se(l),{min:p,max:g}=ye(l);a.data.rr={...f,minZ:p,maxZ:g},a.info.noise={positive:d,negative:m}}return a.zones={values:[],options:{},...u},{...i,...a}}import{xSequentialFillFromTo as Ne}from"ml-spectra-processing";import{isAnyArray as be}from"is-any-array";function L(e,t=0){if(be(e)){let n=e.at(t);if(n!==void 0)return n;throw new RangeError("An array with a index out of boundaries")}return e}var he=new Set(["t1ir","T1"]);function $(e){let t=[];for(let n of e){let{info:{pulseSequence:r,isFid:o}}=n,{data:s,info:u,meta:{vdlistValues:i=[]}}=n;if(!(r&&he.has(r))||i.length===0){t.push(n);continue}let c=o?"re":"rr",f={};for(let S in u)f[S]=L(u[S]);let{z:l,maxX:d,minX:m}=s[c],p=Ne({from:m,to:d,size:l[0].length}),[g,y]=Oe(n);for(let S=0;S<i.length;S++){let h={re:p,x:p};for(let D in s)h[De(D)]=s[D].z.at(g*(S+y));t.push(N({data:h,info:{...f,name:`${f.name}_${i[S]}`,dimension:1,vd:i[S]}}))}}return t}function De(e){return["rr","re"].includes(e)?"re":["im","ri","ir","ii"].includes(e)?"im":"x"}function Oe(e){let{meta:{PAGE:t}}=e,n=!0;if(t){let r=o=>Number.parseFloat(o.replace(/[F|T]1=/,""));n=r(t[0])>r(t[2])}return n?[-1,1]:[1,0]}var Re=2,ve=1;function Ce(e){let{spectra:t=[],molecules:n}=e,r=[];for(let o of t){let{info:s}=o;switch(s.dimension){case ve:r.push(N(o));break;case Re:r.push(O(o));break;default:throw new Error("dimension does not supported")}}return{molecules:n,spectra:$(r)}}function x(e,t){return JSON.parse(JSON.stringify(e),function(r,o){if(r in t){this[t[r]]=o;return}return o})}function V(e){if(e?.version===1)return e;let t={...e,version:1},n={j:"js",signal:"signals",integral:"integration",peak:"peaks",diaID:"diaIDs"};for(let r of t.spectra){if(r.ranges){let o=x(r.ranges,n);r.ranges=Array.isArray(o)?{values:o}:o}else if(r.zones){let o=x(r.zones,n);r.zones=Array.isArray(o)?{values:o}:o}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 z(e){if(e?.version===2)return e;let t={...e,version:2},n={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,n.peaks):r.ranges?r.ranges=x(r.ranges,n.ranges):r.zones&&(r.zones.values=we(r.zones.values));return t}function we(e){return e.map(t=>(t.signals&&(t.signals=t.signals.map(n=>{if(n.x&&n.y){let{x:{fromTo:r,...o},y:{fromTo:s,...u}}=n;n={...n,x:{...o,...r},y:{...u,...s}}}else{let{fromTo:r,deltaX:o,resolutionX:s,nucleusX:u,deltaY:i,resolutionY:a,nucleusY:c,shiftX:f,shiftY:l,...d}=n;n={...d,x:{from:r[0].from,to:r[0].to,delta:o,resolution:s,nucleus:u},y:{from:r[1].from,to:r[1].to,delta:i,resolution:a,nucleus:c}}}return n},[])),t),[])}var Fe={name:"apodization",label:"Apodization",value:{lineBroadening:1,gaussBroadening:0,lineBroadeningCenter:0}};function B(e){if(e?.version===3)return e;let t={...e,version:3};for(let n of t.spectra)if(Array.isArray(n?.filters)&&n?.filters.length>0){let r=n.filters.findIndex(o=>o.name==="lineBroadening");if(r!==-1){let o={...n.filters[r],...Fe};n.filters[r]=n.filters[r-1],n.filters[r-1]=o}}return t}function _(e){if(e?.version===4)return e;let{version:t,...n}=e,r=[],o={};for(let{source:i,...a}of n.spectra){let c={},{info:f={},display:l={}}=a;if(f?.dimension===2&&!i?.jcampURL)if(f.isFt)c.data={rr:a.data};else continue;if(i?.jcampURL){let{jcampURL:p,jcampSpectrumIndex:g}=i,y=p.match(/(?<baseURL>^\w+:\/{2}\w+\/)(?<relativePath>.*)/);o[p]||(o[p]={baseURL:y?.groups.baseURL||"",relativePath:y?.groups.relativePath||p.replace(/^\.\//,"")}),c.sourceSelector={files:[o[p].relativePath]},g!==void 0&&(c.sourceSelector.jcamp={index:g})}c.filters=Ae(a.filters);let{name:d,...m}=l;d&&(c.info={...f,name:d}),c.display=m,r.push({...a,...c})}let s={data:{...n,spectra:r},version:4},u={entries:Object.values(o)};return u.entries.length>0&&(s.data.source=u),s}function Ae(e=[]){let t=[];for(let n of e){let{name:r,value:o}=n;switch(r){case"zeroFilling":t.push({...n,value:{nbPoints:o}});break;case"shiftX":case"shift2DX":case"shift2DY":t.push({...n,value:{shift:o}});break;default:t.push({...n})}}return t}function U(e){if(e?.version===5)return e;let t={...e,version:5},n={originFrom:"originalFrom",originTo:"originalTo",originDelta:"originalDelta",originX:"originalX",originY:"originalY",originZ:"originalZ"};for(let r of t?.data?.spectra||[])for(let o of["peaks","ranges","zones"])r?.[o]&&(r[o]=x(r[o],n));return t}function K(e){if(e?.version===6)return e;let t={...e,version:6};for(let n of t?.data?.spectra||[]){let{digitalFilter:r,fft:o,phaseCorrection:s}=Me(n);o?.flag&&r?.flag&&s&&Math.floor(r.value.digitalFilterValue)%2>0&&(s.value.ph0-=180)}return t}function Me(e,t=["phaseCorrection","fft","digitalFilter"]){let{filters:n=[]}=e,r={};for(let o of t)r[o]=n.find(s=>s.name===o);return r}function R(e,t="localStorage"){if(e?.version===7)return e;if(t==="nmrium")return q(e);let n={...e,version:7};for(let r in e.workspaces)n.workspaces[r]=q(n.workspaces[r]);return n}function q(e){let{formatting:{nuclei:t,panels:n}={nuclei:null,panels:null},version:r,...o}=e,s={...o};return t&&(s.nuclei=Te(t)),n&&(s.panels=n),s}function Te(e){let t=[],n={name:"nucleus",ppm:"ppmFormat",hz:"hzFormat"};for(let r in e)t.push(x(e[r],n));return t}function W(e){if(e?.version===7)return e;let t={...e,version:7};return t?.settings&&(t.settings=R(t.settings,"nmrium")),t}function v(e,t="localStorage"){if(e?.version===8)return e;if(t==="nmrium")return J(e);let n={...e,version:8};for(let r in e.workspaces)n.workspaces[r]=J(n.workspaces[r]);return n}function J(e){let{version:t,...n}=e,r={...n};return r.display.panels=Ee(e),r}function Ee(e){let t={},n=e.display.panels;for(let r of Object.keys(n)){let{display:o,open:s}=n[r];t[r]={display:o,visible:o,open:s}}return t}function X(e){if(e?.version===8)return e;let t={...e,version:8};t?.settings&&(t.settings=v(t.settings,"nmrium"));for(let n of t?.data?.spectra||[]){let{filters:r=[]}=n;for(let i=0;i<r.length;i++){let{flag:a,isDeleteAllow:c,label:f,...l}=r[i];r[i]={...l,enabled:a}}let o=r.findIndex(i=>i.name==="apodization");if(o!==-1){let i=r[o],{lineBroadening:a,gaussBroadening:c,lineBroadeningCenter:f}=i.value;i.value={exponential:{apply:!0,options:{lineBroadening:c>0?-a:a}}},c>0&&(i.value.gaussian={apply:!0,options:{lineBroadening:.6*c,lineBroadeningCenter:f}}),r[o]=i}let s=r.findIndex(i=>i.name==="apodizationDimension1"),u=r.findIndex(i=>i.name==="apodizationDimension2");if(s!==-1){let i=r[s],{shapes:a}=i.value.compose;i.value=H(a)}if(u!==-1){let i=r[u],{shapes:a}=i.value.compose;i.value=H(a)}}return t}function H(e){let t={};for(let{shape:n}of e){let{kind:r,options:o}=n;if(r==="sineBell"){let{exponent:s,offset:u}=o,i=s===2?"sineSquare":"sineBell";t[i]={apply:!0,options:{offset:u}}}}return t}function Y(e){let{version:t,plugins:n,...r}=e;return t===9?e:{version:9,plugins:{},...r}}var ke=[V,z,B,_,U,K,W,X,Y];function Q(e,t,n){let r=structuredClone(e),o=Object.entries(e?.plugins??{});for(let[i,{version:a}]of o){let c=n.get(i);if(!(c&&c.version>=a)){if(c){console.warn(`Plugin "${c.id}" is loaded with a version older (${c.version}) than the one used to save the state (${a}).
1
+ var ce={NORMAL:"NORMAL",FORMULA:"FORMULA"};var ue={RELATIVE:"relative",ABSOLUTE:"absolute",MIN:"min",MAX:"max"};var me=[{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 fe=[{key:"CT",description:"CT from NMR Solutions"}];import{isAnyArray as de}from"is-any-array";import{xMultiply as k}from"ml-spectra-processing";var ge=crypto.randomUUID.bind(crypto),b=ge;function N(e){let{id:t=b(),meta:o,peaks:r={},filters:n=[],info:s={},ranges:c={},integrals:i={},selector:a,dependentVariables:l=[],...u}=e,p={id:t,meta:o,filters:n},{data:d=Se(l[0].components)}=e;if(Array.isArray(s.nucleus)&&(s.nucleus=s.nucleus[0]),p.data={x:[],re:[],im:[],...d},"scaleFactor"in s){let{scaleFactor:m}=s,{re:g,im:S}=p.data;k(g,m,{output:g}),S&&k(S,m,{output:S})}a&&(p.selector=a);let f=de(d.im);if(p.info={phc0:0,phc1:0,nucleus:"1H",isFid:!1,isComplex:f,dimension:1,name:s?.name||t,...s},s.isFid&&s.reverse&&f){let{im:m}=p.data;k(m,-1,{output:m}),p.info.reverse=!1}return p.display={isVisible:!0,isPeaksMarkersVisible:!0,isRealSpectrumVisible:!0,isVisibleInDomain:!0,...e.display},p.peaks={values:[],options:{},...r},p.ranges={values:[],options:{sum:null,isSumConstant:!0,sumAuto:!0},...c},p.integrals={values:[],options:{},...i},{...u,...p}}function Se(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 ye,xMinMaxValues as Pe,xNoiseSanPlot as xe}from"ml-spectra-processing";var j={z:[[]],minX:0,minY:0,maxX:0,maxY:0},be={re:j,im:j},Ne={rr:j};function O(e){let{id:t=b(),meta:o={},dependentVariables:r=[],info:n={},filters:s=[],zones:c=[],...i}=e,a={id:t,meta:o,filters:s};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?be:Ne,...l},a.originalData=structuredClone(a.data),!("spectrumSize"in n)){let u=n.isFid?"re":"rr",p=a.data[u].z.length,d=p>0?a.data[u].z[0].length:0;a.info.spectrumSize=[d,p]}if(!n.isFid){let u=a.data.rr,p=ye(u.z),{positive:d,negative:f}=xe(p),{min:m,max:g}=Pe(p);a.data.rr={...u,minZ:m,maxZ:g},a.info.noise={positive:d,negative:f}}return a.zones={values:[],options:{},...c},{...i,...a}}import{xSequentialFillFromTo as De}from"ml-spectra-processing";import{isAnyArray as he}from"is-any-array";function L(e,t=0){if(he(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 Oe=new Set(["t1ir","T1"]);function q(e){let t=[];for(let o of e){let{info:{pulseSequence:r,isFid:n}}=o,{data:s,info:c,meta:{vdlistValues:i=[]}}=o;if(!(r&&Oe.has(r))||i.length===0){t.push(o);continue}let l=n?"re":"rr",u={};for(let y in c)u[y]=L(c[y]);let{z:p,maxX:d,minX:f}=s[l],m=De({from:f,to:d,size:p[0].length}),[g,S]=Ie(o);for(let y=0;y<i.length;y++){let h={re:m,x:m};for(let D in s)h[Re(D)]=s[D].z.at(g*(y+S));t.push(N({data:h,info:{...u,name:`${u.name}_${i[y]}`,dimension:1,vd:i[y]}}))}}return t}function Re(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 Ce=2,ve=1;function we(e){let{spectra:t=[],molecules:o}=e,r=[];for(let n of t){let{info:s}=n;switch(s.dimension){case ve:r.push(N(n));break;case Ce:r.push(O(n));break;default:throw new Error("dimension does not supported")}}return{molecules:o,spectra:q(r)}}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 U(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 V(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=Te(r.zones.values));return t}function Te(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:s,...c}}=o;o={...o,x:{...n,...r},y:{...c,...s}}}else{let{fromTo:r,deltaX:n,resolutionX:s,nucleusX:c,deltaY:i,resolutionY:a,nucleusY:l,shiftX:u,shiftY:p,...d}=o;o={...d,x:{from:r[0].from,to:r[0].to,delta:n,resolution:s,nucleus:c},y:{from:r[1].from,to:r[1].to,delta:i,resolution:a,nucleus:l}}}return o},[])),t),[])}var Ae={name:"apodization",label:"Apodization",value:{lineBroadening:1,gaussBroadening:0,lineBroadeningCenter:0}};function _(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],...Ae};o.filters[r]=o.filters[r-1],o.filters[r-1]=n}}return t}function z(e){if(e?.version===4)return e;let{version:t,...o}=e,r=[],n={};for(let{source:i,...a}of o.spectra){let l={},{info:u={},display:p={}}=a;if(u?.dimension===2&&!i?.jcampURL)if(u.isFt)l.data={rr:a.data};else continue;if(i?.jcampURL){let{jcampURL:m,jcampSpectrumIndex:g}=i,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}=p;d&&(l.info={...u,name:d}),l.display=f,r.push({...a,...l})}let s={data:{...o,spectra:r},version:4},c={entries:Object.values(n)};return c.entries.length>0&&(s.data.source=c),s}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 B(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 K(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:s}=Ee(o);n?.flag&&r?.flag&&s&&Math.floor(r.value.digitalFilterValue)%2>0&&(s.value.ph0-=180)}return t}function Ee(e,t=["phaseCorrection","fft","digitalFilter"]){let{filters:o=[]}=e,r={};for(let n of t)r[n]=o.find(s=>s.name===n);return r}function R(e,t="localStorage"){if(e?.version===7)return e;if(t==="nmrium")return J(e);let o={...e,version:7};for(let r in e.workspaces)o.workspaces[r]=J(o.workspaces[r]);return o}function J(e){let{formatting:{nuclei:t,panels:o}={nuclei:null,panels:null},version:r,...n}=e,s={...n};return t&&(s.nuclei=Me(t)),o&&(s.panels=o),s}function Me(e){let t=[],o={name:"nucleus",ppm:"ppmFormat",hz:"hzFormat"};for(let r in e)t.push(x(e[r],o));return t}function X(e){if(e?.version===7)return e;let t={...e,version:7};return t?.settings&&(t.settings=R(t.settings,"nmrium")),t}function I(e,t="localStorage"){if(e?.version===8)return e;if(t==="nmrium")return H(e);let o={...e,version:8};for(let r in e.workspaces)o.workspaces[r]=H(o.workspaces[r]);return o}function H(e){let{version:t,...o}=e,r={...o};return r.display.panels=ke(e),r}function ke(e){let t={},o=e.display.panels;for(let r of Object.keys(o)){let{display:n,open:s}=o[r];t[r]={display:n,visible:n,open:s}}return t}function Y(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 i=0;i<r.length;i++){let{flag:a,isDeleteAllow:l,label:u,...p}=r[i];r[i]={...p,enabled:a}}let n=r.findIndex(i=>i.name==="apodization");if(n!==-1){let i=r[n],{lineBroadening:a,gaussBroadening:l,lineBroadeningCenter:u}=i.value;i.value={exponential:{apply:!0,options:{lineBroadening:l>0?-a:a}}},l>0&&(i.value.gaussian={apply:!0,options:{lineBroadening:.6*l,lineBroadeningCenter:u}}),r[n]=i}let s=r.findIndex(i=>i.name==="apodizationDimension1"),c=r.findIndex(i=>i.name==="apodizationDimension2");if(s!==-1){let i=r[s],{shapes:a}=i.value.compose;i.value=Q(a)}if(c!==-1){let i=r[c],{shapes:a}=i.value.compose;i.value=Q(a)}}return t}function Q(e){let t={};for(let{shape:o}of e){let{kind:r,options:n}=o;if(r==="sineBell"){let{exponent:s,offset:c}=n,i=s===2?"sineSquare":"sineBell";t[i]={apply:!0,options:{offset:c}}}}return t}function W(e){let{version:t,plugins:o,...r}=e;return t===9?e:{version:9,plugins:{},...r}}var je=[U,V,_,z,B,K,X,Y,W];function ee(e,t,o){let r=structuredClone(e),n=Object.entries(e?.plugins??{});for(let[i,{version:a}]of n){let l=o.get(i);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 "${i}@${a}" is not registered. NMRium may fail to load the state.
4
- Please consider open this file with the plugin installed.`)}}let s=new Set,u=()=>{let i=r.version;for(let a of n.values())for(let c of a.migrations){if(s.has(c)||i<c.minCore||c.maxCore&&i>c.maxCore)continue;if((r.plugins?.[a.id]?.version||0)===a.version)break;r=c.up(r),s.add(c)}};for(let i=e?.version||0;i<t;i++){let a=ke[i];r=a(r),u()}u(),r.plugins||(r.plugins={});for(let i of n.values())r.plugins?.[i.id]||(r.plugins[i.id]={id:i.id,version:i.version}),r.plugins[i.id].id=i.id,r.plugins[i.id].version=i.version;return r}import{FileCollection as Ke}from"filelist-utils";var ee={SDF:"sdf",MOL:"mol",NMRIUM:"nmrium",JSON:"json",JCAMP:"jcamp",DX:"dx",JDX:"jdx",JDF:"jdf",NMREDATA:"nmredata",SMILES:"smiles",SMI:"smi"};function C(e){return e.includes(".")?e.replace(/^.*\./,"").toLowerCase():""}function F(e,t={},n){let{data:r,...o}=e;if(!r)return e;let{spectra:s=[]}=r,{keep1D:u=!0,keep2D:i=!0,onlyReal:a}=t,c=a?"ft":t.dataSelection||"both",f=[];for(let l of s){if(!l.info){f.push(l);continue}let{isFid:d,dimension:m,name:p}=l.info;if(!w(m===1&&!u,p,n)&&!w(m===2&&!i,p,n)&&!w(d&&c==="ft",p,n)&&!w(!d&&c==="fid",p,n))if(a&&!d)if(l.info.isComplex=!1,Ie(l)){let{rr:g}=l.data;f.push({...l,data:{rr:g}})}else{let{re:g,x:y}=l.data;f.push({...l,data:{re:g,x:y}})}else f.push(l)}return{data:{...r,spectra:f},...o}}function w(e,t,n){return e?(n?.warn(`Skipping ${t} because it didn't match the import filters.`),!0):!1}function Ie(e){let{info:t}=e;return t?.dimension===2}function A(e){let{nmriumState:t,plugins:n,options:r}=e;for(let o of n.values()){let s=o.onReadProcess?.onProcessing;s&&s(t,r)}}async function M(e,t,n={}){let{sourceSelector:r,converter:o,keepSource:s,logger:u}=n,i=[],a=[];for(let m of t.values()){let{onReadProcess:p}=m;p&&(p?.onFiles&&i.push(m),p?.supportedExtensions?.length&&p?.onFile&&a.push(m))}let c=await Promise.allSettled(i.map(m=>m.onReadProcess.onFiles(e,n))),f=[],l=await Promise.allSettled(e.files.flatMap(m=>{let p=C(m.name).toLowerCase();return a.flatMap(g=>{let{supportedExtensions:y,onFile:S}=g.onReadProcess;return y.includes(p)?(f.push({file:m,plugin:g}),S(m,{logger:u,sourceSelector:r,converter:o,keepSource:s})):[]})})),d={spectra:[],molecules:[]};for(let m=0;m<c.length;m++){let p=c[m];switch(p.status){case"fulfilled":{let{spectra:g=[],molecules:y=[]}=p.value||{};d.spectra.push(...g),d.molecules.push(...y);break}case"rejected":{let g=p.reason,y=i[m];n.logger?.error(`Load file collection with plugin ${y.id}@${y.version} fails with: ${g}`);break}}}for(let m=0;m<l.length;m++){let p=l[m];switch(p.status){case"fulfilled":{let{spectra:g=[],molecules:y=[]}=p.value||{};d.spectra.push(...g),d.molecules.push(...y);break}case"rejected":{let g=p.reason,{file:y,plugin:S}=f[m];n.logger?.error(`Load file ${y.relativePath} with plugin ${S.id}@${S.version} fails with: ${g}`);break}}}return d}import{fileCollectionFromZip as Be}from"filelist-utils";import{fileCollectionFromWebSource as je}from"filelist-utils";import te from"lodash.merge";import{xIsEquallySpaced as Le}from"ml-spectra-processing";async function T(e){let{nmriumObjectInput:t,options:n={},migrator:r,plugins:o}=e,s=r(t),{data:u,...i}=s;if(!u)return{...i};let a={data:{...u,spectra:[]},...i},c=a.data,{source:f,spectra:l,molecules:d}=c,m;f&&(m=await je(f,{unzip:{zipExtensions:["zip","nmredata"]}}));let p=[];for(let g of u.spectra)if(m){let{sourceSelector:y}=g,S=E({input:m,migrator:r,plugins:o,options:{...n,sourceSelector:y}}).then(h=>{let{nmriumState:{data:D}}=h,{spectra:se=[],molecules:Z=[]}=D||{};Z.length>0&&d.length===0&&d.push(...Z);for(let ae of se)l.push(Ve(g,ze(ae)))});p.push(S)}else{let{dimension:y}=g.info;if(y===1){if(!Le(g.data)){n.logger?.error('The ".nmrium" file is corrupted; the X-axis values are not equally distant.');continue}l.push(N(g))}else y===2&&l.push(O(g))}return await Promise.allSettled(p),a}function Ve(e,t){let{data:n,...r}=e;if("ranges"in t){let{data:o,...s}=t;return{...te(s,r),data:o}}else if("zones"in t){let{data:o,...s}=t;return{...te(s,r),data:o}}else return t}function ze(e){return{...e,id:b()}}async function re(e){let{file:t,options:n={},migrator:r,plugins:o}=e,s=await t.arrayBuffer(),u=await(Ue(s)?_e(s):t.text());return T({nmriumObjectInput:JSON.parse(u),plugins:o,migrator:r,options:n})}async function _e(e){let t=await Be(e);if(t.files.length===0)throw new Error("compressed nmrium file is corrupted");return t.files[0].text()}function Ue(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 E(e){let{options:t={},input:n,migrator:r,plugins:o}=e,s=Ye(We(n),t.sourceSelector?.files),u=Ge(s);if(u)return{nmriumState:await re({file:u,migrator:r,plugins:o,options:t}),containsNmrium:!0};let i=await M(s,o,t),a=F({version:9,data:i},t?.sourceSelector?.general,t.logger),{onLoadProcessing:c,experimentalFeatures:f}=t,l={...c,autoProcessing:c?.autoProcessing??!1,experimentalFeatures:f};return A({nmriumState:a,plugins:o,options:l}),{nmriumState:a,containsNmrium:!1}}function We(e){if(Array.isArray(e))throw new Error("For a set of fileCollectionItems pass a FileCollection instance");return Xe(e)?e:new Ke([e])}function Xe(e){return typeof e=="object"&&"files"in e}function Ye(e,t){return t?e.filter(n=>t.includes(n.relativePath)):e}function Ge(e){return e.files.find(t=>C(t.name).toLowerCase()===ee.NMRIUM)}function k(e,t){let n={};for(let r in e)t.includes(r)||(n[r]=e[r]);return n}var Ze=["data","originalData","info","originalInfo","meta","customInfo"],$e=["sourceSelector","originalData","originalInfo"];function ne(e,t={}){let{version:n,data:r}=e;if(r.actionType)return e;let o={version:n,plugins:e.plugins},{includeData:s}=t;s!=="noData"&&(o.data=qe({...r},s));let{includeSettings:u,includeView:i}=t;return u&&(o.settings=e.settings),i&&(o.view=e.view),o}function qe(e,t="rawData"){let{spectra:n}=e;switch(t){case"dataSource":return Je(e);case"rawData":return{...k(e,["source"]),spectra:n.map(Qe)};default:return e}}function Je(e){let{spectra:t}=e;if(!e.source)throw new Error("source property should exists for dataSource serialization");return{...e,spectra:t.map(He)}}function He(e){return k(e,Ze)}function Qe(e){let{data:t,info:n,originalData:r,originalInfo:o}=e,s=k(e,$e);return s.data=r||t,s.info=o||n,s}import{fileCollectionFromWebSource as et}from"filelist-utils";async function oe(e){let{source:t,plugins:n,options:r={}}=e,{keepSource:o=!0,converter:s,...u}=r,i={source:t,spectra:[],molecules:[]},a=await et(t,{unzip:{zipExtensions:["zip","nmredata"]}}),{spectra:c=[],molecules:f=[]}=await M(a,n,{keepSource:o,converter:{...s,bruker:{keepFiles:!0,...Reflect.get(s??{},"bruker")}},...u});i.spectra.push(...c),i.molecules.push(...f);let l=F({version:9,data:i},r?.sourceSelector?.general),{onLoadProcessing:d}=u,m={filters:d?.filters,autoProcessing:d?.autoProcessing??!1,experimentalFeatures:r.experimentalFeatures};return A({nmriumState:l,plugins:n,options:m}),l}var G=class{version=9;plugins=new Map;registerPlugin(t){if(this.plugins.has(t.id)){console.warn(`Plugin ${t.id} is already registered. skip.`),console.debug("Plugin already registered:",this.plugins.get(t.id)),console.debug("Plugin to register:",t);return}this.plugins.set(t.id,t)}registerPlugins(t){for(let n of t)this.registerPlugin(n)}migrate(t){return Q(t,this.version,this.plugins)}read(t,n={}){return E({input:t,migrator:this.migrate.bind(this),plugins:this.plugins,options:n})}readNMRiumObject(t,n){return T({nmriumObjectInput:t,options:n,plugins:this.plugins,migrator:this.migrate.bind(this)})}readFromWebSource(t,n){return oe({source:t,options:n,plugins:this.plugins})}serializeNmriumState(t,n){return ne(t,n)}};function tt(e,t){if(t>9)return 0;let n=-1;for(let r=0;r<e.length;r++)if(e[r].version>t){n=r;break}return n}var ie=[{version:6,fun:R},{version:7,fun:v}];function rt(e){let{version:t}=e||{},n=tt(ie,t);if(n===-1)return{...e,version:9};let r=ie.slice(n);for(let o of r)e=o.fun(e);return e}export{le as ANALYSIS_COLUMN_TYPES,ce as ANALYSIS_COLUMN_VALUES_KEYS,P as CURRENT_EXPORT_VERSION,pe as EXTERNAL_API_KEYS,G as NMRiumCore,Ce as formatSpectra,b as generateID,L as getOneIfArray,rt as migrateSettings,ue as units};
4
+ Please consider open this file with the plugin installed.`)}}let s=new Set,c=()=>{let i=r.version;for(let a of o.values())for(let l of a.migrations){if(s.has(l)||i<l.minCore||l.maxCore&&i>l.maxCore)continue;if((r.plugins?.[a.id]?.version||0)===a.version)break;r=l.up(r),s.add(l)}};for(let i=e?.version||0;i<t;i++){let a=je[i];r=a(r),c()}c(),r.plugins||(r.plugins={});for(let i of o.values())r.plugins?.[i.id]||(r.plugins[i.id]={id:i.id,version:i.version}),r.plugins[i.id].id=i.id,r.plugins[i.id].version=i.version;return r}import{FileCollection as Ye}from"file-collection";var te={SDF:"sdf",MOL:"mol",NMRIUM:"nmrium",JSON:"json",JCAMP:"jcamp",DX:"dx",JDX:"jdx",JDF:"jdf",NMREDATA:"nmredata",SMILES:"smiles",SMI:"smi"};function C(e){return e.includes(".")?e.replace(/^.*\./,"").toLowerCase():""}function w(e,t={},o){let{data:r,...n}=e;if(!r)return e;let{spectra:s=[]}=r,{keep1D:c=!0,keep2D:i=!0,onlyReal:a}=t,l=a?"ft":t.dataSelection||"both",u=[];for(let p of s){if(!p.info){u.push(p);continue}let{isFid:d,dimension:f,name:m}=p.info;if(!v(f===1&&!c,m,o)&&!v(f===2&&!i,m,o)&&!v(d&&l==="ft",m,o)&&!v(!d&&l==="fid",m,o))if(a&&!d)if(p.info.isComplex=!1,Le(p)){let{rr:g}=p.data;u.push({...p,data:{rr:g}})}else{let{re:g,x:S}=p.data;u.push({...p,data:{re:g,x:S}})}else u.push(p)}return{data:{...r,spectra:u},...n}}function v(e,t,o){return e?(o?.warn(`Skipping ${t} because it didn't match the import filters.`),!0):!1}function Le(e){let{info:t}=e;return t?.dimension===2}function T(e){let{nmriumState:t,plugins:o,options:r}=e;for(let n of o.values()){let s=n.onReadProcess?.onProcessing;s&&s(t,r)}}async function A(e,t,o={}){let{sourceSelector:r,converter:n,keepSource:s,logger:c}=o,i=[],a=[];for(let f of t.values()){let{onReadProcess:m}=f;m&&(m?.onFiles&&i.push(f),m?.supportedExtensions?.length&&m?.onFile&&a.push(f))}let l=await Promise.allSettled(i.map(f=>f.onReadProcess.onFiles(e,o))),u=[],p=await Promise.allSettled(e.files.flatMap(f=>{let m=C(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:c,sourceSelector:r,converter:n,keepSource:s})):[]})})),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=i[f];o.logger?.error(`Load file collection with plugin ${S.id}@${S.version} fails with: ${g}`);break}}}for(let f=0;f<p.length;f++){let m=p[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 Be}from"file-collection";import{FileCollection as Ue}from"file-collection";import re from"lodash.merge";import{xIsEquallySpaced as Ve}from"ml-spectra-processing";async function F(e){let{nmriumObjectInput:t,options:o={},migrator:r,plugins:n}=e,s=r(t),{data:c,...i}=s;if(!c)return{...i};let a={data:{...c,spectra:[]},...i},l=a.data,{source:u,spectra:p,molecules:d}=l,f;u&&(f=await Ue.fromSource(u,{unzip:{zipExtensions:["zip","nmredata"]}}));let m=[];for(let g of c.spectra)if(f){let{sourceSelector:S}=g,y=E({input:f,migrator:r,plugins:n,options:{...o,sourceSelector:S}}).then(h=>{let{nmriumState:{data:D}}=h,{spectra:le=[],molecules:Z=[]}=D||{};Z.length>0&&d.length===0&&d.push(...Z);for(let pe of le)p.push(_e(g,ze(pe)))});m.push(y)}else{let{dimension:S}=g.info;if(S===1){if(!Ve(g.data)){o.logger?.error('The ".nmrium" file is corrupted; the X-axis values are not equally distant.');continue}p.push(N(g))}else S===2&&p.push(O(g))}return await Promise.allSettled(m),a}function _e(e,t){let{data:o,...r}=e;if("ranges"in t){let{data:n,...s}=t;return{...re(s,r),data:n}}else if("zones"in t){let{data:n,...s}=t;return{...re(s,r),data:n}}else return t}function ze(e){return{...e,id:b()}}async function oe(e){let{file:t,options:o={},migrator:r,plugins:n}=e,s=await t.arrayBuffer(),c=await(Xe(s)?Ke(s):t.text());return F({nmriumObjectInput:JSON.parse(c),plugins:n,migrator:r,options:o})}async function Ke(e){let t=await Be.fromZip(e);if(t.files.length===0)throw new Error("compressed nmrium file is corrupted");return t.files[0].text()}function Xe(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 E(e){let{options:t={},input:o,migrator:r,plugins:n}=e,s=Ge(await We(o),t.sourceSelector?.files),c=Ze(s);if(c)return{nmriumState:await oe({file:c,migrator:r,plugins:n,options:t}),containsNmrium:!0};let i=await A(s,n,t),a=w({version:9,data:i},t?.sourceSelector?.general,t.logger),{onLoadProcessing:l,experimentalFeatures:u}=t,p={...l,autoProcessing:l?.autoProcessing??!1,experimentalFeatures:u};return T({nmriumState:a,plugins:n,options:p}),{nmriumState:a,containsNmrium:!1}}function We(e){return Array.isArray(e)?Promise.reject(new Error("For a set of fileCollectionItems pass a FileCollection instance")):$e(e)?Promise.resolve(e):new Ye().appendExtendedSource({...e,uuid:crypto.randomUUID()})}function $e(e){return typeof e=="object"&&"files"in e}function Ge(e,t){if(!t)return e;let o=new Set(t);return e.filter(r=>o.has(r.relativePath))}function Ze(e){return e.files.find(t=>C(t.name).toLowerCase()===te.NMRIUM)}function M(e,t){let o={};for(let r in e)t.includes(r)||(o[r]=e[r]);return o}var qe=["data","originalData","info","originalInfo","meta","customInfo"],Je=["sourceSelector","originalData","originalInfo"];function ne(e,t={}){let{version:o,data:r}=e;if(r.actionType)return e;let n={version:o,plugins:e.plugins},{includeData:s}=t;s!=="noData"&&(n.data=He({...r},s));let{includeSettings:c,includeView:i}=t;return c&&(n.settings=e.settings),i&&(n.view=e.view),n}function He(e,t="rawData"){let{spectra:o}=e;switch(t){case"dataSource":return Qe(e);case"rawData":return{...M(e,["source"]),spectra:o.map(tt)};default:return e}}function Qe(e){let{spectra:t}=e;if(!e.source)throw new Error("source property should exists for dataSource serialization");return{...e,spectra:t.map(et)}}function et(e){return M(e,qe)}function tt(e){let{data:t,info:o,originalData:r,originalInfo:n}=e,s=M(e,Je);return s.data=r||t,s.info=n||o,s}var rt=["topbar.right"],ot=[],Xr=[...rt,...ot],nt={},$={};{let e=nt,t=$;for(let[o,r]of Object.entries(e))t[r]||(t[r]=[]),t[r]?.push(o)}function*ie(e){let{slot:t,plugins:o,supportedToDeprecatedSlots:r=$}=e,n=r[t];for(let[s,c]of o.entries()){let i=c.ui;if(!i)continue;let a=i[t];if(a){yield[s,a];continue}if(n)for(let l of n){let u=c.ui?.[l];if(u){yield[s,u],console.warn(`Plugin ${c.id} used deprecated slot "${l}". Please update this plugin to use "${t}" instead.`);break}}}}import{FileCollection as it}from"file-collection";async function se(e){let{source:t,plugins:o,options:r={}}=e,{keepSource:n=!0,converter:s,...c}=r,i={source:t,spectra:[],molecules:[]},a=await it.fromSource(t,{unzip:{zipExtensions:["zip","nmredata"]}}),{spectra:l=[],molecules:u=[]}=await A(a,o,{keepSource:n,converter:{...s,bruker:{keepFiles:!0,...Reflect.get(s??{},"bruker")}},...c});i.spectra.push(...l),i.molecules.push(...u);let p=w({version:9,data:i},r?.sourceSelector?.general),{onLoadProcessing:d}=c,f={filters:d?.filters,autoProcessing:d?.autoProcessing??!1,experimentalFeatures:r.experimentalFeatures};return T({nmriumState:p,plugins:o,options:f}),p}var G=class{version=9;plugins=new Map;registerPlugin(t){if(this.plugins.has(t.id)){console.warn(`Plugin ${t.id} is already registered. skip.`),console.debug("Plugin already registered:",this.plugins.get(t.id)),console.debug("Plugin to register:",t);return}this.plugins.set(t.id,t)}registerPlugins(t){for(let o of t)this.registerPlugin(o)}migrate(t){return ee(t,this.version,this.plugins)}read(t,o={}){return E({input:t,migrator:this.migrate.bind(this),plugins:this.plugins,options:o})}readNMRiumObject(t,o){return F({nmriumObjectInput:t,options:o,plugins:this.plugins,migrator:this.migrate.bind(this)})}readFromWebSource(t,o){return se({source:t,options:o,plugins:this.plugins})}serializeNmriumState(t,o){return ne(t,o)}slot(t){return ie({slot:t,plugins:this.plugins})}};function st(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 ae=[{version:6,fun:R},{version:7,fun:I}];function at(e){let{version:t}=e||{},o=st(ae,t);if(o===-1)return{...e,version:9};let r=ae.slice(o);for(let n of r)e=n.fun(e);return e}export{ce as ANALYSIS_COLUMN_TYPES,ue as ANALYSIS_COLUMN_VALUES_KEYS,P as CURRENT_EXPORT_VERSION,fe as EXTERNAL_API_KEYS,G as NMRiumCore,we as formatSpectra,b as generateID,L as getOneIfArray,at as migrateSettings,me as units};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zakodium/nmrium-core",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
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",
@@ -18,25 +18,24 @@
18
18
  "bundle": "node scripts/esbuild.js && npm run bundle-types",
19
19
  "bundle-types": "npm run tsc && yarn g:api-extractor",
20
20
  "clean": "rimraf types dist coverage",
21
- "dev:eslint-fix": "eslint --cache --fix $(git diff --name-only --relative) --quiet",
22
21
  "prepack": "npm run clean && npm run bundle",
23
- "dev:prettier-write": "prettier --write $(git diff --name-only --relative)",
24
22
  "test": "yarn g:test-only && yarn g:check-types && yarn g:eslint && yarn g:prettier",
25
23
  "tsc": "tsc --project tsconfig.types.json"
26
24
  },
27
25
  "devDependencies": {
28
26
  "@types/lodash.merge": "^4.6.9",
29
- "@types/node": "^22.15.31",
30
- "@zakodium/nmr-types": "^0.0.1",
27
+ "@types/node": "^24.0.14",
28
+ "@types/react": "^18.3.13",
29
+ "@zakodium/nmr-types": "^0.1.0",
31
30
  "esbuild": "^0.25.5",
32
31
  "jest-matcher-deep-close-to": "^3.0.2",
33
32
  "rimraf": "^6.0.1",
34
- "vitest": "^3.2.3"
33
+ "vitest": "^3.2.4"
35
34
  },
36
35
  "dependencies": {
37
36
  "cheminfo-types": "^1.8.1",
38
- "fifo-logger": "^1.0.0",
39
- "filelist-utils": "^1.11.3",
37
+ "fifo-logger": "^2.0.0",
38
+ "file-collection": "^5.1.0",
40
39
  "is-any-array": "^2.0.1",
41
40
  "lodash.merge": "^4.6.2",
42
41
  "ml-spectra-processing": "^14.12.0",