jcampconverter 11.2.1 → 11.3.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.
@@ -180,7 +180,10 @@ declare interface ParsedCS {
180
180
  }
181
181
 
182
182
  /**
183
- *
183
+ * Parse a JCAMP-CS entry and return a molecule and its molfile.
184
+ * We try to extract the chirality either from the coordinates or from the STEREOCENTER field.
185
+ * If chirality is present we will loose the coordinates as we need to
186
+ * @see https://doi.org/10.1366/0003702914337894
184
187
  * @param entry
185
188
  * @param options
186
189
  * @returns ParsedCS
@@ -1,11 +1,11 @@
1
- import{ensureString as fe}from"ensure-string";var $=/\s*\$\$.*/;function M(e,m=/\r\n/.exec(e)?`\r
1
+ import{ensureString as me}from"ensure-string";var $=/\s*\$\$.*/;function E(e,m=/\r\n/.exec(e)?`\r
2
2
  `:`
3
- `){return e.split(m).map(s=>s.replace($,"")).filter(Boolean).join(m).trim()}function Te(e,m={}){e=fe(e);let{flatten:n=!1}=m,s=e.split(/\r?\n/),f=[],i=[],t=[],l={title:"",jcamp:"",children:[]},r=0,p=e.includes("## ");for(let c=0;c<s.length;c++){let b=s[c],h=p?b.replaceAll(" ",""):b;if(h.startsWith("##NTUPLES")&&r++,h.startsWith("##TITLE")){let o=[h.slice(8).trim()];for(let a=c+1;a<s.length&&!s[a].startsWith("##");a++)o.push(s[a].trim());i.push({title:o.join(`
3
+ `){return e.split(m).map(o=>o.replace($,"")).filter(Boolean).join(m).trim()}function Le(e,m={}){e=me(e);let{flatten:t=!1}=m,o=e.split(/\r?\n/),l=[],i=[],n=[],f={title:"",jcamp:"",children:[]},s=0,u=e.includes("## ");for(let c=0;c<o.length;c++){let b=o[c],p=u?b.replaceAll(" ",""):b;if(p.startsWith("##NTUPLES")&&s++,p.startsWith("##TITLE")){let r=[p.slice(8).trim()];for(let a=c+1;a<o.length&&!o[a].startsWith("##");a++)r.push(o[a].trim());i.push({title:r.join(`
4
4
  `),jcamp:`${b}
5
- `,children:[]}),l=i.at(-1),f.push(l)}else if(h.startsWith("##END")&&r===0&&l){l.jcamp+=`${b}
6
- `;let o=i.pop();if(!o)throw new Error("Not finished");i.length>0?(l=i.at(-1),l.children?.push(o)):(l=void 0,t.push(o))}else if(l?.jcamp){l.jcamp+=`${b}
7
- `;let o=h.match(/^##(.*?)=(.+)/);if(o){let a=o[1].replaceAll(/[ _-]/g,"").toUpperCase();a==="DATATYPE"?l.dataType=o[2].trim():a==="DATACLASS"?l.dataClass=o[2].trim():a==="JCAMPDX"?l.jcampDX=M(o[2].trim()):a==="JCAMPCS"&&(l.jcampCS=M(o[2].trim()))}}h.startsWith("##END")&&r>0&&r--}if(n){for(let c of f)c.children=void 0;return f}else return t}import{parseString as de}from"dynamic-typing";import{ensureString as be}from"ensure-string";var ee=["TIC",".RIC","SCANNUMBER"];function te(e){let m=e.spectra,n=m.length,s={times:new Array(n),series:{ms:{dimension:2,data:new Array(n)}}},f=[];for(let i of ee){let t=U(i);m[0][t]&&(f.push(t),s.series[t]={dimension:1,data:new Array(n)})}for(let i=0;i<n;i++){let t=m[i];s.times[i]=t.pageValue;for(let l of f)s.series[l].data[i]=Number(t[l]);t.data&&(s.series.ms.data[i]=[t.data.x,t.data.y])}e.chromatogram=s}function ne(e){return ee.includes(e)}function U(e){return e.toLowerCase().replaceAll(/[^a-z0-9]/g,"")}function E(e){return e.map(Number)}function k(e,m,n){let{logger:s}=n;s&&(e.xFactor||s.info("The xFactor is not defined, it will be set to 1"),e.yFactor||s.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 c=e.firstX||0,b=e.firstY||0,h=!1,o,a=0;for(;a<m.length;a++)if(o=m.codePointAt(a),o===13||o===10)h=!0;else if(h)break;let u=0,d=!0,C=!1,x=!1,j=0,N=!1,S=!1,g=0,X=0,O=!1,A=!1,Y=!1,R=0;for(;a<=m.length;a++)if(a===m.length?o=13:o=m.codePointAt(a),S)(o===13||o===10)&&(d=!0,S=!1,u++);else if(o<=57&&o>=48)A=!0,R>0?g+=(o-48)/10**R++:(g*=10,g+=o-48);else if(o===44||o===46)A=!0,R++;else{if(A){if(O&&(g=g*-1,O=!1),d)g*=i,s&&(x?Math.abs(c-t-g)>l&&(Math.abs(c-g)<l?s.trace(`Data line ${u}: After a DIFFERENCE the next line should repeat the last value and this does not seem to be the case: Current value: ${g} - Expected: ${c}.`):Math.abs(c-t-g)>10*l?s.trace(`Data line ${u}: The difference between the first value ${g} and the expected first x value ${c} based on increment after a DIFFERENCE is too high`):s.trace(`Data line ${u}: The difference between the first value ${g} and the expected first x value ${c} based on increment after a DIFFERENCE is too high`)):Math.abs(c-g)>l&&s.trace(`Data line ${u}: The difference between the first value ${g} and the first x value ${c} is too high`)),d=!1,x&&(Y=!0);else if(Y)Y=!1,s&&Math.abs(b-g)>r&&s.trace(`Data line ${u}: After a duplicate the next line should repeat the same value ${g} !== ${b}`),b=g;else{C?(j=O?0-g:g,x=!0,C=!1):N||(X=O?0-g:g);let y=N?g-1:1;for(let F=0;F<y;F++)x?b+=j:b=X,p.x.push(c),p.y.push(b*f),c+=t}O=!1,g=0,R=0,A=!1,N=!1}if(o<74&&o>63)A=!0,x=!1,g=o-64;else if(o>96&&o<106)A=!0,x=!1,g=o-96,O=!0;else if(o===115)A=!0,N=!0,g=9;else if(o>82&&o<91)A=!0,N=!0,g=o-82;else if(o>73&&o<83)A=!0,C=!0,g=o-73;else if(o>105&&o<115)A=!0,C=!0,g=o-105,O=!0;else if(o===36&&m.codePointAt(a+1)===36)A=!0,S=!0;else if(o===37)A=!0,C=!0,g=0,O=!1;else if(o===45){let y=m.codePointAt(a+1);(y!==void 0&&y>=48&&y<=57||y===44||y===46)&&(A=!0,d||(x=!1),O=!0)}else(o===13||o===10)&&(d=!0,S=!1,u++)}s&&x&&s.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?me(e,m,n):ce(e,m,n),e.variables)for(let s in e.variables)e.variables[s].data=e.data?.[s]}function me(e,m,n){let{logger:s}=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 s?.warn(`Format error: ${l.toString()}`)}}function ce(e,m,n){let{logger:s}=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 c=0;c<p.length;c++)f[i[c%t]].push(Number(p[c]));else s?.warn(`Wrong number of columns: ${p.toString()}`)}}function V(e,m){e.isXYAdata=!0;let n={};e.data=n;let s=m.split(/\r?\n/),f=s[0].replace(/^.*?([A-Z]+).*$/,"$1").split("").map(i=>i.toLowerCase());for(let i=1;i<s.length;i++){let t=s[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 se}from"gyromagnetic-ratio";import ie from"ml-array-median";function oe(e){return Array.isArray(e)?e[0]:e}function B(e){let{spectra:m}=e,n=m[0].data.y[0],s=n,f=m.length,i=m[0].data.x.length||0,t=new Array(f);for(let o=0;o<f;o++){t[o]=m[o].data.y;for(let a=0;a<i;a++){let u=t[o][a];u<n&&(n=u),u>s&&(s=u)}}let l=m[0].data.x[0],r=m[0].data.x.at(-1),{firstY:p,lastY:c}=ue(e);if(l>r)for(let o of t)o.reverse();p>c&&t.reverse();let b=[];for(let o of t){let a=Float64Array.from(o);for(let u=0;u<a.length;u++)a[u]<0&&(a[u]=-a[u]);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,c),maxY:Math.max(p,c),minZ:n,maxZ:s,noise:h}}function ue(e){let{spectra:m,ntuples:n,info:s}=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=oe(s[".OBSERVEFREQUENCY"]),{nucleus:p}=n.find(u=>u.symbol.match(/[F|T]2/));if([r,p,t].some(u=>!u))break;let c=se(p),b=se(t),{first:h,last:o}=f,a=b!==null&&c!==null?r*b/c:r;return{firstY:h/a,lastY:o/a}}}return{firstY:m[0].pageValue,lastY:m.at(-1).pageValue}}function Z(e,m){let n=e.noise,s=e.z,f,i,t,l,r,p,c,b,h=s.length,o=s[0].length,a,u,d,C,x=e.minX,N=(e.maxX-x)/(o-1),S=e.minY,X=(e.maxY-S)/(h-1),O=e.minZ,A=e.maxZ,Y=m.nbContourLevels*2,R=new Array(Y),y;for(let F=0;F<Y;F++){let I={};R[F]=I;let le=F%2,K=(A-m.noiseMultiplier*n)*Math.exp((F>>1)-m.nbContourLevels);le===0?y=K+m.noiseMultiplier*n:y=0-K-m.noiseMultiplier*n;let D=[];if(I.zValue=y,I.lines=D,!(y<=O||y>=A))for(let T=0;T<h-1;T++){let Q=s[T],_=s[T+1];for(let v=0;v<o-1;v++)f=Q[v],i=Q[v+1],t=_[v],l=_[v+1],r=f>y,p=i>y,c=t>y,b=l>y,r!==p&&r!==c&&(a=v+(y-f)/(i-f),u=T,d=v,C=T+(y-f)/(t-f),D.push(a*N+x,u*X+S,d*N+x,C*X+S)),b!==p&&b!==c&&(a=v+1,u=T+1-(y-l)/(i-l),d=v+1-(y-l)/(t-l),C=T+1,D.push(a*N+x,u*X+S,d*N+x,C*X+S)),p!==c&&(a=(v+1-(y-i)/(t-i))*N+x,u=(T+(y-i)/(t-i))*X+S,p!==r&&(d=v+1-(y-i)/(f-i),C=T,D.push(a,u,d*N+x,C*X+S)),c!==r&&(d=v,C=T+1-(y-t)/(f-t),D.push(a,u,d*N+x,C*X+S)),p!==b&&(d=v+1,C=T+(y-i)/(l-i),D.push(a,u,d*N+x,C*X+S)),c!==b&&(d=v+(y-t)/(l-t),C=T+1,D.push(a,u,d*N+x,C*X+S)))}}return{minX:e.minX,maxX:e.maxX,minY:e.minY,maxY:e.maxY,segments:R}}function G(e,m){let n=B(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 s=0,f=0;for(let i of n.spectra){if(n.ntuples?.symbol?(!s&&i.observeFrequency&&(s=i.observeFrequency),!f&&i.shiftOffsetVal&&(f=i.shiftOffsetVal)):(s=i.observeFrequency,f=i.shiftOffsetVal),s&&i.xUnits?.toUpperCase().includes("HZ")&&(i.xUnits="PPM",i.xFactor=i.xFactor!==void 0?i.xFactor/s:void 0,i.firstX=i.firstX!==void 0?i.firstX/s:void 0,i.lastX=i.lastX!==void 0?i.lastX/s:void 0,i.deltaX=i.deltaX!==void 0?i.deltaX/s:void 0,i.data))for(let t=0;t<i.data.x.length;t++)i.data.x[t]/=s;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(s&&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,c=W(p[0]),b=W(p[1]);if(!c||!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=c/b*s;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),pe(e,n);for(let s of e){if(Object.keys(s.ntuples).length>0){let f=[],i=Object.keys(s.ntuples);for(let t of i){let l=s.ntuples[t];if(l)for(let r=0;r<l.length;r++)f[r]||(f[r]={}),f[r][t]=l[r]}s.ntuples=f}s.twoD&&n.wantXY&&(G(s,n),n.logger?.trace({profiling:!0},"Finished countour plot calculation"),n.keepSpectra||delete s.spectra),n.chromatogram&&(s.spectra.length>1?te(s):J(s),n.logger?.trace({profiling:!0},"Finished chromatogram calculation")),delete s.tmp}}function pe(e,m){for(let n of e)for(let s in n.meta){let f=n.meta[s];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[s+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 c=l;c<=r;c++)m.dynamicTyping&&typeof p[c-l]=="string"?n.meta[s+String(c)]=ae(p[c-l]):n.meta[s+String(c)]=p[c-l]}}}}}function z(e,m,n){let s=-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 c in e.ntuples)e.ntuples[c]?.[p]&&(m.variables[r][c.replace(/^var/,"")]=e.ntuples[c]?.[p])}}s=e.ntuples.symbol?.indexOf(i)??-1,f=e.ntuples.symbol?.indexOf(t)??-1,s===-1&&(s=0),f===-1&&(f=0),e.ntuples.first&&(e.ntuples.first.length>s&&(m.firstX=e.ntuples.first[s]),e.ntuples.first.length>f&&(m.firstY=e.ntuples.first[f])),e.ntuples.last&&(e.ntuples.last.length>s&&(m.lastX=e.ntuples.last[s]),e.ntuples.last.length>f&&(m.lastY=e.ntuples.last[f])),e.ntuples.vardim&&e.ntuples.vardim.length>s&&(m.nbPoints=e.ntuples.vardim[s]),e.ntuples.factor&&(e.ntuples.factor.length>s&&(m.xFactor=e.ntuples.factor[s]),e.ntuples.factor.length>f&&(m.yFactor=e.ntuples.factor[f])),e.ntuples.units&&(e.ntuples.units.length>s&&(e.ntuples.varname?.[s]?m.xUnits=`${e.ntuples.varname[s]} [${e.ntuples.units[s]}]`:m.xUnits=e.ntuples.units[s]),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]*/,ge={removeComments:!1,keepRecordsRegExp:/^$/,canonicDataLabels:!0,canonicMetadataLabels:!1,dynamicTyping:!0,withoutXY:!1,noTrimRegExp:/^$/,chromatogram:!1,keepSpectra:!1,noContour:!1,nbContourLevels:7,noiseMultiplier:5};function mt(e,m={}){e=be(e);let n={...ge,...m};n.logger?.debug("Starting jcamp conversion"),n.wantXY=!n.withoutXY,n.start=Date.now();let s=[],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,`
5
+ `,children:[]}),f=i.at(-1),l.push(f)}else if(p.startsWith("##END")&&s===0&&f){f.jcamp+=`${b}
6
+ `;let r=i.pop();if(!r)throw new Error("Not finished");i.length>0?(f=i.at(-1),f.children?.push(r)):(f=void 0,n.push(r))}else if(f?.jcamp){f.jcamp+=`${b}
7
+ `;let r=p.match(/^##(.*?)=(.+)/);if(r){let a=r[1].replaceAll(/[ _-]/g,"").toUpperCase();a==="DATATYPE"?f.dataType=r[2].trim():a==="DATACLASS"?f.dataClass=r[2].trim():a==="JCAMPDX"?f.jcampDX=E(r[2].trim()):a==="JCAMPCS"&&(f.jcampCS=E(r[2].trim()))}}p.startsWith("##END")&&s>0&&s--}if(t){for(let c of l)c.children=void 0;return l}else return n}import{parseString as be}from"dynamic-typing";import{ensureString as ge}from"ensure-string";var te=["TIC",".RIC","SCANNUMBER"];function ne(e){let m=e.spectra,t=m.length,o={times:new Array(t),series:{ms:{dimension:2,data:new Array(t)}}},l=[];for(let i of te){let n=k(i);m[0][n]&&(l.push(n),o.series[n]={dimension:1,data:new Array(t)})}for(let i=0;i<t;i++){let n=m[i];o.times[i]=n.pageValue;for(let f of l)o.series[f].data[i]=Number(n[f]);n.data&&(o.series.ms.data[i]=[n.data.x,n.data.y])}e.chromatogram=o}function re(e){return te.includes(e)}function k(e){return e.toLowerCase().replaceAll(/[^a-z0-9]/g,"")}function O(e){return e.map(Number)}function V(e,m,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 l=e.yFactor??1,i=e.xFactor??1,n=e.deltaX??1,f=Math.abs(n*.1),s=.01;e.isXYdata=!0;let u={x:[],y:[]};e.data=u;let c=e.firstX||0,b=e.firstY||0,p=!1,r,a=0;for(;a<m.length;a++)if(r=m.codePointAt(a),r===13||r===10)p=!0;else if(p)break;let d=0,g=!0,A=!1,x=!1,I=0,S=!1,C=!1,h=0,X=0,L=!1,N=!1,Y=!1,F=0;for(;a<=m.length;a++)if(a===m.length?r=13:r=m.codePointAt(a),C)(r===13||r===10)&&(g=!0,C=!1,d++);else if(r<=57&&r>=48)N=!0,F>0?h+=(r-48)/10**F++:(h*=10,h+=r-48);else if(r===44||r===46)N=!0,F++;else{if(N){if(L&&(h=h*-1,L=!1),g)h*=i,o&&(x?Math.abs(c-n-h)>f&&(Math.abs(c-h)<f?o.trace(`Data line ${d}: After a DIFFERENCE the next line should repeat the last value and this does not seem to be the case: Current value: ${h} - Expected: ${c}.`):Math.abs(c-n-h)>10*f?o.trace(`Data line ${d}: The difference between the first value ${h} and the expected first x value ${c} based on increment after a DIFFERENCE is too high`):o.trace(`Data line ${d}: The difference between the first value ${h} and the expected first x value ${c} based on increment after a DIFFERENCE is too high`)):Math.abs(c-h)>f&&o.trace(`Data line ${d}: The difference between the first value ${h} and the first x value ${c} is too high`)),g=!1,x&&(Y=!0);else if(Y)Y=!1,o&&Math.abs(b-h)>s&&o.trace(`Data line ${d}: After a duplicate the next line should repeat the same value ${h} !== ${b}`),b=h;else{A?(I=L?0-h:h,x=!0,A=!1):S||(X=L?0-h:h);let y=S?h-1:1;for(let M=0;M<y;M++)x?b+=I:b=X,u.x.push(c),u.y.push(b*l),c+=n}L=!1,h=0,F=0,N=!1,S=!1}if(r<74&&r>63)N=!0,x=!1,h=r-64;else if(r>96&&r<106)N=!0,x=!1,h=r-96,L=!0;else if(r===115)N=!0,S=!0,h=9;else if(r>82&&r<91)N=!0,S=!0,h=r-82;else if(r>73&&r<83)N=!0,A=!0,h=r-73;else if(r>105&&r<115)N=!0,A=!0,h=r-105,L=!0;else if(r===36&&m.codePointAt(a+1)===36)N=!0,C=!0;else if(r===37)N=!0,A=!0,h=0,L=!1;else if(r===45){let y=m.codePointAt(a+1);(y!==void 0&&y>=48&&y<=57||y===44||y===46)&&(N=!0,g||(x=!1),L=!0)}else(r===13||r===10)&&(g=!0,C=!1,d++)}o&&x&&o.warn("The last value is a difference, it should be repeated on the next line")}var oe=/[,\t ]+/;function w(e,m,t){if(e.isPeaktable=!0,!e.variables||Object.keys(e.variables).length===2?ce(e,m,t):ue(e,m,t),e.variables)for(let o in e.variables)e.variables[o].data=e.data?.[o]}function ce(e,m,t){let{logger:o}=t,l={x:[],y:[]};e.data=l;let i=m.split(/,? *,?[;\r\n]+ */);for(let n=1;n<i.length;n++){let f=i[n].trim().replace($,"").split(oe);if(f.length%2===0)for(let s=0;s<f.length;s=s+2)e.xFactor!==void 0&&e.yFactor!==void 0&&(l.x.push(Number(f[s])*e.xFactor),l.y.push(Number(f[s+1])*e.yFactor));else o?.warn(`Format error: ${f.toString()}`)}}function ue(e,m,t){let{logger:o}=t,l={},i=Object.keys(e.variables),n=i.length;for(let s of i)l[s]=[];e.data=l;let f=m.split(/,? *,?[;\r\n]+ */);for(let s=1;s<f.length;s++){let u=f[s].trim().replace($,"").split(oe);if(u.length%n===0)for(let c=0;c<u.length;c++)l[i[c%n]].push(Number(u[c]));else o?.warn(`Wrong number of columns: ${u.toString()}`)}}function B(e,m){e.isXYAdata=!0;let t={};e.data=t;let o=m.split(/\r?\n/),l=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 f=0;f<l.length;f++){let s=n[f];switch(l[f]){case"x":case"y":case"w":s=Number.parseFloat(s);break;case"a":s=s.replace(/^<(.*)>$/,"$1");break;case"m":break;default:continue}t[l[f]]||(t[l[f]]=[]),t[l[f]].push(s)}}}import{parseString as le}from"dynamic-typing";import{getGyromagneticRatio as ie}from"gyromagnetic-ratio";import ae from"ml-array-median";function se(e){return Array.isArray(e)?e[0]:e}function Z(e){let{spectra:m}=e,t=m[0].data.y[0],o=t,l=m.length,i=m[0].data.x.length||0,n=new Array(l);for(let r=0;r<l;r++){n[r]=m[r].data.y;for(let a=0;a<i;a++){let d=n[r][a];d<t&&(t=d),d>o&&(o=d)}}let f=m[0].data.x[0],s=m[0].data.x.at(-1),{firstY:u,lastY:c}=pe(e);if(f>s)for(let r of n)r.reverse();u>c&&n.reverse();let b=[];for(let r of n){let a=Float64Array.from(r);for(let d=0;d<a.length;d++)a[d]<0&&(a[d]=-a[d]);b.push(ae(a))}let p=ae(b);return{z:n,minX:Math.min(f,s),maxX:Math.max(f,s),minY:Math.min(u,c),maxY:Math.max(u,c),minZ:t,maxZ:o,noise:p}}function pe(e){let{spectra:m,ntuples:t,info:o}=e;if(t)for(let l of t){let{symbol:i,nucleus:n,units:f}=l;if(i.match(/[F|T]1/)&&f?.toUpperCase().match("HZ")){let s=se(o[".OBSERVEFREQUENCY"]),{nucleus:u}=t.find(d=>d.symbol.match(/[F|T]2/));if([s,u,n].some(d=>!d))break;let c=ie(u),b=ie(n),{first:p,last:r}=l,a=b!==null&&c!==null?s*b/c:s;return{firstY:p/a,lastY:r/a}}}return{firstY:m[0].pageValue,lastY:m.at(-1).pageValue}}function H(e,m){let t=e.noise,o=e.z,l,i,n,f,s,u,c,b,p=o.length,r=o[0].length,a,d,g,A,x=e.minX,S=(e.maxX-x)/(r-1),C=e.minY,X=(e.maxY-C)/(p-1),L=e.minZ,N=e.maxZ,Y=m.nbContourLevels*2,F=new Array(Y),y;for(let M=0;M<Y;M++){let U={};F[M]=U;let fe=M%2,Q=(N-m.noiseMultiplier*t)*Math.exp((M>>1)-m.nbContourLevels);fe===0?y=Q+m.noiseMultiplier*t:y=0-Q-m.noiseMultiplier*t;let D=[];if(U.zValue=y,U.lines=D,!(y<=L||y>=N))for(let v=0;v<p-1;v++){let _=o[v],ee=o[v+1];for(let T=0;T<r-1;T++)l=_[T],i=_[T+1],n=ee[T],f=ee[T+1],s=l>y,u=i>y,c=n>y,b=f>y,s!==u&&s!==c&&(a=T+(y-l)/(i-l),d=v,g=T,A=v+(y-l)/(n-l),D.push(a*S+x,d*X+C,g*S+x,A*X+C)),b!==u&&b!==c&&(a=T+1,d=v+1-(y-f)/(i-f),g=T+1-(y-f)/(n-f),A=v+1,D.push(a*S+x,d*X+C,g*S+x,A*X+C)),u!==c&&(a=(T+1-(y-i)/(n-i))*S+x,d=(v+(y-i)/(n-i))*X+C,u!==s&&(g=T+1-(y-i)/(l-i),A=v,D.push(a,d,g*S+x,A*X+C)),c!==s&&(g=T,A=v+1-(y-n)/(l-n),D.push(a,d,g*S+x,A*X+C)),u!==b&&(g=T+1,A=v+(y-i)/(f-i),D.push(a,d,g*S+x,A*X+C)),c!==b&&(g=T+(y-n)/(f-n),A=v+1,D.push(a,d,g*S+x,A*X+C)))}}return{minX:e.minX,maxX:e.maxX,minY:e.minY,maxY:e.maxY,segments:F}}function G(e,m){let t=Z(e);m.noContour||(e.contourLines=H(t,m),delete t.z),e.minMax=t}import{getGyromagneticRatio as W}from"gyromagnetic-ratio";function z(e,m){for(let t of e){let o=0,l=0;for(let i of t.spectra){if(t.ntuples?.symbol?(!o&&i.observeFrequency&&(o=i.observeFrequency),!l&&i.shiftOffsetVal&&(l=i.shiftOffsetVal)):(o=i.observeFrequency,l=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(l&&i.xUnits.toLowerCase().includes("ppm")&&i.firstX!==void 0&&i.lastX!==void 0){let n=i.firstX-l;if(i.firstX=i.firstX-n,i.lastX=i.lastX-n,i.data)for(let f=0;f<i.data.x.length;f++)i.data.x[f]-=n}if(t.ntuples?.nucleus&&t.ntuples.symbol)for(let n=0;n<t.ntuples.nucleus.length;n++){let f=t.ntuples.symbol[n],s=t.ntuples.nucleus[n];if(f.match(/^[F|T]/)&&!s){if(f.match(/[F|T]1/))if(t.tmp.$NUC2&&typeof t.tmp.$NUC2=="string")t.ntuples.nucleus[n]=t.tmp.$NUC2;else{let u=t.ntuples.symbol.indexOf(f.replace(/^([F|T]).*/,"$12"));u&&t.ntuples.nucleus[u]&&(t.ntuples.nucleus[n]=t.ntuples.nucleus[u])}f.match(/[F|T]2/)&&typeof t.tmp.$NUC1=="string"&&(t.ntuples.nucleus[n]=t.tmp.$NUC1)}f.match(/[F|T]2/)&&(t.yType=t.ntuples.nucleus[0],t.xType&&!W(t.xType)&&(t.xType=t.ntuples.nucleus[1]))}if(o&&t.ntuples?.symbol&&t.ntuples.nucleus){let n="",f=t.ntuples.symbol.indexOf(i.pageSymbol);t.ntuples.units?.[f]&&(n=t.ntuples.units[f]);let{nucleus:s}=t.ntuples;if(!n.toLowerCase().match(/(ppm|seconds)/)&&s.length>1){if(f!==0){let p="Not sure about this ntuples format";if(m){m.warn(p);continue}else throw new Error(p)}let{nucleus:u}=t.ntuples,c=W(u[0]),b=W(u[1]);if(!c||!b){let p=`Problem with determination of gyromagnetic ratio for ${u.join("-")}`;if(m)m.error(p);else throw new Error(p)}else{let p=c/b*o;i.pageValue/=p}}}}}}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,t){z(e,t.logger),de(e,t);for(let o of e){if(Object.keys(o.ntuples).length>0){let l=[],i=Object.keys(o.ntuples);for(let n of i){let f=o.ntuples[n];if(f)for(let s=0;s<f.length;s++)l[s]||(l[s]={}),l[s][n]=f[s]}o.ntuples=l}o.twoD&&t.wantXY&&(G(o,t),t.logger?.trace({profiling:!0},"Finished countour plot calculation"),t.keepSpectra||delete o.spectra),t.chromatogram&&(o.spectra.length>1?ne(o):J(o),t.logger?.trace({profiling:!0},"Finished chromatogram calculation")),delete o.tmp}}function de(e,m){for(let t of e)for(let o in t.meta){let l=t.meta[o];if(typeof l=="string"){if(l.startsWith("{")){if(!l.includes(":")&&l.endsWith("}")){let i=l.slice(1,-1).split(/[,; ]+/).filter(Boolean);for(let n=0;n<i.length;n++)t.meta[o+String(n)]=m.dynamicTyping?le(i[n]):i[n]}}else if(l.startsWith("(")){let i=l.split(/\r?\n/),n=/^\((?<from>\d+)\.\.(?<to>\d+)\).*$/;if(n.test(i[0])){let[f,s]=i[0].match(n)?.slice(1).map(Number)??[],u=i.slice(1).join(" ").split(/[,; ]+/).filter(Boolean);for(let c=f;c<=s;c++)m.dynamicTyping&&typeof u[c-f]=="string"?t.meta[o+String(c)]=le(u[c-f]):t.meta[o+String(c)]=u[c-f]}}}}}function K(e,m,t){let o=-1,l=-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),m.variables={};for(let f of t){let s=f.toLowerCase(),u=e.ntuples.symbol?.indexOf(f)||0;if(u===-1)throw new Error(`Symbol undefined: ${f}`);m.variables[s]={};for(let c in e.ntuples)e.ntuples[c]?.[u]&&(m.variables[s][c.replace(/^var/,"")]=e.ntuples[c]?.[u])}}o=e.ntuples.symbol?.indexOf(i)??-1,l=e.ntuples.symbol?.indexOf(n)??-1,o===-1&&(o=0),l===-1&&(l=0),e.ntuples.first&&(e.ntuples.first.length>o&&(m.firstX=e.ntuples.first[o]),e.ntuples.first.length>l&&(m.firstY=e.ntuples.first[l])),e.ntuples.last&&(e.ntuples.last.length>o&&(m.lastX=e.ntuples.last[o]),e.ntuples.last.length>l&&(m.lastY=e.ntuples.last[l])),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>l&&(m.yFactor=e.ntuples.factor[l])),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>l&&(e.ntuples.varname?.[l]?m.yUnits=`${e.ntuples.varname[l]} [${e.ntuples.units[l]}]`:m.yUnits=e.ntuples.units[l]))}function j(e){e.xFactor||(e.xFactor=1),e.yFactor||(e.yFactor=1)}var R=/[ \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 pt(e,m={}){e=ge(e);let t={...he,...m};t.logger?.debug("Starting jcamp conversion"),t.wantXY=!t.withoutXY,t.start=Date.now();let o=[],l={entries:[],flatten:[]},i={children:[],spectra:[],ntuples:{},info:{},meta:{},tmp:{}},n=i,f=[],s={data:{}};t.logger?.trace({profiling:!0},"Before split to LDRS");let u=e.replaceAll(/[\r\n]+##/g,`
8
8
  ##`).split(`
9
- ##`);n.logger?.trace({profiling:!0},"Split to LDRS"),p[0]&&(p[0]=p[0].replace(/^[\r\n ]*##/,""));for(let c of p){let b=c.indexOf("="),h=b>0?c.slice(0,Math.max(0,b)):c,o=b>0?h.match(n.noTrimRegExp)?c.slice(Math.max(0,b+1)):c.slice(Math.max(0,b+1)).trim():"",a=h.replaceAll(/[_ -]/g,"").toUpperCase();if(a==="DATATABLE"){let u=o.indexOf(`
10
- `);if(u===-1&&(u=o.indexOf("\r")),u>0){let d=o.slice(0,Math.max(0,u)).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),o.match(/.*\+\+.*/)?(r.nbPoints&&r.lastX!==void 0&&r.firstX!==void 0&&(r.deltaX=(r.lastX-r.firstX)/(r.nbPoints-1)),k(r,o,n)):P(r,o,n),t?.spectra.push(r),r={data:{}});continue}else if(a==="PEAKTABLE"){n.wantXY&&(w(r),P(r,o,n),t?.spectra.push(r),r={data:{}});continue}if(a==="PEAKASSIGNMENTS"){n.wantXY&&(o.match(/.*[^A-Z]*.*/)&&V(r,o),t?.spectra.push(r),r={data:{}});continue}if(n.removeComments&&(o=o.split(/\r?\n/).map(u=>u.replace(/ *\$\$.*$/,"")).join(`
11
- `)),a==="TITLE"){let u=t;u.children||(u.children=[]),t={spectra:[],ntuples:{},info:{},meta:{},tmp:{}},u.children.push(t),l.push(u),s.push(t),t.title=o}else a==="DATATYPE"?(t.dataType=o,o.match(/^nd|\snd\s/i)&&(t.twoD=!0)):a==="NTUPLES"?o.match(/^nd|\snd\s/i)&&(t.twoD=!0):a==="DATACLASS"?t.dataClass=o:a==="JCAMPDX"?t.jcampDX=M(o):a==="JCAMPCS"?t.jcampCS=M(o):a==="XUNITS"?r.xUnits=o:a==="YUNITS"?r.yUnits=o:a==="FIRSTX"?r.firstX=Number(o):a==="LASTX"?r.lastX=Number(o):a==="FIRSTY"?r.firstY=Number(o):a==="LASTY"?r.lastY=Number(o):a==="NPOINTS"?r.nbPoints=Number(o):a==="XFACTOR"?r.xFactor=Number(o):a==="YFACTOR"?r.yFactor=Number(o):a==="MAXX"?r.maxX=Number(o):a==="MINX"?r.minX=Number(o):a==="MAXY"?r.maxY=Number(o):a==="MINY"?r.minY=Number(o):a==="DELTAX"?r.deltaX=Number(o):a===".OBSERVEFREQUENCY"||a==="$SFO1"?r.observeFrequency||(r.observeFrequency=Number(o)):a===".OBSERVENUCLEUS"?r.xType||(t.xType=o.replaceAll(/[^a-zA-Z0-9]/g,"")):a==="$OFFSET"?(t.shiftOffsetNum=0,r.shiftOffsetVal||(r.shiftOffsetVal=Number(o))):a==="$REFERENCEPOINT"||(a==="VARNAME"?t.ntuples.varname=o.split(L):a==="SYMBOL"?t.ntuples.symbol=o.split(L):a==="VARTYPE"?t.ntuples.vartype=o.split(L):a==="VARFORM"?t.ntuples.varform=o.split(L):a==="VARDIM"?t.ntuples.vardim=E(o.split(L)):a==="UNITS"?t.ntuples.units=o.split(L):a==="FACTOR"?t.ntuples.factor=E(o.split(L)):a==="FIRST"?t.ntuples.first=E(o.split(L)):a==="LAST"?t.ntuples.last=E(o.split(L)):a==="MIN"?t.ntuples.min=E(o.split(L)):a==="MAX"?t.ntuples.max=E(o.split(L)):a===".NUCLEUS"?t.ntuples&&(t.ntuples.nucleus=o.split(L).map(u=>u.replaceAll(/[^a-zA-Z0-9]/g,""))):a==="PAGE"?(r.page=o.trim(),r.pageValue=Number(o.replace(/^.*=/,"")),r.pageSymbol=r.page.replace(/[=].*/,"")):a==="RETENTIONTIME"?r.pageValue=Number(o):ne(a)?r[U(a)]=o:a==="SAMPLEDESCRIPTION"?r.sampleDescription=o:a.startsWith("$NUC")?!t.tmp[a]&&!o.includes("off")&&(t.tmp[a]=o.replaceAll(/[<>]/g,"")):a==="END"&&(t=l.pop()));if(t?.info&&t.meta&&a.match(n.keepRecordsRegExp)){let u,d;h.startsWith("$")?(d=n.canonicMetadataLabels?a.slice(1):h.slice(1),u=t.meta):(d=n.canonicDataLabels?a:h,u=t.info),n.dynamicTyping&&(o=de(o)),u[d]?(Array.isArray(u[d])||(u[d]=[u[d]]),u[d].push(o)):u[d]=o}}if(n.logger?.trace({profiling:!0},"Finished parsing"),q(s,f,n),n.logger?.trace({profiling:!0},"Total time"),f.entries=i.children||[],f.flatten=s,n.logger){n.logger.debug("Finished jcamp conversion");for(let c of f.flatten)n.logger.debug(`${c.dataType} - ${c.title}`)}return f}function pt(e,m){let{logger:n,OCL:s}=m;if(!e.info.ATOMLIST||!e.info.BONDLIST){n?.warn("No ATOMLIST or BONDLIST in the JCAMP-CS entry");return}Ae(e,n);let f=ye(e.info.ATOMLIST),i=xe(e.info.BONDLIST),t=Ce(e.info.CHARGE,n),l=he(s,f,i,t,n);return{molecule:l,molfile:l.toMolfile()}}function he(e,m,n,s,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 s){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 ye(e){let m=e.split(/\r?\n/).map(s=>M(s)).filter(Boolean),n=[];for(let s of m){let[f,i,t]=s.trim().split(/\s+/);n.push({atomNumber:Number(f),element:i,nbImplicitHydrogens:t?.length>0?Number(t):void 0})}return n}function xe(e){let m=e.split(/\r?\n/).map(s=>M(s)).filter(Boolean),n=[];for(let s of m){let[f,i,t]=s.trim().split(/\s+/);n.push({atomNumber1:Number(f),atomNumber2:Number(i),bondType:t})}return n}function Ce(e,m){if(!e)return[];let n=e.split(/\r?\n/).map(f=>M(f)).filter(Boolean),s=[];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"),s.push({atomNumber:Number(t),value:Number(i)})}return s}function Ae(e,m){let n=["STEREOPAIR","STEREOCENTER","RADICAL","STEREOMOLECULE"];for(let s of n)e.info[s]&&m?.warn(`JCAMP-CS parser do not support: ${s}`)}export{mt as convert,Te as createTree,pt as parseJcampCS,M as removeComment,$ as removeCommentRegExp};
9
+ ##`);t.logger?.trace({profiling:!0},"Split to LDRS"),u[0]&&(u[0]=u[0].replace(/^[\r\n ]*##/,""));for(let c of u){let b=c.indexOf("="),p=b>0?c.slice(0,Math.max(0,b)):c,r=b>0?p.match(t.noTrimRegExp)?c.slice(Math.max(0,b+1)):c.slice(Math.max(0,b+1)).trim():"",a=p.replaceAll(/[_ -]/g,"").toUpperCase();if(a==="DATATABLE"){let d=r.indexOf(`
10
+ `);if(d===-1&&(d=r.indexOf("\r")),d>0){let g=r.slice(0,Math.max(0,d)).split(/[ ,;\t]+/);K(n,s,g[0]),s.datatable=g[0],g[1]?.includes("PEAKS")?a="PEAKTABLE":g[1]&&(g[1].indexOf("XYDATA")||g[0].indexOf("++")>0)&&(a="XYDATA",s.nbPoints&&s.lastX!==void 0&&s.firstX!==void 0&&(s.deltaX=(s.lastX-s.firstX)/(s.nbPoints-1)))}}if(a==="XYDATA"){t.wantXY&&(j(s),r.match(/.*\+\+.*/)?(s.nbPoints&&s.lastX!==void 0&&s.firstX!==void 0&&(s.deltaX=(s.lastX-s.firstX)/(s.nbPoints-1)),V(s,r,t)):w(s,r,t),n?.spectra.push(s),s={data:{}});continue}else if(a==="PEAKTABLE"){t.wantXY&&(j(s),w(s,r,t),n?.spectra.push(s),s={data:{}});continue}if(a==="PEAKASSIGNMENTS"){t.wantXY&&(r.match(/.*[^A-Z]*.*/)&&B(s,r),n?.spectra.push(s),s={data:{}});continue}if(t.removeComments&&(r=r.split(/\r?\n/).map(d=>d.replace(/ *\$\$.*$/,"")).join(`
11
+ `)),a==="TITLE"){let d=n;d.children||(d.children=[]),n={spectra:[],ntuples:{},info:{},meta:{},tmp:{}},d.children.push(n),f.push(d),o.push(n),n.title=r}else a==="DATATYPE"?(n.dataType=r,r.match(/^nd|\snd\s/i)&&(n.twoD=!0)):a==="NTUPLES"?r.match(/^nd|\snd\s/i)&&(n.twoD=!0):a==="DATACLASS"?n.dataClass=r:a==="JCAMPDX"?n.jcampDX=E(r):a==="JCAMPCS"?n.jcampCS=E(r):a==="XUNITS"?s.xUnits=r:a==="YUNITS"?s.yUnits=r:a==="FIRSTX"?s.firstX=Number(r):a==="LASTX"?s.lastX=Number(r):a==="FIRSTY"?s.firstY=Number(r):a==="LASTY"?s.lastY=Number(r):a==="NPOINTS"?s.nbPoints=Number(r):a==="XFACTOR"?s.xFactor=Number(r):a==="YFACTOR"?s.yFactor=Number(r):a==="MAXX"?s.maxX=Number(r):a==="MINX"?s.minX=Number(r):a==="MAXY"?s.maxY=Number(r):a==="MINY"?s.minY=Number(r):a==="DELTAX"?s.deltaX=Number(r):a===".OBSERVEFREQUENCY"||a==="$SFO1"?s.observeFrequency||(s.observeFrequency=Number(r)):a===".OBSERVENUCLEUS"?s.xType||(n.xType=r.replaceAll(/[^a-zA-Z0-9]/g,"")):a==="$OFFSET"?(n.shiftOffsetNum=0,s.shiftOffsetVal||(s.shiftOffsetVal=Number(r))):a==="$REFERENCEPOINT"||(a==="VARNAME"?n.ntuples.varname=r.split(R):a==="SYMBOL"?n.ntuples.symbol=r.split(R):a==="VARTYPE"?n.ntuples.vartype=r.split(R):a==="VARFORM"?n.ntuples.varform=r.split(R):a==="VARDIM"?n.ntuples.vardim=O(r.split(R)):a==="UNITS"?n.ntuples.units=r.split(R):a==="FACTOR"?n.ntuples.factor=O(r.split(R)):a==="FIRST"?n.ntuples.first=O(r.split(R)):a==="LAST"?n.ntuples.last=O(r.split(R)):a==="MIN"?n.ntuples.min=O(r.split(R)):a==="MAX"?n.ntuples.max=O(r.split(R)):a===".NUCLEUS"?n.ntuples&&(n.ntuples.nucleus=r.split(R).map(d=>d.replaceAll(/[^a-zA-Z0-9]/g,""))):a==="PAGE"?(s.page=r.trim(),s.pageValue=Number(r.replace(/^.*=/,"")),s.pageSymbol=s.page.replace(/[=].*/,"")):a==="RETENTIONTIME"?s.pageValue=Number(r):re(a)?s[k(a)]=r:a==="SAMPLEDESCRIPTION"?s.sampleDescription=r:a.startsWith("$NUC")?!n.tmp[a]&&!r.includes("off")&&(n.tmp[a]=r.replaceAll(/[<>]/g,"")):a==="END"&&(n=f.pop()));if(n?.info&&n.meta&&a.match(t.keepRecordsRegExp)){let d,g;p.startsWith("$")?(g=t.canonicMetadataLabels?a.slice(1):p.slice(1),d=n.meta):(g=t.canonicDataLabels?a:p,d=n.info),t.dynamicTyping&&(r=be(r)),d[g]?(Array.isArray(d[g])||(d[g]=[d[g]]),d[g].push(r)):d[g]=r}}if(t.logger?.trace({profiling:!0},"Finished parsing"),q(o,l,t),t.logger?.trace({profiling:!0},"Total time"),l.entries=i.children||[],l.flatten=o,t.logger){t.logger.debug("Finished jcamp conversion");for(let c of l.flatten)t.logger.debug(`${c.dataType} - ${c.title}`)}return l}function gt(e,m){let{logger:t,OCL:o}=m;if(!e.info.ATOMLIST||!e.info.BONDLIST){t?.warn("No ATOMLIST or BONDLIST in the JCAMP-CS entry");return}Te(e,t);let l=xe(e.info.ATOMLIST),i=Ae(e.info.BONDLIST),n=Ne(e.info.CHARGE,t),f=Se(e.info.XYRASTER,t),s=Ce(e.info.STEREOCENTER,t),u=ye(o,{atoms:l,bonds:i,charges:n,xyRasters:f,stereocenters:s},t);return{molecule:u,molfile:u.toMolfile()}}function ye(e,m,t){let{atoms:o,bonds:l,charges:i,xyRasters:n,stereocenters:f}=m,s={S:e.Molecule.cBondTypeSingle,D:e.Molecule.cBondTypeDouble,T:e.Molecule.cBondTypeTriple,Q:e.Molecule.cBondTypeQuadruple},u={},c=new e.Molecule(o.length,l.length);for(let p of o){let r=e.Molecule.getAtomicNoFromLabel(p.element);r||(t?.error(`Atomic number of ${p.element} could not be determined`),r=e.Molecule.getAtomicNoFromLabel("X")),u[p.atomNumber]=c.addAtom(r),c.setAtomMapNo(u[p.atomNumber],p.atomNumber,!1)}for(let p of l){if(u[p.atomNumber1]===void 0){t?.error(`A bond goes from atomNumber ${p.atomNumber1} that does not exists`);continue}if(u[p.atomNumber2]===void 0){t?.error(`A bond goes to atomNumber ${p.atomNumber2} that does not exists`);continue}let r=c.addBond(u[p.atomNumber1],u[p.atomNumber2]);c.setBondType(r,s[p.bondType])}for(let p of i){if(u[p.atomNumber]===void 0){t?.error(`A charge goes to atomNumber ${p.atomNumber} that does not exists`);continue}c.setAtomCharge(u[p.atomNumber],p.value)}let b=n.length===0||f.length>0;for(let p of n){if(u[p.atomNumber]===void 0){t?.error(`A XYRASTER goes to atomNumber ${p.atomNumber} that does not exists`);continue}c.setAtomX(u[p.atomNumber],p.x),c.setAtomY(u[p.atomNumber],p.y),c.setAtomZ(u[p.atomNumber],p.z)}c.ensureHelperArrays(e.Molecule.cHelperParities);for(let p of f){let{atomNumber:r,type:a}=p,d=u[r];if(d===void 0){t?.error(`A stereocenter goes to atomNumber ${r} that does not exists`);continue}if(!c.isAtomStereoCenter(d)){t?.warn(`Want to set chirality of atom number ${r} but it is not a stereocenter`);continue}if(c.getAtomParity(d)!==e.Molecule.cAtomParityUnknown){t?.debug(`Atom number ${r} already has a parity defined based on 3D coordinates`);continue}let x=a==="P"?e.Molecule.cAtomParity1:e.Molecule.cAtomParity2;c.setAtomParity(u[r],x,!1)}return c.ensureHelperArrays(e.Molecule.cHelperParities),b&&c.inventCoordinates(),c}function xe(e){let m=P(e),t=[];for(let o of m){let[l,i,n]=o.trim().split(/\s+/);t.push({atomNumber:Number(l),element:i,nbImplicitHydrogens:n?.length>0?Number(n):void 0})}return t}function Ae(e){let m=P(e),t=[];for(let o of m){let[l,i,n]=o.trim().split(/\s+/);t.push({atomNumber1:Number(l),atomNumber2:Number(i),bondType:n})}return t}function Ne(e,m){if(!e)return[];let t=P(e),o=[];for(let l of t){let[i,n,f]=l.trim().split(/\s+/);f!==void 0&&m?.warn("Charge on multiple atom is not supported"),o.push({atomNumber:Number(n),value:Number(i)})}return o}function Se(e,m){if(!e)return[];let t=P(e),o=[];for(let l of t){let[i,n,f,s]=l.trim().split(/\s+/);if(i===void 0){m?.warn("XYRASTER without atom number is not supported");continue}o.push({atomNumber:Number(i),x:Number(n),y:Number(f),z:s!==void 0?Number(s):0})}return o}function Ce(e,m){if(!e)return[];let t=P(e),o=[];for(let l of t){let[i,n]=l.trim().split(/\s+/);if(!["P","M"].includes(n)){m?.warn(`Stereocenter type ${n} is not supported`);continue}o.push({atomNumber:Number(i),type:n})}return o}function P(e){return e.split(/\r?\n/).map(m=>E(m)).filter(Boolean)}function Te(e,m){let t=["STEREOPAIR","STEREOCENTER","RADICAL","STEREOMOLECULE"];for(let o of t)e.info[o]&&m?.warn(`JCAMP-CS parser do not support: ${o}`)}export{pt as convert,Le as createTree,gt as parseJcampCS,E as removeComment,$ as removeCommentRegExp};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jcampconverter",
3
- "version": "11.2.1",
3
+ "version": "11.3.0",
4
4
  "description": "Parse and convert JCAMP-DX data",
5
5
  "license": "CC-BY-NC-SA-4.0",
6
6
  "type": "module",
@@ -58,5 +58,5 @@
58
58
  "volta": {
59
59
  "extends": "../../../package.json"
60
60
  },
61
- "gitHead": "590a8e4b1d464902733151fcefa7c9a739fddccf"
61
+ "gitHead": "dcc9fca3e0f8316accd10ed7f439fb90d521fb3f"
62
62
  }