jcampconverter 9.6.4 → 10.0.1

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=[],t=[],r=[],l,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());t.push({title:f.join(`
2
- `),jcamp:`${d}
3
- `,children:[]}),l=t[t.length-1],n.push(l)}else if(u.substring(0,5)==="##END"&&o===0){l.jcamp+=`${d}
4
- `;let f=t.pop();t.length!==0?(l=t[t.length-1],l.children.push(f)):(l=void 0,r.push(f))}else if(l&&l.jcamp){l.jcamp+=`${d}
5
- `;let f=u.match(/^##(.*?)=(.+)/);if(f){let m=f[1].replace(/[ _-]/g,"").toUpperCase();m==="DATATYPE"?l.dataType=f[2].trim():m==="DATACLASS"?l.dataClass=f[2].trim():m==="JCAMPDX"?l.jcampDX=M(f[2].trim()):m==="JCAMPCS"&&(l.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 t=0;t<U.length;t++){let r=V(U[t]);i[0][r]&&(n.push(r),a.series[r]={dimension:1,data:new Array(s)})}for(let t=0;t<s;t++){let r=i[t];a.times[t]=r.pageValue;for(let l=0;l<n.length;l++)a.series[n[l]].data[t]=Number(r[n[l]]);r.data&&(a.series.ms.data[t]=[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 t=e.firstX,r=e.firstY,l=!1,o,p=0;for(;p<i.length;p++)if(o=i.charCodeAt(p),o===13||o===10)l=!0;else if(l)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(t),n.y.push(r*s),t+=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 t=1;t<n.length;t++){let r=n[t].trim().replace(D,"").split(ue);if(r.length%2===0)for(let l=0;l<r.length;l=l+2)a.x.push(Number(r[l])*e.xFactor),a.y.push(Number(r[l+1])*e.yFactor);else s.logs.push(`Format error: ${r}`)}}function Fe(e,i,s){let a={},n=Object.keys(e.variables),t=n.length;n.forEach(l=>a[l]=[]),e.data=a;let r=i.split(/,? *,?[;\r\n]+ */);for(let l=1;l<r.length;l++){let o=r[l].trim().replace(D,"").split(ue);if(o.length%t===0)for(let p=0;p<o.length;p++)a[n[p%t]].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(t=>t.toLowerCase());for(let t=1;t<a.length;t++){let r=a[t].replace(/^\((.*)\)$/,"$1").split(/ *, */);for(let l=0;l<n.length;l++){let o=r[l];switch(n[l]){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[l]]||(s[n[l]]=[]),s[n[l]].push(o)}}}var Q=require("dynamic-typing");var Z=require("gyromagnetic-ratio"),j=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,t=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<t;m++){let h=r[f][m];h<s&&(s=h),h>a&&(a=h)}}let l=i[0].data.x[0],o=i[0].data.x[i[0].data.x.length-1],{firstY:p,lastY:c}=Me(e);if(l>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,j.default)(m))}let u=(0,j.default)(d);return{z:r,minX:Math.min(l,o),maxX:Math.max(l,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:t,nucleus:r,units:l}=s[n];if(t.match(/[F|T]1/)&&l?.toUpperCase().match("HZ")){let o=pe(a[".OBSERVEFREQUENCY"]),{nucleus:p}=s.find(h=>h.symbol.match(/[F|T]2/));if([o,p,r].some(h=>!h))break;let c=(0,Z.getGyromagneticRatio)(p),d=(0,Z.getGyromagneticRatio)(r),{first:u,last:f}=s[n],m=o*d/c;return{firstY:u/m,lastY:f/m}}}return{firstY:i[0].pageValue,lastY:i[i.length-1].pageValue}}function G(e,i){let s=e.noise,a=e.z,n,t,r,l,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],t=se[S+1],r=ie[S],l=ie[S+1],o=n>x,p=t>x,c=r>x,d=l>x,o!==p&&o!==c&&(m=S+(x-n)/(t-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-l)/(t-l),g=S+1-(x-l)/(r-l),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-t)/(r-t))*C+N,h=(X+(x-t)/(r-t))*v+T,p!==o&&(g=S+1-(x-t)/(n-t),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-t)/(l-t),b.push(m),b.push(h),b.push(g*C+N),b.push(A*v+T)),c!==d&&(g=S+(x-r)/(l-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 t of s.spectra){if(s.ntuples&&s.ntuples.symbol?(!a&&t.observeFrequency&&(a=t.observeFrequency),!n&&t.shiftOffsetVal&&(n=t.shiftOffsetVal)):(a=t.observeFrequency,n=t.shiftOffsetVal),a&&t.xUnits&&t.xUnits.toUpperCase().includes("HZ")){t.xUnits="PPM",t.xFactor=t.xFactor/a,t.firstX=t.firstX/a,t.lastX=t.lastX/a,t.deltaX=t.deltaX/a;for(let r=0;r<t.data.x.length;r++)t.data.x[r]/=a}if(n&&t.xUnits.toLowerCase().includes("ppm")){let r=t.firstX-n;t.firstX=t.firstX-r,t.lastX=t.lastX-r;for(let l=0;l<t.data.x.length;l++)t.data.x[l]-=r}if(s.ntuples&&s.ntuples.nucleus&&s.ntuples.symbol)for(let r=0;r<s.ntuples.nucleus.length;r++){let l=s.ntuples.symbol[r],o=s.ntuples.nucleus[r];if(l.match(/^[F|T]/)&&!o){if(l.match(/[F|T]1/))if(s.tmp.$NUC2)s.ntuples.nucleus[r]=s.tmp.$NUC2;else{let p=s.ntuples.symbol.indexOf(l.replace(/^([F|T]).*/,"$12"));p&&s.ntuples.nucleus[p]&&(s.ntuples.nucleus[r]=s.ntuples.nucleus[p])}l.match(/[F|T]2/)&&(s.ntuples.nucleus[r]=s.tmp.$NUC1)}l.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="",l=s.ntuples.symbol.indexOf(t.pageSymbol);if(s.ntuples.units&&s.ntuples.units[l]&&(r=s.ntuples.units[l]),!r.toLowerCase().match(/(ppm|seconds)/)){if(l!==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;t.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=[],t=Object.keys(a.ntuples);for(let r=0;r<t.length;r++){let l=t[r],o=a.ntuples[l];for(let p=0;p<o.length;p++)n[p]||(n[p]={}),n[p][l]=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 t=n.slice(1,-1).split(/[,; ]+/).filter(r=>r);for(let r=0;r<t.length;r++)s.meta[a+String(r)]=i.dynamicTyping?(0,Q.parseString)(t[r]):t[r]}}else if(n[0]==="("){let t=n.split(/\r?\n/),r=/^\((?<from>\d+)\.\.(?<to>\d+)\).*$/;if(r.test(t[0])){let[l,o]=t[0].match(r).slice(1).map(Number),p=t.slice(1).join(" ").split(/[,; ]+/).filter(c=>c);for(let c=l;c<=o;c++)i.dynamicTyping&&typeof p[c-l]=="string"?s.meta[a+String(c)]=(0,Q.parseString)(p[c-l]):s.meta[a+String(c)]=p[c-l]}}}}}function _(e,i,s){let a=-1,n=-1,t="",r="";if(s.indexOf("++")>0)t=s.replace(/.*\(([a-zA-Z0-9]+)\+\+.*/,"$1"),r=s.replace(/.*\.\.([a-zA-Z0-9]+).*/,"$1");else{s=s.replace(/[^a-zA-Z%]/g,""),t=s.charAt(0),r=s.charAt(1),i.variables={};for(let l of s){let o=l.toLowerCase(),p=e.ntuples.symbol.indexOf(l);if(p===-1)throw Error(`Symbol undefined: ${l}`);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(t),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:[]},t=n,r=[],l={};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,Ce=Object.prototype.hasOwnProperty;var Se=(e,f)=>{for(var t in f)$(e,t,{get:f[t],enumerable:!0})},se=(e,f,t,o)=>{if(f&&typeof f=="object"||typeof f=="function")for(let a of ye(f))!Ce.call(e,a)&&a!==t&&$(e,a,{get:()=>f[a],enumerable:!(o=xe(f,a))||o.enumerable});return e};var Ne=(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={};Se($e,{convert:()=>de,createTree:()=>ie,parseJcampCS:()=>be});module.exports=Te($e);var oe=require("ensure-string");var P=/\s*\$\$.*/;function O(e){return e.replace(P,"")}function ie(e,f={}){e=(0,oe.ensureString)(e);let{flatten:t=!1}=f,o=e.split(/\r?\n/),a=[],i=[],n=[],m={title:"",jcamp:"",children:[]},r=0,p=e.includes("## ");for(let u=0;u<o.length;u++){let b=o[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<o.length&&!o[l].startsWith("##");l++)s.push(o[l].trim());i.push({title:s.join(`
2
+ `),jcamp:`${b}
3
+ `,children:[]}),m=i.at(-1),a.push(m)}else if(h.startsWith("##END")&&r===0&&m){m.jcamp+=`${b}
4
+ `;let s=i.pop();if(!s)throw new Error("Not finished");i.length>0?(m=i.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,o={times:new Array(t),series:{ms:{dimension:2,data:new Array(t)}}},a=[];for(let i of ae){let n=B(i);f[0][n]&&(a.push(n),o.series[n]={dimension:1,data:new Array(t)})}for(let i=0;i<t;i++){let n=f[i];o.times[i]=n.pageValue;for(let m of a)o.series[m].data[i]=Number(n[m]);n.data&&(o.series.ms.data[i]=[n.data.x,n.data.y])}e.chromatogram=o}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:o}=t;o&&(e.xFactor||o.info("The xFactor is not defined, it will be set to 1"),e.yFactor||o.info("The yFactor is not defined, it will be set to 1"));let a=e.yFactor??1,i=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,S=!1,N=!1,g=0,X=0,M=!1,C=!1,Y=!1,R=0;for(;l<=f.length;l++)if(l===f.length?s=13:s=f.codePointAt(l),N)(s===13||s===10)&&(d=!0,N=!1,c++);else if(s<=57&&s>=48)C=!0,R>0?g+=(s-48)/10**R++:(g*=10,g+=s-48);else if(s===44||s===46)C=!0,R++;else{if(C){if(M&&(g=g*-1,M=!1),d)g*=i,o&&(y?Math.abs(u-n-g)>m&&(Math.abs(u-g)<m?o.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?o.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`):o.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&&o.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,o&&Math.abs(b-g)>r&&o.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):S||(X=M?0-g:g);let x=S?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,C=!1,S=!1}if(s<74&&s>63)C=!0,y=!1,g=s-64;else if(s>96&&s<106)C=!0,y=!1,g=s-96,M=!0;else if(s===115)C=!0,S=!0,g=9;else if(s>82&&s<91)C=!0,S=!0,g=s-82;else if(s>73&&s<83)C=!0,A=!0,g=s-73;else if(s>105&&s<115)C=!0,A=!0,g=s-105,M=!0;else if(s===36&&f.codePointAt(l+1)===36)C=!0,N=!0;else if(s===37)C=!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)&&(C=!0,d||(y=!1),M=!0)}else(s===13||s===10)&&(d=!0,N=!1,c++)}o&&y&&o.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 o in e.variables)e.variables[o].data=e.data?.[o]}function ve(e,f,t){let{logger:o}=t,a={x:[],y:[]};e.data=a;let i=f.split(/,? *,?[;\r\n]+ */);for(let n=1;n<i.length;n++){let m=i[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 o?.warn(`Format error: ${m.toString()}`)}}function Xe(e,f,t){let{logger:o}=t,a={},i=Object.keys(e.variables),n=i.length;for(let r of i)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[i[u%n]].push(Number(p[u]));else o?.warn(`Wrong number of columns: ${p.toString()}`)}}function Z(e,f){e.isXYAdata=!0;let t={};e.data=t;let o=f.split(/\r?\n/),a=o[0].replace(/^.*?([A-Z]+).*$/,"$1").split("").map(i=>i.toLowerCase());for(let i=1;i<o.length;i++){let n=o[i].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=Ne(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],o=t,a=f.length,i=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<i;l++){let c=n[s][l];c<t&&(t=c),c>o&&(o=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:o,noise:h}}function Le(e){let{spectra:f,ntuples:t,info:o}=e;if(t)for(let a of t){let{symbol:i,nucleus:n,units:m}=a;if(i.match(/[F|T]1/)&&m?.toUpperCase().match("HZ")){let r=ue(o[".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,o=e.z,a,i,n,m,r,p,u,b,h=o.length,s=o[0].length,l,c,d,A,y=e.minX,S=(e.maxX-y)/(s-1),N=e.minY,X=(e.maxY-N)/(h-1),M=e.minZ,C=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=(C-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>=C))for(let v=0;v<h-1;v++){let ne=o[v],re=o[v+1];for(let T=0;T<s-1;T++)a=ne[T],i=ne[T+1],n=re[T],m=re[T+1],r=a>x,p=i>x,u=n>x,b=m>x,r!==p&&r!==u&&(l=T+(x-a)/(i-a),c=v,d=T,A=v+(x-a)/(n-a),D.push(l*S+y,c*X+N,d*S+y,A*X+N)),b!==p&&b!==u&&(l=T+1,c=v+1-(x-m)/(i-m),d=T+1-(x-m)/(n-m),A=v+1,D.push(l*S+y,c*X+N,d*S+y,A*X+N)),p!==u&&(l=(T+1-(x-i)/(n-i))*S+y,c=(v+(x-i)/(n-i))*X+N,p!==r&&(d=T+1-(x-i)/(a-i),A=v,D.push(l,c,d*S+y,A*X+N)),u!==r&&(d=T,A=v+1-(x-n)/(a-n),D.push(l,c,d*S+y,A*X+N)),p!==b&&(d=T+1,A=v+(x-i)/(m-i),D.push(l,c,d*S+y,A*X+N)),u!==b&&(d=T+(x-n)/(m-n),A=v+1,D.push(l,c,d*S+y,A*X+N)))}}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 o=0,a=0;for(let i of t.spectra){if(t.ntuples?.symbol?(!o&&i.observeFrequency&&(o=i.observeFrequency),!a&&i.shiftOffsetVal&&(a=i.shiftOffsetVal)):(o=i.observeFrequency,a=i.shiftOffsetVal),o&&i.xUnits?.toUpperCase().includes("HZ")&&(i.xUnits="PPM",i.xFactor=i.xFactor!==void 0?i.xFactor/o:void 0,i.firstX=i.firstX!==void 0?i.firstX/o:void 0,i.lastX=i.lastX!==void 0?i.lastX/o:void 0,i.deltaX=i.deltaX!==void 0?i.deltaX/o:void 0,i.data))for(let n=0;n<i.data.x.length;n++)i.data.x[n]/=o;if(a&&i.xUnits.toLowerCase().includes("ppm")&&i.firstX!==void 0&&i.lastX!==void 0){let n=i.firstX-a;if(i.firstX=i.firstX-n,i.lastX=i.lastX-n,i.data)for(let m=0;m<i.data.x.length;m++)i.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(o&&t.ntuples?.symbol&&t.ntuples.nucleus){let n="",m=t.ntuples.symbol.indexOf(i.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*o;i.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 o of e){if(Object.keys(o.ntuples).length>0){let a=[],i=Object.keys(o.ntuples);for(let n of i){let m=o.ntuples[n];if(m)for(let r=0;r<m.length;r++)a[r]||(a[r]={}),a[r][n]=m[r]}o.ntuples=a}o.twoD&&t.wantXY&&(q(o,t),t.logger?.trace({profiling:!0},"Finished countour plot calculation"),t.keepSpectra||delete o.spectra),t.chromatogram&&(o.spectra.length>1?le(o):K(o),t.logger?.trace({profiling:!0},"Finished chromatogram calculation")),delete o.tmp}}function Me(e,f){for(let t of e)for(let o in t.meta){let a=t.meta[o];if(typeof a=="string"){if(a.startsWith("{")){if(!a.includes(":")&&a.endsWith("}")){let i=a.slice(1,-1).split(/[,; ]+/).filter(Boolean);for(let n=0;n<i.length;n++)t.meta[o+String(n)]=f.dynamicTyping?(0,Q.parseString)(i[n]):i[n]}}else if(a.startsWith("(")){let i=a.split(/\r?\n/),n=/^\((?<from>\d+)\.\.(?<to>\d+)\).*$/;if(n.test(i[0])){let[m,r]=i[0].match(n)?.slice(1).map(Number)??[],p=i.slice(1).join(" ").split(/[,; ]+/).filter(Boolean);for(let u=m;u<=r;u++)f.dynamicTyping&&typeof p[u-m]=="string"?t.meta[o+String(u)]=(0,Q.parseString)(p[u-m]):t.meta[o+String(u)]=p[u-m]}}}}}function ee(e,f,t){let o=-1,a=-1,i="",n="";if(t.indexOf("++")>0)i=t.replace(/.*\(([a-zA-Z0-9]+)\+\+.*/,"$1"),n=t.replace(/.*\.\.([a-zA-Z0-9]+).*/,"$1");else{t=t.replaceAll(/[^a-zA-Z%]/g,""),i=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])}}o=e.ntuples.symbol?.indexOf(i)??-1,a=e.ntuples.symbol?.indexOf(n)??-1,o===-1&&(o=0),a===-1&&(a=0),e.ntuples.first&&(e.ntuples.first.length>o&&(f.firstX=e.ntuples.first[o]),e.ntuples.first.length>a&&(f.firstY=e.ntuples.first[a])),e.ntuples.last&&(e.ntuples.last.length>o&&(f.lastX=e.ntuples.last[o]),e.ntuples.last.length>a&&(f.lastY=e.ntuples.last[a])),e.ntuples.vardim&&e.ntuples.vardim.length>o&&(f.nbPoints=e.ntuples.vardim[o]),e.ntuples.factor&&(e.ntuples.factor.length>o&&(f.xFactor=e.ntuples.factor[o]),e.ntuples.factor.length>a&&(f.yFactor=e.ntuples.factor[a])),e.ntuples.units&&(e.ntuples.units.length>o&&(e.ntuples.varname?.[o]?f.xUnits=`${e.ntuples.varname[o]} [${e.ntuples.units[o]}]`:f.xUnits=e.ntuples.units[o]),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={removeComments:!1,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 o=[],a={entries:[],flatten:[]},i={children:[],spectra:[],ntuples:{},info:{},meta:{},tmp:{}},n=i,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]+/);_(t,l,h[0]),l.datatable=h[0],h[1]&&h[1].indexOf("PEAKS")>-1?f="PEAKTABLE":h[1]&&(h[1].indexOf("XYDATA")||h[0].indexOf("++")>0)&&(f="XYDATA",l.nbPoints&&(l.deltaX=(l.lastX-l.firstX)/(l.nbPoints-1)))}}if(f==="XYDATA"){i.wantXY&&(E(l),u.match(/.*\+\+.*/)?(l.nbPoints&&(l.deltaX=(l.lastX-l.firstX)/(l.nbPoints-1)),B(l,u,a)):w(l,u,a),t.spectra.push(l),l={});continue}else if(f==="PEAKTABLE"){i.wantXY&&(E(l),w(l,u,a),t.spectra.push(l),l={});continue}if(f==="PEAKASSIGNMENTS"){i.wantXY&&(u.match(/.*([^A-Z]*).*/)&&k(l,u),t.spectra.push(l),l={});continue}if(f==="TITLE"){let m=t;m.children||(m.children=[]),t={spectra:[],ntuples:{},info:{},meta:{},tmp:{}},m.children.push(t),r.push(m),s.push(t),t.title=u}else f==="DATATYPE"?(t.dataType=u,u.match(/(^nd|\snd\s)/i)&&(t.twoD=!0)):f==="NTUPLES"?u.match(/(^nd|\snd\s)/i)&&(t.twoD=!0):f==="DATACLASS"?t.dataClass=u:f==="JCAMPDX"?t.jcampDX=M(u):f==="JCAMPCS"?t.jcampCS=M(u):f==="XUNITS"?l.xUnits=u:f==="YUNITS"?l.yUnits=u:f==="FIRSTX"?l.firstX=Number(u):f==="LASTX"?l.lastX=Number(u):f==="FIRSTY"?l.firstY=Number(u):f==="LASTY"?l.lastY=Number(u):f==="NPOINTS"?l.nbPoints=Number(u):f==="XFACTOR"?l.xFactor=Number(u):f==="YFACTOR"?l.yFactor=Number(u):f==="MAXX"?l.maxX=Number(u):f==="MINX"?l.minX=Number(u):f==="MAXY"?l.maxY=Number(u):f==="MINY"?l.minY=Number(u):f==="DELTAX"?l.deltaX=Number(u):f===".OBSERVEFREQUENCY"||f==="$SFO1"?l.observeFrequency||(l.observeFrequency=Number(u)):f===".OBSERVENUCLEUS"?l.xType||(t.xType=u.replace(/[^a-zA-Z0-9]/g,"")):f==="$OFFSET"?(t.shiftOffsetNum=0,l.shiftOffsetVal||(l.shiftOffsetVal=Number(u))):f==="$REFERENCEPOINT"||(f==="VARNAME"?t.ntuples.varname=u.split(F):f==="SYMBOL"?t.ntuples.symbol=u.split(F):f==="VARTYPE"?t.ntuples.vartype=u.split(F):f==="VARFORM"?t.ntuples.varform=u.split(F):f==="VARDIM"?t.ntuples.vardim=Y(u.split(F)):f==="UNITS"?t.ntuples.units=u.split(F):f==="FACTOR"?t.ntuples.factor=Y(u.split(F)):f==="FIRST"?t.ntuples.first=Y(u.split(F)):f==="LAST"?t.ntuples.last=Y(u.split(F)):f==="MIN"?t.ntuples.min=Y(u.split(F)):f==="MAX"?t.ntuples.max=Y(u.split(F)):f===".NUCLEUS"?t.ntuples&&(t.ntuples.nucleus=u.split(F).map(m=>m.replace(/[^a-zA-Z0-9]/g,""))):f==="PAGE"?(l.page=u.trim(),l.pageValue=Number(u.replace(/^.*=/,"")),l.pageSymbol=l.page.replace(/[=].*/,"")):f==="RETENTIONTIME"?l.pageValue=Number(u):fe(f)?l[V(f)]=u:f==="SAMPLEDESCRIPTION"?l.sampleDescription=u:f.startsWith("$NUC")?!t.tmp[f]&&!u.includes("off")&&(t.tmp[f]=u.replace(/[<>]/g,"")):f==="END"&&(t=r.pop()));if(t&&t.info&&t.meta&&f.match(i.keepRecordsRegExp)){let m,h;d.startsWith("$")?(h=i.canonicMetadataLabels?f.substring(1):d.substring(1),m=t.meta):(h=i.canonicDataLabels?f:d,m=t.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),t=Pe(e.info.BONDLIST),r=De(e.info.CHARGE,s),l=Oe(a,n,t,r,s);return{molecule:l,molfile:l.toMolfile()}}function Oe(e,i,s,a,n){let t={S:e.Molecule.cBondTypeSingle,D:e.Molecule.cBondTypeDouble,T:e.Molecule.cBondTypeTriple,Q:e.Molecule.cBondTypeQuadruple},r={},l=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]=l.addAtom(p),l.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=l.addBond(r[o.atomNumber1],r[o.atomNumber2]);l.setBondType(p,t[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}l.setAtomCharge(r[o.atomNumber],o.value)}return l}function Re(e){let i=e.split(/\r?\n/).map(a=>M(a)).filter(a=>a),s=[];for(let a of i){let[n,t,r]=a.trim().split(/\s+/);s.push({atomNumber:Number(n),element:t,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,t,r]=a.trim().split(/\s+/);s.push({atomNumber1:Number(n),atomNumber2:Number(t),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[t,r,l]=n.trim().split(/\s+/);l!==void 0&&i?.warn("Charge on multiple atom is not supported"),a.push({atomNumber:Number(r),value:Number(t)})}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(t.removeComments&&(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),o.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"),_(o,a,t),t.logger?.trace({profiling:!0},"Total time"),a.entries=i.children||[],a.flatten=o,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:o}=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),i=Re(e.info.BONDLIST),n=De(e.info.CHARGE,t),m=Fe(o,a,i,n,t);return{molecule:m,molfile:m.toMolfile()}}function Fe(e,f,t,o,a){let i={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,i[r.bondType])}for(let r of o){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(o=>O(o)).filter(Boolean),t=[];for(let o of f){let[a,i,n]=o.trim().split(/\s+/);t.push({atomNumber:Number(a),element:i,nbImplicitHydrogens:n?.length>0?Number(n):void 0})}return t}function Re(e){let f=e.split(/\r?\n/).map(o=>O(o)).filter(Boolean),t=[];for(let o of f){let[a,i,n]=o.trim().split(/\s+/);t.push({atomNumber1:Number(a),atomNumber2:Number(i),bondType:n})}return t}function De(e,f){if(!e)return[];let t=e.split(/\r?\n/).map(a=>O(a)).filter(Boolean),o=[];for(let a of t){let[i,n,m]=a.trim().split(/\s+/);m!==void 0&&f?.warn("Charge on multiple atom is not supported"),o.push({atomNumber:Number(n),value:Number(i)})}return o}function Ye(e,f){let t=["STEREOPAIR","STEREOCENTER","RADICAL","STEREOMOLECULE"];for(let o of t)e.info[o]&&f?.warn(`JCAMP-CS parser do not support: ${o}`)}
@@ -1,253 +1,218 @@
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
+ * If it is true, anywhere out of XYDATA, PEAKTABLE n PEAKASSIGNMENTS the comments are removed
47
+ * @default false
98
48
  */
99
- keepRecordsRegExp?: RegExp | undefined;
49
+ removeComments?: boolean;
100
50
  /**
101
- * - Canonize the Labels (uppercase without symbol).
51
+ * By default we don't keep meta information.
52
+ * @default `/^$/`
102
53
  */
103
- canonicDataLabels?: boolean | undefined;
54
+ keepRecordsRegExp?: RegExp;
104
55
  /**
105
- * - Canonize the metadata Labels (uppercase without symbol).
56
+ * Canonize the Labels (uppercase without symbol).
106
57
  */
107
- canonicMetadataLabels?: boolean | undefined;
58
+ canonicDataLabels?: boolean;
108
59
  /**
109
- * - Convert numbers to Number.
60
+ * Canonize the metadata Labels (uppercase without symbol).
110
61
  */
111
- dynamicTyping?: boolean | undefined;
62
+ canonicMetadataLabels?: boolean;
112
63
  /**
113
- * - Remove the XY data.
64
+ * Convert numbers to Number.
114
65
  */
115
- withoutXY?: boolean | undefined;
66
+ dynamicTyping?: boolean;
116
67
  /**
117
- * - Special post-processing for GC / HPLC / MS.
68
+ * Remove the XY data.
118
69
  */
119
- chromatogram?: boolean | undefined;
70
+ withoutXY?: boolean;
120
71
  /**
121
- * - Force to keep the spectra in case of 2D.
72
+ * Special post-processing for GC / HPLC / MS.
122
73
  */
123
- keepSpectra?: boolean | undefined;
74
+ chromatogram?: boolean;
124
75
  /**
125
- * - For which fields we should not trim ?
76
+ * Force to keep the spectra in case of 2D.
126
77
  */
127
- noTrimRegExp?: RegExp | undefined;
78
+ keepSpectra?: boolean;
128
79
  /**
129
- * - Don't calculate countour in case of 2D.
80
+ * For which fields we should not trim ?
81
+ * @default `/^$/`
130
82
  */
131
- noContour?: boolean | undefined;
83
+ noTrimRegExp?: RegExp;
132
84
  /**
133
- * - Number of positive / negative contour levels to calculate.
85
+ * A logger like `pino`.
134
86
  */
135
- nbContourLevels?: number | undefined;
87
+ logger?: Logger;
136
88
  /**
137
- * - Define for 2D the level as 5 times the median as default.
89
+ * Add profiling information.
138
90
  */
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
- };
91
+ wantXY?: boolean;
92
+ start?: number;
93
+ fastParse?: boolean;
94
+ }
149
95
 
150
- declare type ConvertResult = {
151
- profiling: object[] | boolean;
152
- logs: string[];
153
- entries: object[];
96
+ declare interface ConvertResult {
97
+ entries: Entry[];
154
98
  flatten: Entry[];
155
- };
99
+ }
156
100
 
157
101
  /**
158
- *
159
- * @typedef {object} CreateTreeOptions@typedef {object} CreateTreeOptions
160
- * @property {boolean} [flatten=false]
161
- */
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[]}
102
+ * Parse the JCAMP-DX to extract the structure as a tree.
103
+ * @param jcamp
104
+ * @param options
105
+ * @returns Tree.
175
106
  */
176
- export declare function createTree(jcamp: string | ArrayBuffer | Uint8Array, options?: CreateTreeOptions | undefined): Tree[];
107
+ export declare function createTree(jcamp: string | ArrayBuffer | Uint8Array, options?: CreateTreeOptions): Stack[];
177
108
 
178
- declare type CreateTreeOptions = {
179
- flatten?: boolean | undefined;
180
- };
109
+ declare interface CreateTreeOptions {
110
+ flatten?: boolean;
111
+ }
181
112
 
182
- declare type Entry = {
113
+ declare interface Entry {
183
114
  spectra: Spectrum[];
184
115
  ntuples: Ntuples;
185
116
  meta: Record<string, string | string[] | number | number[] | boolean | boolean[] | undefined>;
186
117
  info: Record<string, string | string[] | number | number[] | boolean | boolean[] | undefined>;
187
118
  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;
119
+ title?: string;
120
+ dataType?: string;
121
+ dataClass?: string;
122
+ jcampDX?: string;
123
+ jcampCS?: string;
124
+ twoD?: boolean;
125
+ minMax?: MinMax;
126
+ children?: Entry[];
127
+ shiftOffsetVal?: number;
128
+ shiftOffsetNum?: number;
129
+ xType?: string;
130
+ yType?: string;
131
+ chromatogram?: Chromatogram;
132
+ contourLines?: ContourLines;
133
+ }
134
+
135
+ declare interface GenerateContourLinesOptions {
136
+ /**
137
+ * Number of positive / negative contour levels to calculate.
138
+ * @default `7`
139
+ */
140
+ nbContourLevels: number;
141
+ /**
142
+ * Define for 2D the level as 5 times the median as default.
143
+ * @default `5`
144
+ */
145
+ noiseMultiplier: number;
146
+ }
147
+
148
+ declare interface MinMax {
149
+ z: number[][];
199
150
  minX: number;
200
151
  maxX: number;
201
152
  minY: number;
202
153
  maxY: number;
203
154
  minZ: number;
204
155
  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
- };
156
+ median?: number;
157
+ noice?: number;
158
+ }
159
+
160
+ declare interface Ntuples {
161
+ varname?: string[];
162
+ symbol?: string[];
163
+ vartype?: string[];
164
+ varform?: string[];
165
+ vardim?: number[];
166
+ units?: string[];
167
+ factor?: number[];
168
+ first?: number[];
169
+ last?: number[];
170
+ min?: number[];
171
+ max?: number[];
172
+ nucleus?: string[];
173
+ [key: string]: any | undefined;
174
+ }
175
+
176
+ declare type OCL = openchemlib;
177
+
178
+ declare interface ParsedCS {
179
+ molfile: string;
180
+ molecule: Molecule;
181
+ }
222
182
 
223
183
  /**
224
184
  *
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]
185
+ * @param entry
186
+ * @param options
235
187
  * @returns ParsedCS
236
188
  */
237
- export declare function parseJcampCS(entry: Entry, options?: {
238
- logger?: any;
239
- OCL?: any;
240
- } | undefined): {
241
- molecule: any;
242
- molfile: any;
243
- } | undefined;
189
+ export declare function parseJcampCS(entry: Entry, options: ParseJcampCSOptions): ParsedCS | undefined;
190
+
191
+ declare interface ParseJcampCSOptions {
192
+ OCL: OCL;
193
+ logger?: Logger;
194
+ }
244
195
 
245
- declare type Spectrum = Record<string, any>;
196
+ declare interface Spectrum {
197
+ [key: string]: any;
198
+ data: Record<string, number[]>;
199
+ firstX?: number;
200
+ firstY?: number;
201
+ lastX?: number;
202
+ deltaX?: number;
203
+ yFactor?: number;
204
+ xFactor?: number;
205
+ nbPoints?: number;
206
+ }
246
207
 
247
- declare type Tree = {
208
+ declare interface Stack {
248
209
  title: string;
249
210
  jcamp: string;
250
- children?: Tree[] | undefined;
251
- };
211
+ children: Stack[] | undefined;
212
+ jcampDX?: string;
213
+ jcampCS?: string;
214
+ dataType?: string;
215
+ dataClass?: string;
216
+ }
252
217
 
253
218
  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=[],t=[],r=[],l,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());t.push({title:f.join(`
2
- `),jcamp:`${d}
3
- `,children:[]}),l=t[t.length-1],o.push(l)}else if(u.substring(0,5)==="##END"&&n===0){l.jcamp+=`${d}
4
- `;let f=t.pop();t.length!==0?(l=t[t.length-1],l.children.push(f)):(l=void 0,r.push(f))}else if(l&&l.jcamp){l.jcamp+=`${d}
5
- `;let f=u.match(/^##(.*?)=(.+)/);if(f){let m=f[1].replace(/[ _-]/g,"").toUpperCase();m==="DATATYPE"?l.dataType=f[2].trim():m==="DATACLASS"?l.dataClass=f[2].trim():m==="JCAMPDX"?l.jcampDX=M(f[2].trim()):m==="JCAMPCS"&&(l.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 t=0;t<E.length;t++){let r=I(E[t]);a[0][r]&&(o.push(r),i.series[r]={dimension:1,data:new Array(s)})}for(let t=0;t<s;t++){let r=a[t];i.times[t]=r.pageValue;for(let l=0;l<o.length;l++)i.series[o[l]].data[t]=Number(r[o[l]]);r.data&&(i.series.ms.data[t]=[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 t=e.firstX,r=e.firstY,l=!1,n,p=0;for(;p<a.length;p++)if(n=a.charCodeAt(p),n===13||n===10)l=!0;else if(l)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(t),o.y.push(r*s),t+=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 t=1;t<o.length;t++){let r=o[t].trim().replace(P,"").split(se);if(r.length%2===0)for(let l=0;l<r.length;l=l+2)i.x.push(Number(r[l])*e.xFactor),i.y.push(Number(r[l+1])*e.yFactor);else s.logs.push(`Format error: ${r}`)}}function ce(e,a,s){let i={},o=Object.keys(e.variables),t=o.length;o.forEach(l=>i[l]=[]),e.data=i;let r=a.split(/,? *,?[;\r\n]+ */);for(let l=1;l<r.length;l++){let n=r[l].trim().replace(P,"").split(se);if(n.length%t===0)for(let p=0;p<n.length;p++)i[o[p%t]].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(t=>t.toLowerCase());for(let t=1;t<i.length;t++){let r=i[t].replace(/^\((.*)\)$/,"$1").split(/ *, */);for(let l=0;l<o.length;l++){let n=r[l];switch(o[l]){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[l]]||(s[o[l]]=[]),s[o[l]].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,t=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<t;m++){let h=r[f][m];h<s&&(s=h),h>i&&(i=h)}}let l=a[0].data.x[0],n=a[0].data.x[a[0].data.x.length-1],{firstY:p,lastY:c}=he(e);if(l>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(l,n),maxX:Math.max(l,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:t,nucleus:r,units:l}=s[o];if(t.match(/[F|T]1/)&&l?.toUpperCase().match("HZ")){let n=ie(i[".OBSERVEFREQUENCY"]),{nucleus:p}=s.find(h=>h.symbol.match(/[F|T]2/));if([n,p,r].some(h=>!h))break;let c=ae(p),d=ae(r),{first:u,last:f}=s[o],m=n*d/c;return{firstY:u/m,lastY:f/m}}}return{firstY:a[0].pageValue,lastY:a[a.length-1].pageValue}}function k(e,a){let s=e.noise,i=e.z,o,t,r,l,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],t=z[S+1],r=ee[S],l=ee[S+1],n=o>x,p=t>x,c=r>x,d=l>x,n!==p&&n!==c&&(m=S+(x-o)/(t-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-l)/(t-l),g=S+1-(x-l)/(r-l),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-t)/(r-t))*C+N,h=(X+(x-t)/(r-t))*v+T,p!==n&&(g=S+1-(x-t)/(o-t),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-t)/(l-t),b.push(m),b.push(h),b.push(g*C+N),b.push(A*v+T)),c!==d&&(g=S+(x-r)/(l-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 Z(e,a){let s=B(e);a.noContour||(e.contourLines=k(s,a),delete s.z),e.minMax=s}import{getGyromagneticRatio as j}from"gyromagnetic-ratio";function J(e,a){for(let s of e){let i=0,o=0;for(let t of s.spectra){if(s.ntuples&&s.ntuples.symbol?(!i&&t.observeFrequency&&(i=t.observeFrequency),!o&&t.shiftOffsetVal&&(o=t.shiftOffsetVal)):(i=t.observeFrequency,o=t.shiftOffsetVal),i&&t.xUnits&&t.xUnits.toUpperCase().includes("HZ")){t.xUnits="PPM",t.xFactor=t.xFactor/i,t.firstX=t.firstX/i,t.lastX=t.lastX/i,t.deltaX=t.deltaX/i;for(let r=0;r<t.data.x.length;r++)t.data.x[r]/=i}if(o&&t.xUnits.toLowerCase().includes("ppm")){let r=t.firstX-o;t.firstX=t.firstX-r,t.lastX=t.lastX-r;for(let l=0;l<t.data.x.length;l++)t.data.x[l]-=r}if(s.ntuples&&s.ntuples.nucleus&&s.ntuples.symbol)for(let r=0;r<s.ntuples.nucleus.length;r++){let l=s.ntuples.symbol[r],n=s.ntuples.nucleus[r];if(l.match(/^[F|T]/)&&!n){if(l.match(/[F|T]1/))if(s.tmp.$NUC2)s.ntuples.nucleus[r]=s.tmp.$NUC2;else{let p=s.ntuples.symbol.indexOf(l.replace(/^([F|T]).*/,"$12"));p&&s.ntuples.nucleus[p]&&(s.ntuples.nucleus[r]=s.ntuples.nucleus[p])}l.match(/[F|T]2/)&&(s.ntuples.nucleus[r]=s.tmp.$NUC1)}l.match(/[F|T]2/)&&(s.yType=s.ntuples.nucleus[0],j(s.xType)||(s.xType=s.ntuples.nucleus[1]))}if(i&&s.ntuples&&s.ntuples.symbol&&s.ntuples.nucleus){let r="",l=s.ntuples.symbol.indexOf(t.pageSymbol);if(s.ntuples.units&&s.ntuples.units[l]&&(r=s.ntuples.units[l]),!r.toLowerCase().match(/(ppm|seconds)/)){if(l!==0){let u="Not sure about this ntuples format";if(a)a.warn(u);else throw Error(u)}let{nucleus:n}=s.ntuples,p=j(n[0]),c=j(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;t.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=[],t=Object.keys(i.ntuples);for(let r=0;r<t.length;r++){let l=t[r],n=i.ntuples[l];for(let p=0;p<n.length;p++)o[p]||(o[p]={}),o[p][l]=n[p]}i.ntuples=o}i.twoD&&s.wantXY&&(Z(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 t=o.slice(1,-1).split(/[,; ]+/).filter(r=>r);for(let r=0;r<t.length;r++)s.meta[i+String(r)]=a.dynamicTyping?ne(t[r]):t[r]}}else if(o[0]==="("){let t=o.split(/\r?\n/),r=/^\((?<from>\d+)\.\.(?<to>\d+)\).*$/;if(r.test(t[0])){let[l,n]=t[0].match(r).slice(1).map(Number),p=t.slice(1).join(" ").split(/[,; ]+/).filter(c=>c);for(let c=l;c<=n;c++)a.dynamicTyping&&typeof p[c-l]=="string"?s.meta[i+String(c)]=ne(p[c-l]):s.meta[i+String(c)]=p[c-l]}}}}}function q(e,a,s){let i=-1,o=-1,t="",r="";if(s.indexOf("++")>0)t=s.replace(/.*\(([a-zA-Z0-9]+)\+\+.*/,"$1"),r=s.replace(/.*\.\.([a-zA-Z0-9]+).*/,"$1");else{s=s.replace(/[^a-zA-Z%]/g,""),t=s.charAt(0),r=s.charAt(1),a.variables={};for(let l of s){let n=l.toLowerCase(),p=e.ntuples.symbol.indexOf(l);if(p===-1)throw Error(`Symbol undefined: ${l}`);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(t),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:[]},t=o,r=[],l={};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,o=e.split(/\r?\n/),f=[],i=[],t=[],l={title:"",jcamp:"",children:[]},r=0,p=e.includes("## ");for(let u=0;u<o.length;u++){let b=o[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<o.length&&!o[a].startsWith("##");a++)s.push(o[a].trim());i.push({title:s.join(`
2
+ `),jcamp:`${b}
3
+ `,children:[]}),l=i.at(-1),f.push(l)}else if(h.startsWith("##END")&&r===0&&l){l.jcamp+=`${b}
4
+ `;let s=i.pop();if(!s)throw new Error("Not finished");i.length>0?(l=i.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,o={times:new Array(n),series:{ms:{dimension:2,data:new Array(n)}}},f=[];for(let i of ee){let t=k(i);m[0][t]&&(f.push(t),o.series[t]={dimension:1,data:new Array(n)})}for(let i=0;i<n;i++){let t=m[i];o.times[i]=t.pageValue;for(let l of f)o.series[l].data[i]=Number(t[l]);t.data&&(o.series.ms.data[i]=[t.data.x,t.data.y])}e.chromatogram=o}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:o}=n;o&&(e.xFactor||o.info("The xFactor is not defined, it will be set to 1"),e.yFactor||o.info("The yFactor is not defined, it will be set to 1"));let f=e.yFactor??1,i=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,S=!1,N=!1,g=0,X=0,M=!1,C=!1,Y=!1,R=0;for(;a<=m.length;a++)if(a===m.length?s=13:s=m.codePointAt(a),N)(s===13||s===10)&&(d=!0,N=!1,c++);else if(s<=57&&s>=48)C=!0,R>0?g+=(s-48)/10**R++:(g*=10,g+=s-48);else if(s===44||s===46)C=!0,R++;else{if(C){if(M&&(g=g*-1,M=!1),d)g*=i,o&&(y?Math.abs(u-t-g)>l&&(Math.abs(u-g)<l?o.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?o.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`):o.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&&o.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,o&&Math.abs(b-g)>r&&o.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):S||(X=M?0-g:g);let x=S?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,C=!1,S=!1}if(s<74&&s>63)C=!0,y=!1,g=s-64;else if(s>96&&s<106)C=!0,y=!1,g=s-96,M=!0;else if(s===115)C=!0,S=!0,g=9;else if(s>82&&s<91)C=!0,S=!0,g=s-82;else if(s>73&&s<83)C=!0,A=!0,g=s-73;else if(s>105&&s<115)C=!0,A=!0,g=s-105,M=!0;else if(s===36&&m.codePointAt(a+1)===36)C=!0,N=!0;else if(s===37)C=!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)&&(C=!0,d||(y=!1),M=!0)}else(s===13||s===10)&&(d=!0,N=!1,c++)}o&&y&&o.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 o in e.variables)e.variables[o].data=e.data?.[o]}function ue(e,m,n){let{logger:o}=n,f={x:[],y:[]};e.data=f;let i=m.split(/,? *,?[;\r\n]+ */);for(let t=1;t<i.length;t++){let l=i[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 o?.warn(`Format error: ${l.toString()}`)}}function ce(e,m,n){let{logger:o}=n,f={},i=Object.keys(e.variables),t=i.length;for(let r of i)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[i[u%t]].push(Number(p[u]));else o?.warn(`Wrong number of columns: ${p.toString()}`)}}function B(e,m){e.isXYAdata=!0;let n={};e.data=n;let o=m.split(/\r?\n/),f=o[0].replace(/^.*?([A-Z]+).*$/,"$1").split("").map(i=>i.toLowerCase());for(let i=1;i<o.length;i++){let t=o[i].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 oe}from"gyromagnetic-ratio";import ie 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],o=n,f=m.length,i=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<i;a++){let c=t[s][a];c<n&&(n=c),c>o&&(o=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(ie(a))}let h=ie(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:o,noise:h}}function pe(e){let{spectra:m,ntuples:n,info:o}=e;if(n)for(let f of n){let{symbol:i,nucleus:t,units:l}=f;if(i.match(/[F|T]1/)&&l?.toUpperCase().match("HZ")){let r=se(o[".OBSERVEFREQUENCY"]),{nucleus:p}=n.find(c=>c.symbol.match(/[F|T]2/));if([r,p,t].some(c=>!c))break;let u=oe(p),b=oe(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,o=e.z,f,i,t,l,r,p,u,b,h=o.length,s=o[0].length,a,c,d,A,y=e.minX,S=(e.maxX-y)/(s-1),N=e.minY,X=(e.maxY-N)/(h-1),M=e.minZ,C=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=(C-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>=C))for(let v=0;v<h-1;v++){let Q=o[v],_=o[v+1];for(let T=0;T<s-1;T++)f=Q[T],i=Q[T+1],t=_[T],l=_[T+1],r=f>x,p=i>x,u=t>x,b=l>x,r!==p&&r!==u&&(a=T+(x-f)/(i-f),c=v,d=T,A=v+(x-f)/(t-f),D.push(a*S+y,c*X+N,d*S+y,A*X+N)),b!==p&&b!==u&&(a=T+1,c=v+1-(x-l)/(i-l),d=T+1-(x-l)/(t-l),A=v+1,D.push(a*S+y,c*X+N,d*S+y,A*X+N)),p!==u&&(a=(T+1-(x-i)/(t-i))*S+y,c=(v+(x-i)/(t-i))*X+N,p!==r&&(d=T+1-(x-i)/(f-i),A=v,D.push(a,c,d*S+y,A*X+N)),u!==r&&(d=T,A=v+1-(x-t)/(f-t),D.push(a,c,d*S+y,A*X+N)),p!==b&&(d=T+1,A=v+(x-i)/(l-i),D.push(a,c,d*S+y,A*X+N)),u!==b&&(d=T+(x-t)/(l-t),A=v+1,D.push(a,c,d*S+y,A*X+N)))}}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 o=0,f=0;for(let i of n.spectra){if(n.ntuples?.symbol?(!o&&i.observeFrequency&&(o=i.observeFrequency),!f&&i.shiftOffsetVal&&(f=i.shiftOffsetVal)):(o=i.observeFrequency,f=i.shiftOffsetVal),o&&i.xUnits?.toUpperCase().includes("HZ")&&(i.xUnits="PPM",i.xFactor=i.xFactor!==void 0?i.xFactor/o:void 0,i.firstX=i.firstX!==void 0?i.firstX/o:void 0,i.lastX=i.lastX!==void 0?i.lastX/o:void 0,i.deltaX=i.deltaX!==void 0?i.deltaX/o:void 0,i.data))for(let t=0;t<i.data.x.length;t++)i.data.x[t]/=o;if(f&&i.xUnits.toLowerCase().includes("ppm")&&i.firstX!==void 0&&i.lastX!==void 0){let t=i.firstX-f;if(i.firstX=i.firstX-t,i.lastX=i.lastX-t,i.data)for(let l=0;l<i.data.x.length;l++)i.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(o&&n.ntuples?.symbol&&n.ntuples.nucleus){let t="",l=n.ntuples.symbol.indexOf(i.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*o;i.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 o of e){if(Object.keys(o.ntuples).length>0){let f=[],i=Object.keys(o.ntuples);for(let t of i){let l=o.ntuples[t];if(l)for(let r=0;r<l.length;r++)f[r]||(f[r]={}),f[r][t]=l[r]}o.ntuples=f}o.twoD&&n.wantXY&&(G(o,n),n.logger?.trace({profiling:!0},"Finished countour plot calculation"),n.keepSpectra||delete o.spectra),n.chromatogram&&(o.spectra.length>1?te(o):J(o),n.logger?.trace({profiling:!0},"Finished chromatogram calculation")),delete o.tmp}}function de(e,m){for(let n of e)for(let o in n.meta){let f=n.meta[o];if(typeof f=="string"){if(f.startsWith("{")){if(!f.includes(":")&&f.endsWith("}")){let i=f.slice(1,-1).split(/[,; ]+/).filter(Boolean);for(let t=0;t<i.length;t++)n.meta[o+String(t)]=m.dynamicTyping?ae(i[t]):i[t]}}else if(f.startsWith("(")){let i=f.split(/\r?\n/),t=/^\((?<from>\d+)\.\.(?<to>\d+)\).*$/;if(t.test(i[0])){let[l,r]=i[0].match(t)?.slice(1).map(Number)??[],p=i.slice(1).join(" ").split(/[,; ]+/).filter(Boolean);for(let u=l;u<=r;u++)m.dynamicTyping&&typeof p[u-l]=="string"?n.meta[o+String(u)]=ae(p[u-l]):n.meta[o+String(u)]=p[u-l]}}}}}function z(e,m,n){let o=-1,f=-1,i="",t="";if(n.indexOf("++")>0)i=n.replace(/.*\(([a-zA-Z0-9]+)\+\+.*/,"$1"),t=n.replace(/.*\.\.([a-zA-Z0-9]+).*/,"$1");else{n=n.replaceAll(/[^a-zA-Z%]/g,""),i=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])}}o=e.ntuples.symbol?.indexOf(i)??-1,f=e.ntuples.symbol?.indexOf(t)??-1,o===-1&&(o=0),f===-1&&(f=0),e.ntuples.first&&(e.ntuples.first.length>o&&(m.firstX=e.ntuples.first[o]),e.ntuples.first.length>f&&(m.firstY=e.ntuples.first[f])),e.ntuples.last&&(e.ntuples.last.length>o&&(m.lastX=e.ntuples.last[o]),e.ntuples.last.length>f&&(m.lastY=e.ntuples.last[f])),e.ntuples.vardim&&e.ntuples.vardim.length>o&&(m.nbPoints=e.ntuples.vardim[o]),e.ntuples.factor&&(e.ntuples.factor.length>o&&(m.xFactor=e.ntuples.factor[o]),e.ntuples.factor.length>f&&(m.yFactor=e.ntuples.factor[f])),e.ntuples.units&&(e.ntuples.units.length>o&&(e.ntuples.varname?.[o]?m.xUnits=`${e.ntuples.varname[o]} [${e.ntuples.units[o]}]`:m.xUnits=e.ntuples.units[o]),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={removeComments:!1,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 o=[],f={entries:[],flatten:[]},i={children:[],spectra:[],ntuples:{},info:{},meta:{},tmp:{}},t=i,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(t,l,h[0]),l.datatable=h[0],h[1]&&h[1].indexOf("PEAKS")>-1?f="PEAKTABLE":h[1]&&(h[1].indexOf("XYDATA")||h[0].indexOf("++")>0)&&(f="XYDATA",l.nbPoints&&(l.deltaX=(l.lastX-l.firstX)/(l.nbPoints-1)))}}if(f==="XYDATA"){a.wantXY&&(w(l),u.match(/.*\+\+.*/)?(l.nbPoints&&(l.deltaX=(l.lastX-l.firstX)/(l.nbPoints-1)),U(l,u,i)):D(l,u,i),t.spectra.push(l),l={});continue}else if(f==="PEAKTABLE"){a.wantXY&&(w(l),D(l,u,i),t.spectra.push(l),l={});continue}if(f==="PEAKASSIGNMENTS"){a.wantXY&&(u.match(/.*([^A-Z]*).*/)&&V(l,u),t.spectra.push(l),l={});continue}if(f==="TITLE"){let m=t;m.children||(m.children=[]),t={spectra:[],ntuples:{},info:{},meta:{},tmp:{}},m.children.push(t),r.push(m),s.push(t),t.title=u}else f==="DATATYPE"?(t.dataType=u,u.match(/(^nd|\snd\s)/i)&&(t.twoD=!0)):f==="NTUPLES"?u.match(/(^nd|\snd\s)/i)&&(t.twoD=!0):f==="DATACLASS"?t.dataClass=u:f==="JCAMPDX"?t.jcampDX=M(u):f==="JCAMPCS"?t.jcampCS=M(u):f==="XUNITS"?l.xUnits=u:f==="YUNITS"?l.yUnits=u:f==="FIRSTX"?l.firstX=Number(u):f==="LASTX"?l.lastX=Number(u):f==="FIRSTY"?l.firstY=Number(u):f==="LASTY"?l.lastY=Number(u):f==="NPOINTS"?l.nbPoints=Number(u):f==="XFACTOR"?l.xFactor=Number(u):f==="YFACTOR"?l.yFactor=Number(u):f==="MAXX"?l.maxX=Number(u):f==="MINX"?l.minX=Number(u):f==="MAXY"?l.maxY=Number(u):f==="MINY"?l.minY=Number(u):f==="DELTAX"?l.deltaX=Number(u):f===".OBSERVEFREQUENCY"||f==="$SFO1"?l.observeFrequency||(l.observeFrequency=Number(u)):f===".OBSERVENUCLEUS"?l.xType||(t.xType=u.replace(/[^a-zA-Z0-9]/g,"")):f==="$OFFSET"?(t.shiftOffsetNum=0,l.shiftOffsetVal||(l.shiftOffsetVal=Number(u))):f==="$REFERENCEPOINT"||(f==="VARNAME"?t.ntuples.varname=u.split(F):f==="SYMBOL"?t.ntuples.symbol=u.split(F):f==="VARTYPE"?t.ntuples.vartype=u.split(F):f==="VARFORM"?t.ntuples.varform=u.split(F):f==="VARDIM"?t.ntuples.vardim=Y(u.split(F)):f==="UNITS"?t.ntuples.units=u.split(F):f==="FACTOR"?t.ntuples.factor=Y(u.split(F)):f==="FIRST"?t.ntuples.first=Y(u.split(F)):f==="LAST"?t.ntuples.last=Y(u.split(F)):f==="MIN"?t.ntuples.min=Y(u.split(F)):f==="MAX"?t.ntuples.max=Y(u.split(F)):f===".NUCLEUS"?t.ntuples&&(t.ntuples.nucleus=u.split(F).map(m=>m.replace(/[^a-zA-Z0-9]/g,""))):f==="PAGE"?(l.page=u.trim(),l.pageValue=Number(u.replace(/^.*=/,"")),l.pageSymbol=l.page.replace(/[=].*/,"")):f==="RETENTIONTIME"?l.pageValue=Number(u):le(f)?l[I(f)]=u:f==="SAMPLEDESCRIPTION"?l.sampleDescription=u:f.startsWith("$NUC")?!t.tmp[f]&&!u.includes("off")&&(t.tmp[f]=u.replace(/[<>]/g,"")):f==="END"&&(t=r.pop()));if(t&&t.info&&t.meta&&f.match(a.keepRecordsRegExp)){let m,h;d.startsWith("$")?(h=a.canonicMetadataLabels?f.substring(1):d.substring(1),m=t.meta):(h=a.canonicDataLabels?f:d,m=t.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),t=ye(e.info.BONDLIST),r=Ce(e.info.CHARGE,s),l=Te(i,o,t,r,s);return{molecule:l,molfile:l.toMolfile()}}function Te(e,a,s,i,o){let t={S:e.Molecule.cBondTypeSingle,D:e.Molecule.cBondTypeDouble,T:e.Molecule.cBondTypeTriple,Q:e.Molecule.cBondTypeQuadruple},r={},l=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]=l.addAtom(p),l.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=l.addBond(r[n.atomNumber1],r[n.atomNumber2]);l.setBondType(p,t[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}l.setAtomCharge(r[n.atomNumber],n.value)}return l}function Se(e){let a=e.split(/\r?\n/).map(i=>M(i)).filter(i=>i),s=[];for(let i of a){let[o,t,r]=i.trim().split(/\s+/);s.push({atomNumber:Number(o),element:t,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,t,r]=i.trim().split(/\s+/);s.push({atomNumber1:Number(o),atomNumber2:Number(t),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[t,r,l]=o.trim().split(/\s+/);l!==void 0&&a?.warn("Charge on multiple atom is not supported"),i.push({atomNumber:Number(r),value:Number(t)})}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(n.removeComments&&(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),o.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(o,f,n),n.logger?.trace({profiling:!0},"Total time"),f.entries=i.children||[],f.flatten=o,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:o}=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=Ce(e.info.ATOMLIST),i=Se(e.info.BONDLIST),t=Ne(e.info.CHARGE,n),l=Ae(o,f,i,t,n);return{molecule:l,molfile:l.toMolfile()}}function Ae(e,m,n,o,f){let i={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,i[r.bondType])}for(let r of o){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 Ce(e){let m=e.split(/\r?\n/).map(o=>O(o)).filter(Boolean),n=[];for(let o of m){let[f,i,t]=o.trim().split(/\s+/);n.push({atomNumber:Number(f),element:i,nbImplicitHydrogens:t?.length>0?Number(t):void 0})}return n}function Se(e){let m=e.split(/\r?\n/).map(o=>O(o)).filter(Boolean),n=[];for(let o of m){let[f,i,t]=o.trim().split(/\s+/);n.push({atomNumber1:Number(f),atomNumber2:Number(i),bondType:t})}return n}function Ne(e,m){if(!e)return[];let n=e.split(/\r?\n/).map(f=>O(f)).filter(Boolean),o=[];for(let f of n){let[i,t,l]=f.trim().split(/\s+/);l!==void 0&&m?.warn("Charge on multiple atom is not supported"),o.push({atomNumber:Number(t),value:Number(i)})}return o}function Te(e,m){let n=["STEREOPAIR","STEREOCENTER","RADICAL","STEREOMOLECULE"];for(let o of n)e.info[o]&&m?.warn(`JCAMP-CS parser do not support: ${o}`)}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.4",
3
+ "version": "10.0.1",
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,54 @@
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",
61
+ "jcamp-data-test": "^0.8.1",
65
62
  "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"
63
+ "jscpd": "^4.0.5",
64
+ "ml-spectra-processing": "^14.6.0",
65
+ "openchemlib": "^8.15.0",
66
+ "prettier": "^3.3.3",
67
+ "rimraf": "^6.0.1",
68
+ "typescript": "^5.6.3",
69
+ "vitest": "^2.1.3"
73
70
  },
74
71
  "dependencies": {
75
- "cheminfo-types": "^1.7.2",
76
- "dynamic-typing": "^1.0.0",
72
+ "cheminfo-types": "^1.8.0",
73
+ "dynamic-typing": "^1.0.1",
77
74
  "ensure-string": "^1.2.0",
78
- "gyromagnetic-ratio": "^1.1.1",
75
+ "gyromagnetic-ratio": "^1.2.0",
79
76
  "ml-array-median": "^1.1.6"
80
77
  }
81
78
  }