jcampconverter 9.6.3 → 10.0.0

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
@@ -1,6 +1,5 @@
1
1
  [![NPM version][npm-image]][npm-url]
2
2
  [![build status][ci-image]][ci-url]
3
- [![Test coverage][codecov-image]][codecov-url]
4
3
  [![npm download][download-image]][download-url]
5
4
  [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5091526.svg)](https://doi.org/10.5281/zenodo.5091526)
6
5
 
@@ -82,8 +81,6 @@ npm run benchmark
82
81
 
83
82
  [npm-image]: https://img.shields.io/npm/v/jcampconverter.svg
84
83
  [npm-url]: https://npmjs.org/package/jcampconverter
85
- [codecov-image]: https://img.shields.io/codecov/c/github/cheminfo/jcampconverter.svg
86
- [codecov-url]: https://codecov.io/gh/cheminfo/jcampconverter
87
84
  [ci-image]: https://github.com/cheminfo/jcampconverter/workflows/Node.js%20CI/badge.svg?branch=main
88
85
  [ci-url]: https://github.com/cheminfo/jcampconverter/actions?query=workflow%3A%22Node.js+CI%22
89
86
  [download-image]: https://img.shields.io/npm/dm/jcampconverter.svg
@@ -1,8 +1,9 @@
1
- "use strict";var xe=Object.create;var P=Object.defineProperty;var Ne=Object.getOwnPropertyDescriptor;var Ae=Object.getOwnPropertyNames;var Te=Object.getPrototypeOf,Se=Object.prototype.hasOwnProperty;var ye=(e,i)=>{for(var s in i)P(e,s,{get:i[s],enumerable:!0})},ae=(e,i,s,a)=>{if(i&&typeof i=="object"||typeof i=="function")for(let n of Ae(i))!Se.call(e,n)&&n!==s&&P(e,n,{get:()=>i[n],enumerable:!(a=Ne(i,n))||a.enumerable});return e};var Ce=(e,i,s)=>(s=e!=null?xe(Te(e)):{},ae(i||!e||!e.__esModule?P(s,"default",{value:e,enumerable:!0}):s,e)),Xe=e=>ae(P({},"__esModule",{value:!0}),e);var $e={};ye($e,{convert:()=>he,createTree:()=>ne,parseJcampCS:()=>de});module.exports=Xe($e);var re=require("ensure-string");var D=/\s*\$\$.*/;function M(e){return e.replace(D,"")}function ne(e,i={}){e=(0,re.ensureString)(e);let{flatten:s=!1}=i;if(typeof e!="string")throw new TypeError("the JCAMP should be a string");let a=e.split(/\r?\n/),n=[],l=[],r=[],t,o=0,p=e.includes("## ");for(let c=0;c<a.length;c++){let d=a[c],u=p?d.replace(/ /g,""):d;if(u.substring(0,9)==="##NTUPLES"&&o++,u.substring(0,7)==="##TITLE"){let f=[u.substring(8).trim()];for(let m=c+1;m<a.length&&!a[m].startsWith("##");m++)f.push(a[m].trim());l.push({title:f.join(`
2
- `),jcamp:`${d}
3
- `,children:[]}),t=l[l.length-1],n.push(t)}else if(u.substring(0,5)==="##END"&&o===0){t.jcamp+=`${d}
4
- `;let f=l.pop();l.length!==0?(t=l[l.length-1],t.children.push(f)):(t=void 0,r.push(f))}else if(t&&t.jcamp){t.jcamp+=`${d}
5
- `;let f=u.match(/^##(.*?)=(.+)/);if(f){let m=f[1].replace(/[ _-]/g,"").toUpperCase();m==="DATATYPE"?t.dataType=f[2].trim():m==="DATACLASS"?t.dataClass=f[2].trim():m==="JCAMPDX"?t.jcampDX=M(f[2].trim()):m==="JCAMPCS"&&(t.jcampCS=M(f[2].trim()))}}u.substring(0,5)==="##END"&&o>0&&o--}return s?(n.forEach(c=>{c.children=void 0}),n):r}var me=require("dynamic-typing"),ce=require("ensure-string");var U=["TIC",".RIC","SCANNUMBER"];function oe(e){let i=e.spectra,s=i.length,a={times:new Array(s),series:{ms:{dimension:2,data:new Array(s)}}},n=[];for(let l=0;l<U.length;l++){let r=V(U[l]);i[0][r]&&(n.push(r),a.series[r]={dimension:1,data:new Array(s)})}for(let l=0;l<s;l++){let r=i[l];a.times[l]=r.pageValue;for(let t=0;t<n.length;t++)a.series[n[t]].data[l]=Number(r[n[t]]);r.data&&(a.series.ms.data[l]=[r.data.x,r.data.y])}e.chromatogram=a}function fe(e){return U.indexOf(e)!==-1}function V(e){return e.toLowerCase().replace(/[^a-z0-9]/g,"")}function Y(e){let i=[];for(let s=0;s<e.length;s++)i.push(Number(e[s]));return i}function B(e,i){let s=e.yFactor,a=e.deltaX;e.isXYdata=!0;let n={x:[],y:[]};e.data=n;let l=e.firstX,r=e.firstY,t=!1,o,p=0;for(;p<i.length;p++)if(o=i.charCodeAt(p),o===13||o===10)t=!0;else if(t)break;let c=!0,d=!1,u=!1,f=0,m=!1,h=!1,g=0,A=0,N=!1,y=!1,C=!1,T=0;for(;p<=i.length;p++)if(p===i.length?o=13:o=i.charCodeAt(p),h)(o===13||o===10)&&(c=!0,h=!1);else if(o<=57&&o>=48)y=!0,T>0?g+=(o-48)/10**T++:(g*=10,g+=o-48);else if(o===44||o===46)y=!0,T++;else{if(y){if(c)c=!1,u&&(C=!0);else if(C)C=!1;else{d?(f=N?0-g:g,u=!0,d=!1):m||(A=N?0-g:g);let O=m?g-1:1;for(let v=0;v<O;v++)u?r+=f:r=A,n.x.push(l),n.y.push(r*s),l+=a}N=!1,g=0,T=0,y=!1,m=!1}if(o<74&&o>63)y=!0,u=!1,g=o-64;else if(o>96&&o<106)y=!0,u=!1,g=o-96,N=!0;else if(o===115)y=!0,m=!0,g=9;else if(o>82&&o<91)y=!0,m=!0,g=o-82;else if(o>73&&o<83)y=!0,d=!0,g=o-73;else if(o>105&&o<115)y=!0,d=!0,g=o-105,N=!0;else if(o===36&&i.charCodeAt(p+1)===36)y=!0,h=!0;else if(o===37)y=!0,d=!0,g=0,N=!1;else if(o===45){let O=i.charCodeAt(p+1);(O>=48&&O<=57||O===44||O===46)&&(y=!0,c||(u=!1),N=!0)}else(o===13||o===10)&&(c=!0,h=!1)}}var ue=/[,\t ]+/;function w(e,i,s){if(e.isPeaktable=!0,!e.variables||Object.keys(e.variables)===2?ve(e,i,s):Fe(e,i,s),e.variables)for(let a in e.variables)e.variables[a].data=e.data[a]}function ve(e,i,s){let a={x:[],y:[]};e.data=a;let n=i.split(/,? *,?[;\r\n]+ */);for(let l=1;l<n.length;l++){let r=n[l].trim().replace(D,"").split(ue);if(r.length%2===0)for(let t=0;t<r.length;t=t+2)a.x.push(Number(r[t])*e.xFactor),a.y.push(Number(r[t+1])*e.yFactor);else s.logs.push(`Format error: ${r}`)}}function Fe(e,i,s){let a={},n=Object.keys(e.variables),l=n.length;n.forEach(t=>a[t]=[]),e.data=a;let r=i.split(/,? *,?[;\r\n]+ */);for(let t=1;t<r.length;t++){let o=r[t].trim().replace(D,"").split(ue);if(o.length%l===0)for(let p=0;p<o.length;p++)a[n[p%l]].push(Number(o[p]));else s.logs.push(`Wrong number of columns: ${o}`)}}function k(e,i){e.isXYAdata=!0;let s={};e.data=s;let a=i.split(/\r?\n/),n=a[0].replace(/^.*?([A-Z]+).*$/,"$1").split("").map(l=>l.toLowerCase());for(let l=1;l<a.length;l++){let r=a[l].replace(/^\((.*)\)$/,"$1").split(/ *, */);for(let t=0;t<n.length;t++){let o=r[t];switch(n[t]){case"x":case"y":case"w":o=Number.parseFloat(o);break;case"a":o=o.replace(/^<(.*)>$/,"$1");break;case"m":break;default:continue}s[n[t]]||(s[n[t]]=[]),s[n[t]].push(o)}}}var Q=require("dynamic-typing");var j=require("gyromagnetic-ratio"),Z=Ce(require("ml-array-median"));function pe(e){return Array.isArray(e)?e[0]:e}function J(e){let{spectra:i}=e,s=i[0].data.y[0],a=s,n=i.length,l=i[0].data.x.length,r=new Array(n);for(let f=0;f<n;f++){r[f]=i[f].data.y;for(let m=0;m<l;m++){let h=r[f][m];h<s&&(s=h),h>a&&(a=h)}}let t=i[0].data.x[0],o=i[0].data.x[i[0].data.x.length-1],{firstY:p,lastY:c}=Me(e);if(t>o)for(let f of r)f.reverse();p>c&&r.reverse();let d=[];for(let f=0;f<r.length;f++){let m=Float64Array.from(r[f]);for(let h=0;h<m.length;h++)m[h]<0&&(m[h]=-m[h]);d.push((0,Z.default)(m))}let u=(0,Z.default)(d);return{z:r,minX:Math.min(t,o),maxX:Math.max(t,o),minY:Math.min(p,c),maxY:Math.max(p,c),minZ:s,maxZ:a,noise:u}}function Me(e){let{spectra:i,ntuples:s,info:a}=e;if(s)for(let n=0;n<s.length;n++){let{symbol:l,nucleus:r}=s[n];if(l.match(/[F|T]1/)){let t=pe(a[".OBSERVEFREQUENCY"]),{nucleus:o}=s.find(m=>m.symbol.match(/[F|T]2/));if([t,o,r].some(m=>!m))break;let p=(0,j.getGyromagneticRatio)(o),c=(0,j.getGyromagneticRatio)(r),{first:d,last:u}=s[n],f=t*c/p;return{firstY:d/f,lastY:u/f}}}return{firstY:i[0].pageValue,lastY:i[i.length-1].pageValue}}function G(e,i){let s=e.noise,a=e.z,n,l,r,t,o,p,c,d,u=a.length,f=a[0].length,m,h,g,A,N=e.minX,C=(e.maxX-N)/(f-1),T=e.minY,v=(e.maxY-T)/(u-1),ge=e.minZ,z=e.maxZ,ee=i.nbContourLevels*2,te=new Array(ee),x;for(let R=0;R<ee;R++){let I={};te[R]=I;let be=R%2,le=(z-i.noiseMultiplier*s)*Math.exp((R>>1)-i.nbContourLevels);be===0?x=le+i.noiseMultiplier*s:x=0-le-i.noiseMultiplier*s;let b=[];if(I.zValue=x,I.lines=b,!(x<=ge||x>=z))for(let X=0;X<u-1;X++){let se=a[X],ie=a[X+1];for(let S=0;S<f-1;S++)n=se[S],l=se[S+1],r=ie[S],t=ie[S+1],o=n>x,p=l>x,c=r>x,d=t>x,o!==p&&o!==c&&(m=S+(x-n)/(l-n),h=X,g=S,A=X+(x-n)/(r-n),b.push(m*C+N),b.push(h*v+T),b.push(g*C+N),b.push(A*v+T)),d!==p&&d!==c&&(m=S+1,h=X+1-(x-t)/(l-t),g=S+1-(x-t)/(r-t),A=X+1,b.push(m*C+N),b.push(h*v+T),b.push(g*C+N),b.push(A*v+T)),p!==c&&(m=(S+1-(x-l)/(r-l))*C+N,h=(X+(x-l)/(r-l))*v+T,p!==o&&(g=S+1-(x-l)/(n-l),A=X,b.push(m),b.push(h),b.push(g*C+N),b.push(A*v+T)),c!==o&&(g=S,A=X+1-(x-r)/(n-r),b.push(m),b.push(h),b.push(g*C+N),b.push(A*v+T)),p!==d&&(g=S+1,A=X+(x-l)/(t-l),b.push(m),b.push(h),b.push(g*C+N),b.push(A*v+T)),c!==d&&(g=S+(x-r)/(t-r),A=X+1,b.push(m),b.push(h),b.push(g*C+N),b.push(A*v+T)))}}return{minX:e.minX,maxX:e.maxX,minY:e.minY,maxY:e.maxY,segments:te}}function H(e,i){let s=J(e);i.noContour||(e.contourLines=G(s,i),delete s.z),e.minMax=s}var $=require("gyromagnetic-ratio");function q(e,i){for(let s of e){let a=0,n=0;for(let l of s.spectra){if(s.ntuples&&s.ntuples.symbol?(!a&&l.observeFrequency&&(a=l.observeFrequency),!n&&l.shiftOffsetVal&&(n=l.shiftOffsetVal)):(a=l.observeFrequency,n=l.shiftOffsetVal),a&&l.xUnits&&l.xUnits.toUpperCase().includes("HZ")){l.xUnits="PPM",l.xFactor=l.xFactor/a,l.firstX=l.firstX/a,l.lastX=l.lastX/a,l.deltaX=l.deltaX/a;for(let r=0;r<l.data.x.length;r++)l.data.x[r]/=a}if(n&&l.xUnits.toLowerCase().includes("ppm")){let r=l.firstX-n;l.firstX=l.firstX-r,l.lastX=l.lastX-r;for(let t=0;t<l.data.x.length;t++)l.data.x[t]-=r}if(s.ntuples&&s.ntuples.nucleus&&s.ntuples.symbol)for(let r=0;r<s.ntuples.nucleus.length;r++){let t=s.ntuples.symbol[r],o=s.ntuples.nucleus[r];if(t.match(/^[F|T]/)&&!o){if(t.match(/[F|T]1/))if(s.tmp.$NUC2)s.ntuples.nucleus[r]=s.tmp.$NUC2;else{let p=s.ntuples.symbol.indexOf(t.replace(/^([F|T]).*/,"$12"));p&&s.ntuples.nucleus[p]&&(s.ntuples.nucleus[r]=s.ntuples.nucleus[p])}t.match(/[F|T]2/)&&(s.ntuples.nucleus[r]=s.tmp.$NUC1)}t.match(/[F|T]2/)&&(s.yType=s.ntuples.nucleus[0],(0,$.getGyromagneticRatio)(s.xType)||(s.xType=s.ntuples.nucleus[1]))}if(a&&s.ntuples&&s.ntuples.symbol&&s.ntuples.nucleus){let r="",t=s.ntuples.symbol.indexOf(l.pageSymbol);if(s.ntuples.units&&s.ntuples.units[t]&&(r=s.ntuples.units[t]),!r.toLowerCase().match(/(ppm|seconds)/)){if(t!==0){let u="Not sure about this ntuples format";if(i)i.warn(u);else throw Error(u)}let{nucleus:o}=s.ntuples,p=(0,$.getGyromagneticRatio)(o[0]),c=(0,$.getGyromagneticRatio)(o[1]);if(!p||!c){let u=`Problem with determination of gyromagnetic ratio for ${o.join("-")}`;if(i)i.error(u);else throw Error(u)}let d=p/c*a;l.pageValue/=d}}}}}function L(e,i,s={}){s.logger?.trace(i),e.profiling&&e.profiling.push({action:i,time:Date.now()-s.start})}function K(e){let i=e.spectra[0].data;e.chromatogram={times:i.x.slice(),series:{intensity:{dimension:1,data:i.y.slice()}}}}function W(e,i,s){q(e,s.logger),Le(e,s);for(let a of e){if(Object.keys(a.ntuples).length>0){let n=[],l=Object.keys(a.ntuples);for(let r=0;r<l.length;r++){let t=l[r],o=a.ntuples[t];for(let p=0;p<o.length;p++)n[p]||(n[p]={}),n[p][t]=o[p]}a.ntuples=n}a.twoD&&s.wantXY&&(H(a,s),L(i,"Finished countour plot calculation",s),s.keepSpectra||delete a.spectra),s.chromatogram&&(a.spectra.length>1?oe(a):K(a),L(i,"Finished chromatogram calculation",s)),delete a.tmp}}function Le(e,i){for(let s of e)for(let a in s.meta){let n=s.meta[a];if(typeof n=="string"){if(n[0]==="{"){if(!n.includes(":")&&n[n.length-1]==="}"){let l=n.slice(1,-1).split(/[,; ]+/).filter(r=>r);for(let r=0;r<l.length;r++)s.meta[a+String(r)]=i.dynamicTyping?(0,Q.parseString)(l[r]):l[r]}}else if(n[0]==="("){let l=n.split(/\r?\n/),r=/^\((?<from>\d+)\.\.(?<to>\d+)\).*$/;if(r.test(l[0])){let[t,o]=l[0].match(r).slice(1).map(Number),p=l.slice(1).join(" ").split(/[,; ]+/).filter(c=>c);for(let c=t;c<=o;c++)i.dynamicTyping&&typeof p[c-t]=="string"?s.meta[a+String(c)]=(0,Q.parseString)(p[c-t]):s.meta[a+String(c)]=p[c-t]}}}}}function _(e,i,s){let a=-1,n=-1,l="",r="";if(s.indexOf("++")>0)l=s.replace(/.*\(([a-zA-Z0-9]+)\+\+.*/,"$1"),r=s.replace(/.*\.\.([a-zA-Z0-9]+).*/,"$1");else{s=s.replace(/[^a-zA-Z%]/g,""),l=s.charAt(0),r=s.charAt(1),i.variables={};for(let t of s){let o=t.toLowerCase(),p=e.ntuples.symbol.indexOf(t);if(p===-1)throw Error(`Symbol undefined: ${t}`);i.variables[o]={};for(let c in e.ntuples)e.ntuples[c][p]&&(i.variables[o][c.replace(/^var/,"")]=e.ntuples[c][p])}}a=e.ntuples.symbol.indexOf(l),n=e.ntuples.symbol.indexOf(r),a===-1&&(a=0),n===-1&&(n=0),e.ntuples.first&&(e.ntuples.first.length>a&&(i.firstX=e.ntuples.first[a]),e.ntuples.first.length>n&&(i.firstY=e.ntuples.first[n])),e.ntuples.last&&(e.ntuples.last.length>a&&(i.lastX=e.ntuples.last[a]),e.ntuples.last.length>n&&(i.lastY=e.ntuples.last[n])),e.ntuples.vardim&&e.ntuples.vardim.length>a&&(i.nbPoints=e.ntuples.vardim[a]),e.ntuples.factor&&(e.ntuples.factor.length>a&&(i.xFactor=e.ntuples.factor[a]),e.ntuples.factor.length>n&&(i.yFactor=e.ntuples.factor[n])),e.ntuples.units&&(e.ntuples.units.length>a&&(e.ntuples.varname&&e.ntuples.varname[a]?i.xUnits=`${e.ntuples.varname[a]} [${e.ntuples.units[a]}]`:i.xUnits=e.ntuples.units[a]),e.ntuples.units.length>n&&(e.ntuples.varname&&e.ntuples.varname[n]?i.yUnits=`${e.ntuples.varname[n]} [${e.ntuples.units[n]}]`:i.yUnits=e.ntuples.units[n]))}function E(e){e.xFactor||(e.xFactor=1),e.yFactor||(e.yFactor=1)}var F=/[ \t]*,[ \t]*/,Ye={keepRecordsRegExp:/^$/,canonicDataLabels:!0,canonicMetadataLabels:!1,dynamicTyping:!0,withoutXY:!1,noTrimRegExp:/^$/,chromatogram:!1,keepSpectra:!1,noContour:!1,nbContourLevels:7,noiseMultiplier:5,profiling:!1};function he(e,i={}){e=(0,ce.ensureString)(e),i={...Ye,...i},i.logger?.debug("Starting jcamp conversion"),i.wantXY=!i.withoutXY,i.start=Date.now();let s=[],a={profiling:i.profiling?[]:!1,logs:[],entries:[]},n={children:[]},l=n,r=[],t={};if(typeof e!="string")throw new TypeError("the JCAMP should be a string");L(a,"Before split to LDRS",i);let o=e.replace(/[\r\n]+##/g,`
1
+ "use strict";var he=Object.create;var $=Object.defineProperty;var xe=Object.getOwnPropertyDescriptor;var ye=Object.getOwnPropertyNames;var Ae=Object.getPrototypeOf,Se=Object.prototype.hasOwnProperty;var Ne=(e,f)=>{for(var t in f)$(e,t,{get:f[t],enumerable:!0})},se=(e,f,t,i)=>{if(f&&typeof f=="object"||typeof f=="function")for(let a of ye(f))!Se.call(e,a)&&a!==t&&$(e,a,{get:()=>f[a],enumerable:!(i=xe(f,a))||i.enumerable});return e};var Ce=(e,f,t)=>(t=e!=null?he(Ae(e)):{},se(f||!e||!e.__esModule?$(t,"default",{value:e,enumerable:!0}):t,e)),Te=e=>se($({},"__esModule",{value:!0}),e);var $e={};Ne($e,{convert:()=>de,createTree:()=>oe,parseJcampCS:()=>be});module.exports=Te($e);var ie=require("ensure-string");var P=/\s*\$\$.*/;function O(e){return e.replace(P,"")}function oe(e,f={}){e=(0,ie.ensureString)(e);let{flatten:t=!1}=f,i=e.split(/\r?\n/),a=[],o=[],n=[],m={title:"",jcamp:"",children:[]},r=0,p=e.includes("## ");for(let u=0;u<i.length;u++){let b=i[u],h=p?b.replaceAll(" ",""):b;if(h.startsWith("##NTUPLES")&&r++,h.startsWith("##TITLE")){let s=[h.slice(8).trim()];for(let l=u+1;l<i.length&&!i[l].startsWith("##");l++)s.push(i[l].trim());o.push({title:s.join(`
2
+ `),jcamp:`${b}
3
+ `,children:[]}),m=o.at(-1),a.push(m)}else if(h.startsWith("##END")&&r===0&&m){m.jcamp+=`${b}
4
+ `;let s=o.pop();if(!s)throw new Error("Not finished");o.length>0?(m=o.at(-1),m.children?.push(s)):(m=void 0,n.push(s))}else if(m?.jcamp){m.jcamp+=`${b}
5
+ `;let s=h.match(/^##(.*?)=(.+)/);if(s){let l=s[1].replaceAll(/[ _-]/g,"").toUpperCase();l==="DATATYPE"?m.dataType=s[2].trim():l==="DATACLASS"?m.dataClass=s[2].trim():l==="JCAMPDX"?m.jcampDX=O(s[2].trim()):l==="JCAMPCS"&&(m.jcampCS=O(s[2].trim()))}}h.startsWith("##END")&&r>0&&r--}if(t){for(let u of a)u.children=void 0;return a}else return n}var ce=require("dynamic-typing"),pe=require("ensure-string");var ae=["TIC",".RIC","SCANNUMBER"];function le(e){let f=e.spectra,t=f.length,i={times:new Array(t),series:{ms:{dimension:2,data:new Array(t)}}},a=[];for(let o of ae){let n=B(o);f[0][n]&&(a.push(n),i.series[n]={dimension:1,data:new Array(t)})}for(let o=0;o<t;o++){let n=f[o];i.times[o]=n.pageValue;for(let m of a)i.series[m].data[o]=Number(n[m]);n.data&&(i.series.ms.data[o]=[n.data.x,n.data.y])}e.chromatogram=i}function fe(e){return ae.includes(e)}function B(e){return e.toLowerCase().replaceAll(/[^a-z0-9]/g,"")}function E(e){return e.map(Number)}function j(e,f,t){let{logger:i}=t;i&&(e.xFactor||i.info("The xFactor is not defined, it will be set to 1"),e.yFactor||i.info("The yFactor is not defined, it will be set to 1"));let a=e.yFactor??1,o=e.xFactor??1,n=e.deltaX??1,m=Math.abs(n*.1),r=.01;e.isXYdata=!0;let p={x:[],y:[]};e.data=p;let u=e.firstX||0,b=e.firstY||0,h=!1,s,l=0;for(;l<f.length;l++)if(s=f.codePointAt(l),s===13||s===10)h=!0;else if(h)break;let c=0,d=!0,A=!1,y=!1,k=0,N=!1,C=!1,g=0,X=0,M=!1,S=!1,Y=!1,R=0;for(;l<=f.length;l++)if(l===f.length?s=13:s=f.codePointAt(l),C)(s===13||s===10)&&(d=!0,C=!1,c++);else if(s<=57&&s>=48)S=!0,R>0?g+=(s-48)/10**R++:(g*=10,g+=s-48);else if(s===44||s===46)S=!0,R++;else{if(S){if(M&&(g=g*-1,M=!1),d)g*=o,i&&(y?Math.abs(u-n-g)>m&&(Math.abs(u-g)<m?i.trace(`Data line ${c}: After a DIFFERENCE the next line should repeat the last value and this does not seem to be the case: Current value: ${g} - Expected: ${u}.`):Math.abs(u-n-g)>10*m?i.trace(`Data line ${c}: The difference between the first value ${g} and the expected first x value ${u} based on increment after a DIFFERENCE is too high`):i.trace(`Data line ${c}: The difference between the first value ${g} and the expected first x value ${u} based on increment after a DIFFERENCE is too high`)):Math.abs(u-g)>m&&i.trace(`Data line ${c}: The difference between the first value ${g} and the first x value ${u} is too high`)),d=!1,y&&(Y=!0);else if(Y)Y=!1,i&&Math.abs(b-g)>r&&i.trace(`Data line ${c}: After a duplicate the next line should repeat the same value ${g} !== ${b}`),b=g;else{A?(k=M?0-g:g,y=!0,A=!1):N||(X=M?0-g:g);let x=N?g-1:1;for(let F=0;F<x;F++)y?b+=k:b=X,p.x.push(u),p.y.push(b*a),u+=n}M=!1,g=0,R=0,S=!1,N=!1}if(s<74&&s>63)S=!0,y=!1,g=s-64;else if(s>96&&s<106)S=!0,y=!1,g=s-96,M=!0;else if(s===115)S=!0,N=!0,g=9;else if(s>82&&s<91)S=!0,N=!0,g=s-82;else if(s>73&&s<83)S=!0,A=!0,g=s-73;else if(s>105&&s<115)S=!0,A=!0,g=s-105,M=!0;else if(s===36&&f.codePointAt(l+1)===36)S=!0,C=!0;else if(s===37)S=!0,A=!0,g=0,M=!1;else if(s===45){let x=f.codePointAt(l+1);(x!==void 0&&x>=48&&x<=57||x===44||x===46)&&(S=!0,d||(y=!1),M=!0)}else(s===13||s===10)&&(d=!0,C=!1,c++)}i&&y&&i.warn("The last value is a difference, it should be repeated on the next line")}var me=/[,\t ]+/;function w(e,f,t){if(e.isPeaktable=!0,!e.variables||Object.keys(e.variables).length===2?ve(e,f,t):Xe(e,f,t),e.variables)for(let i in e.variables)e.variables[i].data=e.data?.[i]}function ve(e,f,t){let{logger:i}=t,a={x:[],y:[]};e.data=a;let o=f.split(/,? *,?[;\r\n]+ */);for(let n=1;n<o.length;n++){let m=o[n].trim().replace(P,"").split(me);if(m.length%2===0)for(let r=0;r<m.length;r=r+2)e.xFactor!==void 0&&e.yFactor!==void 0&&(a.x.push(Number(m[r])*e.xFactor),a.y.push(Number(m[r+1])*e.yFactor));else i?.warn(`Format error: ${m.toString()}`)}}function Xe(e,f,t){let{logger:i}=t,a={},o=Object.keys(e.variables),n=o.length;for(let r of o)a[r]=[];e.data=a;let m=f.split(/,? *,?[;\r\n]+ */);for(let r=1;r<m.length;r++){let p=m[r].trim().replace(P,"").split(me);if(p.length%n===0)for(let u=0;u<p.length;u++)a[o[u%n]].push(Number(p[u]));else i?.warn(`Wrong number of columns: ${p.toString()}`)}}function Z(e,f){e.isXYAdata=!0;let t={};e.data=t;let i=f.split(/\r?\n/),a=i[0].replace(/^.*?([A-Z]+).*$/,"$1").split("").map(o=>o.toLowerCase());for(let o=1;o<i.length;o++){let n=i[o].replace(/^\((.*)\)$/,"$1").split(/ *, */);for(let m=0;m<a.length;m++){let r=n[m];switch(a[m]){case"x":case"y":case"w":r=Number.parseFloat(r);break;case"a":r=r.replace(/^<(.*)>$/,"$1");break;case"m":break;default:continue}t[a[m]]||(t[a[m]]=[]),t[a[m]].push(r)}}}var Q=require("dynamic-typing");var G=require("gyromagnetic-ratio"),W=Ce(require("ml-array-median"));function ue(e){return Array.isArray(e)?e[0]:e}function H(e){let{spectra:f}=e,t=f[0].data.y[0],i=t,a=f.length,o=f[0].data.x.length||0,n=new Array(a);for(let s=0;s<a;s++){n[s]=f[s].data.y;for(let l=0;l<o;l++){let c=n[s][l];c<t&&(t=c),c>i&&(i=c)}}let m=f[0].data.x[0],r=f[0].data.x.at(-1),{firstY:p,lastY:u}=Le(e);if(m>r)for(let s of n)s.reverse();p>u&&n.reverse();let b=[];for(let s of n){let l=Float64Array.from(s);for(let c=0;c<l.length;c++)l[c]<0&&(l[c]=-l[c]);b.push((0,W.default)(l))}let h=(0,W.default)(b);return{z:n,minX:Math.min(m,r),maxX:Math.max(m,r),minY:Math.min(p,u),maxY:Math.max(p,u),minZ:t,maxZ:i,noise:h}}function Le(e){let{spectra:f,ntuples:t,info:i}=e;if(t)for(let a of t){let{symbol:o,nucleus:n,units:m}=a;if(o.match(/[F|T]1/)&&m?.toUpperCase().match("HZ")){let r=ue(i[".OBSERVEFREQUENCY"]),{nucleus:p}=t.find(c=>c.symbol.match(/[F|T]2/));if([r,p,n].some(c=>!c))break;let u=(0,G.getGyromagneticRatio)(p),b=(0,G.getGyromagneticRatio)(n),{first:h,last:s}=a,l=b!==null&&u!==null?r*b/u:r;return{firstY:h/l,lastY:s/l}}}return{firstY:f[0].pageValue,lastY:f.at(-1).pageValue}}function J(e,f){let t=e.noise,i=e.z,a,o,n,m,r,p,u,b,h=i.length,s=i[0].length,l,c,d,A,y=e.minX,N=(e.maxX-y)/(s-1),C=e.minY,X=(e.maxY-C)/(h-1),M=e.minZ,S=e.maxZ,Y=f.nbContourLevels*2,R=new Array(Y),x;for(let F=0;F<Y;F++){let V={};R[F]=V;let ge=F%2,te=(S-f.noiseMultiplier*t)*Math.exp((F>>1)-f.nbContourLevels);ge===0?x=te+f.noiseMultiplier*t:x=0-te-f.noiseMultiplier*t;let D=[];if(V.zValue=x,V.lines=D,!(x<=M||x>=S))for(let v=0;v<h-1;v++){let ne=i[v],re=i[v+1];for(let T=0;T<s-1;T++)a=ne[T],o=ne[T+1],n=re[T],m=re[T+1],r=a>x,p=o>x,u=n>x,b=m>x,r!==p&&r!==u&&(l=T+(x-a)/(o-a),c=v,d=T,A=v+(x-a)/(n-a),D.push(l*N+y,c*X+C,d*N+y,A*X+C)),b!==p&&b!==u&&(l=T+1,c=v+1-(x-m)/(o-m),d=T+1-(x-m)/(n-m),A=v+1,D.push(l*N+y,c*X+C,d*N+y,A*X+C)),p!==u&&(l=(T+1-(x-o)/(n-o))*N+y,c=(v+(x-o)/(n-o))*X+C,p!==r&&(d=T+1-(x-o)/(a-o),A=v,D.push(l,c,d*N+y,A*X+C)),u!==r&&(d=T,A=v+1-(x-n)/(a-n),D.push(l,c,d*N+y,A*X+C)),p!==b&&(d=T+1,A=v+(x-o)/(m-o),D.push(l,c,d*N+y,A*X+C)),u!==b&&(d=T+(x-n)/(m-n),A=v+1,D.push(l,c,d*N+y,A*X+C)))}}return{minX:e.minX,maxX:e.maxX,minY:e.minY,maxY:e.maxY,segments:R}}function q(e,f){let t=H(e);f.noContour||(e.contourLines=J(t,f),delete t.z),e.minMax=t}var I=require("gyromagnetic-ratio");function z(e,f){for(let t of e){let i=0,a=0;for(let o of t.spectra){if(t.ntuples?.symbol?(!i&&o.observeFrequency&&(i=o.observeFrequency),!a&&o.shiftOffsetVal&&(a=o.shiftOffsetVal)):(i=o.observeFrequency,a=o.shiftOffsetVal),i&&o.xUnits?.toUpperCase().includes("HZ")&&(o.xUnits="PPM",o.xFactor=o.xFactor!==void 0?o.xFactor/i:void 0,o.firstX=o.firstX!==void 0?o.firstX/i:void 0,o.lastX=o.lastX!==void 0?o.lastX/i:void 0,o.deltaX=o.deltaX!==void 0?o.deltaX/i:void 0,o.data))for(let n=0;n<o.data.x.length;n++)o.data.x[n]/=i;if(a&&o.xUnits.toLowerCase().includes("ppm")&&o.firstX!==void 0&&o.lastX!==void 0){let n=o.firstX-a;if(o.firstX=o.firstX-n,o.lastX=o.lastX-n,o.data)for(let m=0;m<o.data.x.length;m++)o.data.x[m]-=n}if(t.ntuples?.nucleus&&t.ntuples.symbol)for(let n=0;n<t.ntuples.nucleus.length;n++){let m=t.ntuples.symbol[n],r=t.ntuples.nucleus[n];if(m.match(/^[F|T]/)&&!r){if(m.match(/[F|T]1/))if(t.tmp.$NUC2&&typeof t.tmp.$NUC2=="string")t.ntuples.nucleus[n]=t.tmp.$NUC2;else{let p=t.ntuples.symbol.indexOf(m.replace(/^([F|T]).*/,"$12"));p&&t.ntuples.nucleus[p]&&(t.ntuples.nucleus[n]=t.ntuples.nucleus[p])}m.match(/[F|T]2/)&&typeof t.tmp.$NUC1=="string"&&(t.ntuples.nucleus[n]=t.tmp.$NUC1)}m.match(/[F|T]2/)&&(t.yType=t.ntuples.nucleus[0],t.xType&&!(0,I.getGyromagneticRatio)(t.xType)&&(t.xType=t.ntuples.nucleus[1]))}if(i&&t.ntuples?.symbol&&t.ntuples.nucleus){let n="",m=t.ntuples.symbol.indexOf(o.pageSymbol);t.ntuples.units?.[m]&&(n=t.ntuples.units[m]);let{nucleus:r}=t.ntuples;if(!n.toLowerCase().match(/(ppm|seconds)/)&&r.length>1){if(m!==0){let h="Not sure about this ntuples format";if(f){f.warn(h);continue}else throw new Error(h)}let{nucleus:p}=t.ntuples,u=(0,I.getGyromagneticRatio)(p[0]),b=(0,I.getGyromagneticRatio)(p[1]);if(!u||!b){let h=`Problem with determination of gyromagnetic ratio for ${p.join("-")}`;if(f)f.error(h);else throw new Error(h)}else{let h=u/b*i;o.pageValue/=h}}}}}}function K(e){let f=e.spectra[0].data;e.chromatogram={times:f.x.slice(),series:{intensity:{dimension:1,data:f.y.slice()}}}}function _(e,f,t){z(e,t.logger),Me(e,t);for(let i of e){if(Object.keys(i.ntuples).length>0){let a=[],o=Object.keys(i.ntuples);for(let n of o){let m=i.ntuples[n];if(m)for(let r=0;r<m.length;r++)a[r]||(a[r]={}),a[r][n]=m[r]}i.ntuples=a}i.twoD&&t.wantXY&&(q(i,t),t.logger?.trace({profiling:!0},"Finished countour plot calculation"),t.keepSpectra||delete i.spectra),t.chromatogram&&(i.spectra.length>1?le(i):K(i),t.logger?.trace({profiling:!0},"Finished chromatogram calculation")),delete i.tmp}}function Me(e,f){for(let t of e)for(let i in t.meta){let a=t.meta[i];if(typeof a=="string"){if(a.startsWith("{")){if(!a.includes(":")&&a.endsWith("}")){let o=a.slice(1,-1).split(/[,; ]+/).filter(Boolean);for(let n=0;n<o.length;n++)t.meta[i+String(n)]=f.dynamicTyping?(0,Q.parseString)(o[n]):o[n]}}else if(a.startsWith("(")){let o=a.split(/\r?\n/),n=/^\((?<from>\d+)\.\.(?<to>\d+)\).*$/;if(n.test(o[0])){let[m,r]=o[0].match(n)?.slice(1).map(Number)??[],p=o.slice(1).join(" ").split(/[,; ]+/).filter(Boolean);for(let u=m;u<=r;u++)f.dynamicTyping&&typeof p[u-m]=="string"?t.meta[i+String(u)]=(0,Q.parseString)(p[u-m]):t.meta[i+String(u)]=p[u-m]}}}}}function ee(e,f,t){let i=-1,a=-1,o="",n="";if(t.indexOf("++")>0)o=t.replace(/.*\(([a-zA-Z0-9]+)\+\+.*/,"$1"),n=t.replace(/.*\.\.([a-zA-Z0-9]+).*/,"$1");else{t=t.replaceAll(/[^a-zA-Z%]/g,""),o=t.charAt(0),n=t.charAt(1),f.variables={};for(let m of t){let r=m.toLowerCase(),p=e.ntuples.symbol?.indexOf(m)||0;if(p===-1)throw new Error(`Symbol undefined: ${m}`);f.variables[r]={};for(let u in e.ntuples)e.ntuples[u]?.[p]&&(f.variables[r][u.replace(/^var/,"")]=e.ntuples[u]?.[p])}}i=e.ntuples.symbol?.indexOf(o)??-1,a=e.ntuples.symbol?.indexOf(n)??-1,i===-1&&(i=0),a===-1&&(a=0),e.ntuples.first&&(e.ntuples.first.length>i&&(f.firstX=e.ntuples.first[i]),e.ntuples.first.length>a&&(f.firstY=e.ntuples.first[a])),e.ntuples.last&&(e.ntuples.last.length>i&&(f.lastX=e.ntuples.last[i]),e.ntuples.last.length>a&&(f.lastY=e.ntuples.last[a])),e.ntuples.vardim&&e.ntuples.vardim.length>i&&(f.nbPoints=e.ntuples.vardim[i]),e.ntuples.factor&&(e.ntuples.factor.length>i&&(f.xFactor=e.ntuples.factor[i]),e.ntuples.factor.length>a&&(f.yFactor=e.ntuples.factor[a])),e.ntuples.units&&(e.ntuples.units.length>i&&(e.ntuples.varname?.[i]?f.xUnits=`${e.ntuples.varname[i]} [${e.ntuples.units[i]}]`:f.xUnits=e.ntuples.units[i]),e.ntuples.units.length>a&&(e.ntuples.varname?.[a]?f.yUnits=`${e.ntuples.varname[a]} [${e.ntuples.units[a]}]`:f.yUnits=e.ntuples.units[a]))}function U(e){e.xFactor||(e.xFactor=1),e.yFactor||(e.yFactor=1)}var L=/[ \t]*,[ \t]*/,Oe={keepRecordsRegExp:/^$/,canonicDataLabels:!0,canonicMetadataLabels:!1,dynamicTyping:!0,withoutXY:!1,noTrimRegExp:/^$/,chromatogram:!1,keepSpectra:!1,noContour:!1,nbContourLevels:7,noiseMultiplier:5};function de(e,f={}){e=(0,pe.ensureString)(e);let t={...Oe,...f};t.logger?.debug("Starting jcamp conversion"),t.wantXY=!t.withoutXY,t.start=Date.now();let i=[],a={entries:[],flatten:[]},o={children:[],spectra:[],ntuples:{},info:{},meta:{},tmp:{}},n=o,m=[],r={data:{}};t.logger?.trace({profiling:!0},"Before split to LDRS");let p=e.replaceAll(/[\r\n]+##/g,`
6
6
  ##`).split(`
7
- ##`);L(a,"Split to LDRS",i),o[0]&&(o[0]=o[0].replace(/^[\r\n ]*##/,""));for(let p of o){let c=p.indexOf("="),d=c>0?p.substring(0,c):p,u=c>0?d.match(i.noTrimRegExp)?p.substring(c+1):p.substring(c+1).trim():"",f=d.replace(/[_ -]/g,"").toUpperCase();if(f==="DATATABLE"){let m=u.indexOf(`
8
- `);if(m===-1&&(m=u.indexOf("\r")),m>0){let h=u.substring(0,m).split(/[ ,;\t]+/);_(l,t,h[0]),t.datatable=h[0],h[1]&&h[1].indexOf("PEAKS")>-1?f="PEAKTABLE":h[1]&&(h[1].indexOf("XYDATA")||h[0].indexOf("++")>0)&&(f="XYDATA",t.nbPoints&&(t.deltaX=(t.lastX-t.firstX)/(t.nbPoints-1)))}}if(f==="XYDATA"){i.wantXY&&(E(t),u.match(/.*\+\+.*/)?(t.nbPoints&&(t.deltaX=(t.lastX-t.firstX)/(t.nbPoints-1)),B(t,u,a)):w(t,u,a),l.spectra.push(t),t={});continue}else if(f==="PEAKTABLE"){i.wantXY&&(E(t),w(t,u,a),l.spectra.push(t),t={});continue}if(f==="PEAKASSIGNMENTS"){i.wantXY&&(u.match(/.*([^A-Z]*).*/)&&k(t,u),l.spectra.push(t),t={});continue}if(f==="TITLE"){let m=l;m.children||(m.children=[]),l={spectra:[],ntuples:{},info:{},meta:{},tmp:{}},m.children.push(l),r.push(m),s.push(l),l.title=u}else f==="DATATYPE"?(l.dataType=u,u.match(/(^nd|\snd\s)/i)&&(l.twoD=!0)):f==="NTUPLES"?u.match(/(^nd|\snd\s)/i)&&(l.twoD=!0):f==="DATACLASS"?l.dataClass=u:f==="JCAMPDX"?l.jcampDX=M(u):f==="JCAMPCS"?l.jcampCS=M(u):f==="XUNITS"?t.xUnits=u:f==="YUNITS"?t.yUnits=u:f==="FIRSTX"?t.firstX=Number(u):f==="LASTX"?t.lastX=Number(u):f==="FIRSTY"?t.firstY=Number(u):f==="LASTY"?t.lastY=Number(u):f==="NPOINTS"?t.nbPoints=Number(u):f==="XFACTOR"?t.xFactor=Number(u):f==="YFACTOR"?t.yFactor=Number(u):f==="MAXX"?t.maxX=Number(u):f==="MINX"?t.minX=Number(u):f==="MAXY"?t.maxY=Number(u):f==="MINY"?t.minY=Number(u):f==="DELTAX"?t.deltaX=Number(u):f===".OBSERVEFREQUENCY"||f==="$SFO1"?t.observeFrequency||(t.observeFrequency=Number(u)):f===".OBSERVENUCLEUS"?t.xType||(l.xType=u.replace(/[^a-zA-Z0-9]/g,"")):f==="$OFFSET"?(l.shiftOffsetNum=0,t.shiftOffsetVal||(t.shiftOffsetVal=Number(u))):f==="$REFERENCEPOINT"||(f==="VARNAME"?l.ntuples.varname=u.split(F):f==="SYMBOL"?l.ntuples.symbol=u.split(F):f==="VARTYPE"?l.ntuples.vartype=u.split(F):f==="VARFORM"?l.ntuples.varform=u.split(F):f==="VARDIM"?l.ntuples.vardim=Y(u.split(F)):f==="UNITS"?l.ntuples.units=u.split(F):f==="FACTOR"?l.ntuples.factor=Y(u.split(F)):f==="FIRST"?l.ntuples.first=Y(u.split(F)):f==="LAST"?l.ntuples.last=Y(u.split(F)):f==="MIN"?l.ntuples.min=Y(u.split(F)):f==="MAX"?l.ntuples.max=Y(u.split(F)):f===".NUCLEUS"?l.ntuples&&(l.ntuples.nucleus=u.split(F).map(m=>m.replace(/[^a-zA-Z0-9]/g,""))):f==="PAGE"?(t.page=u.trim(),t.pageValue=Number(u.replace(/^.*=/,"")),t.pageSymbol=t.page.replace(/[=].*/,"")):f==="RETENTIONTIME"?t.pageValue=Number(u):fe(f)?t[V(f)]=u:f==="SAMPLEDESCRIPTION"?t.sampleDescription=u:f.startsWith("$NUC")?!l.tmp[f]&&!u.includes("off")&&(l.tmp[f]=u.replace(/[<>]/g,"")):f==="END"&&(l=r.pop()));if(l&&l.info&&l.meta&&f.match(i.keepRecordsRegExp)){let m,h;d.startsWith("$")?(h=i.canonicMetadataLabels?f.substring(1):d.substring(1),m=l.meta):(h=i.canonicDataLabels?f:d,m=l.info),i.dynamicTyping&&(u=(0,me.parseString)(u)),m[h]?(Array.isArray(m[h])||(m[h]=[m[h]]),m[h].push(u)):m[h]=u}}if(L(a,"Finished parsing",i),W(s,a,i),L(a,"Total time",i),a.entries=n.children,a.flatten=s,i.logger){i.logger.debug("Finished jcamp conversion");for(let p of a.flatten)i.logger.debug(`${p.dataType} - ${p.title}`)}return a}function de(e,i={}){let{logger:s,OCL:a}=i;if(!e.info.ATOMLIST||!e.info.BONDLIST){s?.warn("No ATOMLIST or BONDLIST in the JCAMP-CS entry");return}we(e,s);let n=Re(e.info.ATOMLIST),l=Pe(e.info.BONDLIST),r=De(e.info.CHARGE,s),t=Oe(a,n,l,r,s);return{molecule:t,molfile:t.toMolfile()}}function Oe(e,i,s,a,n){let l={S:e.Molecule.cBondTypeSingle,D:e.Molecule.cBondTypeDouble,T:e.Molecule.cBondTypeTriple,Q:e.Molecule.cBondTypeQuadruple},r={},t=new e.Molecule(i.length,s.length);for(let o of i){let p=e.Molecule.getAtomicNoFromLabel(o.element);p||(n?.error(`Atomic number of ${o.element} could not be determined`),p=e.Molecule.getAtomicNoFromLabel("X")),r[o.atomNumber]=t.addAtom(p),t.setAtomMapNo(r[o.atomNumber],o.atomNumber)}for(let o of s){if(r[o.atomNumber1]===void 0){n?.error(`A bond goes to atomNumber ${o.atomNumber1} that does not exists`);continue}if(r[o.atomNumber2]===void 0){n?.error(`A bond goes to atomNumber ${o.atomNumber2} that does not exists`);continue}let p=t.addBond(r[o.atomNumber1],r[o.atomNumber2]);t.setBondType(p,l[o.bondType])}for(let o of a){if(r[o.atomNumber]===void 0){n?.error(`A charge goes to atomNumber ${o.atomNumber1} that does not exists`);continue}t.setAtomCharge(r[o.atomNumber],o.value)}return t}function Re(e){let i=e.split(/\r?\n/).map(a=>M(a)).filter(a=>a),s=[];for(let a of i){let[n,l,r]=a.trim().split(/\s+/);s.push({atomNumber:Number(n),element:l,nbImplicitHydrogens:r?.length>0?Number(r):void 0})}return s}function Pe(e){let i=e.split(/\r?\n/).map(a=>M(a)).filter(a=>a),s=[];for(let a of i){let[n,l,r]=a.trim().split(/\s+/);s.push({atomNumber1:Number(n),atomNumber2:Number(l),bondType:r})}return s}function De(e,i){if(!e)return[];let s=e.split(/\r?\n/).map(n=>M(n)).filter(n=>n),a=[];for(let n of s){let[l,r,t]=n.trim().split(/\s+/);t!==void 0&&i?.warn("Charge on multiple atom is not supported"),a.push({atomNumber:Number(r),value:Number(l)})}return a}function we(e,i){let s=["STEREOPAIR","STEREOCENTER","RADICAL","STEREOMOLECULE"];for(let a of s)e.info[a]&&i?.warn(`JCAMP-CS parser do not support: ${a}`)}
7
+ ##`);t.logger?.trace({profiling:!0},"Split to LDRS"),p[0]&&(p[0]=p[0].replace(/^[\r\n ]*##/,""));for(let u of p){let b=u.indexOf("="),h=b>0?u.slice(0,Math.max(0,b)):u,s=b>0?h.match(t.noTrimRegExp)?u.slice(Math.max(0,b+1)):u.slice(Math.max(0,b+1)).trim():"",l=h.replaceAll(/[_ -]/g,"").toUpperCase();if(l==="DATATABLE"){let c=s.indexOf(`
8
+ `);if(c===-1&&(c=s.indexOf("\r")),c>0){let d=s.slice(0,Math.max(0,c)).split(/[ ,;\t]+/);ee(n,r,d[0]),r.datatable=d[0],d[1]?.includes("PEAKS")?l="PEAKTABLE":d[1]&&(d[1].indexOf("XYDATA")||d[0].indexOf("++")>0)&&(l="XYDATA",r.nbPoints&&r.lastX!==void 0&&r.firstX!==void 0&&(r.deltaX=(r.lastX-r.firstX)/(r.nbPoints-1)))}}if(l==="XYDATA"){t.wantXY&&(U(r),s.match(/.*\+\+.*/)?(r.nbPoints&&r.lastX!==void 0&&r.firstX!==void 0&&(r.deltaX=(r.lastX-r.firstX)/(r.nbPoints-1)),j(r,s,t)):w(r,s,t),n?.spectra.push(r),r={data:{}});continue}else if(l==="PEAKTABLE"){t.wantXY&&(U(r),w(r,s,t),n?.spectra.push(r),r={data:{}});continue}if(l==="PEAKASSIGNMENTS"){t.wantXY&&(s.match(/.*[^A-Z]*.*/)&&Z(r,s),n?.spectra.push(r),r={data:{}});continue}if(s=s.split(/\r?\n/).map(c=>c.replace(/ *\$\$.*$/,"")).join(`
9
+ `),l==="TITLE"){let c=n;c.children||(c.children=[]),n={spectra:[],ntuples:{},info:{},meta:{},tmp:{}},c.children.push(n),m.push(c),i.push(n),n.title=s}else l==="DATATYPE"?(n.dataType=s,s.match(/^nd|\snd\s/i)&&(n.twoD=!0)):l==="NTUPLES"?s.match(/^nd|\snd\s/i)&&(n.twoD=!0):l==="DATACLASS"?n.dataClass=s:l==="JCAMPDX"?n.jcampDX=O(s):l==="JCAMPCS"?n.jcampCS=O(s):l==="XUNITS"?r.xUnits=s:l==="YUNITS"?r.yUnits=s:l==="FIRSTX"?r.firstX=Number(s):l==="LASTX"?r.lastX=Number(s):l==="FIRSTY"?r.firstY=Number(s):l==="LASTY"?r.lastY=Number(s):l==="NPOINTS"?r.nbPoints=Number(s):l==="XFACTOR"?r.xFactor=Number(s):l==="YFACTOR"?r.yFactor=Number(s):l==="MAXX"?r.maxX=Number(s):l==="MINX"?r.minX=Number(s):l==="MAXY"?r.maxY=Number(s):l==="MINY"?r.minY=Number(s):l==="DELTAX"?r.deltaX=Number(s):l===".OBSERVEFREQUENCY"||l==="$SFO1"?r.observeFrequency||(r.observeFrequency=Number(s)):l===".OBSERVENUCLEUS"?r.xType||(n.xType=s.replaceAll(/[^a-zA-Z0-9]/g,"")):l==="$OFFSET"?(n.shiftOffsetNum=0,r.shiftOffsetVal||(r.shiftOffsetVal=Number(s))):l==="$REFERENCEPOINT"||(l==="VARNAME"?n.ntuples.varname=s.split(L):l==="SYMBOL"?n.ntuples.symbol=s.split(L):l==="VARTYPE"?n.ntuples.vartype=s.split(L):l==="VARFORM"?n.ntuples.varform=s.split(L):l==="VARDIM"?n.ntuples.vardim=E(s.split(L)):l==="UNITS"?n.ntuples.units=s.split(L):l==="FACTOR"?n.ntuples.factor=E(s.split(L)):l==="FIRST"?n.ntuples.first=E(s.split(L)):l==="LAST"?n.ntuples.last=E(s.split(L)):l==="MIN"?n.ntuples.min=E(s.split(L)):l==="MAX"?n.ntuples.max=E(s.split(L)):l===".NUCLEUS"?n.ntuples&&(n.ntuples.nucleus=s.split(L).map(c=>c.replaceAll(/[^a-zA-Z0-9]/g,""))):l==="PAGE"?(r.page=s.trim(),r.pageValue=Number(s.replace(/^.*=/,"")),r.pageSymbol=r.page.replace(/[=].*/,"")):l==="RETENTIONTIME"?r.pageValue=Number(s):fe(l)?r[B(l)]=s:l==="SAMPLEDESCRIPTION"?r.sampleDescription=s:l.startsWith("$NUC")?!n.tmp[l]&&!s.includes("off")&&(n.tmp[l]=s.replaceAll(/[<>]/g,"")):l==="END"&&(n=m.pop()));if(n?.info&&n.meta&&l.match(t.keepRecordsRegExp)){let c,d;h.startsWith("$")?(d=t.canonicMetadataLabels?l.slice(1):h.slice(1),c=n.meta):(d=t.canonicDataLabels?l:h,c=n.info),t.dynamicTyping&&(s=(0,ce.parseString)(s)),c[d]?(Array.isArray(c[d])||(c[d]=[c[d]]),c[d].push(s)):c[d]=s}}if(t.logger?.trace({profiling:!0},"Finished parsing"),_(i,a,t),t.logger?.trace({profiling:!0},"Total time"),a.entries=o.children||[],a.flatten=i,t.logger){t.logger.debug("Finished jcamp conversion");for(let u of a.flatten)t.logger.debug(`${u.dataType} - ${u.title}`)}return a}function be(e,f){let{logger:t,OCL:i}=f;if(!e.info.ATOMLIST||!e.info.BONDLIST){t?.warn("No ATOMLIST or BONDLIST in the JCAMP-CS entry");return}Ye(e,t);let a=Ee(e.info.ATOMLIST),o=Re(e.info.BONDLIST),n=De(e.info.CHARGE,t),m=Fe(i,a,o,n,t);return{molecule:m,molfile:m.toMolfile()}}function Fe(e,f,t,i,a){let o={S:e.Molecule.cBondTypeSingle,D:e.Molecule.cBondTypeDouble,T:e.Molecule.cBondTypeTriple,Q:e.Molecule.cBondTypeQuadruple},n={},m=new e.Molecule(f.length,t.length);for(let r of f){let p=e.Molecule.getAtomicNoFromLabel(r.element);p||(a?.error(`Atomic number of ${r.element} could not be determined`),p=e.Molecule.getAtomicNoFromLabel("X")),n[r.atomNumber]=m.addAtom(p),m.setAtomMapNo(n[r.atomNumber],r.atomNumber,!1)}for(let r of t){if(n[r.atomNumber1]===void 0){a?.error(`A bond goes to atomNumber ${r.atomNumber1} that does not exists`);continue}if(n[r.atomNumber2]===void 0){a?.error(`A bond goes to atomNumber ${r.atomNumber2} that does not exists`);continue}let p=m.addBond(n[r.atomNumber1],n[r.atomNumber2]);m.setBondType(p,o[r.bondType])}for(let r of i){if(n[r.atomNumber]===void 0){a?.error(`A charge goes to atomNumber ${r.atomNumber} that does not exists`);continue}m.setAtomCharge(n[r.atomNumber],r.value)}return m}function Ee(e){let f=e.split(/\r?\n/).map(i=>O(i)).filter(Boolean),t=[];for(let i of f){let[a,o,n]=i.trim().split(/\s+/);t.push({atomNumber:Number(a),element:o,nbImplicitHydrogens:n?.length>0?Number(n):void 0})}return t}function Re(e){let f=e.split(/\r?\n/).map(i=>O(i)).filter(Boolean),t=[];for(let i of f){let[a,o,n]=i.trim().split(/\s+/);t.push({atomNumber1:Number(a),atomNumber2:Number(o),bondType:n})}return t}function De(e,f){if(!e)return[];let t=e.split(/\r?\n/).map(a=>O(a)).filter(Boolean),i=[];for(let a of t){let[o,n,m]=a.trim().split(/\s+/);m!==void 0&&f?.warn("Charge on multiple atom is not supported"),i.push({atomNumber:Number(n),value:Number(o)})}return i}function Ye(e,f){let t=["STEREOPAIR","STEREOCENTER","RADICAL","STEREOMOLECULE"];for(let i of t)e.info[i]&&f?.warn(`JCAMP-CS parser do not support: ${i}`)}
@@ -1,253 +1,213 @@
1
1
  import { Logger } from 'cheminfo-types';
2
+ import type { Molecule } from 'openchemlib';
3
+ import { openchemlib } from 'openchemlib';
4
+
5
+ declare interface Add2DOptions extends GenerateContourLinesOptions {
6
+ /**
7
+ * Don't calculate contour in case of 2D.
8
+ */
9
+ noContour?: boolean;
10
+ }
11
+
12
+ declare interface Chromatogram {
13
+ times: number[];
14
+ series: Record<string, {
15
+ dimension: number;
16
+ data: any[];
17
+ }>;
18
+ }
19
+
20
+ declare interface ContourLines {
21
+ minX: number;
22
+ maxX: number;
23
+ minY: number;
24
+ maxY: number;
25
+ segments: Array<{
26
+ zValue?: number;
27
+ lines?: number[];
28
+ }>;
29
+ }
2
30
 
3
31
  /**
4
- * Conversion options
5
- * @typedef {object} ConvertOptions@typedef {object} ConvertOptions
6
- * @property {RegExp} [keepRecordsRegExp=/^$/] - By default we don't keep meta information.
7
- * @property {boolean} [canonicDataLabels=true] - Canonize the Labels (uppercase without symbol).
8
- * @property {boolean} [canonicMetadataLabels=false] - Canonize the metadata Labels (uppercase without symbol).
9
- * @property {boolean} [dynamicTyping=false] - Convert numbers to Number.
10
- * @property {boolean} [withoutXY=false] - Remove the XY data.
11
- * @property {boolean} [chromatogram=false] - Special post-processing for GC / HPLC / MS.
12
- * @property {boolean} [keepSpectra=false] - Force to keep the spectra in case of 2D.
13
- * @property {RegExp} [noTrimRegExp=/^$/] - For which fields we should not trim ?
14
- * @property {boolean} [noContour=false] - Don't calculate countour in case of 2D.
15
- * @property {number} [nbContourLevels=7] - Number of positive / negative contour levels to calculate.
16
- * @property {number} [noiseMultiplier=5] - Define for 2D the level as 5 times the median as default.
17
- * @property {import('cheminfo-types').Logger} [logger] - A logger like 'pino'
18
- * @property {boolean} [profiling=false] - Add profiling information.
19
- */
20
- /**
21
- *
22
- * @typedef {object} Ntuples@typedef {object} Ntuples
23
- * @property {string[]} [varname]
24
- * @property {string[]} [symbol]
25
- * @property {string[]} [vartype]
26
- * @property {string[]} [varform]
27
- * @property {number[]} [vardim]
28
- * @property {string[]} [units]
29
- * @property {number[]} [factor]
30
- * @property {number[]} [first]
31
- * @property {number[]} [last]
32
- * @property {number[]} [min]
33
- * @property {number[]} [max]
34
- * @property {string[]} [nucleus]
35
- */
36
- /**
37
- * @typedef { Record<string, any> } Spectrum
38
- * @property {Record<string, number[]>} [data]
39
- * @property {number} [firstX] - first X value
40
- * @property {number} [lastX] - last X value
41
- * @property {number} [deltaX] - distance between 2 consecutive x axis values
42
- * @property {number} [yFactor] - y axis scaling factor
43
- * @property {number} [xFactor] - x axis scaling factor
44
- * @property {number} [nbPoints] - Number of points
45
- */
46
- /**
47
- *
48
- * @typedef {object} MinMax@typedef {object} MinMax
49
- * @property {number[][]} [z]
50
- * @property {number} minX
51
- * @property {number} maxX
52
- * @property {number} minY
53
- * @property {number} maxY
54
- * @property {number} minZ
55
- * @property {number} maxZ
56
- * @property {number} median
57
- */
58
- /**
59
- *
60
- * @typedef {object} Entry@typedef {object} Entry
61
- * @property {Spectrum[]} spectra
62
- * @property {Ntuples} ntuples
63
- * @property {Record<String, string | string[] | number | number[] | boolean | boolean[] | undefined>} meta
64
- * @property {Record<String, string | string[] | number | number[] | boolean | boolean[] | undefined>} info
65
- * @property {Record<String, string | string[] | number | number[] | boolean | boolean[] | undefined>} tmp
66
- * @property {string} [title]
67
- * @property {string} [dataType]
68
- * @property {string} [dataClass]
69
- * @property {string?} [jcampDX]
70
- * @property {string?} [jcampCS]
71
- * @property {boolean} [twoD]
72
- * @property {MinMax} [minMax]
73
- */
74
- /**
75
- *
76
- * @typedef { object } ConvertResult@typedef { object } ConvertResult
77
- * @property { object[] | boolean } profiling
78
- * @property { string[] } logs
79
- * @property { object[] } entries
80
- * @property { Entry[] } flatten
81
- */
82
- /**
83
- * Parse a jcamp.
84
- * The data can be provide as a string or array buffer. In this later case
32
+ * Parse JCAMP-DX data.
33
+ * The data can be provided as a string or array buffer. In this latter case
85
34
  * we will convert it first to a string before parsing.
86
- * @param {string|ArrayBuffer|Uint8Array} jcamp
87
- * @param {ConvertOptions} [options]
88
- * @returns {ConvertResult}
35
+ * @param jcamp
36
+ * @param optionsParam
37
+ * @returns Converted result.
89
38
  */
90
- export declare function convert(jcamp: string | ArrayBuffer | Uint8Array, options?: ConvertOptions | undefined): ConvertResult;
39
+ export declare function convert(jcamp: string | ArrayBuffer | Uint8Array, optionsParam?: ConvertOptions): ConvertResult;
91
40
 
92
41
  /**
93
- * Conversion options
42
+ * Conversion options.
94
43
  */
95
- declare type ConvertOptions = {
44
+ declare interface ConvertOptions extends Partial<Add2DOptions> {
96
45
  /**
97
- * - By default we don't keep meta information.
46
+ * By default we don't keep meta information.
47
+ * @default `/^$/`
98
48
  */
99
- keepRecordsRegExp?: RegExp | undefined;
49
+ keepRecordsRegExp?: RegExp;
100
50
  /**
101
- * - Canonize the Labels (uppercase without symbol).
51
+ * Canonize the Labels (uppercase without symbol).
102
52
  */
103
- canonicDataLabels?: boolean | undefined;
53
+ canonicDataLabels?: boolean;
104
54
  /**
105
- * - Canonize the metadata Labels (uppercase without symbol).
55
+ * Canonize the metadata Labels (uppercase without symbol).
106
56
  */
107
- canonicMetadataLabels?: boolean | undefined;
57
+ canonicMetadataLabels?: boolean;
108
58
  /**
109
- * - Convert numbers to Number.
59
+ * Convert numbers to Number.
110
60
  */
111
- dynamicTyping?: boolean | undefined;
61
+ dynamicTyping?: boolean;
112
62
  /**
113
- * - Remove the XY data.
63
+ * Remove the XY data.
114
64
  */
115
- withoutXY?: boolean | undefined;
65
+ withoutXY?: boolean;
116
66
  /**
117
- * - Special post-processing for GC / HPLC / MS.
67
+ * Special post-processing for GC / HPLC / MS.
118
68
  */
119
- chromatogram?: boolean | undefined;
69
+ chromatogram?: boolean;
120
70
  /**
121
- * - Force to keep the spectra in case of 2D.
71
+ * Force to keep the spectra in case of 2D.
122
72
  */
123
- keepSpectra?: boolean | undefined;
73
+ keepSpectra?: boolean;
124
74
  /**
125
- * - For which fields we should not trim ?
75
+ * For which fields we should not trim ?
76
+ * @default `/^$/`
126
77
  */
127
- noTrimRegExp?: RegExp | undefined;
78
+ noTrimRegExp?: RegExp;
128
79
  /**
129
- * - Don't calculate countour in case of 2D.
80
+ * A logger like `pino`.
130
81
  */
131
- noContour?: boolean | undefined;
82
+ logger?: Logger;
132
83
  /**
133
- * - Number of positive / negative contour levels to calculate.
84
+ * Add profiling information.
134
85
  */
135
- nbContourLevels?: number | undefined;
136
- /**
137
- * - Define for 2D the level as 5 times the median as default.
138
- */
139
- noiseMultiplier?: number | undefined;
140
- /**
141
- * - A logger like 'pino'
142
- */
143
- logger?: Logger | undefined;
144
- /**
145
- * - Add profiling information.
146
- */
147
- profiling?: boolean | undefined;
148
- };
86
+ wantXY?: boolean;
87
+ start?: number;
88
+ fastParse?: boolean;
89
+ }
149
90
 
150
- declare type ConvertResult = {
151
- profiling: object[] | boolean;
152
- logs: string[];
153
- entries: object[];
91
+ declare interface ConvertResult {
92
+ entries: Entry[];
154
93
  flatten: Entry[];
155
- };
94
+ }
156
95
 
157
96
  /**
158
- *
159
- * @typedef {object} CreateTreeOptions@typedef {object} CreateTreeOptions
160
- * @property {boolean} [flatten=false]
97
+ * Parse the JCAMP-DX to extract the structure as a tree.
98
+ * @param jcamp
99
+ * @param options
100
+ * @returns Tree.
161
101
  */
162
- /**
163
- *
164
- * @typedef {object} Tree@typedef {object} Tree
165
- * @property {string} title
166
- * @property {string} jcamp
167
- * @property {Tree[]} [children]
168
- */
169
- /**
170
- * Parse the jcamp to extract the structure as a tree.
171
- *
172
- * @param {string|ArrayBuffer|Uint8Array} jcamp
173
- * @param {CreateTreeOptions} [options={}]
174
- * @returns {Tree[]}
175
- */
176
- export declare function createTree(jcamp: string | ArrayBuffer | Uint8Array, options?: CreateTreeOptions | undefined): Tree[];
102
+ export declare function createTree(jcamp: string | ArrayBuffer | Uint8Array, options?: CreateTreeOptions): Stack[];
177
103
 
178
- declare type CreateTreeOptions = {
179
- flatten?: boolean | undefined;
180
- };
104
+ declare interface CreateTreeOptions {
105
+ flatten?: boolean;
106
+ }
181
107
 
182
- declare type Entry = {
108
+ declare interface Entry {
183
109
  spectra: Spectrum[];
184
110
  ntuples: Ntuples;
185
111
  meta: Record<string, string | string[] | number | number[] | boolean | boolean[] | undefined>;
186
112
  info: Record<string, string | string[] | number | number[] | boolean | boolean[] | undefined>;
187
113
  tmp: Record<string, string | string[] | number | number[] | boolean | boolean[] | undefined>;
188
- title?: string | undefined;
189
- dataType?: string | undefined;
190
- dataClass?: string | undefined;
191
- jcampDX?: string | null | undefined;
192
- jcampCS?: string | null | undefined;
193
- twoD?: boolean | undefined;
194
- minMax?: MinMax | undefined;
195
- };
196
-
197
- declare type MinMax = {
198
- z?: number[][] | undefined;
114
+ title?: string;
115
+ dataType?: string;
116
+ dataClass?: string;
117
+ jcampDX?: string;
118
+ jcampCS?: string;
119
+ twoD?: boolean;
120
+ minMax?: MinMax;
121
+ children?: Entry[];
122
+ shiftOffsetVal?: number;
123
+ shiftOffsetNum?: number;
124
+ xType?: string;
125
+ yType?: string;
126
+ chromatogram?: Chromatogram;
127
+ contourLines?: ContourLines;
128
+ }
129
+
130
+ declare interface GenerateContourLinesOptions {
131
+ /**
132
+ * Number of positive / negative contour levels to calculate.
133
+ * @default `7`
134
+ */
135
+ nbContourLevels: number;
136
+ /**
137
+ * Define for 2D the level as 5 times the median as default.
138
+ * @default `5`
139
+ */
140
+ noiseMultiplier: number;
141
+ }
142
+
143
+ declare interface MinMax {
144
+ z: number[][];
199
145
  minX: number;
200
146
  maxX: number;
201
147
  minY: number;
202
148
  maxY: number;
203
149
  minZ: number;
204
150
  maxZ: number;
205
- median: number;
206
- };
207
-
208
- declare type Ntuples = {
209
- varname?: string[] | undefined;
210
- symbol?: string[] | undefined;
211
- vartype?: string[] | undefined;
212
- varform?: string[] | undefined;
213
- vardim?: number[] | undefined;
214
- units?: string[] | undefined;
215
- factor?: number[] | undefined;
216
- first?: number[] | undefined;
217
- last?: number[] | undefined;
218
- min?: number[] | undefined;
219
- max?: number[] | undefined;
220
- nucleus?: string[] | undefined;
221
- };
151
+ median?: number;
152
+ noice?: number;
153
+ }
154
+
155
+ declare interface Ntuples {
156
+ varname?: string[];
157
+ symbol?: string[];
158
+ vartype?: string[];
159
+ varform?: string[];
160
+ vardim?: number[];
161
+ units?: string[];
162
+ factor?: number[];
163
+ first?: number[];
164
+ last?: number[];
165
+ min?: number[];
166
+ max?: number[];
167
+ nucleus?: string[];
168
+ [key: string]: any | undefined;
169
+ }
170
+
171
+ declare type OCL = openchemlib;
172
+
173
+ declare interface ParsedCS {
174
+ molfile: string;
175
+ molecule: Molecule;
176
+ }
222
177
 
223
178
  /**
224
179
  *
225
- * @typedef {object} ParsedCS@typedef {object} ParsedCS
226
- * @property {string} molfile
227
- * @property {import("openchemlib").OCL} molecule
228
- */
229
- /**
230
- *
231
- * @param {import("./convert.js").Entry} entry
232
- * @param {object} [options={}]
233
- * @param {import("fifo-logger").Logger} [options.logger]
234
- * @param {import("openchemlib").OCL} [options.OCL]
180
+ * @param entry
181
+ * @param options
235
182
  * @returns ParsedCS
236
183
  */
237
- export declare function parseJcampCS(entry: Entry, options?: {
238
- logger?: any;
239
- OCL?: any;
240
- } | undefined): {
241
- molecule: any;
242
- molfile: any;
243
- } | undefined;
184
+ export declare function parseJcampCS(entry: Entry, options: ParseJcampCSOptions): ParsedCS | undefined;
185
+
186
+ declare interface ParseJcampCSOptions {
187
+ OCL: OCL;
188
+ logger?: Logger;
189
+ }
244
190
 
245
- declare type Spectrum = Record<string, any>;
191
+ declare interface Spectrum {
192
+ [key: string]: any;
193
+ data: Record<string, number[]>;
194
+ firstX?: number;
195
+ firstY?: number;
196
+ lastX?: number;
197
+ deltaX?: number;
198
+ yFactor?: number;
199
+ xFactor?: number;
200
+ nbPoints?: number;
201
+ }
246
202
 
247
- declare type Tree = {
203
+ declare interface Stack {
248
204
  title: string;
249
205
  jcamp: string;
250
- children?: Tree[] | undefined;
251
- };
206
+ children: Stack[] | undefined;
207
+ jcampDX?: string;
208
+ jcampCS?: string;
209
+ dataType?: string;
210
+ dataClass?: string;
211
+ }
252
212
 
253
213
  export { }
@@ -1,8 +1,9 @@
1
- import{ensureString as ue}from"ensure-string";var P=/\s*\$\$.*/;function M(e){return e.replace(P,"")}function pe(e,a={}){e=ue(e);let{flatten:s=!1}=a;if(typeof e!="string")throw new TypeError("the JCAMP should be a string");let i=e.split(/\r?\n/),o=[],l=[],r=[],t,n=0,p=e.includes("## ");for(let c=0;c<i.length;c++){let d=i[c],u=p?d.replace(/ /g,""):d;if(u.substring(0,9)==="##NTUPLES"&&n++,u.substring(0,7)==="##TITLE"){let f=[u.substring(8).trim()];for(let m=c+1;m<i.length&&!i[m].startsWith("##");m++)f.push(i[m].trim());l.push({title:f.join(`
2
- `),jcamp:`${d}
3
- `,children:[]}),t=l[l.length-1],o.push(t)}else if(u.substring(0,5)==="##END"&&n===0){t.jcamp+=`${d}
4
- `;let f=l.pop();l.length!==0?(t=l[l.length-1],t.children.push(f)):(t=void 0,r.push(f))}else if(t&&t.jcamp){t.jcamp+=`${d}
5
- `;let f=u.match(/^##(.*?)=(.+)/);if(f){let m=f[1].replace(/[ _-]/g,"").toUpperCase();m==="DATATYPE"?t.dataType=f[2].trim():m==="DATACLASS"?t.dataClass=f[2].trim():m==="JCAMPDX"?t.jcampDX=M(f[2].trim()):m==="JCAMPCS"&&(t.jcampCS=M(f[2].trim()))}}u.substring(0,5)==="##END"&&n>0&&n--}return s?(o.forEach(c=>{c.children=void 0}),o):r}import{parseString as ge}from"dynamic-typing";import{ensureString as be}from"ensure-string";var E=["TIC",".RIC","SCANNUMBER"];function te(e){let a=e.spectra,s=a.length,i={times:new Array(s),series:{ms:{dimension:2,data:new Array(s)}}},o=[];for(let l=0;l<E.length;l++){let r=I(E[l]);a[0][r]&&(o.push(r),i.series[r]={dimension:1,data:new Array(s)})}for(let l=0;l<s;l++){let r=a[l];i.times[l]=r.pageValue;for(let t=0;t<o.length;t++)i.series[o[t]].data[l]=Number(r[o[t]]);r.data&&(i.series.ms.data[l]=[r.data.x,r.data.y])}e.chromatogram=i}function le(e){return E.indexOf(e)!==-1}function I(e){return e.toLowerCase().replace(/[^a-z0-9]/g,"")}function Y(e){let a=[];for(let s=0;s<e.length;s++)a.push(Number(e[s]));return a}function U(e,a){let s=e.yFactor,i=e.deltaX;e.isXYdata=!0;let o={x:[],y:[]};e.data=o;let l=e.firstX,r=e.firstY,t=!1,n,p=0;for(;p<a.length;p++)if(n=a.charCodeAt(p),n===13||n===10)t=!0;else if(t)break;let c=!0,d=!1,u=!1,f=0,m=!1,h=!1,g=0,A=0,N=!1,y=!1,C=!1,T=0;for(;p<=a.length;p++)if(p===a.length?n=13:n=a.charCodeAt(p),h)(n===13||n===10)&&(c=!0,h=!1);else if(n<=57&&n>=48)y=!0,T>0?g+=(n-48)/10**T++:(g*=10,g+=n-48);else if(n===44||n===46)y=!0,T++;else{if(y){if(c)c=!1,u&&(C=!0);else if(C)C=!1;else{d?(f=N?0-g:g,u=!0,d=!1):m||(A=N?0-g:g);let O=m?g-1:1;for(let v=0;v<O;v++)u?r+=f:r=A,o.x.push(l),o.y.push(r*s),l+=i}N=!1,g=0,T=0,y=!1,m=!1}if(n<74&&n>63)y=!0,u=!1,g=n-64;else if(n>96&&n<106)y=!0,u=!1,g=n-96,N=!0;else if(n===115)y=!0,m=!0,g=9;else if(n>82&&n<91)y=!0,m=!0,g=n-82;else if(n>73&&n<83)y=!0,d=!0,g=n-73;else if(n>105&&n<115)y=!0,d=!0,g=n-105,N=!0;else if(n===36&&a.charCodeAt(p+1)===36)y=!0,h=!0;else if(n===37)y=!0,d=!0,g=0,N=!1;else if(n===45){let O=a.charCodeAt(p+1);(O>=48&&O<=57||O===44||O===46)&&(y=!0,c||(u=!1),N=!0)}else(n===13||n===10)&&(c=!0,h=!1)}}var se=/[,\t ]+/;function D(e,a,s){if(e.isPeaktable=!0,!e.variables||Object.keys(e.variables)===2?me(e,a,s):ce(e,a,s),e.variables)for(let i in e.variables)e.variables[i].data=e.data[i]}function me(e,a,s){let i={x:[],y:[]};e.data=i;let o=a.split(/,? *,?[;\r\n]+ */);for(let l=1;l<o.length;l++){let r=o[l].trim().replace(P,"").split(se);if(r.length%2===0)for(let t=0;t<r.length;t=t+2)i.x.push(Number(r[t])*e.xFactor),i.y.push(Number(r[t+1])*e.yFactor);else s.logs.push(`Format error: ${r}`)}}function ce(e,a,s){let i={},o=Object.keys(e.variables),l=o.length;o.forEach(t=>i[t]=[]),e.data=i;let r=a.split(/,? *,?[;\r\n]+ */);for(let t=1;t<r.length;t++){let n=r[t].trim().replace(P,"").split(se);if(n.length%l===0)for(let p=0;p<n.length;p++)i[o[p%l]].push(Number(n[p]));else s.logs.push(`Wrong number of columns: ${n}`)}}function V(e,a){e.isXYAdata=!0;let s={};e.data=s;let i=a.split(/\r?\n/),o=i[0].replace(/^.*?([A-Z]+).*$/,"$1").split("").map(l=>l.toLowerCase());for(let l=1;l<i.length;l++){let r=i[l].replace(/^\((.*)\)$/,"$1").split(/ *, */);for(let t=0;t<o.length;t++){let n=r[t];switch(o[t]){case"x":case"y":case"w":n=Number.parseFloat(n);break;case"a":n=n.replace(/^<(.*)>$/,"$1");break;case"m":break;default:continue}s[o[t]]||(s[o[t]]=[]),s[o[t]].push(n)}}}import{parseString as ne}from"dynamic-typing";import{getGyromagneticRatio as ae}from"gyromagnetic-ratio";import re from"ml-array-median";function ie(e){return Array.isArray(e)?e[0]:e}function B(e){let{spectra:a}=e,s=a[0].data.y[0],i=s,o=a.length,l=a[0].data.x.length,r=new Array(o);for(let f=0;f<o;f++){r[f]=a[f].data.y;for(let m=0;m<l;m++){let h=r[f][m];h<s&&(s=h),h>i&&(i=h)}}let t=a[0].data.x[0],n=a[0].data.x[a[0].data.x.length-1],{firstY:p,lastY:c}=he(e);if(t>n)for(let f of r)f.reverse();p>c&&r.reverse();let d=[];for(let f=0;f<r.length;f++){let m=Float64Array.from(r[f]);for(let h=0;h<m.length;h++)m[h]<0&&(m[h]=-m[h]);d.push(re(m))}let u=re(d);return{z:r,minX:Math.min(t,n),maxX:Math.max(t,n),minY:Math.min(p,c),maxY:Math.max(p,c),minZ:s,maxZ:i,noise:u}}function he(e){let{spectra:a,ntuples:s,info:i}=e;if(s)for(let o=0;o<s.length;o++){let{symbol:l,nucleus:r}=s[o];if(l.match(/[F|T]1/)){let t=ie(i[".OBSERVEFREQUENCY"]),{nucleus:n}=s.find(m=>m.symbol.match(/[F|T]2/));if([t,n,r].some(m=>!m))break;let p=ae(n),c=ae(r),{first:d,last:u}=s[o],f=t*c/p;return{firstY:d/f,lastY:u/f}}}return{firstY:a[0].pageValue,lastY:a[a.length-1].pageValue}}function k(e,a){let s=e.noise,i=e.z,o,l,r,t,n,p,c,d,u=i.length,f=i[0].length,m,h,g,A,N=e.minX,C=(e.maxX-N)/(f-1),T=e.minY,v=(e.maxY-T)/(u-1),oe=e.minZ,K=e.maxZ,Q=a.nbContourLevels*2,W=new Array(Q),x;for(let R=0;R<Q;R++){let $={};W[R]=$;let fe=R%2,_=(K-a.noiseMultiplier*s)*Math.exp((R>>1)-a.nbContourLevels);fe===0?x=_+a.noiseMultiplier*s:x=0-_-a.noiseMultiplier*s;let b=[];if($.zValue=x,$.lines=b,!(x<=oe||x>=K))for(let X=0;X<u-1;X++){let z=i[X],ee=i[X+1];for(let S=0;S<f-1;S++)o=z[S],l=z[S+1],r=ee[S],t=ee[S+1],n=o>x,p=l>x,c=r>x,d=t>x,n!==p&&n!==c&&(m=S+(x-o)/(l-o),h=X,g=S,A=X+(x-o)/(r-o),b.push(m*C+N),b.push(h*v+T),b.push(g*C+N),b.push(A*v+T)),d!==p&&d!==c&&(m=S+1,h=X+1-(x-t)/(l-t),g=S+1-(x-t)/(r-t),A=X+1,b.push(m*C+N),b.push(h*v+T),b.push(g*C+N),b.push(A*v+T)),p!==c&&(m=(S+1-(x-l)/(r-l))*C+N,h=(X+(x-l)/(r-l))*v+T,p!==n&&(g=S+1-(x-l)/(o-l),A=X,b.push(m),b.push(h),b.push(g*C+N),b.push(A*v+T)),c!==n&&(g=S,A=X+1-(x-r)/(o-r),b.push(m),b.push(h),b.push(g*C+N),b.push(A*v+T)),p!==d&&(g=S+1,A=X+(x-l)/(t-l),b.push(m),b.push(h),b.push(g*C+N),b.push(A*v+T)),c!==d&&(g=S+(x-r)/(t-r),A=X+1,b.push(m),b.push(h),b.push(g*C+N),b.push(A*v+T)))}}return{minX:e.minX,maxX:e.maxX,minY:e.minY,maxY:e.maxY,segments:W}}function j(e,a){let s=B(e);a.noContour||(e.contourLines=k(s,a),delete s.z),e.minMax=s}import{getGyromagneticRatio as Z}from"gyromagnetic-ratio";function J(e,a){for(let s of e){let i=0,o=0;for(let l of s.spectra){if(s.ntuples&&s.ntuples.symbol?(!i&&l.observeFrequency&&(i=l.observeFrequency),!o&&l.shiftOffsetVal&&(o=l.shiftOffsetVal)):(i=l.observeFrequency,o=l.shiftOffsetVal),i&&l.xUnits&&l.xUnits.toUpperCase().includes("HZ")){l.xUnits="PPM",l.xFactor=l.xFactor/i,l.firstX=l.firstX/i,l.lastX=l.lastX/i,l.deltaX=l.deltaX/i;for(let r=0;r<l.data.x.length;r++)l.data.x[r]/=i}if(o&&l.xUnits.toLowerCase().includes("ppm")){let r=l.firstX-o;l.firstX=l.firstX-r,l.lastX=l.lastX-r;for(let t=0;t<l.data.x.length;t++)l.data.x[t]-=r}if(s.ntuples&&s.ntuples.nucleus&&s.ntuples.symbol)for(let r=0;r<s.ntuples.nucleus.length;r++){let t=s.ntuples.symbol[r],n=s.ntuples.nucleus[r];if(t.match(/^[F|T]/)&&!n){if(t.match(/[F|T]1/))if(s.tmp.$NUC2)s.ntuples.nucleus[r]=s.tmp.$NUC2;else{let p=s.ntuples.symbol.indexOf(t.replace(/^([F|T]).*/,"$12"));p&&s.ntuples.nucleus[p]&&(s.ntuples.nucleus[r]=s.ntuples.nucleus[p])}t.match(/[F|T]2/)&&(s.ntuples.nucleus[r]=s.tmp.$NUC1)}t.match(/[F|T]2/)&&(s.yType=s.ntuples.nucleus[0],Z(s.xType)||(s.xType=s.ntuples.nucleus[1]))}if(i&&s.ntuples&&s.ntuples.symbol&&s.ntuples.nucleus){let r="",t=s.ntuples.symbol.indexOf(l.pageSymbol);if(s.ntuples.units&&s.ntuples.units[t]&&(r=s.ntuples.units[t]),!r.toLowerCase().match(/(ppm|seconds)/)){if(t!==0){let u="Not sure about this ntuples format";if(a)a.warn(u);else throw Error(u)}let{nucleus:n}=s.ntuples,p=Z(n[0]),c=Z(n[1]);if(!p||!c){let u=`Problem with determination of gyromagnetic ratio for ${n.join("-")}`;if(a)a.error(u);else throw Error(u)}let d=p/c*i;l.pageValue/=d}}}}}function L(e,a,s={}){s.logger?.trace(a),e.profiling&&e.profiling.push({action:a,time:Date.now()-s.start})}function G(e){let a=e.spectra[0].data;e.chromatogram={times:a.x.slice(),series:{intensity:{dimension:1,data:a.y.slice()}}}}function H(e,a,s){J(e,s.logger),de(e,s);for(let i of e){if(Object.keys(i.ntuples).length>0){let o=[],l=Object.keys(i.ntuples);for(let r=0;r<l.length;r++){let t=l[r],n=i.ntuples[t];for(let p=0;p<n.length;p++)o[p]||(o[p]={}),o[p][t]=n[p]}i.ntuples=o}i.twoD&&s.wantXY&&(j(i,s),L(a,"Finished countour plot calculation",s),s.keepSpectra||delete i.spectra),s.chromatogram&&(i.spectra.length>1?te(i):G(i),L(a,"Finished chromatogram calculation",s)),delete i.tmp}}function de(e,a){for(let s of e)for(let i in s.meta){let o=s.meta[i];if(typeof o=="string"){if(o[0]==="{"){if(!o.includes(":")&&o[o.length-1]==="}"){let l=o.slice(1,-1).split(/[,; ]+/).filter(r=>r);for(let r=0;r<l.length;r++)s.meta[i+String(r)]=a.dynamicTyping?ne(l[r]):l[r]}}else if(o[0]==="("){let l=o.split(/\r?\n/),r=/^\((?<from>\d+)\.\.(?<to>\d+)\).*$/;if(r.test(l[0])){let[t,n]=l[0].match(r).slice(1).map(Number),p=l.slice(1).join(" ").split(/[,; ]+/).filter(c=>c);for(let c=t;c<=n;c++)a.dynamicTyping&&typeof p[c-t]=="string"?s.meta[i+String(c)]=ne(p[c-t]):s.meta[i+String(c)]=p[c-t]}}}}}function q(e,a,s){let i=-1,o=-1,l="",r="";if(s.indexOf("++")>0)l=s.replace(/.*\(([a-zA-Z0-9]+)\+\+.*/,"$1"),r=s.replace(/.*\.\.([a-zA-Z0-9]+).*/,"$1");else{s=s.replace(/[^a-zA-Z%]/g,""),l=s.charAt(0),r=s.charAt(1),a.variables={};for(let t of s){let n=t.toLowerCase(),p=e.ntuples.symbol.indexOf(t);if(p===-1)throw Error(`Symbol undefined: ${t}`);a.variables[n]={};for(let c in e.ntuples)e.ntuples[c][p]&&(a.variables[n][c.replace(/^var/,"")]=e.ntuples[c][p])}}i=e.ntuples.symbol.indexOf(l),o=e.ntuples.symbol.indexOf(r),i===-1&&(i=0),o===-1&&(o=0),e.ntuples.first&&(e.ntuples.first.length>i&&(a.firstX=e.ntuples.first[i]),e.ntuples.first.length>o&&(a.firstY=e.ntuples.first[o])),e.ntuples.last&&(e.ntuples.last.length>i&&(a.lastX=e.ntuples.last[i]),e.ntuples.last.length>o&&(a.lastY=e.ntuples.last[o])),e.ntuples.vardim&&e.ntuples.vardim.length>i&&(a.nbPoints=e.ntuples.vardim[i]),e.ntuples.factor&&(e.ntuples.factor.length>i&&(a.xFactor=e.ntuples.factor[i]),e.ntuples.factor.length>o&&(a.yFactor=e.ntuples.factor[o])),e.ntuples.units&&(e.ntuples.units.length>i&&(e.ntuples.varname&&e.ntuples.varname[i]?a.xUnits=`${e.ntuples.varname[i]} [${e.ntuples.units[i]}]`:a.xUnits=e.ntuples.units[i]),e.ntuples.units.length>o&&(e.ntuples.varname&&e.ntuples.varname[o]?a.yUnits=`${e.ntuples.varname[o]} [${e.ntuples.units[o]}]`:a.yUnits=e.ntuples.units[o]))}function w(e){e.xFactor||(e.xFactor=1),e.yFactor||(e.yFactor=1)}var F=/[ \t]*,[ \t]*/,xe={keepRecordsRegExp:/^$/,canonicDataLabels:!0,canonicMetadataLabels:!1,dynamicTyping:!0,withoutXY:!1,noTrimRegExp:/^$/,chromatogram:!1,keepSpectra:!1,noContour:!1,nbContourLevels:7,noiseMultiplier:5,profiling:!1};function Ne(e,a={}){e=be(e),a={...xe,...a},a.logger?.debug("Starting jcamp conversion"),a.wantXY=!a.withoutXY,a.start=Date.now();let s=[],i={profiling:a.profiling?[]:!1,logs:[],entries:[]},o={children:[]},l=o,r=[],t={};if(typeof e!="string")throw new TypeError("the JCAMP should be a string");L(i,"Before split to LDRS",a);let n=e.replace(/[\r\n]+##/g,`
1
+ import{ensureString as fe}from"ensure-string";var $=/\s*\$\$.*/;function O(e){return e.replace($,"")}function me(e,m={}){e=fe(e);let{flatten:n=!1}=m,i=e.split(/\r?\n/),f=[],o=[],t=[],l={title:"",jcamp:"",children:[]},r=0,p=e.includes("## ");for(let u=0;u<i.length;u++){let b=i[u],h=p?b.replaceAll(" ",""):b;if(h.startsWith("##NTUPLES")&&r++,h.startsWith("##TITLE")){let s=[h.slice(8).trim()];for(let a=u+1;a<i.length&&!i[a].startsWith("##");a++)s.push(i[a].trim());o.push({title:s.join(`
2
+ `),jcamp:`${b}
3
+ `,children:[]}),l=o.at(-1),f.push(l)}else if(h.startsWith("##END")&&r===0&&l){l.jcamp+=`${b}
4
+ `;let s=o.pop();if(!s)throw new Error("Not finished");o.length>0?(l=o.at(-1),l.children?.push(s)):(l=void 0,t.push(s))}else if(l?.jcamp){l.jcamp+=`${b}
5
+ `;let s=h.match(/^##(.*?)=(.+)/);if(s){let a=s[1].replaceAll(/[ _-]/g,"").toUpperCase();a==="DATATYPE"?l.dataType=s[2].trim():a==="DATACLASS"?l.dataClass=s[2].trim():a==="JCAMPDX"?l.jcampDX=O(s[2].trim()):a==="JCAMPCS"&&(l.jcampCS=O(s[2].trim()))}}h.startsWith("##END")&&r>0&&r--}if(n){for(let u of f)u.children=void 0;return f}else return t}import{parseString as be}from"dynamic-typing";import{ensureString as ge}from"ensure-string";var ee=["TIC",".RIC","SCANNUMBER"];function te(e){let m=e.spectra,n=m.length,i={times:new Array(n),series:{ms:{dimension:2,data:new Array(n)}}},f=[];for(let o of ee){let t=k(o);m[0][t]&&(f.push(t),i.series[t]={dimension:1,data:new Array(n)})}for(let o=0;o<n;o++){let t=m[o];i.times[o]=t.pageValue;for(let l of f)i.series[l].data[o]=Number(t[l]);t.data&&(i.series.ms.data[o]=[t.data.x,t.data.y])}e.chromatogram=i}function ne(e){return ee.includes(e)}function k(e){return e.toLowerCase().replaceAll(/[^a-z0-9]/g,"")}function E(e){return e.map(Number)}function V(e,m,n){let{logger:i}=n;i&&(e.xFactor||i.info("The xFactor is not defined, it will be set to 1"),e.yFactor||i.info("The yFactor is not defined, it will be set to 1"));let f=e.yFactor??1,o=e.xFactor??1,t=e.deltaX??1,l=Math.abs(t*.1),r=.01;e.isXYdata=!0;let p={x:[],y:[]};e.data=p;let u=e.firstX||0,b=e.firstY||0,h=!1,s,a=0;for(;a<m.length;a++)if(s=m.codePointAt(a),s===13||s===10)h=!0;else if(h)break;let c=0,d=!0,A=!1,y=!1,I=0,N=!1,C=!1,g=0,X=0,M=!1,S=!1,Y=!1,R=0;for(;a<=m.length;a++)if(a===m.length?s=13:s=m.codePointAt(a),C)(s===13||s===10)&&(d=!0,C=!1,c++);else if(s<=57&&s>=48)S=!0,R>0?g+=(s-48)/10**R++:(g*=10,g+=s-48);else if(s===44||s===46)S=!0,R++;else{if(S){if(M&&(g=g*-1,M=!1),d)g*=o,i&&(y?Math.abs(u-t-g)>l&&(Math.abs(u-g)<l?i.trace(`Data line ${c}: After a DIFFERENCE the next line should repeat the last value and this does not seem to be the case: Current value: ${g} - Expected: ${u}.`):Math.abs(u-t-g)>10*l?i.trace(`Data line ${c}: The difference between the first value ${g} and the expected first x value ${u} based on increment after a DIFFERENCE is too high`):i.trace(`Data line ${c}: The difference between the first value ${g} and the expected first x value ${u} based on increment after a DIFFERENCE is too high`)):Math.abs(u-g)>l&&i.trace(`Data line ${c}: The difference between the first value ${g} and the first x value ${u} is too high`)),d=!1,y&&(Y=!0);else if(Y)Y=!1,i&&Math.abs(b-g)>r&&i.trace(`Data line ${c}: After a duplicate the next line should repeat the same value ${g} !== ${b}`),b=g;else{A?(I=M?0-g:g,y=!0,A=!1):N||(X=M?0-g:g);let x=N?g-1:1;for(let F=0;F<x;F++)y?b+=I:b=X,p.x.push(u),p.y.push(b*f),u+=t}M=!1,g=0,R=0,S=!1,N=!1}if(s<74&&s>63)S=!0,y=!1,g=s-64;else if(s>96&&s<106)S=!0,y=!1,g=s-96,M=!0;else if(s===115)S=!0,N=!0,g=9;else if(s>82&&s<91)S=!0,N=!0,g=s-82;else if(s>73&&s<83)S=!0,A=!0,g=s-73;else if(s>105&&s<115)S=!0,A=!0,g=s-105,M=!0;else if(s===36&&m.codePointAt(a+1)===36)S=!0,C=!0;else if(s===37)S=!0,A=!0,g=0,M=!1;else if(s===45){let x=m.codePointAt(a+1);(x!==void 0&&x>=48&&x<=57||x===44||x===46)&&(S=!0,d||(y=!1),M=!0)}else(s===13||s===10)&&(d=!0,C=!1,c++)}i&&y&&i.warn("The last value is a difference, it should be repeated on the next line")}var re=/[,\t ]+/;function P(e,m,n){if(e.isPeaktable=!0,!e.variables||Object.keys(e.variables).length===2?ue(e,m,n):ce(e,m,n),e.variables)for(let i in e.variables)e.variables[i].data=e.data?.[i]}function ue(e,m,n){let{logger:i}=n,f={x:[],y:[]};e.data=f;let o=m.split(/,? *,?[;\r\n]+ */);for(let t=1;t<o.length;t++){let l=o[t].trim().replace($,"").split(re);if(l.length%2===0)for(let r=0;r<l.length;r=r+2)e.xFactor!==void 0&&e.yFactor!==void 0&&(f.x.push(Number(l[r])*e.xFactor),f.y.push(Number(l[r+1])*e.yFactor));else i?.warn(`Format error: ${l.toString()}`)}}function ce(e,m,n){let{logger:i}=n,f={},o=Object.keys(e.variables),t=o.length;for(let r of o)f[r]=[];e.data=f;let l=m.split(/,? *,?[;\r\n]+ */);for(let r=1;r<l.length;r++){let p=l[r].trim().replace($,"").split(re);if(p.length%t===0)for(let u=0;u<p.length;u++)f[o[u%t]].push(Number(p[u]));else i?.warn(`Wrong number of columns: ${p.toString()}`)}}function B(e,m){e.isXYAdata=!0;let n={};e.data=n;let i=m.split(/\r?\n/),f=i[0].replace(/^.*?([A-Z]+).*$/,"$1").split("").map(o=>o.toLowerCase());for(let o=1;o<i.length;o++){let t=i[o].replace(/^\((.*)\)$/,"$1").split(/ *, */);for(let l=0;l<f.length;l++){let r=t[l];switch(f[l]){case"x":case"y":case"w":r=Number.parseFloat(r);break;case"a":r=r.replace(/^<(.*)>$/,"$1");break;case"m":break;default:continue}n[f[l]]||(n[f[l]]=[]),n[f[l]].push(r)}}}import{parseString as ae}from"dynamic-typing";import{getGyromagneticRatio as ie}from"gyromagnetic-ratio";import oe from"ml-array-median";function se(e){return Array.isArray(e)?e[0]:e}function j(e){let{spectra:m}=e,n=m[0].data.y[0],i=n,f=m.length,o=m[0].data.x.length||0,t=new Array(f);for(let s=0;s<f;s++){t[s]=m[s].data.y;for(let a=0;a<o;a++){let c=t[s][a];c<n&&(n=c),c>i&&(i=c)}}let l=m[0].data.x[0],r=m[0].data.x.at(-1),{firstY:p,lastY:u}=pe(e);if(l>r)for(let s of t)s.reverse();p>u&&t.reverse();let b=[];for(let s of t){let a=Float64Array.from(s);for(let c=0;c<a.length;c++)a[c]<0&&(a[c]=-a[c]);b.push(oe(a))}let h=oe(b);return{z:t,minX:Math.min(l,r),maxX:Math.max(l,r),minY:Math.min(p,u),maxY:Math.max(p,u),minZ:n,maxZ:i,noise:h}}function pe(e){let{spectra:m,ntuples:n,info:i}=e;if(n)for(let f of n){let{symbol:o,nucleus:t,units:l}=f;if(o.match(/[F|T]1/)&&l?.toUpperCase().match("HZ")){let r=se(i[".OBSERVEFREQUENCY"]),{nucleus:p}=n.find(c=>c.symbol.match(/[F|T]2/));if([r,p,t].some(c=>!c))break;let u=ie(p),b=ie(t),{first:h,last:s}=f,a=b!==null&&u!==null?r*b/u:r;return{firstY:h/a,lastY:s/a}}}return{firstY:m[0].pageValue,lastY:m.at(-1).pageValue}}function Z(e,m){let n=e.noise,i=e.z,f,o,t,l,r,p,u,b,h=i.length,s=i[0].length,a,c,d,A,y=e.minX,N=(e.maxX-y)/(s-1),C=e.minY,X=(e.maxY-C)/(h-1),M=e.minZ,S=e.maxZ,Y=m.nbContourLevels*2,R=new Array(Y),x;for(let F=0;F<Y;F++){let U={};R[F]=U;let le=F%2,K=(S-m.noiseMultiplier*n)*Math.exp((F>>1)-m.nbContourLevels);le===0?x=K+m.noiseMultiplier*n:x=0-K-m.noiseMultiplier*n;let D=[];if(U.zValue=x,U.lines=D,!(x<=M||x>=S))for(let v=0;v<h-1;v++){let Q=i[v],_=i[v+1];for(let T=0;T<s-1;T++)f=Q[T],o=Q[T+1],t=_[T],l=_[T+1],r=f>x,p=o>x,u=t>x,b=l>x,r!==p&&r!==u&&(a=T+(x-f)/(o-f),c=v,d=T,A=v+(x-f)/(t-f),D.push(a*N+y,c*X+C,d*N+y,A*X+C)),b!==p&&b!==u&&(a=T+1,c=v+1-(x-l)/(o-l),d=T+1-(x-l)/(t-l),A=v+1,D.push(a*N+y,c*X+C,d*N+y,A*X+C)),p!==u&&(a=(T+1-(x-o)/(t-o))*N+y,c=(v+(x-o)/(t-o))*X+C,p!==r&&(d=T+1-(x-o)/(f-o),A=v,D.push(a,c,d*N+y,A*X+C)),u!==r&&(d=T,A=v+1-(x-t)/(f-t),D.push(a,c,d*N+y,A*X+C)),p!==b&&(d=T+1,A=v+(x-o)/(l-o),D.push(a,c,d*N+y,A*X+C)),u!==b&&(d=T+(x-t)/(l-t),A=v+1,D.push(a,c,d*N+y,A*X+C)))}}return{minX:e.minX,maxX:e.maxX,minY:e.minY,maxY:e.maxY,segments:R}}function G(e,m){let n=j(e);m.noContour||(e.contourLines=Z(n,m),delete n.z),e.minMax=n}import{getGyromagneticRatio as W}from"gyromagnetic-ratio";function H(e,m){for(let n of e){let i=0,f=0;for(let o of n.spectra){if(n.ntuples?.symbol?(!i&&o.observeFrequency&&(i=o.observeFrequency),!f&&o.shiftOffsetVal&&(f=o.shiftOffsetVal)):(i=o.observeFrequency,f=o.shiftOffsetVal),i&&o.xUnits?.toUpperCase().includes("HZ")&&(o.xUnits="PPM",o.xFactor=o.xFactor!==void 0?o.xFactor/i:void 0,o.firstX=o.firstX!==void 0?o.firstX/i:void 0,o.lastX=o.lastX!==void 0?o.lastX/i:void 0,o.deltaX=o.deltaX!==void 0?o.deltaX/i:void 0,o.data))for(let t=0;t<o.data.x.length;t++)o.data.x[t]/=i;if(f&&o.xUnits.toLowerCase().includes("ppm")&&o.firstX!==void 0&&o.lastX!==void 0){let t=o.firstX-f;if(o.firstX=o.firstX-t,o.lastX=o.lastX-t,o.data)for(let l=0;l<o.data.x.length;l++)o.data.x[l]-=t}if(n.ntuples?.nucleus&&n.ntuples.symbol)for(let t=0;t<n.ntuples.nucleus.length;t++){let l=n.ntuples.symbol[t],r=n.ntuples.nucleus[t];if(l.match(/^[F|T]/)&&!r){if(l.match(/[F|T]1/))if(n.tmp.$NUC2&&typeof n.tmp.$NUC2=="string")n.ntuples.nucleus[t]=n.tmp.$NUC2;else{let p=n.ntuples.symbol.indexOf(l.replace(/^([F|T]).*/,"$12"));p&&n.ntuples.nucleus[p]&&(n.ntuples.nucleus[t]=n.ntuples.nucleus[p])}l.match(/[F|T]2/)&&typeof n.tmp.$NUC1=="string"&&(n.ntuples.nucleus[t]=n.tmp.$NUC1)}l.match(/[F|T]2/)&&(n.yType=n.ntuples.nucleus[0],n.xType&&!W(n.xType)&&(n.xType=n.ntuples.nucleus[1]))}if(i&&n.ntuples?.symbol&&n.ntuples.nucleus){let t="",l=n.ntuples.symbol.indexOf(o.pageSymbol);n.ntuples.units?.[l]&&(t=n.ntuples.units[l]);let{nucleus:r}=n.ntuples;if(!t.toLowerCase().match(/(ppm|seconds)/)&&r.length>1){if(l!==0){let h="Not sure about this ntuples format";if(m){m.warn(h);continue}else throw new Error(h)}let{nucleus:p}=n.ntuples,u=W(p[0]),b=W(p[1]);if(!u||!b){let h=`Problem with determination of gyromagnetic ratio for ${p.join("-")}`;if(m)m.error(h);else throw new Error(h)}else{let h=u/b*i;o.pageValue/=h}}}}}}function J(e){let m=e.spectra[0].data;e.chromatogram={times:m.x.slice(),series:{intensity:{dimension:1,data:m.y.slice()}}}}function q(e,m,n){H(e,n.logger),de(e,n);for(let i of e){if(Object.keys(i.ntuples).length>0){let f=[],o=Object.keys(i.ntuples);for(let t of o){let l=i.ntuples[t];if(l)for(let r=0;r<l.length;r++)f[r]||(f[r]={}),f[r][t]=l[r]}i.ntuples=f}i.twoD&&n.wantXY&&(G(i,n),n.logger?.trace({profiling:!0},"Finished countour plot calculation"),n.keepSpectra||delete i.spectra),n.chromatogram&&(i.spectra.length>1?te(i):J(i),n.logger?.trace({profiling:!0},"Finished chromatogram calculation")),delete i.tmp}}function de(e,m){for(let n of e)for(let i in n.meta){let f=n.meta[i];if(typeof f=="string"){if(f.startsWith("{")){if(!f.includes(":")&&f.endsWith("}")){let o=f.slice(1,-1).split(/[,; ]+/).filter(Boolean);for(let t=0;t<o.length;t++)n.meta[i+String(t)]=m.dynamicTyping?ae(o[t]):o[t]}}else if(f.startsWith("(")){let o=f.split(/\r?\n/),t=/^\((?<from>\d+)\.\.(?<to>\d+)\).*$/;if(t.test(o[0])){let[l,r]=o[0].match(t)?.slice(1).map(Number)??[],p=o.slice(1).join(" ").split(/[,; ]+/).filter(Boolean);for(let u=l;u<=r;u++)m.dynamicTyping&&typeof p[u-l]=="string"?n.meta[i+String(u)]=ae(p[u-l]):n.meta[i+String(u)]=p[u-l]}}}}}function z(e,m,n){let i=-1,f=-1,o="",t="";if(n.indexOf("++")>0)o=n.replace(/.*\(([a-zA-Z0-9]+)\+\+.*/,"$1"),t=n.replace(/.*\.\.([a-zA-Z0-9]+).*/,"$1");else{n=n.replaceAll(/[^a-zA-Z%]/g,""),o=n.charAt(0),t=n.charAt(1),m.variables={};for(let l of n){let r=l.toLowerCase(),p=e.ntuples.symbol?.indexOf(l)||0;if(p===-1)throw new Error(`Symbol undefined: ${l}`);m.variables[r]={};for(let u in e.ntuples)e.ntuples[u]?.[p]&&(m.variables[r][u.replace(/^var/,"")]=e.ntuples[u]?.[p])}}i=e.ntuples.symbol?.indexOf(o)??-1,f=e.ntuples.symbol?.indexOf(t)??-1,i===-1&&(i=0),f===-1&&(f=0),e.ntuples.first&&(e.ntuples.first.length>i&&(m.firstX=e.ntuples.first[i]),e.ntuples.first.length>f&&(m.firstY=e.ntuples.first[f])),e.ntuples.last&&(e.ntuples.last.length>i&&(m.lastX=e.ntuples.last[i]),e.ntuples.last.length>f&&(m.lastY=e.ntuples.last[f])),e.ntuples.vardim&&e.ntuples.vardim.length>i&&(m.nbPoints=e.ntuples.vardim[i]),e.ntuples.factor&&(e.ntuples.factor.length>i&&(m.xFactor=e.ntuples.factor[i]),e.ntuples.factor.length>f&&(m.yFactor=e.ntuples.factor[f])),e.ntuples.units&&(e.ntuples.units.length>i&&(e.ntuples.varname?.[i]?m.xUnits=`${e.ntuples.varname[i]} [${e.ntuples.units[i]}]`:m.xUnits=e.ntuples.units[i]),e.ntuples.units.length>f&&(e.ntuples.varname?.[f]?m.yUnits=`${e.ntuples.varname[f]} [${e.ntuples.units[f]}]`:m.yUnits=e.ntuples.units[f]))}function w(e){e.xFactor||(e.xFactor=1),e.yFactor||(e.yFactor=1)}var L=/[ \t]*,[ \t]*/,he={keepRecordsRegExp:/^$/,canonicDataLabels:!0,canonicMetadataLabels:!1,dynamicTyping:!0,withoutXY:!1,noTrimRegExp:/^$/,chromatogram:!1,keepSpectra:!1,noContour:!1,nbContourLevels:7,noiseMultiplier:5};function xe(e,m={}){e=ge(e);let n={...he,...m};n.logger?.debug("Starting jcamp conversion"),n.wantXY=!n.withoutXY,n.start=Date.now();let i=[],f={entries:[],flatten:[]},o={children:[],spectra:[],ntuples:{},info:{},meta:{},tmp:{}},t=o,l=[],r={data:{}};n.logger?.trace({profiling:!0},"Before split to LDRS");let p=e.replaceAll(/[\r\n]+##/g,`
6
6
  ##`).split(`
7
- ##`);L(i,"Split to LDRS",a),n[0]&&(n[0]=n[0].replace(/^[\r\n ]*##/,""));for(let p of n){let c=p.indexOf("="),d=c>0?p.substring(0,c):p,u=c>0?d.match(a.noTrimRegExp)?p.substring(c+1):p.substring(c+1).trim():"",f=d.replace(/[_ -]/g,"").toUpperCase();if(f==="DATATABLE"){let m=u.indexOf(`
8
- `);if(m===-1&&(m=u.indexOf("\r")),m>0){let h=u.substring(0,m).split(/[ ,;\t]+/);q(l,t,h[0]),t.datatable=h[0],h[1]&&h[1].indexOf("PEAKS")>-1?f="PEAKTABLE":h[1]&&(h[1].indexOf("XYDATA")||h[0].indexOf("++")>0)&&(f="XYDATA",t.nbPoints&&(t.deltaX=(t.lastX-t.firstX)/(t.nbPoints-1)))}}if(f==="XYDATA"){a.wantXY&&(w(t),u.match(/.*\+\+.*/)?(t.nbPoints&&(t.deltaX=(t.lastX-t.firstX)/(t.nbPoints-1)),U(t,u,i)):D(t,u,i),l.spectra.push(t),t={});continue}else if(f==="PEAKTABLE"){a.wantXY&&(w(t),D(t,u,i),l.spectra.push(t),t={});continue}if(f==="PEAKASSIGNMENTS"){a.wantXY&&(u.match(/.*([^A-Z]*).*/)&&V(t,u),l.spectra.push(t),t={});continue}if(f==="TITLE"){let m=l;m.children||(m.children=[]),l={spectra:[],ntuples:{},info:{},meta:{},tmp:{}},m.children.push(l),r.push(m),s.push(l),l.title=u}else f==="DATATYPE"?(l.dataType=u,u.match(/(^nd|\snd\s)/i)&&(l.twoD=!0)):f==="NTUPLES"?u.match(/(^nd|\snd\s)/i)&&(l.twoD=!0):f==="DATACLASS"?l.dataClass=u:f==="JCAMPDX"?l.jcampDX=M(u):f==="JCAMPCS"?l.jcampCS=M(u):f==="XUNITS"?t.xUnits=u:f==="YUNITS"?t.yUnits=u:f==="FIRSTX"?t.firstX=Number(u):f==="LASTX"?t.lastX=Number(u):f==="FIRSTY"?t.firstY=Number(u):f==="LASTY"?t.lastY=Number(u):f==="NPOINTS"?t.nbPoints=Number(u):f==="XFACTOR"?t.xFactor=Number(u):f==="YFACTOR"?t.yFactor=Number(u):f==="MAXX"?t.maxX=Number(u):f==="MINX"?t.minX=Number(u):f==="MAXY"?t.maxY=Number(u):f==="MINY"?t.minY=Number(u):f==="DELTAX"?t.deltaX=Number(u):f===".OBSERVEFREQUENCY"||f==="$SFO1"?t.observeFrequency||(t.observeFrequency=Number(u)):f===".OBSERVENUCLEUS"?t.xType||(l.xType=u.replace(/[^a-zA-Z0-9]/g,"")):f==="$OFFSET"?(l.shiftOffsetNum=0,t.shiftOffsetVal||(t.shiftOffsetVal=Number(u))):f==="$REFERENCEPOINT"||(f==="VARNAME"?l.ntuples.varname=u.split(F):f==="SYMBOL"?l.ntuples.symbol=u.split(F):f==="VARTYPE"?l.ntuples.vartype=u.split(F):f==="VARFORM"?l.ntuples.varform=u.split(F):f==="VARDIM"?l.ntuples.vardim=Y(u.split(F)):f==="UNITS"?l.ntuples.units=u.split(F):f==="FACTOR"?l.ntuples.factor=Y(u.split(F)):f==="FIRST"?l.ntuples.first=Y(u.split(F)):f==="LAST"?l.ntuples.last=Y(u.split(F)):f==="MIN"?l.ntuples.min=Y(u.split(F)):f==="MAX"?l.ntuples.max=Y(u.split(F)):f===".NUCLEUS"?l.ntuples&&(l.ntuples.nucleus=u.split(F).map(m=>m.replace(/[^a-zA-Z0-9]/g,""))):f==="PAGE"?(t.page=u.trim(),t.pageValue=Number(u.replace(/^.*=/,"")),t.pageSymbol=t.page.replace(/[=].*/,"")):f==="RETENTIONTIME"?t.pageValue=Number(u):le(f)?t[I(f)]=u:f==="SAMPLEDESCRIPTION"?t.sampleDescription=u:f.startsWith("$NUC")?!l.tmp[f]&&!u.includes("off")&&(l.tmp[f]=u.replace(/[<>]/g,"")):f==="END"&&(l=r.pop()));if(l&&l.info&&l.meta&&f.match(a.keepRecordsRegExp)){let m,h;d.startsWith("$")?(h=a.canonicMetadataLabels?f.substring(1):d.substring(1),m=l.meta):(h=a.canonicDataLabels?f:d,m=l.info),a.dynamicTyping&&(u=ge(u)),m[h]?(Array.isArray(m[h])||(m[h]=[m[h]]),m[h].push(u)):m[h]=u}}if(L(i,"Finished parsing",a),H(s,i,a),L(i,"Total time",a),i.entries=o.children,i.flatten=s,a.logger){a.logger.debug("Finished jcamp conversion");for(let p of i.flatten)a.logger.debug(`${p.dataType} - ${p.title}`)}return i}function Ae(e,a={}){let{logger:s,OCL:i}=a;if(!e.info.ATOMLIST||!e.info.BONDLIST){s?.warn("No ATOMLIST or BONDLIST in the JCAMP-CS entry");return}Xe(e,s);let o=Se(e.info.ATOMLIST),l=ye(e.info.BONDLIST),r=Ce(e.info.CHARGE,s),t=Te(i,o,l,r,s);return{molecule:t,molfile:t.toMolfile()}}function Te(e,a,s,i,o){let l={S:e.Molecule.cBondTypeSingle,D:e.Molecule.cBondTypeDouble,T:e.Molecule.cBondTypeTriple,Q:e.Molecule.cBondTypeQuadruple},r={},t=new e.Molecule(a.length,s.length);for(let n of a){let p=e.Molecule.getAtomicNoFromLabel(n.element);p||(o?.error(`Atomic number of ${n.element} could not be determined`),p=e.Molecule.getAtomicNoFromLabel("X")),r[n.atomNumber]=t.addAtom(p),t.setAtomMapNo(r[n.atomNumber],n.atomNumber)}for(let n of s){if(r[n.atomNumber1]===void 0){o?.error(`A bond goes to atomNumber ${n.atomNumber1} that does not exists`);continue}if(r[n.atomNumber2]===void 0){o?.error(`A bond goes to atomNumber ${n.atomNumber2} that does not exists`);continue}let p=t.addBond(r[n.atomNumber1],r[n.atomNumber2]);t.setBondType(p,l[n.bondType])}for(let n of i){if(r[n.atomNumber]===void 0){o?.error(`A charge goes to atomNumber ${n.atomNumber1} that does not exists`);continue}t.setAtomCharge(r[n.atomNumber],n.value)}return t}function Se(e){let a=e.split(/\r?\n/).map(i=>M(i)).filter(i=>i),s=[];for(let i of a){let[o,l,r]=i.trim().split(/\s+/);s.push({atomNumber:Number(o),element:l,nbImplicitHydrogens:r?.length>0?Number(r):void 0})}return s}function ye(e){let a=e.split(/\r?\n/).map(i=>M(i)).filter(i=>i),s=[];for(let i of a){let[o,l,r]=i.trim().split(/\s+/);s.push({atomNumber1:Number(o),atomNumber2:Number(l),bondType:r})}return s}function Ce(e,a){if(!e)return[];let s=e.split(/\r?\n/).map(o=>M(o)).filter(o=>o),i=[];for(let o of s){let[l,r,t]=o.trim().split(/\s+/);t!==void 0&&a?.warn("Charge on multiple atom is not supported"),i.push({atomNumber:Number(r),value:Number(l)})}return i}function Xe(e,a){let s=["STEREOPAIR","STEREOCENTER","RADICAL","STEREOMOLECULE"];for(let i of s)e.info[i]&&a?.warn(`JCAMP-CS parser do not support: ${i}`)}export{Ne as convert,pe as createTree,Ae as parseJcampCS};
7
+ ##`);n.logger?.trace({profiling:!0},"Split to LDRS"),p[0]&&(p[0]=p[0].replace(/^[\r\n ]*##/,""));for(let u of p){let b=u.indexOf("="),h=b>0?u.slice(0,Math.max(0,b)):u,s=b>0?h.match(n.noTrimRegExp)?u.slice(Math.max(0,b+1)):u.slice(Math.max(0,b+1)).trim():"",a=h.replaceAll(/[_ -]/g,"").toUpperCase();if(a==="DATATABLE"){let c=s.indexOf(`
8
+ `);if(c===-1&&(c=s.indexOf("\r")),c>0){let d=s.slice(0,Math.max(0,c)).split(/[ ,;\t]+/);z(t,r,d[0]),r.datatable=d[0],d[1]?.includes("PEAKS")?a="PEAKTABLE":d[1]&&(d[1].indexOf("XYDATA")||d[0].indexOf("++")>0)&&(a="XYDATA",r.nbPoints&&r.lastX!==void 0&&r.firstX!==void 0&&(r.deltaX=(r.lastX-r.firstX)/(r.nbPoints-1)))}}if(a==="XYDATA"){n.wantXY&&(w(r),s.match(/.*\+\+.*/)?(r.nbPoints&&r.lastX!==void 0&&r.firstX!==void 0&&(r.deltaX=(r.lastX-r.firstX)/(r.nbPoints-1)),V(r,s,n)):P(r,s,n),t?.spectra.push(r),r={data:{}});continue}else if(a==="PEAKTABLE"){n.wantXY&&(w(r),P(r,s,n),t?.spectra.push(r),r={data:{}});continue}if(a==="PEAKASSIGNMENTS"){n.wantXY&&(s.match(/.*[^A-Z]*.*/)&&B(r,s),t?.spectra.push(r),r={data:{}});continue}if(s=s.split(/\r?\n/).map(c=>c.replace(/ *\$\$.*$/,"")).join(`
9
+ `),a==="TITLE"){let c=t;c.children||(c.children=[]),t={spectra:[],ntuples:{},info:{},meta:{},tmp:{}},c.children.push(t),l.push(c),i.push(t),t.title=s}else a==="DATATYPE"?(t.dataType=s,s.match(/^nd|\snd\s/i)&&(t.twoD=!0)):a==="NTUPLES"?s.match(/^nd|\snd\s/i)&&(t.twoD=!0):a==="DATACLASS"?t.dataClass=s:a==="JCAMPDX"?t.jcampDX=O(s):a==="JCAMPCS"?t.jcampCS=O(s):a==="XUNITS"?r.xUnits=s:a==="YUNITS"?r.yUnits=s:a==="FIRSTX"?r.firstX=Number(s):a==="LASTX"?r.lastX=Number(s):a==="FIRSTY"?r.firstY=Number(s):a==="LASTY"?r.lastY=Number(s):a==="NPOINTS"?r.nbPoints=Number(s):a==="XFACTOR"?r.xFactor=Number(s):a==="YFACTOR"?r.yFactor=Number(s):a==="MAXX"?r.maxX=Number(s):a==="MINX"?r.minX=Number(s):a==="MAXY"?r.maxY=Number(s):a==="MINY"?r.minY=Number(s):a==="DELTAX"?r.deltaX=Number(s):a===".OBSERVEFREQUENCY"||a==="$SFO1"?r.observeFrequency||(r.observeFrequency=Number(s)):a===".OBSERVENUCLEUS"?r.xType||(t.xType=s.replaceAll(/[^a-zA-Z0-9]/g,"")):a==="$OFFSET"?(t.shiftOffsetNum=0,r.shiftOffsetVal||(r.shiftOffsetVal=Number(s))):a==="$REFERENCEPOINT"||(a==="VARNAME"?t.ntuples.varname=s.split(L):a==="SYMBOL"?t.ntuples.symbol=s.split(L):a==="VARTYPE"?t.ntuples.vartype=s.split(L):a==="VARFORM"?t.ntuples.varform=s.split(L):a==="VARDIM"?t.ntuples.vardim=E(s.split(L)):a==="UNITS"?t.ntuples.units=s.split(L):a==="FACTOR"?t.ntuples.factor=E(s.split(L)):a==="FIRST"?t.ntuples.first=E(s.split(L)):a==="LAST"?t.ntuples.last=E(s.split(L)):a==="MIN"?t.ntuples.min=E(s.split(L)):a==="MAX"?t.ntuples.max=E(s.split(L)):a===".NUCLEUS"?t.ntuples&&(t.ntuples.nucleus=s.split(L).map(c=>c.replaceAll(/[^a-zA-Z0-9]/g,""))):a==="PAGE"?(r.page=s.trim(),r.pageValue=Number(s.replace(/^.*=/,"")),r.pageSymbol=r.page.replace(/[=].*/,"")):a==="RETENTIONTIME"?r.pageValue=Number(s):ne(a)?r[k(a)]=s:a==="SAMPLEDESCRIPTION"?r.sampleDescription=s:a.startsWith("$NUC")?!t.tmp[a]&&!s.includes("off")&&(t.tmp[a]=s.replaceAll(/[<>]/g,"")):a==="END"&&(t=l.pop()));if(t?.info&&t.meta&&a.match(n.keepRecordsRegExp)){let c,d;h.startsWith("$")?(d=n.canonicMetadataLabels?a.slice(1):h.slice(1),c=t.meta):(d=n.canonicDataLabels?a:h,c=t.info),n.dynamicTyping&&(s=be(s)),c[d]?(Array.isArray(c[d])||(c[d]=[c[d]]),c[d].push(s)):c[d]=s}}if(n.logger?.trace({profiling:!0},"Finished parsing"),q(i,f,n),n.logger?.trace({profiling:!0},"Total time"),f.entries=o.children||[],f.flatten=i,n.logger){n.logger.debug("Finished jcamp conversion");for(let u of f.flatten)n.logger.debug(`${u.dataType} - ${u.title}`)}return f}function ye(e,m){let{logger:n,OCL:i}=m;if(!e.info.ATOMLIST||!e.info.BONDLIST){n?.warn("No ATOMLIST or BONDLIST in the JCAMP-CS entry");return}Te(e,n);let f=Se(e.info.ATOMLIST),o=Ne(e.info.BONDLIST),t=Ce(e.info.CHARGE,n),l=Ae(i,f,o,t,n);return{molecule:l,molfile:l.toMolfile()}}function Ae(e,m,n,i,f){let o={S:e.Molecule.cBondTypeSingle,D:e.Molecule.cBondTypeDouble,T:e.Molecule.cBondTypeTriple,Q:e.Molecule.cBondTypeQuadruple},t={},l=new e.Molecule(m.length,n.length);for(let r of m){let p=e.Molecule.getAtomicNoFromLabel(r.element);p||(f?.error(`Atomic number of ${r.element} could not be determined`),p=e.Molecule.getAtomicNoFromLabel("X")),t[r.atomNumber]=l.addAtom(p),l.setAtomMapNo(t[r.atomNumber],r.atomNumber,!1)}for(let r of n){if(t[r.atomNumber1]===void 0){f?.error(`A bond goes to atomNumber ${r.atomNumber1} that does not exists`);continue}if(t[r.atomNumber2]===void 0){f?.error(`A bond goes to atomNumber ${r.atomNumber2} that does not exists`);continue}let p=l.addBond(t[r.atomNumber1],t[r.atomNumber2]);l.setBondType(p,o[r.bondType])}for(let r of i){if(t[r.atomNumber]===void 0){f?.error(`A charge goes to atomNumber ${r.atomNumber} that does not exists`);continue}l.setAtomCharge(t[r.atomNumber],r.value)}return l}function Se(e){let m=e.split(/\r?\n/).map(i=>O(i)).filter(Boolean),n=[];for(let i of m){let[f,o,t]=i.trim().split(/\s+/);n.push({atomNumber:Number(f),element:o,nbImplicitHydrogens:t?.length>0?Number(t):void 0})}return n}function Ne(e){let m=e.split(/\r?\n/).map(i=>O(i)).filter(Boolean),n=[];for(let i of m){let[f,o,t]=i.trim().split(/\s+/);n.push({atomNumber1:Number(f),atomNumber2:Number(o),bondType:t})}return n}function Ce(e,m){if(!e)return[];let n=e.split(/\r?\n/).map(f=>O(f)).filter(Boolean),i=[];for(let f of n){let[o,t,l]=f.trim().split(/\s+/);l!==void 0&&m?.warn("Charge on multiple atom is not supported"),i.push({atomNumber:Number(t),value:Number(o)})}return i}function Te(e,m){let n=["STEREOPAIR","STEREOCENTER","RADICAL","STEREOMOLECULE"];for(let i of n)e.info[i]&&m?.warn(`JCAMP-CS parser do not support: ${i}`)}export{xe as convert,me as createTree,ye as parseJcampCS};
package/package.json CHANGED
@@ -1,10 +1,16 @@
1
1
  {
2
2
  "name": "jcampconverter",
3
- "version": "9.6.3",
3
+ "version": "10.0.0",
4
4
  "description": "Parse and convert JCAMP data",
5
- "types": "jcampconverter.d.ts",
6
- "main": "jcampconverter.cjs",
7
- "module": "jcampconverter.mjs",
5
+ "keywords": [
6
+ "jcamp",
7
+ "converter"
8
+ ],
9
+ "author": "Luc Patiny",
10
+ "license": "MIT",
11
+ "types": "./jcampconverter.d.ts",
12
+ "require": "./jcampconverter.cjs",
13
+ "module": "./jcampconverter.mjs",
8
14
  "exports": {
9
15
  ".": {
10
16
  "types": "./jcampconverter.d.ts",
@@ -19,63 +25,53 @@
19
25
  ],
20
26
  "scripts": {
21
27
  "api-extractor": "api-extractor run --local",
22
- "build": "cheminfo-build --entry src/index.js --root JcampConverter --no-source-map && rm dist/jcampconverter.js",
28
+ "benchmark": "node benchmark/benchmark.js",
29
+ "build": "tsc --project tsconfig.cheminfo-build.json && cheminfo-build --entry lib/index.js --root JcampConverter --no-source-map && rm dist/jcampconverter.js",
23
30
  "bundle": "npm run bundle-cjs && npm run bundle-esm",
24
- "bundle-common": "esbuild src/index.js --bundle --packages=external --minify",
31
+ "bundle-common": "esbuild src/index.ts --bundle --packages=external --minify",
25
32
  "bundle-cjs": "npm run bundle-common -- --format=cjs --outfile=jcampconverter.cjs",
26
33
  "bundle-esm": "npm run bundle-common -- --format=esm --outfile=jcampconverter.mjs",
27
34
  "bundle-types": "npm run tsc && npm run api-extractor",
28
35
  "check-types": "tsc --noEmit",
29
- "clean": "rimraf dist types",
36
+ "clean": "rimraf dist lib types",
37
+ "deopt": "node --trace-opt --trace-deopt --code-comments debug/deoptimize.js > deopt.log",
38
+ "hydra": "node --trace-hydrogen --trace-phase=Z --trace-deopt --code-comments --hydrogen-track-positions --redirect-code-traces --redirect-code-traces-to=code.asm debug/deoptimize.js",
30
39
  "eslint": "eslint src __tests__",
31
40
  "eslint-fix": "npm run eslint -- --fix",
32
41
  "jscpd": "jscpd -l 10 -i \"**/__tests__/**\" -t 1 src",
33
42
  "prepack": "npm run bundle && npm run bundle-types",
34
- "prettier": "prettier --check src",
35
- "prettier-write": "prettier --write src",
36
- "test": "npm run test-only && npm run eslint && npm run prettier && npm run check-types",
37
- "test-only": "vitest run --globals --coverage",
38
- "tsc": "tsc --project tsconfig.types.json",
39
- "benchmark": "node benchmark/benchmark.js",
40
- "deopt": "node --trace-opt --trace-deopt --code-comments debug/deoptimize.js > deopt.log",
41
- "hydra": "node --trace-hydrogen --trace-phase=Z --trace-deopt --code-comments --hydrogen-track-positions --redirect-code-traces --redirect-code-traces-to=code.asm debug/deoptimize.js"
43
+ "prettier": "prettier --check src __tests__",
44
+ "prettier-write": "prettier --write src __tests__",
45
+ "test": "npm run test-only && npm run check-types && npm run eslint && npm run prettier",
46
+ "test-only": "vitest run --coverage",
47
+ "tsc": "tsc --project tsconfig.types.json"
42
48
  },
43
- "keywords": [
44
- "jcamp",
45
- "converter"
46
- ],
47
- "author": "Luc Patiny",
48
- "license": "MIT",
49
49
  "bugs": {
50
50
  "url": "https://github.com/cheminfo/nmrium/issues/new?title=%5Bjcampconverter%5D"
51
51
  },
52
52
  "devDependencies": {
53
- "@microsoft/api-extractor": "^7.42.3",
54
- "@types/jest": "^29.5.12",
55
- "@types/pino": "^7.0.5",
56
- "@vitest/coverage-v8": "^1.3.1",
53
+ "@microsoft/api-extractor": "^7.47.10",
54
+ "@vitest/coverage-v8": "^2.1.3",
57
55
  "benchmark": "^2.1.4",
58
- "c8": "^9.1.0",
59
56
  "cheminfo-build": "^1.2.0",
60
- "esbuild": "^0.20.1",
61
- "eslint": "^8.57.0",
62
- "eslint-config-cheminfo-typescript": "^12.2.0",
63
- "esm": "^3.2.25",
64
- "fifo-logger": "^0.6.1",
57
+ "esbuild": "^0.24.0",
58
+ "eslint": "^9.12.0",
59
+ "eslint-config-cheminfo-typescript": "^16.0.0",
60
+ "fifo-logger": "^1.0.0",
65
61
  "jest-matcher-deep-close-to": "^3.0.2",
66
- "jscpd": "^3.5.10",
67
- "ml-spectra-processing": "^14.2.0",
68
- "openchemlib": "^8.9.0",
69
- "prettier": "^3.2.5",
70
- "rimraf": "^5.0.5",
71
- "typescript": "^5.4.2",
72
- "vitest": "^1.3.1"
62
+ "jscpd": "^4.0.5",
63
+ "ml-spectra-processing": "^14.6.0",
64
+ "openchemlib": "^8.15.0",
65
+ "prettier": "^3.3.3",
66
+ "rimraf": "^6.0.1",
67
+ "typescript": "^5.6.3",
68
+ "vitest": "^2.1.3"
73
69
  },
74
70
  "dependencies": {
75
- "cheminfo-types": "^1.7.2",
76
- "dynamic-typing": "^1.0.0",
71
+ "cheminfo-types": "^1.8.0",
72
+ "dynamic-typing": "^1.0.1",
77
73
  "ensure-string": "^1.2.0",
78
- "gyromagnetic-ratio": "^1.1.1",
74
+ "gyromagnetic-ratio": "^1.2.0",
79
75
  "ml-array-median": "^1.1.6"
80
76
  }
81
77
  }